1 package iotruntime.master;
4 import iotruntime.slave.IoTAddress;
5 import iotruntime.slave.IoTDeviceAddress;
6 import iotruntime.messages.*;
9 import org.objectweb.asm.ClassReader;
10 import org.objectweb.asm.ClassWriter;
11 import org.objectweb.asm.ClassVisitor;
16 import java.io.BufferedReader;
17 import java.io.InputStream;
18 import java.io.InputStreamReader;
20 import java.io.FileInputStream;
21 import java.io.FileOutputStream;
22 import java.io.ObjectInputStream;
23 import java.io.ObjectOutputStream;
24 import java.io.IOException;
25 import java.lang.ClassNotFoundException;
26 import java.lang.Class;
27 import java.lang.reflect.*;
28 import java.net.Socket;
29 import java.net.ServerSocket;
31 import static java.lang.Math.toIntExact;
33 /** Class IoTMaster is responsible to use ClassRuntimeInstrumenterMaster
34 * to instrument the controller/device bytecode and starts multiple
35 * IoTSlave running on different JVM's in a distributed fashion.
37 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
41 public class IoTMaster {
44 * IoTMaster class properties
46 * CommunicationHandler maintains the data structure for hostnames and ports
47 * LoadBalancer assigns a job onto a host based on certain metrics
49 private CommunicationHandler commHan;
50 private LoadBalancer lbIoT;
51 private RouterConfig routerConfig;
52 private ObjectInitHandler objInitHand;
53 private ObjectAddressInitHandler objAddInitHand;
54 private String[] strObjectNames;
55 private Map<String,ClassRuntimeInstrumenterMaster> mapClassNameToCrim;
57 * These properties hold information of a certain object
60 private String strObjName;
61 private String strObjClassName;
62 private String strObjClassInterfaceName;
63 private String strObjStubClsIntfaceName;
64 private String strIoTMasterHostAdd;
65 private String strIoTSlaveControllerHostAdd;
66 private String strIoTSlaveObjectHostAdd;
67 private Class[] arrFieldClasses;
68 private Object[] arrFieldValues;
69 private Socket filesocket;
71 // Constants that are to be extracted from config file
72 private static String STR_MASTER_MAC_ADD;
73 private static String STR_IOT_CODE_PATH;
74 private static String STR_CONT_PATH;
75 private static String STR_RUNTIME_DIR;
76 private static String STR_CLS_PATH;
77 private static String STR_RMI_PATH;
78 private static String STR_RMI_HOSTNAME;
79 private static String STR_LOG_FILE_PATH;
80 private static String STR_SSH_USERNAME;
81 private static String STR_ROUTER_ADD;
82 private static String STR_MONITORING_HOST;
83 private static String STR_ZB_GATEWAY_ADDRESS;
84 private static String STR_ZB_GATEWAY_PORT;
85 private static String STR_ZB_IOTMASTER_PORT;
86 private static boolean BOOL_VERBOSE;
89 * IoTMaster class constants
91 * Name constants - not to be configured by users
93 private static final String STR_IOT_MASTER_NAME = "IoTMaster";
94 private static final String STR_CFG_FILE_EXT = ".config";
95 private static final String STR_CLS_FILE_EXT = ".class";
96 private static final String STR_JAR_FILE_EXT = ".jar";
97 private static final String STR_ZIP_FILE_EXT = ".zip";
98 private static final String STR_TCP_PROTOCOL = "tcp";
99 private static final String STR_UDP_PROTOCOL = "udp";
100 private static final String STR_TCPGW_PROTOCOL = "tcpgw";
101 private static final String STR_NO_PROTOCOL = "nopro";
102 private static final String STR_SELF_MAC_ADD = "00:00:00:00:00:00";
103 private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS";
104 private static final String STR_INT_STUB_CLS_CFG = "INTERFACE_STUB_CLASS";
105 private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE";
106 private static final String STR_YES = "Yes";
107 private static final String STR_NO = "No";
110 * Runtime class name constants - not to be configured by users
112 private static final String STR_REL_INSTRUMENTER_CLS = "iotruntime.master.RelationInstrumenter";
113 private static final String STR_SET_INSTRUMENTER_CLS = "iotruntime.master.SetInstrumenter";
114 private static final String STR_IOT_SLAVE_CLS = "iotruntime.slave.IoTSlave";
115 private static final String STR_IOT_DEV_ADD_CLS = "IoTDeviceAddress";
116 private static final String STR_IOT_ZB_ADD_CLS = "IoTZigbeeAddress";
117 private static final String STR_IOT_ADD_CLS = "IoTAddress";
123 public IoTMaster(String[] argObjNms) {
129 objAddInitHand = null;
130 strObjectNames = argObjNms;
132 strObjClassName = null;
133 strObjClassInterfaceName = null;
134 strObjStubClsIntfaceName = null;
135 strIoTMasterHostAdd = null;
136 strIoTSlaveControllerHostAdd = null;
137 strIoTSlaveObjectHostAdd = null;
138 arrFieldClasses = null;
139 arrFieldValues = null;
141 mapClassNameToCrim = null;
143 STR_MASTER_MAC_ADD = null;
144 STR_IOT_CODE_PATH = null;
145 STR_CONT_PATH = null;
146 STR_RUNTIME_DIR = null;
149 STR_RMI_HOSTNAME = null;
150 STR_LOG_FILE_PATH = null;
151 STR_SSH_USERNAME = null;
152 STR_ROUTER_ADD = null;
153 STR_MONITORING_HOST = null;
154 STR_ZB_GATEWAY_ADDRESS = null;
155 STR_ZB_GATEWAY_PORT = null;
156 STR_ZB_IOTMASTER_PORT = null;
157 BOOL_VERBOSE = false;
161 * A method to initialize CommunicationHandler, LoadBalancer, RouterConfig and ObjectInitHandler
165 private void initLiveDataStructure() {
167 commHan = new CommunicationHandler(BOOL_VERBOSE);
168 lbIoT = new LoadBalancer(BOOL_VERBOSE);
169 lbIoT.setupLoadBalancer();
170 routerConfig = new RouterConfig();
171 routerConfig.getAddressList(STR_ROUTER_ADD);
172 objInitHand = new ObjectInitHandler(BOOL_VERBOSE);
173 objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE);
174 mapClassNameToCrim = new HashMap<String,ClassRuntimeInstrumenterMaster>();
178 * A method to initialize constants from config file
182 private void parseIoTMasterConfigFile() {
183 // Parse configuration file
184 Properties prop = new Properties();
185 String strCfgFileName = STR_IOT_MASTER_NAME + STR_CFG_FILE_EXT;
186 File file = new File(strCfgFileName);
187 FileInputStream fis = null;
189 fis = new FileInputStream(file);
192 } catch (IOException ex) {
193 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
194 ex.printStackTrace();
196 // Initialize constants from config file
197 STR_MASTER_MAC_ADD = prop.getProperty("MAC_ADDRESS");
198 STR_IOT_CODE_PATH = prop.getProperty("IOT_CODE_PATH");
199 STR_CONT_PATH = prop.getProperty("CONTROLLERS_CODE_PATH");
200 STR_RUNTIME_DIR = prop.getProperty("RUNTIME_DIR");
201 STR_CLS_PATH = prop.getProperty("CLASS_PATH");
202 STR_RMI_PATH = prop.getProperty("RMI_PATH");
203 STR_RMI_HOSTNAME = prop.getProperty("RMI_HOSTNAME");
204 STR_LOG_FILE_PATH = prop.getProperty("LOG_FILE_PATH");
205 STR_SSH_USERNAME = prop.getProperty("SSH_USERNAME");
206 STR_ROUTER_ADD = prop.getProperty("ROUTER_ADD");
207 STR_MONITORING_HOST = prop.getProperty("MONITORING_HOST");
208 STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS");
209 STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT");
210 STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT");
211 if(prop.getProperty("VERBOSE").equals(STR_YES)) {
215 RuntimeOutput.print("IoTMaster: Extracting information from config file: " + strCfgFileName, BOOL_VERBOSE);
216 RuntimeOutput.print("STR_MASTER_MAC_ADD=" + STR_MASTER_MAC_ADD, BOOL_VERBOSE);
217 RuntimeOutput.print("STR_IOT_CODE_PATH=" + STR_IOT_CODE_PATH, BOOL_VERBOSE);
218 RuntimeOutput.print("STR_CONT_PATH=" + STR_CONT_PATH, BOOL_VERBOSE);
219 RuntimeOutput.print("STR_RUNTIME_DIR=" + STR_RUNTIME_DIR, BOOL_VERBOSE);
220 RuntimeOutput.print("STR_CLS_PATH=" + STR_CLS_PATH, BOOL_VERBOSE);
221 RuntimeOutput.print("STR_RMI_PATH=" + STR_RMI_PATH, BOOL_VERBOSE);
222 RuntimeOutput.print("STR_RMI_HOSTNAME=" + STR_RMI_HOSTNAME, BOOL_VERBOSE);
223 RuntimeOutput.print("STR_LOG_FILE_PATH=" + STR_LOG_FILE_PATH, BOOL_VERBOSE);
224 RuntimeOutput.print("STR_SSH_USERNAME=" + STR_SSH_USERNAME, BOOL_VERBOSE);
225 RuntimeOutput.print("STR_ROUTER_ADD=" + STR_ROUTER_ADD, BOOL_VERBOSE);
226 RuntimeOutput.print("STR_MONITORING_HOST=" + STR_MONITORING_HOST, BOOL_VERBOSE);
227 RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE);
228 RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE);
229 RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE);
230 RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE);
231 RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE);
235 * A method to parse information from a config file
237 * @param strCfgFileName Config file name
238 * @param strCfgField Config file field name
241 private String parseConfigFile(String strCfgFileName, String strCfgField) {
242 // Parse configuration file
243 Properties prop = new Properties();
244 File file = new File(strCfgFileName);
245 FileInputStream fis = null;
247 fis = new FileInputStream(file);
250 } catch (IOException ex) {
251 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
252 ex.printStackTrace();
254 System.out.println("IoTMaster: Reading " + strCfgField +
255 " from config file: " + strCfgFileName + " with value: " +
256 prop.getProperty(strCfgField, null));
257 // NULL is returned if the property isn't found
258 return prop.getProperty(strCfgField, null);
262 * A method to send files from IoTMaster
264 * @param filesocket File socket object
265 * @param sFileName File name
266 * @param lFLength File length
269 private void sendFile(Socket filesocket, String sFileName, long lFLength) throws IOException {
271 File file = new File(sFileName);
272 byte[] bytFile = new byte[toIntExact(lFLength)];
273 InputStream inFileStream = new FileInputStream(file);
275 OutputStream outFileStream = filesocket.getOutputStream();
277 while ((iCount = inFileStream.read(bytFile)) > 0) {
278 outFileStream.write(bytFile, 0, iCount);
281 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
285 * A method to create a thread
287 * @param sSSHCmd SSH command
290 private void createThread(String sSSHCmd) throws IOException {
292 // Start a new thread to start a new JVM
294 Runtime runtime = Runtime.getRuntime();
295 Process process = runtime.exec(sSSHCmd);
297 RuntimeOutput.print("Executing: " + sSSHCmd, BOOL_VERBOSE);
301 * A method to send command from master and receive reply from slave
303 * @params msgSend Message object
304 * @params strPurpose String that prints purpose message
305 * @params inStream Input stream
306 * @params outStream Output stream
309 private void commMasterToSlave(Message msgSend, String strPurpose,
310 ObjectInputStream inStream, ObjectOutputStream outStream)
311 throws IOException, ClassNotFoundException {
313 // Send message/command from master
314 outStream.writeObject(msgSend);
315 RuntimeOutput.print("IoTMaster: Send message: " + strPurpose, BOOL_VERBOSE);
317 // Get reply from slave as acknowledgment
318 Message msgReply = (Message) inStream.readObject();
319 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
323 * A private method to instrument IoTSet device
325 * @params strFieldIdentifier String field name + object ID
326 * @params strFieldName String field name
327 * @params strIoTSlaveObjectHostAdd String slave host address
328 * @params inStream ObjectInputStream communication
329 * @params inStream ObjectOutputStream communication
332 private void instrumentIoTSetDevice(String strFieldIdentifier, String strFieldName, String strIoTSlaveObjectHostAdd,
333 ObjectInputStream inStream, ObjectOutputStream outStream)
334 throws IOException, ClassNotFoundException, InterruptedException {
336 // Get information from the set
337 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
338 // Create a new IoTSet
339 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
340 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream);
341 int iRows = listObject.size();
342 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
343 // Transfer the address
344 for(int iRow=0; iRow<iRows; iRow++) {
345 arrFieldValues = listObject.get(iRow);
346 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
347 String strDeviceAddress = null;
348 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
349 strDeviceAddress = strIoTSlaveObjectHostAdd;
351 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
353 int iDestDeviceDriverPort = (int) arrFieldValues[1];
354 String strProtocol = (String) arrFieldValues[2];
355 // Check for wildcard feature
356 boolean bSrcPortWildCard = false;
357 boolean bDstPortWildCard = false;
358 if (arrFieldValues.length > 3) {
359 bSrcPortWildCard = (boolean) arrFieldValues[3];
360 bDstPortWildCard = (boolean) arrFieldValues[4];
362 // Add the port connection into communication handler - if it's not assigned yet
363 if (commHan.getComPort(strDeviceAddress) == null) {
364 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddress);
366 // Send address one by one
367 Message msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
368 strDeviceAddress, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort,
369 bSrcPortWildCard, bDstPortWildCard);
370 commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream);
372 // Reinitialize IoTSet on device object
373 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
374 "Reinitialize IoTSet fields!", inStream, outStream);
379 * A private method to instrument IoTSet Zigbee device
381 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
382 * @params strFieldName String field name
383 * @params strIoTSlaveObjectHostAdd String slave host address
384 * @params inStream ObjectInputStream communication
385 * @params inStream ObjectOutputStream communication
388 private void instrumentIoTSetZBDevice(Map.Entry<String,Object> map, String strFieldName, String strIoTSlaveObjectHostAdd,
389 ObjectInputStream inStream, ObjectOutputStream outStream)
390 throws IOException, ClassNotFoundException, InterruptedException {
392 // Get information from the set
393 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
394 // Create a new IoTSet
395 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
396 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream);
397 // Prepare ZigbeeConfig
398 String strZigbeeGWAddress = routerConfig.getIPFromMACAddress(STR_ZB_GATEWAY_ADDRESS);
399 int iZigbeeGWPort = Integer.parseInt(STR_ZB_GATEWAY_PORT);
400 int iZigbeeIoTMasterPort = Integer.parseInt(STR_ZB_IOTMASTER_PORT);
401 commHan.addDevicePort(iZigbeeIoTMasterPort);
402 ZigbeeConfig zbConfig = new ZigbeeConfig(strZigbeeGWAddress, iZigbeeGWPort, iZigbeeIoTMasterPort,
404 // Add the port connection into communication handler - if it's not assigned yet
405 if (commHan.getComPort(strZigbeeGWAddress) == null) {
406 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddress);
408 int iRows = setInstrumenter.numberOfRows();
409 RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE);
410 // Transfer the address
411 for(int iRow=0; iRow<iRows; iRow++) {
412 arrFieldValues = setInstrumenter.fieldValues(iRow);
413 // Get device address
414 String strZBDevAddress = (String) arrFieldValues[0];
415 // Send policy to Zigbee gateway - TODO: Need to clear policy first?
416 zbConfig.setPolicy(strIoTSlaveObjectHostAdd, commHan.getComPort(strZigbeeGWAddress), strZBDevAddress);
417 // Send address one by one
418 Message msgGetIoTSetZBObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ZB_DEV_IOTSET_OBJECT,
420 commMasterToSlave(msgGetIoTSetZBObj, "Get IoTSet objects!", inStream, outStream);
422 zbConfig.closeConnection();
423 // Reinitialize IoTSet on device object
424 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
425 "Reinitialize IoTSet fields!", inStream, outStream);
430 * A private method to instrument IoTSet of addresses
432 * @params strFieldIdentifier String field name + object ID
433 * @params strFieldName String field name
434 * @params inStream ObjectInputStream communication
435 * @params inStream ObjectOutputStream communication
438 private void instrumentIoTSetAddress(String strFieldIdentifier, String strFieldName,
439 ObjectInputStream inStream, ObjectOutputStream outStream)
440 throws IOException, ClassNotFoundException, InterruptedException {
442 // Get information from the set
443 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
444 // Create a new IoTSet
445 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
446 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream);
447 int iRows = listObject.size();
448 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
449 // Transfer the address
450 for(int iRow=0; iRow<iRows; iRow++) {
451 arrFieldValues = listObject.get(iRow);
452 // Get device address
453 String strAddress = (String) arrFieldValues[0];
454 // Send address one by one
455 Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT,
457 commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream);
459 // Reinitialize IoTSet on device object
460 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
461 "Reinitialize IoTSet fields!", inStream, outStream);
466 * A private method to instrument an object on a specific machine and setting up policies
468 * @params strFieldObjectID String field object ID
471 private void instrumentObject(String strFieldObjectID) throws IOException {
473 // Extract the interface name for RMI
474 // e.g. ProximitySensorInterface, TempSensorInterface, etc.
476 String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
477 strObjClassInterfaceName = parseConfigFile(strObjCfgFile, STR_INTERFACE_CLS_CFG);
478 strObjStubClsIntfaceName = parseConfigFile(strObjCfgFile, STR_INT_STUB_CLS_CFG);
479 // Create an object name, e.g. ProximitySensorImplPS1
480 strObjName = strObjClassName + strFieldObjectID;
481 // Check first if host exists
482 if(commHan.objectExists(strObjName)) {
483 // If this object exists already ...
484 // Re-read IoTSlave object hostname for further reference
485 strIoTSlaveObjectHostAdd = commHan.getHostAddress(strObjName);
486 RuntimeOutput.print("IoTMaster: Object with name: " + strObjName + " has existed!", BOOL_VERBOSE);
488 // If this is a new object ... then create one
489 // Get host address for IoTSlave from LoadBalancer
490 //strIoTSlaveObjectHostAdd = lbIoT.selectHost();
491 strIoTSlaveObjectHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
492 if (strIoTSlaveControllerHostAdd == null)
493 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
494 RuntimeOutput.print("IoTMaster: Object name: " + strObjName, BOOL_VERBOSE);
495 // Add port connection and get port numbers
496 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
497 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strObjName);
498 commHan.addActiveControllerObject(strFieldObjectID, strObjName, strObjClassName, strObjClassInterfaceName,
499 strObjStubClsIntfaceName, strIoTSlaveObjectHostAdd, arrFieldValues, arrFieldClasses);
500 // ROUTING POLICY: IoTMaster and device/controller object
501 // Master-slave communication
502 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
503 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
504 // ROUTING POLICY: Send the same routing policy to both the hosts
505 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
506 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
507 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTMasterHostAdd,
508 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
509 // Need to accommodate callback functions here - open ports for TCP
510 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd,
511 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
512 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd,
513 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
514 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd,
515 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
516 // Instrument the IoTSet declarations inside the class file
517 instrumentObjectIoTSet(strFieldObjectID);
519 // Send routing policy to router for controller object
520 // ROUTING POLICY: RMI communication - RMI registry and stub ports
521 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
522 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
523 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
524 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
525 // Send the same set of routing policies to compute nodes
526 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
527 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
528 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
529 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
530 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
531 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
532 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
533 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
537 * A private method to set router policies for IoTDeviceAddress objects
539 * @params strFieldIdentifier String field name + object ID
540 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
541 * @params strIoTSlaveObjectHostAdd String slave host address
544 private void setRouterPolicyIoTSetDevice(String strFieldIdentifier, Map.Entry<String,Object> map,
545 String strIoTSlaveObjectHostAdd) {
547 // Get information from the set
548 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
549 int iRows = setInstrumenter.numberOfRows();
550 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
551 // Transfer the address
552 for(int iRow=0; iRow<iRows; iRow++) {
553 arrFieldValues = setInstrumenter.fieldValues(iRow);
554 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
555 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
556 String strDeviceAddress = null;
557 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
558 strDeviceAddress = strIoTSlaveObjectHostAdd;
560 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
562 int iDestDeviceDriverPort = (int) arrFieldValues[1];
563 String strProtocol = (String) arrFieldValues[2];
564 // Add the port connection into communication handler - if it's not assigned yet
565 if (commHan.getComPort(strDeviceAddress) == null) {
566 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddress);
568 // Send routing policy to router for device drivers and devices
569 // ROUTING POLICY: RMI communication - RMI registry and stub ports
570 if((iDestDeviceDriverPort == -1) && (!strProtocol.equals(STR_NO_PROTOCOL))) {
571 // Port number -1 means that we don't set the policy strictly to port number level
572 // "nopro" = no protocol specified for just TCP or just UDP (can be both used as well)
573 // ROUTING POLICY: Device driver and device
574 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress,
576 // ROUTING POLICY: Send to the compute node where the device driver is
577 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd,
578 strDeviceAddress, strProtocol);
579 } else if((iDestDeviceDriverPort == -1) && (strProtocol.equals(STR_NO_PROTOCOL))) {
580 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
581 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
582 } else if(strProtocol.equals(STR_TCPGW_PROTOCOL)) {
583 // This is a TCP protocol that connects, e.g. a phone to our runtime system
584 // that provides a gateway access (accessed through destination port number)
585 commHan.addDevicePort(iDestDeviceDriverPort);
586 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress,
587 STR_TCP_PROTOCOL, iDestDeviceDriverPort);
588 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress,
589 STR_TCP_PROTOCOL, iDestDeviceDriverPort);
590 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
591 routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
593 // Other port numbers...
594 commHan.addDevicePort(iDestDeviceDriverPort);
595 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress,
596 strProtocol, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort);
597 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress,
598 strProtocol, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort);
604 * A private method to set router policies for IoTAddress objects
606 * @params strFieldIdentifier String field name + object ID
607 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
608 * @params strHostAddress String host address
611 private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry<String,Object> map,
612 String strHostAddress) {
614 // Get information from the set
615 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
616 int iRows = setInstrumenter.numberOfRows();
617 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
618 // Transfer the address
619 for(int iRow=0; iRow<iRows; iRow++) {
620 arrFieldValues = setInstrumenter.fieldValues(iRow);
621 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
622 // Get device address
623 String strAddress = (String) arrFieldValues[0];
624 // Setting up router policies for HTTP/HTTPs
625 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress);
626 routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress);
631 * A private method to instrument an object's IoTSet and IoTRelation field to up policies
633 * Mostly the IoTSet fields would contain IoTDeviceAddress objects
635 * @params strFieldObjectID String field object ID
638 private void instrumentObjectIoTSet(String strFieldObjectID) throws IOException {
640 // If this is a new object ... then create one
641 // Instrument the class source code and look for IoTSet for device addresses
642 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
643 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT;
644 FileInputStream fis = new FileInputStream(strObjectClassNamePath);
645 ClassReader cr = new ClassReader(fis);
646 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
647 // We need Object ID to instrument IoTDeviceAddress
648 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE);
651 RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " +
652 strFieldObjectID, BOOL_VERBOSE);
653 // Get the object and the class names
654 // Build objects for IoTSet and IoTRelation fields in the device object classes
655 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
656 HashMap<String,Object> hmObjectFieldObjects = crim.getFieldObjects();
657 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
658 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
659 // Iterate over HashMap and choose between processing
660 String strFieldName = map.getKey();
661 String strClassName = map.getValue().getClass().getName();
662 String strFieldIdentifier = strFieldName + strFieldObjectID;
663 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
664 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
665 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
666 // Instrument the normal IoTDeviceAddress
667 setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
668 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
669 // Instrument the IoTAddress
670 setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
671 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
672 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
673 RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..",
676 String strErrMsg = "IoTMaster: Device driver object" +
677 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
678 " or IoTSet<IoTZigbeeAddress>!";
679 throw new Error(strErrMsg);
682 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
683 throw new Error(strErrMsg);
690 * A private method to create an object on a specific machine
692 * @params strObjName String object name
693 * @params strObjClassName String object class name
694 * @params strObjClassInterfaceName String object class interface name
695 * @params strIoTSlaveObjectHostAdd String IoTSlave host address
696 * @params strFieldObjectID String field object ID
697 * @params arrFieldValues Array of field values
698 * @params arrFieldClasses Array of field classes
701 private void createObject(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
702 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
703 throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException {
710 start = System.currentTimeMillis();
712 // Construct ssh command line
713 // e.g. ssh rtrimana@dw-2.eecs.uci.edu cd <path>;
714 // java -cp $CLASSPATH:./*.jar
715 // -Djava.rmi.server.codebase=file:./*.jar
716 // iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 &
717 // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa
718 String strSSHCommand = STR_SSH_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " sudo java " +
719 STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_RMI_HOSTNAME +
720 strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
721 commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
722 commHan.getRMIStubPort(strObjName) + " >& " + STR_LOG_FILE_PATH + strObjName + ".log &";
723 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
724 // Start a new thread to start a new JVM
725 createThread(strSSHCommand);
726 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjName));
727 Socket socket = serverSocket.accept();
728 ObjectInputStream inStream = new ObjectInputStream(socket.getInputStream());
729 ObjectOutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
732 result = System.currentTimeMillis()-start;
733 System.out.println("\n\n ==> Time needed to start JVM for " + strObjName + ": " + result + "\n\n");
736 start = System.currentTimeMillis();
738 // Create message to transfer file first
739 String sFileName = strObjClassName + STR_JAR_FILE_EXT;
740 String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
741 File file = new File(sPath);
742 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()),
743 "Sending file!", inStream, outStream);
744 // Send file - JAR file for object creation
745 sendFile(serverSocket.accept(), sPath, file.length());
746 Message msgReply = (Message) inStream.readObject();
747 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
750 result = System.currentTimeMillis()-start;
751 System.out.println("\n\n ==> Time needed to send JAR file for " + strObjName + ": " + result + "\n\n");
754 start = System.currentTimeMillis();
756 // Pack object information to create object on a IoTSlave
757 Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd,
758 strObjClassName, strObjName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
759 commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses);
761 commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream);
762 // Instrument the class source code and look for IoTSet for device addresses
763 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
764 RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " +
765 strFieldObjectID, BOOL_VERBOSE);
766 // Get the object and the class names
767 // Build objects for IoTSet and IoTRelation fields in the device object classes
768 ClassRuntimeInstrumenterMaster crim = mapClassNameToCrim.get(strObjClassName + strFieldObjectID);
769 HashMap<String,Object> hmObjectFieldObjects = crim.getFieldObjects();
770 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
771 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
772 // Iterate over HashMap and choose between processing
773 String strFieldName = map.getKey();
774 String strClassName = map.getValue().getClass().getName();
775 String strFieldIdentifier = strFieldName + strFieldObjectID;
776 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
777 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
778 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
779 // Instrument the normal IoTDeviceAddress
781 instrumentIoTSetDevice(strFieldIdentifier, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream);
783 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
784 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
786 instrumentIoTSetZBDevice(map, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream);
788 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
789 // Instrument the IoTAddress
791 instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream);
794 String strErrMsg = "IoTMaster: Device driver object" +
795 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
796 " or IoTSet<IoTZigbeeAddress>!";
797 throw new Error(strErrMsg);
800 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
801 throw new Error(strErrMsg);
805 // TODO: Change this later
806 outStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
809 result = System.currentTimeMillis()-start;
810 System.out.println("\n\n ==> Time needed to create object " + strObjName + " and instrument IoTDeviceAddress: " + result + "\n\n");
816 serverSocket.close();
821 * A private method to create controller objects
825 private void createControllerObjects() throws InterruptedException {
827 // Create a list of threads
828 List<Thread> threads = new ArrayList<Thread>();
829 // Get the list of active controller objects and loop it
830 List<String> listActiveControllerObject = commHan.getActiveControllerObjectList();
831 for(String strObjName : listActiveControllerObject) {
833 ObjectCreationInfo objCrtInfo = commHan.getObjectCreationInfo(strObjName);
834 Thread objectThread = new Thread(new Runnable() {
838 createObject(strObjName, objCrtInfo.getObjectClassName(), objCrtInfo.getObjectClassInterfaceName(),
839 objCrtInfo.getObjectStubClassInterfaceName(), objCrtInfo.getIoTSlaveObjectHostAdd(),
840 commHan.getFieldObjectID(strObjName), commHan.getArrayFieldValues(strObjName),
841 commHan.getArrayFieldClasses(strObjName));
842 } catch (IOException |
843 ClassNotFoundException |
844 InterruptedException ex) {
845 ex.printStackTrace();
850 threads.add(objectThread);
851 objectThread.start();
854 for (Thread thread : threads) {
857 } catch (InterruptedException ex) {
858 ex.printStackTrace();
865 * A private method to instrument IoTSet
867 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
868 * @params strFieldName String field name
871 private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName)
872 throws IOException, ClassNotFoundException, InterruptedException {
874 // Get information from the set
875 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
876 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTSET);
878 int iRows = setInstrumenter.numberOfRows();
879 for(int iRow=0; iRow<iRows; iRow++) {
880 // Get field classes and values
881 arrFieldClasses = setInstrumenter.fieldClasses(iRow);
882 arrFieldValues = setInstrumenter.fieldValues(iRow);
883 // Get object ID and class name
884 String strObjID = setInstrumenter.fieldObjectID(iRow);
885 strObjClassName = setInstrumenter.fieldEntryType(strObjID);
886 // Call the method to create an object
887 instrumentObject(strObjID);
888 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
889 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
890 commHan.getRMIStubPort(strObjName));
896 * A private method to instrument IoTRelation
898 * @params Map.Entry<String,Object> Entry of map IoTRelation instrumentation
899 * @params strFieldName String field name
902 private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName)
903 throws IOException, ClassNotFoundException, InterruptedException {
905 // Get information from the set
906 RelationInstrumenter relationInstrumenter = (RelationInstrumenter) map.getValue();
907 int iRows = relationInstrumenter.numberOfRows();
908 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTRELATION);
910 for(int iRow=0; iRow<iRows; iRow++) {
911 // Operate on the first set first
912 arrFieldClasses = relationInstrumenter.firstFieldClasses(iRow);
913 arrFieldValues = relationInstrumenter.firstFieldValues(iRow);
914 String strObjID = relationInstrumenter.firstFieldObjectID(iRow);
915 strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID);
916 // Call the method to create an object
917 instrumentObject(strObjID);
918 // Get the first object controller host address
919 String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
920 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
921 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
922 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
923 // Operate on the second set
924 arrFieldClasses = relationInstrumenter.secondFieldClasses(iRow);
925 arrFieldValues = relationInstrumenter.secondFieldValues(iRow);
926 strObjID = relationInstrumenter.secondFieldObjectID(iRow);
927 strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID);
928 // Call the method to create an object
929 instrumentObject(strObjID);
930 // Get the second object controller host address
931 String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
932 objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
933 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
934 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
936 // ROUTING POLICY: first and second controller objects in IoTRelation
937 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd,
938 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
939 // ROUTING POLICY: Send the same routing policy to both the hosts
940 routerConfig.configureHostMainPolicies(strFirstIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
941 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
942 routerConfig.configureHostMainPolicies(strSecondIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
943 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
948 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
950 * @params inStream ObjectInputStream communication
951 * @params outStream ObjectOutputStream communication
954 private void initializeSetsAndRelations(ObjectInputStream inStream, ObjectOutputStream outStream)
955 throws IOException, ClassNotFoundException {
956 // Get list of fields
957 List<String> strFields = objInitHand.getListOfFields();
958 // Iterate on HostAddress
959 for(String str : strFields) {
960 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
961 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
962 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
963 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, str);
964 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet!", inStream, outStream);
965 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
966 for (ObjectInitInfo objInitInfo : listObject) {
967 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
968 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(),
969 objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(),
970 objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
971 "Get IoTSet object!", inStream, outStream);
973 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
974 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
975 "Renitialize IoTSet field!", inStream, outStream);
976 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
977 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
978 Message msgCrtIoTRel = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTRELATION, str);
979 commMasterToSlave(msgCrtIoTRel, "Create new IoTRelation!", inStream, outStream);
980 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
981 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
982 Iterator it = listSecondObject.iterator();
983 for (ObjectInitInfo objInitInfo : listObject) {
984 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
985 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT,
986 objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(),
987 objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
988 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
989 "Get IoTRelation first object!", inStream, outStream);
990 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
991 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
992 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT,
993 objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(),
994 objSecObj.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
995 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort()),
996 "Get IoTRelation second object!", inStream, outStream);
998 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
999 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD),
1000 "Renitialize IoTRelation field!", inStream, outStream);
1006 * A method to set router basic policies at once
1008 * @param strRouter String router name
1011 private void setRouterBasicPolicies(String strRouter) {
1013 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1014 routerConfig.configureRouterICMPPolicies(strRouter, strMonitorHost);
1015 routerConfig.configureRouterDHCPPolicies(strRouter);
1016 routerConfig.configureRouterDNSPolicies(strRouter);
1017 routerConfig.configureRouterSSHPolicies(strRouter, strMonitorHost);
1018 routerConfig.configureRejectPolicies(strRouter);
1022 * A method to set host basic policies at once
1024 * @param strHost String host name
1027 private void setHostBasicPolicies(String strHost) {
1029 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1030 routerConfig.configureHostDHCPPolicies(strHost);
1031 routerConfig.configureHostDNSPolicies(strHost);
1032 if (strHost.equals(strMonitorHost)) {
1033 // Check if this is the monitoring host
1034 routerConfig.configureHostICMPPolicies(strHost);
1035 routerConfig.configureHostSSHPolicies(strHost);
1037 routerConfig.configureHostICMPPolicies(strHost, strMonitorHost);
1038 routerConfig.configureHostSSHPolicies(strHost, strMonitorHost);
1040 // Apply SQL allowance policies to master host
1041 if (strHost.equals(strIoTMasterHostAdd)) {
1042 routerConfig.configureHostSQLPolicies(strHost);
1044 routerConfig.configureRejectPolicies(strHost);
1048 * A method to create a thread for policy deployment
1050 * @param strRouterAddress String router address to configure
1051 * @param setHostAddresses Set of strings for host addresses to configure
1054 private void createPolicyThreads(String strRouterAddress, Set<String> setHostAddresses) throws IOException {
1056 // Create a list of threads
1057 List<Thread> threads = new ArrayList<Thread>();
1058 // Start threads for hosts
1059 for(String strAddress : setHostAddresses) {
1060 Thread policyThread = new Thread(new Runnable() {
1062 synchronized(this) {
1063 routerConfig.sendHostPolicies(strAddress);
1067 threads.add(policyThread);
1068 policyThread.start();
1069 RuntimeOutput.print("Deploying policies for: " + strAddress, BOOL_VERBOSE);
1071 // A thread for router
1072 Thread policyThread = new Thread(new Runnable() {
1074 synchronized(this) {
1075 routerConfig.sendRouterPolicies(strRouterAddress);
1079 threads.add(policyThread);
1080 policyThread.start();
1081 RuntimeOutput.print("Deploying policies on router: " + strRouterAddress, BOOL_VERBOSE);
1083 for (Thread thread : threads) {
1086 } catch (InterruptedException ex) {
1087 ex.printStackTrace();
1094 * A method to assign objects to multiple JVMs, including
1095 * the controller/device object that uses other objects
1096 * in IoTSet and IoTRelation
1100 private void createObjects() {
1107 // Extract hostname for this IoTMaster from MySQL DB
1108 strIoTMasterHostAdd = routerConfig.getIPFromMACAddress(STR_MASTER_MAC_ADD);
1109 // Loop as we can still find controller/device classes
1110 for(int i=0; i<strObjectNames.length; i++) {
1112 start = System.currentTimeMillis();
1114 // Assign a new list of PrintWriter objects
1115 routerConfig.renewPrintWriter();
1116 // Get controller names one by one
1117 String strObjControllerName = strObjectNames[i];
1118 // Use LoadBalancer to assign a host address
1119 //strIoTSlaveControllerHostAdd = lbIoT.selectHost();
1120 strIoTSlaveControllerHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
1121 if (strIoTSlaveControllerHostAdd == null)
1122 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
1123 // == START INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1124 // Add port connection and get port numbers
1125 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
1126 commHan.addPortConnection(strIoTSlaveControllerHostAdd, strObjControllerName);
1127 // ROUTING POLICY: IoTMaster and main controller object
1128 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
1129 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1130 // ROUTING POLICY: Send the same routing policy to both the hosts
1131 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
1132 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1133 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd,
1134 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1136 // Construct ssh command line and create a controller thread for e.g. AcmeProximity
1137 String strSSHCommand = STR_SSH_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1138 STR_RUNTIME_DIR + " sudo java " + STR_CLS_PATH + " " +
1139 STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
1140 commHan.getComPort(strObjControllerName) + " " +
1141 commHan.getRMIRegPort(strObjControllerName) + " " +
1142 commHan.getRMIStubPort(strObjControllerName) + " >& " +
1143 STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1144 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
1145 createThread(strSSHCommand);
1146 // Wait for connection
1147 // Create a new socket for communication
1148 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjControllerName));
1149 Socket socket = serverSocket.accept();
1150 ObjectInputStream inStream = new ObjectInputStream(socket.getInputStream());
1151 ObjectOutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
1152 RuntimeOutput.print("IoTMaster: Communication established!", BOOL_VERBOSE);
1155 result = System.currentTimeMillis()-start;
1156 System.out.println("\n\n ==> From start until after SSH for main controller: " + result);
1158 start = System.currentTimeMillis();
1160 // Send files for every controller class
1161 // e.g. AcmeProximity.jar and AcmeProximity.zip
1162 String strControllerClassName = strObjControllerName + STR_CLS_FILE_EXT;
1163 String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1164 strControllerClassName;
1166 String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT;
1167 String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1168 strControllerJarName;
1169 File file = new File(strControllerJarNamePath);
1170 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()),
1171 "Sending file!", inStream, outStream);
1172 // Send file - Class file for object creation
1173 sendFile(serverSocket.accept(), strControllerJarNamePath, file.length());
1174 Message msgReply = (Message) inStream.readObject();
1175 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1176 // Send .zip file if additional zip file is specified
1177 String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT;
1178 String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile;
1179 String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG);
1180 if (strAdditionalFile.equals(STR_YES)) {
1181 String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT;
1182 String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1183 strControllerCmpName;
1184 file = new File(strControllerCmpNamePath);
1185 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()),
1186 "Sending file!", inStream, outStream);
1187 // Send file - Class file for object creation
1188 sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length());
1189 msgReply = (Message) inStream.readObject();
1190 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1192 // Create main controller/device object
1193 commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName),
1194 "Create main object!", inStream, outStream);
1197 result = System.currentTimeMillis()-start;
1198 System.out.println("\n\n ==> From IoTSlave start until main controller object is created: " + result);
1199 System.out.println(" ==> Including file transfer times!\n\n");
1201 start = System.currentTimeMillis();
1203 // == END INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1204 // Instrumenting one file
1205 RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE);
1206 RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE);
1207 FileInputStream fis = new FileInputStream(strControllerClassNamePath);
1208 ClassReader cr = new ClassReader(fis);
1209 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
1210 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE);
1213 // Get the object and the class names
1214 // Build objects for IoTSet and IoTRelation fields in the controller/device classes
1215 HashMap<String,Object> hmControllerFieldObjects = crim.getFieldObjects();
1216 for(Map.Entry<String,Object> map : hmControllerFieldObjects.entrySet()) {
1217 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
1218 // Iterate over HashMap and choose between processing
1219 // SetInstrumenter vs. RelationInstrumenter
1220 String strFieldName = map.getKey();
1221 String strClassName = map.getValue().getClass().getName();
1222 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
1223 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1224 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
1225 String strErrMsg = "IoTMaster: Controller object" +
1226 " cannot have IoTSet<IoTDeviceAddress>!";
1227 throw new Error(strErrMsg);
1228 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
1229 String strErrMsg = "IoTMaster: Controller object" +
1230 " cannot have IoTSet<ZigbeeAddress>!";
1231 throw new Error(strErrMsg);
1232 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
1233 // Instrument the IoTAddress
1234 setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd);
1235 instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream);
1238 instrumentIoTSet(map, strFieldName);
1240 } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) {
1241 instrumentIoTRelation(map, strFieldName);
1245 result = System.currentTimeMillis()-start;
1246 System.out.println("\n\n ==> Time needed to instrument device driver objects: " + result + "\n\n");
1247 System.out.println(" ==> #Objects: " + commHan.getActiveControllerObjectList().size() + "\n\n");
1250 start = System.currentTimeMillis();
1252 // ROUTING POLICY: Deploy basic policies if this is the last controller
1253 if (i == strObjectNames.length-1) {
1254 // ROUTING POLICY: implement basic policies to reject all other irrelevant traffics
1255 for(String s: commHan.getHosts()) {
1256 setHostBasicPolicies(s);
1258 // We retain all the basic policies for router,
1259 // but we delete the initial allowance policies for internal all TCP and UDP communications
1260 setRouterBasicPolicies(STR_ROUTER_ADD);
1262 // Close access to policy files and deploy policies
1263 routerConfig.close();
1264 // Deploy the policy
1265 HashSet<String> setAddresses = new HashSet<String>(commHan.getHosts());
1266 setAddresses.add(strIoTMasterHostAdd);
1267 createPolicyThreads(STR_ROUTER_ADD, setAddresses);
1270 result = System.currentTimeMillis()-start;
1271 System.out.println("\n\n ==> Time needed to send policy files and deploy them : " + result + "\n\n");
1274 start = System.currentTimeMillis();
1276 // Separating object creations and Set/Relation initializations
1277 createControllerObjects();
1280 result = System.currentTimeMillis()-start;
1281 System.out.println("\n\n ==> Time needed to instantiate objects: " + result + "\n\n");
1283 start = System.currentTimeMillis();
1285 // Sets and relations initializations
1286 initializeSetsAndRelations(inStream, outStream);
1289 result = System.currentTimeMillis()-start;
1290 System.out.println("\n\n ==> Time needed to initialize sets and relations: " + result + "\n\n");
1292 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD
1293 commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD),
1294 "Invoke init() method!", inStream, outStream);
1295 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS
1296 outStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
1300 serverSocket.close();
1301 commHan.printLists();
1302 lbIoT.printHostInfo();
1305 } catch (IOException |
1306 InterruptedException |
1307 ClassNotFoundException ex) {
1308 System.out.println("IoTMaster: Exception: "
1310 ex.printStackTrace();
1314 public static void main(String args[]) {
1316 // Detect the available controller/device classes
1317 // Input args[] should be used to list the controllers/devices
1318 // e.g. java IoTMaster AcmeProximity AcmeThermostat AcmeVentController
1319 IoTMaster iotMaster = new IoTMaster(args);
1321 iotMaster.parseIoTMasterConfigFile();
1322 // Initialize CommunicationHandler, LoadBalancer, and RouterConfig
1323 iotMaster.initLiveDataStructure();
1325 iotMaster.createObjects();