PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/snee/compiler/src/main/java/uk/ac/manchester/cs/snee/data/generator/ConstantRatePushStreamGenerator.java

http://snee.googlecode.com/
Java | 359 lines | 246 code | 29 blank | 84 comment | 26 complexity | 29dd8c0735dac5261f8f632f0b391ebc MD5 | raw file
  1. /****************************************************************************\
  2. * *
  3. * SNEE (Sensor NEtwork Engine) *
  4. * http://snee.cs.manchester.ac.uk/ *
  5. * http://code.google.com/p/snee *
  6. * *
  7. * Release 1.x, 2009, under New BSD License. *
  8. * *
  9. * Copyright (c) 2009, University of Manchester *
  10. * All rights reserved. *
  11. * *
  12. * Redistribution and use in source and binary forms, with or without *
  13. * modification, are permitted provided that the following conditions are *
  14. * met: Redistributions of source code must retain the above copyright *
  15. * notice, this list of conditions and the following disclaimer. *
  16. * Redistributions in binary form must reproduce the above copyright notice, *
  17. * this list of conditions and the following disclaimer in the documentation *
  18. * and/or other materials provided with the distribution. *
  19. * Neither the name of the University of Manchester nor the names of its *
  20. * contributors may be used to endorse or promote products derived from this *
  21. * software without specific prior written permission. *
  22. * *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS *
  24. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, *
  25. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR *
  26. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR *
  27. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
  28. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
  29. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
  30. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
  31. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
  32. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
  33. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
  34. * *
  35. \****************************************************************************/
  36. package uk.ac.manchester.cs.snee.data.generator;
  37. import java.io.ByteArrayOutputStream;
  38. import java.io.IOException;
  39. import java.io.ObjectOutputStream;
  40. import java.net.DatagramPacket;
  41. import java.net.InetAddress;
  42. import java.net.MalformedURLException;
  43. import java.net.MulticastSocket;
  44. import java.net.UnknownHostException;
  45. import java.util.ArrayList;
  46. import java.util.HashMap;
  47. import java.util.List;
  48. import java.util.Map;
  49. import java.util.Timer;
  50. import java.util.TimerTask;
  51. import org.apache.log4j.Logger;
  52. import uk.ac.manchester.cs.snee.MetadataException;
  53. import uk.ac.manchester.cs.snee.SNEEDataSourceException;
  54. import uk.ac.manchester.cs.snee.common.SNEEConfigurationException;
  55. import uk.ac.manchester.cs.snee.evaluator.types.EvaluatorAttribute;
  56. import uk.ac.manchester.cs.snee.evaluator.types.Tuple;
  57. import uk.ac.manchester.cs.snee.metadata.CostParametersException;
  58. import uk.ac.manchester.cs.snee.metadata.MetadataManager;
  59. import uk.ac.manchester.cs.snee.metadata.schema.ExtentDoesNotExistException;
  60. import uk.ac.manchester.cs.snee.metadata.schema.ExtentMetadata;
  61. import uk.ac.manchester.cs.snee.metadata.schema.SchemaMetadataException;
  62. import uk.ac.manchester.cs.snee.metadata.schema.TypeMappingException;
  63. import uk.ac.manchester.cs.snee.metadata.schema.UnsupportedAttributeTypeException;
  64. import uk.ac.manchester.cs.snee.metadata.source.SourceMetadataAbstract;
  65. import uk.ac.manchester.cs.snee.metadata.source.SourceMetadataException;
  66. import uk.ac.manchester.cs.snee.metadata.source.SourceType;
  67. import uk.ac.manchester.cs.snee.metadata.source.UDPSourceMetadata;
  68. import uk.ac.manchester.cs.snee.metadata.source.sensornet.TopologyReaderException;
  69. import uk.ac.manchester.cs.snee.sncb.SNCBException;
  70. public class ConstantRatePushStreamGenerator {
  71. Logger logger =
  72. Logger.getLogger(
  73. ConstantRatePushStreamGenerator.class.getName());
  74. /**
  75. * The list of streams
  76. */
  77. List<ExtentMetadata> _streams;
  78. /**
  79. * The generators which create tuples
  80. */
  81. Map<String, TupleGenerator> generators =
  82. new HashMap<String, TupleGenerator>();
  83. /**
  84. * The sockets for the streams to be sent across
  85. */
  86. Map<String, MulticastSocket> sockets =
  87. new HashMap<String, MulticastSocket>();
  88. /**
  89. * The timers which control the threads which generate the streams
  90. */
  91. private List<Timer> _timers;
  92. private List<BroadcastTask> _tasks;
  93. /**
  94. * The constructor initialises the stream generator.
  95. * @throws TypeMappingException
  96. * @throws UnsupportedAttributeTypeException
  97. * @throws SchemaMetadataException
  98. * @throws MetadataException
  99. * @throws SourceMetadataException
  100. * @throws SNEEConfigurationException
  101. * @throws TopologyReaderException
  102. * @throws SNEEDataSourceException
  103. * @throws MalformedURLException
  104. * @throws CostParametersException
  105. * @throws SNCBException
  106. */
  107. public ConstantRatePushStreamGenerator()
  108. throws TypeMappingException, MetadataException,
  109. SchemaMetadataException, UnsupportedAttributeTypeException,
  110. SourceMetadataException, SNEEConfigurationException,
  111. TopologyReaderException, MalformedURLException,
  112. SNEEDataSourceException, CostParametersException, SNCBException
  113. {
  114. if (logger.isDebugEnabled()) {
  115. logger.debug("ENTER ConstantRatePushStreamGenerator()");
  116. }
  117. MetadataManager schema =
  118. new MetadataManager(null);
  119. _streams = schema.getPushedExtents();
  120. _timers = new ArrayList<Timer>();
  121. _tasks = new ArrayList<BroadcastTask>();
  122. // Create a tuple generator and a socket for each stream
  123. for (ExtentMetadata stream : _streams) {
  124. String streamName = stream.getExtentName().toLowerCase();
  125. TupleGenerator tupleGeneator =
  126. new TupleGenerator(stream);
  127. generators.put(streamName, tupleGeneator);
  128. SourceMetadataAbstract source =
  129. schema.getSource(streamName);
  130. initialiseSource(stream, streamName, source);
  131. }
  132. if (logger.isDebugEnabled()) {
  133. logger.debug("RETURN ConstantRatePushStreamGenerator() " +
  134. "#streams=" + _streams.size());
  135. }
  136. }
  137. private void initialiseSource(ExtentMetadata stream,
  138. String streamName, SourceMetadataAbstract source)
  139. throws ExtentDoesNotExistException, SourceMetadataException,
  140. SchemaMetadataException {
  141. if (logger.isTraceEnabled())
  142. logger.trace("ENTER initialiseSource() for " + streamName +
  143. " source=" + source.getSourceName());
  144. if (source.getSourceType() == SourceType.UDP_SOURCE) {
  145. UDPSourceMetadata udpSource =
  146. (UDPSourceMetadata) source;
  147. instantiateUDPSource(udpSource, streamName);
  148. _tasks.add(createBroadcastTask(stream, udpSource));
  149. }
  150. if (logger.isTraceEnabled())
  151. logger.trace("RETURN initialiseSource() " +
  152. "#tasks=" + _tasks.size());
  153. }
  154. private void instantiateUDPSource(UDPSourceMetadata source,
  155. String streamName)
  156. throws ExtentDoesNotExistException {
  157. if (logger.isTraceEnabled())
  158. logger.trace("ENTER instantiateUDPSource() with " +
  159. source.getSourceName());
  160. try {
  161. MulticastSocket socket =
  162. new MulticastSocket(source.getPort(streamName));
  163. socket.joinGroup(InetAddress.getByName(source.getHost()));
  164. sockets.put(streamName, socket);
  165. } catch (IOException e) {
  166. e.printStackTrace();
  167. }
  168. if (logger.isTraceEnabled())
  169. logger.trace("RETURN instantiateUDPSource()");
  170. }
  171. private BroadcastTask createBroadcastTask(ExtentMetadata stream,
  172. UDPSourceMetadata udpSource)
  173. throws ExtentDoesNotExistException, SourceMetadataException,
  174. SchemaMetadataException {
  175. if (logger.isTraceEnabled())
  176. logger.trace("ENTER createBroadcastTask() for " +
  177. stream.getExtentName());
  178. String streamName = stream.getExtentName().toLowerCase();
  179. Timer timer = new Timer();
  180. BroadcastTask task = new BroadcastTask();
  181. // Set variables of the task
  182. task.streamName = streamName;
  183. MulticastSocket socket = sockets.get(streamName);
  184. if (logger.isTraceEnabled())
  185. logger.trace("Socket: " + socket);
  186. task.mcSocket = socket;
  187. String hostAddress = udpSource.getHost();
  188. if (logger.isTraceEnabled()) {
  189. logger.trace("Host: " + hostAddress);
  190. }
  191. task.address = hostAddress;
  192. int port = udpSource.getPort(streamName);
  193. logger.trace("Port: " + port);
  194. task.port = port;
  195. task.tupleGenerator = generators.get(streamName);
  196. task.timer = timer;
  197. task.sleepInterval =
  198. calculateSleepInterval(stream.getRate());
  199. if (logger.isTraceEnabled())
  200. logger.trace("RETURN createBroadcastTask()");
  201. return task;
  202. }
  203. /**
  204. * Creates a task for each stream to send tuples over a socket at the
  205. * desired rate
  206. * @throws SchemaMetadataException
  207. */
  208. public void startTransmission() throws SchemaMetadataException {
  209. logger.debug("ENTER startTransmission()");
  210. Timer timer;
  211. logger.debug("Here with streams " + _streams.size());
  212. for (BroadcastTask task : _tasks) {
  213. timer = new Timer();
  214. // Set schedule for the task
  215. timer.schedule(task, 0, //initial delay
  216. task.sleepInterval); //subsequent rate
  217. // Add timer to the set of timers
  218. _timers.add(timer);
  219. logger.debug("Started stream: " + task.streamName +
  220. " host: " + task.address + ":" + task.port);
  221. }
  222. logger.debug("RETURN startTransmission() #timers=" +
  223. _timers.size());
  224. }
  225. /**
  226. * Calculate the period to wait between each generated tuple
  227. * @param rate
  228. * @return
  229. */
  230. private int calculateSleepInterval(double rate) {
  231. return (int) (1000/rate);
  232. }
  233. /**
  234. * Stop each of the tasks that is generating a stream
  235. */
  236. public void stopTransmission() {
  237. if (logger.isDebugEnabled()) {
  238. logger.debug("ENTER stopTransmission() " +
  239. "Number of active timers: " + _timers.size());
  240. }
  241. for (Timer timer : _timers) {
  242. if (logger.isTraceEnabled()) {
  243. logger.trace("Stopping timer " + timer.toString());
  244. }
  245. timer.cancel();
  246. timer.purge();
  247. }
  248. _timers.removeAll(_timers);
  249. try {
  250. // Give the threads a chance to end
  251. Thread.sleep(1000);
  252. } catch (InterruptedException e) {
  253. }
  254. if (logger.isDebugEnabled()) {
  255. logger.debug("RETURN stopTransmission() " +
  256. "Number of active timers: " + _timers.size());
  257. }
  258. }
  259. class BroadcastTask extends TimerTask {
  260. private TupleGenerator tupleGenerator;
  261. private int curIndex = 0;
  262. private MulticastSocket mcSocket;
  263. private String streamName;
  264. private int port;
  265. private String address;
  266. private Timer timer;
  267. private int sleepInterval;
  268. public void run() {
  269. curIndex++;
  270. try {
  271. InetAddress inetAddress =
  272. InetAddress.getByName(address);
  273. // Generate next tuple for the stream
  274. Tuple tuple = tupleGenerator.generateTuple(curIndex);
  275. String tupleCSV = convertTupleToCSV(tuple);
  276. if (logger.isTraceEnabled())
  277. logger.trace("Creating byte stream for tuple " +
  278. tupleCSV);
  279. // Create a byte stream
  280. ByteArrayOutputStream b_out =
  281. new ByteArrayOutputStream();
  282. ObjectOutputStream o_out =
  283. new ObjectOutputStream(b_out);
  284. // Create a byte array out of the new tuple
  285. o_out.writeObject(tupleCSV);
  286. byte[] b = b_out.toByteArray();
  287. if (logger.isTraceEnabled()) {
  288. logger.trace("Creating packet for " + address +
  289. ":" + port);
  290. }
  291. // Create a UDP packet to send the tuple
  292. DatagramPacket packet =
  293. new DatagramPacket(b, b.length, inetAddress, port);
  294. // Send tuple over the socket
  295. if (logger.isTraceEnabled())
  296. logger.trace("Sending tuple");
  297. mcSocket.send(packet);
  298. if (logger.isTraceEnabled()) {
  299. logger.trace(streamName + " - " +
  300. tuple.toString());
  301. }
  302. } catch (UnknownHostException e) {
  303. logger.warn("Error creating connection for transmission. " + e);
  304. } catch (IOException e) {
  305. logger.warn("Error sending tuple. " + e);
  306. } catch (Exception e) {
  307. logger.warn("Unable to generate tuples. " + e);
  308. cancel();
  309. if (logger.isTraceEnabled())
  310. logger.trace("Removing from set of timers " + timer);
  311. _timers.remove(timer);
  312. }
  313. }
  314. private String convertTupleToCSV(Tuple tuple) {
  315. StringBuffer buffer = new StringBuffer();
  316. for (EvaluatorAttribute attr : tuple.getAttributeValues()) {
  317. buffer.append(attr.getData());
  318. buffer.append(",");
  319. }
  320. int lastCommaIndex = buffer.lastIndexOf(",");
  321. String retString;
  322. if (lastCommaIndex > 0){
  323. retString = buffer.substring(0, lastCommaIndex);
  324. } else {
  325. retString = buffer.toString();
  326. }
  327. return retString;
  328. }
  329. }
  330. }