package org.cloudfoundry.picalc;
import java.text.DateFormat;
import java.util.Date;
import java.util.UUID;
import org.cloudfoundry.picalc.config.QueueNames;
import org.cloudfoundry.picalc.messaging.MasterHandler;
import org.cloudfoundry.picalc.messaging.WorkMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Address;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.ChannelCallback;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.rabbitmq.client.AMQP.Queue.DeclareOk;
import com.rabbitmq.client.Channel;
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private Queue workQueue;
@Autowired
private MasterHandler masterHandler;
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
logger.info("Welcome home!");
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
model.addAttribute(new CalcParams());
return "home";
}
@RequestMapping(value = "/purge", method = RequestMethod.GET)
@ResponseBody
public String purgeQueue() {
RabbitAdmin admin = new RabbitAdmin(rabbitTemplate.getConnectionFactory());
admin.purgeQueue(QueueNames.WORK_QUEUE_NAME, true);
admin.purgeQueue(QueueNames.RESULT_QUEUE_NAME, true);
return QueueNames.WORK_QUEUE_NAME + "and " + QueueNames.RESULT_QUEUE_NAME + " queues were purged.";
}
@RequestMapping(value = "/queue", method = RequestMethod.GET)
@ResponseBody
public String queue() {
return "Message count for " + QueueNames.WORK_QUEUE_NAME + " = " + this.declareQueuePassive(this.workQueue).getMessageCount();
}
@RequestMapping(value="/calculate", method=RequestMethod.POST)
public String publish(Model model, CalcParams calcParams) {
long start = System.nanoTime();
double dPi = getPi(calcParams.getNrOfMessages());
long calcTime = (System.nanoTime() - start) / 1000000;
double error = dPi - Math.PI;
model.addAttribute("piValue", dPi);
model.addAttribute("error", error);
model.addAttribute("calcTime", calcTime);
logger.info("PI = " + dPi + ", error = " + error);
model.addAttribute("calculated", true);
return home(model);
}
public double getPi(int nrOfMessages) {
String corrId = UUID.randomUUID().toString();
int nrOfElements = 10000;
masterHandler.registerAggregate(corrId, nrOfMessages);
for (int i = 0; i < nrOfMessages; i++) {
WorkMessage workMessage = new WorkMessage();
workMessage.setCorrelationId(corrId);
workMessage.setStart(i);
workMessage.setNrOfElements(nrOfElements);
rabbitTemplate.convertAndSend(workMessage, new MessagePostProcessor() {
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setReplyToAddress(new Address("direct://piExchange/" + QueueNames.RESULT_QUEUE_NAME));
return message;
}
});
}
logger.info("Sent messages to workers. Waiting for response...");
try {
masterHandler.await(corrId);
} catch (InterruptedException e) {
logger.error("Error waiting for response from workers", e);
}
return masterHandler.getResult(corrId);
}
public DeclareOk declareQueuePassive(final Queue queue) {
return this.rabbitTemplate.execute(new ChannelCallback<DeclareOk>() {
public DeclareOk doInRabbit(Channel channel) throws Exception {
return channel.queueDeclarePassive(queue.getName());
}
});
}
}