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 strIoTMasterHostAdd;
64 private String strIoTSlaveControllerHostAdd;
65 private String strIoTSlaveObjectHostAdd;
66 private Class[] arrFieldClasses;
67 private Object[] arrFieldValues;
68 private Socket filesocket;
70 // Constants that are to be extracted from config file
71 private static String STR_MASTER_MAC_ADD;
72 private static String STR_IOT_CODE_PATH;
73 private static String STR_CONT_PATH;
74 private static String STR_RUNTIME_DIR;
75 private static String STR_CLS_PATH;
76 private static String STR_RMI_PATH;
77 private static String STR_RMI_HOSTNAME;
78 private static String STR_LOG_FILE_PATH;
79 private static String STR_SSH_USERNAME;
80 private static String STR_ROUTER_ADD;
81 private static String STR_MONITORING_HOST;
82 private static String STR_ZB_GATEWAY_ADDRESS;
83 private static String STR_ZB_GATEWAY_PORT;
84 private static String STR_ZB_IOTMASTER_PORT;
85 private static boolean BOOL_VERBOSE;
88 * IoTMaster class constants
90 * Name constants - not to be configured by users
92 private static final String STR_IOT_MASTER_NAME = "IoTMaster";
93 private static final String STR_CFG_FILE_EXT = ".config";
94 private static final String STR_CLS_FILE_EXT = ".class";
95 private static final String STR_JAR_FILE_EXT = ".jar";
96 private static final String STR_ZIP_FILE_EXT = ".zip";
97 private static final String STR_TCP_PROTOCOL = "tcp";
98 private static final String STR_UDP_PROTOCOL = "udp";
99 private static final String STR_TCPGW_PROTOCOL = "tcpgw";
100 private static final String STR_NO_PROTOCOL = "nopro";
101 private static final String STR_SELF_MAC_ADD = "00:00:00:00:00:00";
102 private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS";
103 private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE";
104 private static final String STR_YES = "Yes";
105 private static final String STR_NO = "No";
108 * Runtime class name constants - not to be configured by users
110 private static final String STR_REL_INSTRUMENTER_CLS = "iotruntime.master.RelationInstrumenter";
111 private static final String STR_SET_INSTRUMENTER_CLS = "iotruntime.master.SetInstrumenter";
112 private static final String STR_IOT_SLAVE_CLS = "iotruntime.slave.IoTSlave";
113 private static final String STR_IOT_DEV_ADD_CLS = "IoTDeviceAddress";
114 private static final String STR_IOT_ZB_ADD_CLS = "IoTZigbeeAddress";
115 private static final String STR_IOT_ADD_CLS = "IoTAddress";
121 public IoTMaster(String[] argObjNms) {
127 objAddInitHand = null;
128 strObjectNames = argObjNms;
130 strObjClassName = null;
131 strObjClassInterfaceName = null;
132 strIoTMasterHostAdd = null;
133 strIoTSlaveControllerHostAdd = null;
134 strIoTSlaveObjectHostAdd = null;
135 arrFieldClasses = null;
136 arrFieldValues = null;
138 mapClassNameToCrim = null;
140 STR_MASTER_MAC_ADD = null;
141 STR_IOT_CODE_PATH = null;
142 STR_CONT_PATH = null;
143 STR_RUNTIME_DIR = null;
146 STR_RMI_HOSTNAME = null;
147 STR_LOG_FILE_PATH = null;
148 STR_SSH_USERNAME = null;
149 STR_ROUTER_ADD = null;
150 STR_MONITORING_HOST = null;
151 STR_ZB_GATEWAY_ADDRESS = null;
152 STR_ZB_GATEWAY_PORT = null;
153 STR_ZB_IOTMASTER_PORT = null;
154 BOOL_VERBOSE = false;
158 * A method to initialize CommunicationHandler, LoadBalancer, RouterConfig and ObjectInitHandler
162 private void initLiveDataStructure() {
164 commHan = new CommunicationHandler(BOOL_VERBOSE);
165 lbIoT = new LoadBalancer(BOOL_VERBOSE);
166 lbIoT.setupLoadBalancer();
167 routerConfig = new RouterConfig();
168 routerConfig.getAddressList(STR_ROUTER_ADD);
169 objInitHand = new ObjectInitHandler(BOOL_VERBOSE);
170 objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE);
171 mapClassNameToCrim = new HashMap<String,ClassRuntimeInstrumenterMaster>();
175 * A method to initialize constants from config file
179 private void parseIoTMasterConfigFile() {
180 // Parse configuration file
181 Properties prop = new Properties();
182 String strCfgFileName = STR_IOT_MASTER_NAME + STR_CFG_FILE_EXT;
183 File file = new File(strCfgFileName);
184 FileInputStream fis = null;
186 fis = new FileInputStream(file);
189 } catch (IOException ex) {
190 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
191 ex.printStackTrace();
193 // Initialize constants from config file
194 STR_MASTER_MAC_ADD = prop.getProperty("MAC_ADDRESS");
195 STR_IOT_CODE_PATH = prop.getProperty("IOT_CODE_PATH");
196 STR_CONT_PATH = prop.getProperty("CONTROLLERS_CODE_PATH");
197 STR_RUNTIME_DIR = prop.getProperty("RUNTIME_DIR");
198 STR_CLS_PATH = prop.getProperty("CLASS_PATH");
199 STR_RMI_PATH = prop.getProperty("RMI_PATH");
200 STR_RMI_HOSTNAME = prop.getProperty("RMI_HOSTNAME");
201 STR_LOG_FILE_PATH = prop.getProperty("LOG_FILE_PATH");
202 STR_SSH_USERNAME = prop.getProperty("SSH_USERNAME");
203 STR_ROUTER_ADD = prop.getProperty("ROUTER_ADD");
204 STR_MONITORING_HOST = prop.getProperty("MONITORING_HOST");
205 STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS");
206 STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT");
207 STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT");
208 if(prop.getProperty("VERBOSE").equals(STR_YES)) {
212 RuntimeOutput.print("IoTMaster: Extracting information from config file: " + strCfgFileName, BOOL_VERBOSE);
213 RuntimeOutput.print("STR_MASTER_MAC_ADD=" + STR_MASTER_MAC_ADD, BOOL_VERBOSE);
214 RuntimeOutput.print("STR_IOT_CODE_PATH=" + STR_IOT_CODE_PATH, BOOL_VERBOSE);
215 RuntimeOutput.print("STR_CONT_PATH=" + STR_CONT_PATH, BOOL_VERBOSE);
216 RuntimeOutput.print("STR_RUNTIME_DIR=" + STR_RUNTIME_DIR, BOOL_VERBOSE);
217 RuntimeOutput.print("STR_CLS_PATH=" + STR_CLS_PATH, BOOL_VERBOSE);
218 RuntimeOutput.print("STR_RMI_PATH=" + STR_RMI_PATH, BOOL_VERBOSE);
219 RuntimeOutput.print("STR_RMI_HOSTNAME=" + STR_RMI_HOSTNAME, BOOL_VERBOSE);
220 RuntimeOutput.print("STR_LOG_FILE_PATH=" + STR_LOG_FILE_PATH, BOOL_VERBOSE);
221 RuntimeOutput.print("STR_SSH_USERNAME=" + STR_SSH_USERNAME, BOOL_VERBOSE);
222 RuntimeOutput.print("STR_ROUTER_ADD=" + STR_ROUTER_ADD, BOOL_VERBOSE);
223 RuntimeOutput.print("STR_MONITORING_HOST=" + STR_MONITORING_HOST, BOOL_VERBOSE);
224 RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE);
225 RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE);
226 RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE);
227 RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE);
228 RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE);
232 * A method to parse information from a config file
234 * @param strCfgFileName Config file name
235 * @param strCfgField Config file field name
238 private String parseConfigFile(String strCfgFileName, String strCfgField) {
239 // Parse configuration file
240 Properties prop = new Properties();
241 File file = new File(strCfgFileName);
242 FileInputStream fis = null;
244 fis = new FileInputStream(file);
247 } catch (IOException ex) {
248 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
249 ex.printStackTrace();
251 System.out.println("IoTMaster: Reading " + strCfgField +
252 " from config file: " + strCfgFileName + " with value: " +
253 prop.getProperty(strCfgField, null));
254 // NULL is returned if the property isn't found
255 return prop.getProperty(strCfgField, null);
259 * A method to send files from IoTMaster
261 * @param filesocket File socket object
262 * @param sFileName File name
263 * @param lFLength File length
266 private void sendFile(Socket filesocket, String sFileName, long lFLength) throws IOException {
268 File file = new File(sFileName);
269 byte[] bytFile = new byte[toIntExact(lFLength)];
270 InputStream inFileStream = new FileInputStream(file);
272 OutputStream outFileStream = filesocket.getOutputStream();
274 while ((iCount = inFileStream.read(bytFile)) > 0) {
275 outFileStream.write(bytFile, 0, iCount);
278 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
282 * A method to create a thread
284 * @param sSSHCmd SSH command
287 private void createThread(String sSSHCmd) throws IOException {
289 // Start a new thread to start a new JVM
291 Runtime runtime = Runtime.getRuntime();
292 Process process = runtime.exec(sSSHCmd);
294 RuntimeOutput.print("Executing: " + sSSHCmd, BOOL_VERBOSE);
298 * A method to send command from master and receive reply from slave
300 * @params msgSend Message object
301 * @params strPurpose String that prints purpose message
302 * @params inStream Input stream
303 * @params outStream Output stream
306 private void commMasterToSlave(Message msgSend, String strPurpose,
307 ObjectInputStream inStream, ObjectOutputStream outStream)
308 throws IOException, ClassNotFoundException {
310 // Send message/command from master
311 outStream.writeObject(msgSend);
312 RuntimeOutput.print("IoTMaster: Send message: " + strPurpose, BOOL_VERBOSE);
314 // Get reply from slave as acknowledgment
315 Message msgReply = (Message) inStream.readObject();
316 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
320 * A private method to instrument IoTSet device
322 * @params strFieldIdentifier String field name + object ID
323 * @params strFieldName String field name
324 * @params strIoTSlaveObjectHostAdd String slave host address
325 * @params inStream ObjectInputStream communication
326 * @params inStream ObjectOutputStream communication
329 private void instrumentIoTSetDevice(String strFieldIdentifier, String strFieldName, String strIoTSlaveObjectHostAdd,
330 ObjectInputStream inStream, ObjectOutputStream outStream)
331 throws IOException, ClassNotFoundException, InterruptedException {
333 // Get information from the set
334 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
335 // Create a new IoTSet
336 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
337 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream);
338 int iRows = listObject.size();
339 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
340 // Transfer the address
341 for(int iRow=0; iRow<iRows; iRow++) {
342 arrFieldValues = listObject.get(iRow);
343 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
344 String strDeviceAddress = null;
345 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
346 strDeviceAddress = strIoTSlaveObjectHostAdd;
348 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
350 int iDestDeviceDriverPort = (int) arrFieldValues[1];
351 String strProtocol = (String) arrFieldValues[2];
352 // Check for wildcard feature
353 boolean bSrcPortWildCard = false;
354 boolean bDstPortWildCard = false;
355 if (arrFieldValues.length > 3) {
356 bSrcPortWildCard = (boolean) arrFieldValues[3];
357 bDstPortWildCard = (boolean) arrFieldValues[4];
359 // Add the port connection into communication handler - if it's not assigned yet
360 if (commHan.getComPort(strDeviceAddress) == null) {
361 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddress);
363 // Send address one by one
364 Message msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
365 strDeviceAddress, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort,
366 bSrcPortWildCard, bDstPortWildCard);
367 commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream);
369 // Reinitialize IoTSet on device object
370 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
371 "Reinitialize IoTSet fields!", inStream, outStream);
376 * A private method to instrument IoTSet Zigbee device
378 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
379 * @params strFieldName String field name
380 * @params strIoTSlaveObjectHostAdd String slave host address
381 * @params inStream ObjectInputStream communication
382 * @params inStream ObjectOutputStream communication
385 private void instrumentIoTSetZBDevice(Map.Entry<String,Object> map, String strFieldName, String strIoTSlaveObjectHostAdd,
386 ObjectInputStream inStream, ObjectOutputStream outStream)
387 throws IOException, ClassNotFoundException, InterruptedException {
389 // Get information from the set
390 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
391 // Create a new IoTSet
392 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
393 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream);
394 // Prepare ZigbeeConfig
395 String strZigbeeGWAddress = routerConfig.getIPFromMACAddress(STR_ZB_GATEWAY_ADDRESS);
396 int iZigbeeGWPort = Integer.parseInt(STR_ZB_GATEWAY_PORT);
397 int iZigbeeIoTMasterPort = Integer.parseInt(STR_ZB_IOTMASTER_PORT);
398 commHan.addDevicePort(iZigbeeIoTMasterPort);
399 ZigbeeConfig zbConfig = new ZigbeeConfig(strZigbeeGWAddress, iZigbeeGWPort, iZigbeeIoTMasterPort,
401 // Add the port connection into communication handler - if it's not assigned yet
402 if (commHan.getComPort(strZigbeeGWAddress) == null) {
403 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddress);
405 int iRows = setInstrumenter.numberOfRows();
406 RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE);
407 // Transfer the address
408 for(int iRow=0; iRow<iRows; iRow++) {
409 arrFieldValues = setInstrumenter.fieldValues(iRow);
410 // Get device address
411 String strZBDevAddress = (String) arrFieldValues[0];
412 // Send policy to Zigbee gateway - TODO: Need to clear policy first?
413 zbConfig.setPolicy(strIoTSlaveObjectHostAdd, commHan.getComPort(strZigbeeGWAddress), strZBDevAddress);
414 // Send address one by one
415 Message msgGetIoTSetZBObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ZB_DEV_IOTSET_OBJECT,
417 commMasterToSlave(msgGetIoTSetZBObj, "Get IoTSet objects!", inStream, outStream);
419 zbConfig.closeConnection();
420 // Reinitialize IoTSet on device object
421 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
422 "Reinitialize IoTSet fields!", inStream, outStream);
427 * A private method to instrument IoTSet of addresses
429 * @params strFieldIdentifier String field name + object ID
430 * @params strFieldName String field name
431 * @params inStream ObjectInputStream communication
432 * @params inStream ObjectOutputStream communication
435 private void instrumentIoTSetAddress(String strFieldIdentifier, String strFieldName,
436 ObjectInputStream inStream, ObjectOutputStream outStream)
437 throws IOException, ClassNotFoundException, InterruptedException {
439 // Get information from the set
440 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
441 // Create a new IoTSet
442 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
443 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream);
444 int iRows = listObject.size();
445 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
446 // Transfer the address
447 for(int iRow=0; iRow<iRows; iRow++) {
448 arrFieldValues = listObject.get(iRow);
449 // Get device address
450 String strAddress = (String) arrFieldValues[0];
451 // Send address one by one
452 Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT,
454 commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream);
456 // Reinitialize IoTSet on device object
457 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
458 "Reinitialize IoTSet fields!", inStream, outStream);
463 * A private method to instrument an object on a specific machine and setting up policies
465 * @params strFieldObjectID String field object ID
468 private void instrumentObject(String strFieldObjectID) throws IOException {
470 // Extract the interface name for RMI
471 // e.g. ProximitySensorInterface, TempSensorInterface, etc.
472 String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
473 strObjClassInterfaceName = parseConfigFile(strObjCfgFile, STR_INTERFACE_CLS_CFG);
474 // Create an object name, e.g. ProximitySensorImplPS1
475 strObjName = strObjClassName + strFieldObjectID;
476 // Check first if host exists
477 if(commHan.objectExists(strObjName)) {
478 // If this object exists already ...
479 // Re-read IoTSlave object hostname for further reference
480 strIoTSlaveObjectHostAdd = commHan.getHostAddress(strObjName);
481 RuntimeOutput.print("IoTMaster: Object with name: " + strObjName + " has existed!", BOOL_VERBOSE);
483 // If this is a new object ... then create one
484 // Get host address for IoTSlave from LoadBalancer
485 //strIoTSlaveObjectHostAdd = lbIoT.selectHost();
486 strIoTSlaveObjectHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
487 if (strIoTSlaveControllerHostAdd == null)
488 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
489 RuntimeOutput.print("IoTMaster: Object name: " + strObjName, BOOL_VERBOSE);
490 // Add port connection and get port numbers
491 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
492 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strObjName);
493 commHan.addActiveControllerObject(strFieldObjectID, strObjName, strObjClassName, strObjClassInterfaceName,
494 strIoTSlaveObjectHostAdd, arrFieldValues, arrFieldClasses);
495 // ROUTING POLICY: IoTMaster and device/controller object
496 // Master-slave communication
497 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
498 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
499 // ROUTING POLICY: Send the same routing policy to both the hosts
500 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
501 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
502 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTMasterHostAdd,
503 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
504 // Need to accommodate callback functions here - open ports for TCP
505 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd,
506 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
507 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd,
508 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
509 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd,
510 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
511 // Instrument the IoTSet declarations inside the class file
512 instrumentObjectIoTSet(strFieldObjectID);
514 // Send routing policy to router for controller object
515 // ROUTING POLICY: RMI communication - RMI registry and stub ports
516 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
517 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
518 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
519 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
520 // Send the same set of routing policies to compute nodes
521 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
522 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
523 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
524 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
525 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
526 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
527 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
528 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
532 * A private method to set router policies for IoTDeviceAddress objects
534 * @params strFieldIdentifier String field name + object ID
535 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
536 * @params strIoTSlaveObjectHostAdd String slave host address
539 private void setRouterPolicyIoTSetDevice(String strFieldIdentifier, Map.Entry<String,Object> map,
540 String strIoTSlaveObjectHostAdd) {
542 // Get information from the set
543 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
544 int iRows = setInstrumenter.numberOfRows();
545 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
546 // Transfer the address
547 for(int iRow=0; iRow<iRows; iRow++) {
548 arrFieldValues = setInstrumenter.fieldValues(iRow);
549 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
550 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
551 String strDeviceAddress = null;
552 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
553 strDeviceAddress = strIoTSlaveObjectHostAdd;
555 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
557 int iDestDeviceDriverPort = (int) arrFieldValues[1];
558 String strProtocol = (String) arrFieldValues[2];
559 // Add the port connection into communication handler - if it's not assigned yet
560 if (commHan.getComPort(strDeviceAddress) == null) {
561 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddress);
563 // Send routing policy to router for device drivers and devices
564 // ROUTING POLICY: RMI communication - RMI registry and stub ports
565 if((iDestDeviceDriverPort == -1) && (!strProtocol.equals(STR_NO_PROTOCOL))) {
566 // Port number -1 means that we don't set the policy strictly to port number level
567 // "nopro" = no protocol specified for just TCP or just UDP (can be both used as well)
568 // ROUTING POLICY: Device driver and device
569 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress,
571 // ROUTING POLICY: Send to the compute node where the device driver is
572 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd,
573 strDeviceAddress, strProtocol);
574 } else if((iDestDeviceDriverPort == -1) && (strProtocol.equals(STR_NO_PROTOCOL))) {
575 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
576 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
577 } else if(strProtocol.equals(STR_TCPGW_PROTOCOL)) {
578 // This is a TCP protocol that connects, e.g. a phone to our runtime system
579 // that provides a gateway access (accessed through destination port number)
580 commHan.addDevicePort(iDestDeviceDriverPort);
581 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress,
582 STR_TCP_PROTOCOL, iDestDeviceDriverPort);
583 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress,
584 STR_TCP_PROTOCOL, iDestDeviceDriverPort);
585 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
586 routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
588 // Other port numbers...
589 commHan.addDevicePort(iDestDeviceDriverPort);
590 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress,
591 strProtocol, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort);
592 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress,
593 strProtocol, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort);
599 * A private method to set router policies for IoTAddress objects
601 * @params strFieldIdentifier String field name + object ID
602 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
603 * @params strHostAddress String host address
606 private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry<String,Object> map,
607 String strHostAddress) {
609 // Get information from the set
610 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
611 int iRows = setInstrumenter.numberOfRows();
612 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
613 // Transfer the address
614 for(int iRow=0; iRow<iRows; iRow++) {
615 arrFieldValues = setInstrumenter.fieldValues(iRow);
616 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
617 // Get device address
618 String strAddress = (String) arrFieldValues[0];
619 // Setting up router policies for HTTP/HTTPs
620 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress);
621 routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress);
626 * A private method to instrument an object's IoTSet and IoTRelation field to up policies
628 * Mostly the IoTSet fields would contain IoTDeviceAddress objects
630 * @params strFieldObjectID String field object ID
633 private void instrumentObjectIoTSet(String strFieldObjectID) throws IOException {
635 // If this is a new object ... then create one
636 // Instrument the class source code and look for IoTSet for device addresses
637 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
638 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT;
639 FileInputStream fis = new FileInputStream(strObjectClassNamePath);
640 ClassReader cr = new ClassReader(fis);
641 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
642 // We need Object ID to instrument IoTDeviceAddress
643 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE);
646 RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " +
647 strFieldObjectID, BOOL_VERBOSE);
648 // Get the object and the class names
649 // Build objects for IoTSet and IoTRelation fields in the device object classes
650 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
651 HashMap<String,Object> hmObjectFieldObjects = crim.getFieldObjects();
652 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
653 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
654 // Iterate over HashMap and choose between processing
655 String strFieldName = map.getKey();
656 String strClassName = map.getValue().getClass().getName();
657 String strFieldIdentifier = strFieldName + strFieldObjectID;
658 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
659 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
660 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
661 // Instrument the normal IoTDeviceAddress
662 setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
663 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
664 // Instrument the IoTAddress
665 setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
666 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
667 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
668 RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..",
671 String strErrMsg = "IoTMaster: Device driver object" +
672 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
673 " or IoTSet<IoTZigbeeAddress>!";
674 throw new Error(strErrMsg);
677 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
678 throw new Error(strErrMsg);
685 * A private method to create an object on a specific machine
687 * @params strObjName String object name
688 * @params strObjClassName String object class name
689 * @params strObjClassInterfaceName String object class interface name
690 * @params strIoTSlaveObjectHostAdd String IoTSlave host address
691 * @params strFieldObjectID String field object ID
692 * @params arrFieldValues Array of field values
693 * @params arrFieldClasses Array of field classes
696 private void createObject(String strObjName, String strObjClassName, String strObjClassInterfaceName,
697 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
698 throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException {
705 start = System.currentTimeMillis();
707 // Construct ssh command line
708 // e.g. ssh rtrimana@dw-2.eecs.uci.edu cd <path>;
709 // java -cp $CLASSPATH:./*.jar
710 // -Djava.rmi.server.codebase=file:./*.jar
711 // iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 &
712 // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa
713 String strSSHCommand = STR_SSH_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " sudo java " +
714 STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_RMI_HOSTNAME +
715 strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
716 commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
717 commHan.getRMIStubPort(strObjName) + " >& " + STR_LOG_FILE_PATH + strObjName + ".log &";
718 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
719 // Start a new thread to start a new JVM
720 createThread(strSSHCommand);
721 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjName));
722 Socket socket = serverSocket.accept();
723 ObjectInputStream inStream = new ObjectInputStream(socket.getInputStream());
724 ObjectOutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
727 result = System.currentTimeMillis()-start;
728 System.out.println("\n\n ==> Time needed to start JVM for " + strObjName + ": " + result + "\n\n");
731 start = System.currentTimeMillis();
733 // Create message to transfer file first
734 String sFileName = strObjClassName + STR_JAR_FILE_EXT;
735 String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
736 File file = new File(sPath);
737 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()),
738 "Sending file!", inStream, outStream);
739 // Send file - JAR file for object creation
740 sendFile(serverSocket.accept(), sPath, file.length());
741 Message msgReply = (Message) inStream.readObject();
742 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
745 result = System.currentTimeMillis()-start;
746 System.out.println("\n\n ==> Time needed to send JAR file for " + strObjName + ": " + result + "\n\n");
749 start = System.currentTimeMillis();
751 // Pack object information to create object on a IoTSlave
752 Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd,
753 strObjClassName, strObjName, strObjClassInterfaceName, commHan.getRMIRegPort(strObjName),
754 commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses);
756 commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream);
757 // Instrument the class source code and look for IoTSet for device addresses
758 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
759 RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " +
760 strFieldObjectID, BOOL_VERBOSE);
761 // Get the object and the class names
762 // Build objects for IoTSet and IoTRelation fields in the device object classes
763 ClassRuntimeInstrumenterMaster crim = mapClassNameToCrim.get(strObjClassName + strFieldObjectID);
764 HashMap<String,Object> hmObjectFieldObjects = crim.getFieldObjects();
765 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
766 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
767 // Iterate over HashMap and choose between processing
768 String strFieldName = map.getKey();
769 String strClassName = map.getValue().getClass().getName();
770 String strFieldIdentifier = strFieldName + strFieldObjectID;
771 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
772 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
773 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
774 // Instrument the normal IoTDeviceAddress
776 instrumentIoTSetDevice(strFieldIdentifier, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream);
778 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
779 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
781 instrumentIoTSetZBDevice(map, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream);
783 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
784 // Instrument the IoTAddress
786 instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream);
789 String strErrMsg = "IoTMaster: Device driver object" +
790 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
791 " or IoTSet<IoTZigbeeAddress>!";
792 throw new Error(strErrMsg);
795 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
796 throw new Error(strErrMsg);
800 outStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
803 result = System.currentTimeMillis()-start;
804 System.out.println("\n\n ==> Time needed to create object " + strObjName + " and instrument IoTDeviceAddress: " + result + "\n\n");
810 serverSocket.close();
815 * A private method to create controller objects
819 private void createControllerObjects() throws InterruptedException {
821 // Create a list of threads
822 List<Thread> threads = new ArrayList<Thread>();
823 // Get the list of active controller objects and loop it
824 List<String> listActiveControllerObject = commHan.getActiveControllerObjectList();
825 for(String strObjName : listActiveControllerObject) {
827 ObjectCreationInfo objCrtInfo = commHan.getObjectCreationInfo(strObjName);
828 Thread objectThread = new Thread(new Runnable() {
832 createObject(strObjName, objCrtInfo.getObjectClassName(), objCrtInfo.getObjectClassInterfaceName(),
833 objCrtInfo.getIoTSlaveObjectHostAdd(), commHan.getFieldObjectID(strObjName),
834 commHan.getArrayFieldValues(strObjName), commHan.getArrayFieldClasses(strObjName));
835 } catch (IOException |
836 ClassNotFoundException |
837 InterruptedException ex) {
838 ex.printStackTrace();
843 threads.add(objectThread);
844 objectThread.start();
847 for (Thread thread : threads) {
850 } catch (InterruptedException ex) {
851 ex.printStackTrace();
858 * A private method to instrument IoTSet
860 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
861 * @params strFieldName String field name
864 private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName)
865 throws IOException, ClassNotFoundException, InterruptedException {
867 // Get information from the set
868 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
869 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTSET);
871 int iRows = setInstrumenter.numberOfRows();
872 for(int iRow=0; iRow<iRows; iRow++) {
873 // Get field classes and values
874 arrFieldClasses = setInstrumenter.fieldClasses(iRow);
875 arrFieldValues = setInstrumenter.fieldValues(iRow);
876 // Get object ID and class name
877 String strObjID = setInstrumenter.fieldObjectID(iRow);
878 strObjClassName = setInstrumenter.fieldEntryType(strObjID);
879 // Call the method to create an object
880 instrumentObject(strObjID);
881 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
882 strObjClassName, strObjClassInterfaceName, commHan.getRMIRegPort(strObjName),
883 commHan.getRMIStubPort(strObjName));
889 * A private method to instrument IoTRelation
891 * @params Map.Entry<String,Object> Entry of map IoTRelation instrumentation
892 * @params strFieldName String field name
895 private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName)
896 throws IOException, ClassNotFoundException, InterruptedException {
898 // Get information from the set
899 RelationInstrumenter relationInstrumenter = (RelationInstrumenter) map.getValue();
900 int iRows = relationInstrumenter.numberOfRows();
901 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTRELATION);
903 for(int iRow=0; iRow<iRows; iRow++) {
904 // Operate on the first set first
905 arrFieldClasses = relationInstrumenter.firstFieldClasses(iRow);
906 arrFieldValues = relationInstrumenter.firstFieldValues(iRow);
907 String strObjID = relationInstrumenter.firstFieldObjectID(iRow);
908 strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID);
909 // Call the method to create an object
910 instrumentObject(strObjID);
911 // Get the first object controller host address
912 String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
913 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
914 strObjClassName, strObjClassInterfaceName, commHan.getRMIRegPort(strObjName),
915 commHan.getRMIStubPort(strObjName));
916 // Operate on the second set
917 arrFieldClasses = relationInstrumenter.secondFieldClasses(iRow);
918 arrFieldValues = relationInstrumenter.secondFieldValues(iRow);
919 strObjID = relationInstrumenter.secondFieldObjectID(iRow);
920 strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID);
921 // Call the method to create an object
922 instrumentObject(strObjID);
923 // Get the second object controller host address
924 String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
925 objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
926 strObjClassName, strObjClassInterfaceName, commHan.getRMIRegPort(strObjName),
927 commHan.getRMIStubPort(strObjName));
929 // ROUTING POLICY: first and second controller objects in IoTRelation
930 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd,
931 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
932 // ROUTING POLICY: Send the same routing policy to both the hosts
933 routerConfig.configureHostMainPolicies(strFirstIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
934 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
935 routerConfig.configureHostMainPolicies(strSecondIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
936 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
941 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
943 * @params inStream ObjectInputStream communication
944 * @params outStream ObjectOutputStream communication
947 private void initializeSetsAndRelations(ObjectInputStream inStream, ObjectOutputStream outStream)
948 throws IOException, ClassNotFoundException {
949 // Get list of fields
950 List<String> strFields = objInitHand.getListOfFields();
951 // Iterate on HostAddress
952 for(String str : strFields) {
953 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
954 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
955 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
956 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, str);
957 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet!", inStream, outStream);
958 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
959 for (ObjectInitInfo objInitInfo : listObject) {
960 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
961 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(),
962 objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(),
963 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
964 "Get IoTSet object!", inStream, outStream);
966 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
967 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
968 "Renitialize IoTSet field!", inStream, outStream);
969 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
970 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
971 Message msgCrtIoTRel = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTRELATION, str);
972 commMasterToSlave(msgCrtIoTRel, "Create new IoTRelation!", inStream, outStream);
973 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
974 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
975 Iterator it = listSecondObject.iterator();
976 for (ObjectInitInfo objInitInfo : listObject) {
977 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
978 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT,
979 objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(),
980 objInitInfo.getObjectClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
981 "Get IoTRelation first object!", inStream, outStream);
982 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
983 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
984 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT,
985 objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(),
986 objSecObj.getObjectClassInterfaceName(), objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort()),
987 "Get IoTRelation second object!", inStream, outStream);
989 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
990 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD),
991 "Renitialize IoTRelation field!", inStream, outStream);
997 * A method to set router basic policies at once
999 * @param strRouter String router name
1002 private void setRouterBasicPolicies(String strRouter) {
1004 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1005 routerConfig.configureRouterICMPPolicies(strRouter, strMonitorHost);
1006 routerConfig.configureRouterDHCPPolicies(strRouter);
1007 routerConfig.configureRouterDNSPolicies(strRouter);
1008 routerConfig.configureRouterSSHPolicies(strRouter, strMonitorHost);
1009 routerConfig.configureRejectPolicies(strRouter);
1013 * A method to set host basic policies at once
1015 * @param strHost String host name
1018 private void setHostBasicPolicies(String strHost) {
1020 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1021 routerConfig.configureHostDHCPPolicies(strHost);
1022 routerConfig.configureHostDNSPolicies(strHost);
1023 if (strHost.equals(strMonitorHost)) {
1024 // Check if this is the monitoring host
1025 routerConfig.configureHostICMPPolicies(strHost);
1026 routerConfig.configureHostSSHPolicies(strHost);
1028 routerConfig.configureHostICMPPolicies(strHost, strMonitorHost);
1029 routerConfig.configureHostSSHPolicies(strHost, strMonitorHost);
1031 // Apply SQL allowance policies to master host
1032 if (strHost.equals(strIoTMasterHostAdd)) {
1033 routerConfig.configureHostSQLPolicies(strHost);
1035 routerConfig.configureRejectPolicies(strHost);
1039 * A method to create a thread for policy deployment
1041 * @param strRouterAddress String router address to configure
1042 * @param setHostAddresses Set of strings for host addresses to configure
1045 private void createPolicyThreads(String strRouterAddress, Set<String> setHostAddresses) throws IOException {
1047 // Create a list of threads
1048 List<Thread> threads = new ArrayList<Thread>();
1049 // Start threads for hosts
1050 for(String strAddress : setHostAddresses) {
1051 Thread policyThread = new Thread(new Runnable() {
1053 synchronized(this) {
1054 routerConfig.sendHostPolicies(strAddress);
1058 threads.add(policyThread);
1059 policyThread.start();
1060 RuntimeOutput.print("Deploying policies for: " + strAddress, BOOL_VERBOSE);
1062 // A thread for router
1063 Thread policyThread = new Thread(new Runnable() {
1065 synchronized(this) {
1066 routerConfig.sendRouterPolicies(strRouterAddress);
1070 threads.add(policyThread);
1071 policyThread.start();
1072 RuntimeOutput.print("Deploying policies on router: " + strRouterAddress, BOOL_VERBOSE);
1074 for (Thread thread : threads) {
1077 } catch (InterruptedException ex) {
1078 ex.printStackTrace();
1085 * A method to assign objects to multiple JVMs, including
1086 * the controller/device object that uses other objects
1087 * in IoTSet and IoTRelation
1091 private void createObjects() {
1098 // Extract hostname for this IoTMaster from MySQL DB
1099 strIoTMasterHostAdd = routerConfig.getIPFromMACAddress(STR_MASTER_MAC_ADD);
1100 // Loop as we can still find controller/device classes
1101 for(int i=0; i<strObjectNames.length; i++) {
1103 start = System.currentTimeMillis();
1105 // Assign a new list of PrintWriter objects
1106 routerConfig.renewPrintWriter();
1107 // Get controller names one by one
1108 String strObjControllerName = strObjectNames[i];
1109 // Use LoadBalancer to assign a host address
1110 //strIoTSlaveControllerHostAdd = lbIoT.selectHost();
1111 strIoTSlaveControllerHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
1112 if (strIoTSlaveControllerHostAdd == null)
1113 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
1114 // == START INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1115 // Add port connection and get port numbers
1116 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
1117 commHan.addPortConnection(strIoTSlaveControllerHostAdd, strObjControllerName);
1118 // ROUTING POLICY: IoTMaster and main controller object
1119 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
1120 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1121 // ROUTING POLICY: Send the same routing policy to both the hosts
1122 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
1123 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1124 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd,
1125 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1127 // Construct ssh command line and create a controller thread for e.g. AcmeProximity
1128 String strSSHCommand = STR_SSH_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1129 STR_RUNTIME_DIR + " sudo java " + STR_CLS_PATH + " " +
1130 STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
1131 commHan.getComPort(strObjControllerName) + " " +
1132 commHan.getRMIRegPort(strObjControllerName) + " " +
1133 commHan.getRMIStubPort(strObjControllerName) + " >& " +
1134 STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1135 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
1136 createThread(strSSHCommand);
1137 // Wait for connection
1138 // Create a new socket for communication
1139 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjControllerName));
1140 Socket socket = serverSocket.accept();
1141 ObjectInputStream inStream = new ObjectInputStream(socket.getInputStream());
1142 ObjectOutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
1143 RuntimeOutput.print("IoTMaster: Communication established!", BOOL_VERBOSE);
1146 result = System.currentTimeMillis()-start;
1147 System.out.println("\n\n ==> From start until after SSH for main controller: " + result);
1149 start = System.currentTimeMillis();
1151 // Send files for every controller class
1152 // e.g. AcmeProximity.jar and AcmeProximity.zip
1153 String strControllerClassName = strObjControllerName + STR_CLS_FILE_EXT;
1154 String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1155 strControllerClassName;
1157 String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT;
1158 String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1159 strControllerJarName;
1160 File file = new File(strControllerJarNamePath);
1161 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()),
1162 "Sending file!", inStream, outStream);
1163 // Send file - Class file for object creation
1164 sendFile(serverSocket.accept(), strControllerJarNamePath, file.length());
1165 Message msgReply = (Message) inStream.readObject();
1166 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1167 // Send .zip file if additional zip file is specified
1168 String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT;
1169 String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile;
1170 String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG);
1171 if (strAdditionalFile.equals(STR_YES)) {
1172 String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT;
1173 String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1174 strControllerCmpName;
1175 file = new File(strControllerCmpNamePath);
1176 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()),
1177 "Sending file!", inStream, outStream);
1178 // Send file - Class file for object creation
1179 sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length());
1180 msgReply = (Message) inStream.readObject();
1181 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1183 // Create main controller/device object
1184 commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName),
1185 "Create main object!", inStream, outStream);
1188 result = System.currentTimeMillis()-start;
1189 System.out.println("\n\n ==> From IoTSlave start until main controller object is created: " + result);
1190 System.out.println(" ==> Including file transfer times!\n\n");
1192 start = System.currentTimeMillis();
1194 // == END INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1195 // Instrumenting one file
1196 RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE);
1197 RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE);
1198 FileInputStream fis = new FileInputStream(strControllerClassNamePath);
1199 ClassReader cr = new ClassReader(fis);
1200 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
1201 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE);
1204 // Get the object and the class names
1205 // Build objects for IoTSet and IoTRelation fields in the controller/device classes
1206 HashMap<String,Object> hmControllerFieldObjects = crim.getFieldObjects();
1207 for(Map.Entry<String,Object> map : hmControllerFieldObjects.entrySet()) {
1208 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
1209 // Iterate over HashMap and choose between processing
1210 // SetInstrumenter vs. RelationInstrumenter
1211 String strFieldName = map.getKey();
1212 String strClassName = map.getValue().getClass().getName();
1213 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
1214 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1215 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
1216 String strErrMsg = "IoTMaster: Controller object" +
1217 " cannot have IoTSet<IoTDeviceAddress>!";
1218 throw new Error(strErrMsg);
1219 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
1220 String strErrMsg = "IoTMaster: Controller object" +
1221 " cannot have IoTSet<ZigbeeAddress>!";
1222 throw new Error(strErrMsg);
1223 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
1224 // Instrument the IoTAddress
1225 setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd);
1226 instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream);
1229 instrumentIoTSet(map, strFieldName);
1231 } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) {
1232 instrumentIoTRelation(map, strFieldName);
1236 result = System.currentTimeMillis()-start;
1237 System.out.println("\n\n ==> Time needed to instrument device driver objects: " + result + "\n\n");
1238 System.out.println(" ==> #Objects: " + commHan.getActiveControllerObjectList().size() + "\n\n");
1241 start = System.currentTimeMillis();
1243 // ROUTING POLICY: Deploy basic policies if this is the last controller
1244 if (i == strObjectNames.length-1) {
1245 // ROUTING POLICY: implement basic policies to reject all other irrelevant traffics
1246 for(String s: commHan.getHosts()) {
1247 setHostBasicPolicies(s);
1249 // We retain all the basic policies for router,
1250 // but we delete the initial allowance policies for internal all TCP and UDP communications
1251 setRouterBasicPolicies(STR_ROUTER_ADD);
1253 // Close access to policy files and deploy policies
1254 routerConfig.close();
1255 // Deploy the policy
1256 HashSet<String> setAddresses = new HashSet<String>(commHan.getHosts());
1257 setAddresses.add(strIoTMasterHostAdd);
1258 createPolicyThreads(STR_ROUTER_ADD, setAddresses);
1261 result = System.currentTimeMillis()-start;
1262 System.out.println("\n\n ==> Time needed to send policy files and deploy them : " + result + "\n\n");
1265 start = System.currentTimeMillis();
1267 // Separating object creations and Set/Relation initializations
1268 createControllerObjects();
1271 result = System.currentTimeMillis()-start;
1272 System.out.println("\n\n ==> Time needed to instantiate objects: " + result + "\n\n");
1274 start = System.currentTimeMillis();
1276 // Sets and relations initializations
1277 initializeSetsAndRelations(inStream, outStream);
1280 result = System.currentTimeMillis()-start;
1281 System.out.println("\n\n ==> Time needed to initialize sets and relations: " + result + "\n\n");
1283 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD
1284 commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD),
1285 "Invoke init() method!", inStream, outStream);
1286 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS
1287 outStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
1291 serverSocket.close();
1292 commHan.printLists();
1293 lbIoT.printHostInfo();
1296 } catch (IOException |
1297 InterruptedException |
1298 ClassNotFoundException ex) {
1299 System.out.println("IoTMaster: Exception: "
1301 ex.printStackTrace();
1305 public static void main(String args[]) {
1307 // Detect the available controller/device classes
1308 // Input args[] should be used to list the controllers/devices
1309 // e.g. java IoTMaster AcmeProximity AcmeThermostat AcmeVentController
1310 IoTMaster iotMaster = new IoTMaster(args);
1312 iotMaster.parseIoTMasterConfigFile();
1313 // Initialize CommunicationHandler, LoadBalancer, and RouterConfig
1314 iotMaster.initLiveDataStructure();
1316 iotMaster.createObjects();