/**
* Copyright (C) 2014 Stratio (http://stratio.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.stratio.decision.executables;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.stratio.decision.commons.constants.InternalTopic;
import com.stratio.decision.commons.constants.STREAM_OPERATIONS;
import com.stratio.decision.commons.messages.ColumnNameTypeValue;
import com.stratio.decision.commons.messages.StratioStreamingMessage;
import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scala.Tuple2;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class SensorGridSimulation {
private static Logger logger = LoggerFactory.getLogger(SensorGridSimulation.class);
public static final String[] sensors = { "Temperature", "Humidity", "Carbon dioxide", "Pressure", "Oxygen",
"Anemometer" };
public static final String[] dataRanges = { "20,30", "60,75", "0,1", "50,65", "88,100", "3,16" };
public static final String[] topics = { "commonSensor", "commonSensor", "commonSensor", "commonSensor",
"commonSensor", "commonSensor" };
// public static final String[] ids = {"3", "4", "5", "6", "7", "8"};
// //thingspeak
// public static final String[] ids = {"52516", "52519", "52520", "52521",
// "52522", "52523"}; //open.sen.se
public static final String[] ids = { "1", "1", "1", "1", "1", "1" }; // open.sen.se
public static final String sensorDataStream = "sensor_grid";
public static final long streamSessionId = System.currentTimeMillis();
public SensorGridSimulation() {
}
/**
* @param args
*/
public static void main(String[] args) {
SensorGridSimulation mySelf = new SensorGridSimulation();
try {
mySelf.launchSensorStreaming(args);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void launchSensorStreaming(String[] args) throws Exception {
launchStreamingSensorsData(args[0], Integer.parseInt(args[1]));
}
private void launchStreamingSensorsData(String brokerList, int dataToGenerate) throws Exception {
CountDownLatch shutdownLatch = new CountDownLatch(sensors.length);
AtomicInteger globalMessagesSent = new AtomicInteger(0);
// LAUNCH THROUGHPUT SERVICE
ExecutorService throughputExecutorService = Executors.newFixedThreadPool(1);
throughputExecutorService.execute(new ThroughputThread(globalMessagesSent));
// LAUNCH SENSOR DATA SERVICES
ExecutorService sensorExecutorService = Executors.newFixedThreadPool(sensors.length);
long startMs = System.currentTimeMillis();
for (int i = 0; i < sensors.length; i++) {
sensorExecutorService.execute(new SensorThread(brokerList, sensors[i], Integer.parseInt(ids[i]),
dataRanges[i], topics[i], dataToGenerate, shutdownLatch, globalMessagesSent));
}
shutdownLatch.await();
sensorExecutorService.shutdown();
throughputExecutorService.shutdownNow();
logger.info("====> TOTAL THREADS:"
+ sensors.length
+ "// TOTAL MESSAGES:"
+ (dataToGenerate * sensors.length)
+ "//Time:"
+ TimeUnit.MILLISECONDS.toMillis(System.currentTimeMillis() - startMs)
+ "//Messages/second:"
+ ((dataToGenerate * sensors.length) / TimeUnit.MILLISECONDS.toMillis(System.currentTimeMillis()
- startMs)));
}
protected class SensorThread implements Runnable {
private String name;
private int dataRangeLow;
private int dataRangeHigh;
private String topic;
private String brokerList;
private Producer<String, String> producer;
private Random random;
private int dataToGenerate;
private int index;
private CountDownLatch shutdownLatch;
private AtomicInteger globalMessagesSent;
private Gson gson;
public SensorThread(String brokerList, String name, int index, String dataRange, String topic,
int dataToGenerate, CountDownLatch shutdownLatch, AtomicInteger globalMessagesSent) {
this.name = name;
this.dataRangeLow = Integer.parseInt(dataRange.split(",")[0]);
this.dataRangeHigh = Integer.parseInt(dataRange.split(",")[1]);
this.topic = topic;
this.brokerList = brokerList;
this.producer = new Producer<String, String>(createProducerConfig());
this.dataToGenerate = dataToGenerate;
this.shutdownLatch = shutdownLatch;
this.globalMessagesSent = globalMessagesSent;
this.index = index;
random = new Random();
gson = new Gson();
}
private ProducerConfig createProducerConfig() {
Properties properties = new Properties();
properties.put("serializer.class", "kafka.serializer.StringEncoder");
properties.put("metadata.broker.list", brokerList);
// properties.put("request.required.acks", "1");
// properties.put("compress", "true");
// properties.put("compression.codec", "gzip");
// properties.put("producer.type", "sync");
return new ProducerConfig(properties);
}
@Override
public void run() {
logger.debug(name + index + " is ON... generating " + dataToGenerate + " measures");
StratioStreamingMessage message = new StratioStreamingMessage();
message.setOperation(STREAM_OPERATIONS.MANIPULATION.INSERT);
message.setStreamName(sensorDataStream);
message.setTimestamp(System.currentTimeMillis());
message.setSession_id("" + streamSessionId);
for (int i = 0; i < dataToGenerate; i++) {
List<ColumnNameTypeValue> sensorData = Lists.newArrayList();
sensorData.add(new ColumnNameTypeValue("name", null, name));
sensorData.add(new ColumnNameTypeValue("ind", null, "" + index));
sensorData.add(new ColumnNameTypeValue("data", null, (random
.nextInt((dataRangeHigh - dataRangeLow) + 1) + dataRangeLow)));
message.setRequest_id("" + System.currentTimeMillis());
message.setColumns(sensorData);
message.setRequest("dummy request");
KeyedMessage<String, String> busMessage = new KeyedMessage<String, String>(
InternalTopic.TOPIC_DATA.getTopicName(), STREAM_OPERATIONS.MANIPULATION.INSERT,
gson.toJson(message));
producer.send(busMessage);
globalMessagesSent.getAndIncrement();
}
shutdownLatch.countDown();
producer.close();
}
}
protected class ThroughputThread implements Runnable {
private AtomicInteger globalMessagesSent;
public ThroughputThread(AtomicInteger globalMessagesSent) {
this.globalMessagesSent = globalMessagesSent;
}
@Override
public void run() {
long startTime = System.currentTimeMillis();
List<Tuple2<String, Object>> data = Lists.newArrayList();
try {
while (!Thread.currentThread().isInterrupted()) {
data.clear();
long throughput = (globalMessagesSent.get() == 0) ? 0 : globalMessagesSent.get()
/ TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - startTime);
data.add(new Tuple2<String, Object>("52734", Double.valueOf(throughput)));
// DataToCollectorUtils.sendDataToOpenSense(data);
Thread.currentThread().sleep(7000);
}
}
catch (InterruptedException ie) {
try {
logger.debug("Ending throughput controller" + globalMessagesSent.get());
data.clear();
long throughput = (globalMessagesSent.get() == 0) ? 0 : globalMessagesSent.get()
/ TimeUnit.MILLISECONDS.toMillis(System.currentTimeMillis() - startTime);
data.add(new Tuple2<String, Object>("52734", Double.valueOf(throughput)));
// try {
// DataToCollectorUtils.sendDataToOpenSense(data);
// } catch (Exception e) {
// e.printStackTrace();
// }
long current = System.currentTimeMillis();
while (System.currentTimeMillis() < (current + 1000)) {
}
data.clear();
data.add(new Tuple2<String, Object>("52734", Double.valueOf(0)));
// DataToCollectorUtils.sendDataToOpenSense(data);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}