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.OutputStream;
23 import java.io.ObjectInputStream;
24 import java.io.ObjectOutputStream;
25 import java.io.IOException;
26 import java.lang.ClassNotFoundException;
27 import java.lang.Class;
28 import java.lang.reflect.*;
29 import java.net.Socket;
30 import java.net.ServerSocket;
31 import java.nio.ByteBuffer;
33 import static java.lang.Math.toIntExact;
35 /** Class IoTMaster is responsible to use ClassRuntimeInstrumenterMaster
36 * to instrument the controller/device bytecode and starts multiple
37 * IoTSlave running on different JVM's in a distributed fashion.
39 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
43 public class IoTMaster {
46 * IoTMaster class properties
48 * CommunicationHandler maintains the data structure for hostnames and ports
49 * LoadBalancer assigns a job onto a host based on certain metrics
51 private CommunicationHandler commHan;
52 private LoadBalancer lbIoT;
53 private RouterConfig routerConfig;
54 private ObjectInitHandler objInitHand;
55 private ObjectAddressInitHandler objAddInitHand;
56 private String[] strObjectNames;
57 // Now this can be either ClassRuntimeInstrumenterMaster or CRuntimeInstrumenterMaster
58 private Map<String,Object> mapClassNameToCrim;
61 * These properties hold information of a certain object
64 private String strObjName;
65 private String strObjClassName;
66 private String strObjClassInterfaceName;
67 private String strObjStubClsIntfaceName;
68 private String strIoTMasterHostAdd;
69 private String strIoTSlaveControllerHostAdd;
70 private String strIoTSlaveObjectHostAdd;
71 private Class[] arrFieldClasses;
72 private Object[] arrFieldValues;
73 private Socket filesocket;
76 * For connection with C++ IoTSlave
78 private ServerSocket serverSocketCpp;
79 private Socket socketCpp;
80 private BufferedInputStream inputCpp;
81 private BufferedOutputStream outputCpp;
83 // Constants that are to be extracted from config file
84 private static String STR_MASTER_MAC_ADD;
85 private static String STR_IOT_CODE_PATH;
86 private static String STR_CONT_PATH;
87 private static String STR_RUNTIME_DIR;
88 private static String STR_SLAVE_DIR;
89 private static String STR_CLS_PATH;
90 private static String STR_RMI_PATH;
91 private static String STR_RMI_HOSTNAME;
92 private static String STR_LOG_FILE_PATH;
93 private static String STR_USERNAME;
94 private static String STR_ROUTER_ADD;
95 private static String STR_MONITORING_HOST;
96 private static String STR_ZB_GATEWAY_ADDRESS;
97 private static String STR_ZB_GATEWAY_PORT;
98 private static String STR_ZB_IOTMASTER_PORT;
99 private static String STR_JVM_INIT_HEAP_SIZE;
100 private static String STR_JVM_MAX_HEAP_SIZE;
101 private static String STR_LANGUAGE_CONTROLLER;
102 private static String STR_SKEL_CLASS_SUFFIX;
103 private static String STR_STUB_CLASS_SUFFIX;
104 private static boolean BOOL_VERBOSE;
107 * IoTMaster class constants
109 * Name constants - not to be configured by users
111 private static final String STR_IOT_MASTER_NAME = "IoTMaster";
112 private static final String STR_CFG_FILE_EXT = ".config";
113 private static final String STR_CLS_FILE_EXT = ".class";
114 private static final String STR_JAR_FILE_EXT = ".jar";
115 private static final String STR_SO_FILE_EXT = ".so";
116 private static final String STR_ZIP_FILE_EXT = ".zip";
117 private static final String STR_TCP_PROTOCOL = "tcp";
118 private static final String STR_UDP_PROTOCOL = "udp";
119 private static final String STR_TCPGW_PROTOCOL = "tcpgw";
120 private static final String STR_NO_PROTOCOL = "nopro";
121 private static final String STR_SELF_MAC_ADD = "00:00:00:00:00:00";
122 private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS";
123 private static final String STR_INT_STUB_CLS_CFG = "INTERFACE_STUB_CLASS";
124 private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE";
125 private static final String STR_LANGUAGE = "LANGUAGE";
126 private static final String STR_YES = "Yes";
127 private static final String STR_NO = "No";
128 private static final String STR_JAVA = "Java";
129 private static final String STR_CPP = "C++";
130 private static final String STR_SSH = "ssh";
131 private static final String STR_SCP = "scp";
132 private static final String STR_IOTSLAVE_CPP = "./IoTSlave.o";
134 private static int INT_SIZE = 4; // send length in the size of integer (4 bytes)
137 * Runtime class name constants - not to be configured by users
139 private static final String STR_REL_INSTRUMENTER_CLS = "iotruntime.master.RelationInstrumenter";
140 private static final String STR_SET_INSTRUMENTER_CLS = "iotruntime.master.SetInstrumenter";
141 private static final String STR_IOT_SLAVE_CLS = "iotruntime.slave.IoTSlave";
142 private static final String STR_IOT_DEV_ADD_CLS = "IoTDeviceAddress";
143 private static final String STR_IOT_ZB_ADD_CLS = "IoTZigbeeAddress";
144 private static final String STR_IOT_ADD_CLS = "IoTAddress";
150 public IoTMaster(String[] argObjNms) {
156 objAddInitHand = null;
157 strObjectNames = argObjNms;
159 strObjClassName = null;
160 strObjClassInterfaceName = null;
161 strObjStubClsIntfaceName = null;
162 strIoTMasterHostAdd = null;
163 strIoTSlaveControllerHostAdd = null;
164 strIoTSlaveObjectHostAdd = null;
165 arrFieldClasses = null;
166 arrFieldValues = null;
168 mapClassNameToCrim = null;
169 // Connection with C++ IoTSlave
170 serverSocketCpp = null;
175 STR_MASTER_MAC_ADD = null;
176 STR_IOT_CODE_PATH = null;
177 STR_CONT_PATH = null;
178 STR_RUNTIME_DIR = null;
179 STR_SLAVE_DIR = null;
182 STR_RMI_HOSTNAME = null;
183 STR_LOG_FILE_PATH = null;
185 STR_ROUTER_ADD = null;
186 STR_MONITORING_HOST = null;
187 STR_ZB_GATEWAY_ADDRESS = null;
188 STR_ZB_GATEWAY_PORT = null;
189 STR_ZB_IOTMASTER_PORT = null;
190 STR_JVM_INIT_HEAP_SIZE = null;
191 STR_JVM_MAX_HEAP_SIZE = null;
192 STR_LANGUAGE_CONTROLLER = null;
193 BOOL_VERBOSE = false;
197 * A method to initialize CommunicationHandler, LoadBalancer, RouterConfig and ObjectInitHandler
201 private void initLiveDataStructure() {
203 commHan = new CommunicationHandler(BOOL_VERBOSE);
204 lbIoT = new LoadBalancer(BOOL_VERBOSE);
205 lbIoT.setupLoadBalancer();
206 routerConfig = new RouterConfig();
207 routerConfig.getAddressList(STR_ROUTER_ADD);
208 objInitHand = new ObjectInitHandler(BOOL_VERBOSE);
209 objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE);
210 mapClassNameToCrim = new HashMap<String,Object>();
214 * A method to initialize constants from config file
218 private void parseIoTMasterConfigFile() {
219 // Parse configuration file
220 Properties prop = new Properties();
221 String strCfgFileName = STR_IOT_MASTER_NAME + STR_CFG_FILE_EXT;
222 File file = new File(strCfgFileName);
223 FileInputStream fis = null;
225 fis = new FileInputStream(file);
228 } catch (IOException ex) {
229 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
230 ex.printStackTrace();
232 // Initialize constants from config file
233 STR_MASTER_MAC_ADD = prop.getProperty("MAC_ADDRESS");
234 STR_IOT_CODE_PATH = prop.getProperty("IOT_CODE_PATH");
235 STR_CONT_PATH = prop.getProperty("CONTROLLERS_CODE_PATH");
236 STR_RUNTIME_DIR = prop.getProperty("RUNTIME_DIR");
237 STR_SLAVE_DIR = prop.getProperty("SLAVE_DIR");
238 STR_CLS_PATH = prop.getProperty("CLASS_PATH");
239 STR_RMI_PATH = prop.getProperty("RMI_PATH");
240 STR_RMI_HOSTNAME = prop.getProperty("RMI_HOSTNAME");
241 STR_LOG_FILE_PATH = prop.getProperty("LOG_FILE_PATH");
242 STR_USERNAME = prop.getProperty("USERNAME");
243 STR_ROUTER_ADD = prop.getProperty("ROUTER_ADD");
244 STR_MONITORING_HOST = prop.getProperty("MONITORING_HOST");
245 STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS");
246 STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT");
247 STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT");
248 STR_JVM_INIT_HEAP_SIZE = prop.getProperty("JVM_INIT_HEAP_SIZE");
249 STR_JVM_MAX_HEAP_SIZE = prop.getProperty("JVM_MAX_HEAP_SIZE");
250 STR_SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX");
251 STR_STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX");
252 if(prop.getProperty("VERBOSE").equals(STR_YES)) {
256 RuntimeOutput.print("IoTMaster: Extracting information from config file: " + strCfgFileName, BOOL_VERBOSE);
257 RuntimeOutput.print("STR_MASTER_MAC_ADD=" + STR_MASTER_MAC_ADD, BOOL_VERBOSE);
258 RuntimeOutput.print("STR_IOT_CODE_PATH=" + STR_IOT_CODE_PATH, BOOL_VERBOSE);
259 RuntimeOutput.print("STR_CONT_PATH=" + STR_CONT_PATH, BOOL_VERBOSE);
260 RuntimeOutput.print("STR_RUNTIME_DIR=" + STR_RUNTIME_DIR, BOOL_VERBOSE);
261 RuntimeOutput.print("STR_SLAVE_DIR=" + STR_SLAVE_DIR, BOOL_VERBOSE);
262 RuntimeOutput.print("STR_CLS_PATH=" + STR_CLS_PATH, BOOL_VERBOSE);
263 RuntimeOutput.print("STR_RMI_PATH=" + STR_RMI_PATH, BOOL_VERBOSE);
264 RuntimeOutput.print("STR_RMI_HOSTNAME=" + STR_RMI_HOSTNAME, BOOL_VERBOSE);
265 RuntimeOutput.print("STR_LOG_FILE_PATH=" + STR_LOG_FILE_PATH, BOOL_VERBOSE);
266 RuntimeOutput.print("STR_USERNAME=" + STR_USERNAME, BOOL_VERBOSE);
267 RuntimeOutput.print("STR_ROUTER_ADD=" + STR_ROUTER_ADD, BOOL_VERBOSE);
268 RuntimeOutput.print("STR_MONITORING_HOST=" + STR_MONITORING_HOST, BOOL_VERBOSE);
269 RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE);
270 RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE);
271 RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE);
272 RuntimeOutput.print("STR_JVM_INIT_HEAP_SIZE=" + STR_JVM_INIT_HEAP_SIZE, BOOL_VERBOSE);
273 RuntimeOutput.print("STR_JVM_MAX_HEAP_SIZE=" + STR_JVM_MAX_HEAP_SIZE, BOOL_VERBOSE);
274 RuntimeOutput.print("STR_SKEL_CLASS_SUFFIX=" + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
275 RuntimeOutput.print("STR_STUB_CLASS_SUFFIX=" + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
276 RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE);
277 RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE);
281 * A method to parse information from a config file
283 * @param strCfgFileName Config file name
284 * @param strCfgField Config file field name
287 private String parseConfigFile(String strCfgFileName, String strCfgField) {
288 // Parse configuration file
289 Properties prop = new Properties();
290 File file = new File(strCfgFileName);
291 FileInputStream fis = null;
293 fis = new FileInputStream(file);
296 } catch (IOException ex) {
297 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
298 ex.printStackTrace();
300 System.out.println("IoTMaster: Reading " + strCfgField +
301 " from config file: " + strCfgFileName + " with value: " +
302 prop.getProperty(strCfgField, null));
303 // NULL is returned if the property isn't found
304 return prop.getProperty(strCfgField, null);
308 * A method to send files from IoTMaster
310 * @param filesocket File socket object
311 * @param sFileName File name
312 * @param lFLength File length
315 private void sendFile(Socket filesocket, String sFileName, long lFLength) throws IOException {
317 File file = new File(sFileName);
318 byte[] bytFile = new byte[toIntExact(lFLength)];
319 InputStream inFileStream = new FileInputStream(file);
321 OutputStream outFileStream = filesocket.getOutputStream();
323 while ((iCount = inFileStream.read(bytFile)) > 0) {
324 outFileStream.write(bytFile, 0, iCount);
327 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
331 * A method to create a thread
333 * @param sSSHCmd SSH command
336 private void createThread(String sSSHCmd) throws IOException {
338 // Start a new thread to start a new JVM
340 Runtime runtime = Runtime.getRuntime();
341 Process process = runtime.exec(sSSHCmd);
343 RuntimeOutput.print("Executing: " + sSSHCmd, BOOL_VERBOSE);
347 * A method to send command from master and receive reply from slave
349 * @params msgSend Message object
350 * @params strPurpose String that prints purpose message
351 * @params inStream Input stream
352 * @params outStream Output stream
355 private void commMasterToSlave(Message msgSend, String strPurpose,
356 InputStream _inStream, OutputStream _outStream)
357 throws IOException, ClassNotFoundException {
359 // Send message/command from master
360 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
361 outStream.writeObject(msgSend);
362 RuntimeOutput.print("IoTMaster: Send message: " + strPurpose, BOOL_VERBOSE);
364 // Get reply from slave as acknowledgment
365 ObjectInputStream inStream = (ObjectInputStream) _inStream;
366 Message msgReply = (Message) inStream.readObject();
367 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
371 * A private method to instrument IoTSet device
373 * @params strFieldIdentifier String field name + object ID
374 * @params strFieldName String field name
375 * @params strIoTSlaveObjectHostAdd String slave host address
376 * @params inStream ObjectInputStream communication
377 * @params inStream ObjectOutputStream communication
378 * @params strLanguage String language
381 private void instrumentIoTSetDevice(String strFieldIdentifier, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
382 InputStream inStream, OutputStream outStream, String strLanguage)
383 throws IOException, ClassNotFoundException, InterruptedException {
385 // Get information from the set
386 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
387 // Create a new IoTSet
388 if(strLanguage.equals(STR_JAVA)) {
389 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
390 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream);
392 createNewIoTSetCpp(strFieldName, outStream, inStream);
393 int iRows = listObject.size();
394 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
395 // Transfer the address
396 for(int iRow=0; iRow<iRows; iRow++) {
397 arrFieldValues = listObject.get(iRow);
398 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
399 String strDeviceAddress = null;
400 String strDeviceAddressKey = null;
401 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
402 strDeviceAddress = strIoTSlaveObjectHostAdd;
403 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
405 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
406 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
408 int iDestDeviceDriverPort = (int) arrFieldValues[1];
409 String strProtocol = (String) arrFieldValues[2];
410 // Check for wildcard feature
411 boolean bSrcPortWildCard = false;
412 boolean bDstPortWildCard = false;
413 if (arrFieldValues.length > 3) {
414 bSrcPortWildCard = (boolean) arrFieldValues[3];
415 bDstPortWildCard = (boolean) arrFieldValues[4];
417 // Add the port connection into communication handler - if it's not assigned yet
418 if (commHan.getComPort(strDeviceAddressKey) == null) {
419 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
423 System.out.println("\n\n DEBUG: InstrumentSetDevice: Object Name: " + strObjName);
424 System.out.println("DEBUG: InstrumentSetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey));
425 System.out.println("DEBUG: InstrumentSetDevice: Device address: " + strDeviceAddressKey + "\n\n");
427 // Send address one by one
428 if(strLanguage.equals(STR_JAVA)) {
429 Message msgGetIoTSetObj = null;
430 if (bDstPortWildCard) {
431 String strUniqueDev = strDeviceAddressKey + ":" + iRow;
432 msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
433 strDeviceAddress, commHan.getAdditionalPort(strUniqueDev), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
435 msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
436 strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
437 commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream);
439 getDeviceIoTSetObjectCpp(outStream, inStream, strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort,
440 bSrcPortWildCard, bDstPortWildCard);
442 // Reinitialize IoTSet on device object
443 if(strLanguage.equals(STR_JAVA))
444 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
446 reinitializeIoTSetFieldCpp(outStream, inStream);
451 * A private method to instrument IoTSet Zigbee device
453 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
454 * @params strFieldName String field name
455 * @params strIoTSlaveObjectHostAdd String slave host address
456 * @params inStream ObjectInputStream communication
457 * @params inStream ObjectOutputStream communication
458 * @params strLanguage String language
461 private void instrumentIoTSetZBDevice(Map.Entry<String,Object> map, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
462 InputStream inStream, OutputStream outStream, String strLanguage)
463 throws IOException, ClassNotFoundException, InterruptedException {
465 // Get information from the set
466 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
467 // Create a new IoTSet
468 if(strLanguage.equals(STR_JAVA)) {
469 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
470 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream);
471 } else // TODO: will need to implement IoTSet Zigbee for C++ later
473 // Prepare ZigbeeConfig
474 String strZigbeeGWAddress = routerConfig.getIPFromMACAddress(STR_ZB_GATEWAY_ADDRESS);
475 String strZigbeeGWAddressKey = strObjName + "-" + strZigbeeGWAddress;
476 int iZigbeeGWPort = Integer.parseInt(STR_ZB_GATEWAY_PORT);
477 int iZigbeeIoTMasterPort = Integer.parseInt(STR_ZB_IOTMASTER_PORT);
478 commHan.addDevicePort(iZigbeeIoTMasterPort);
479 ZigbeeConfig zbConfig = new ZigbeeConfig(strZigbeeGWAddress, iZigbeeGWPort, iZigbeeIoTMasterPort,
481 // Add the port connection into communication handler - if it's not assigned yet
482 if (commHan.getComPort(strZigbeeGWAddressKey) == null) {
483 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddressKey);
485 int iRows = setInstrumenter.numberOfRows();
486 RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE);
489 System.out.println("\n\n DEBUG: InstrumentZigbeeDevice: Object Name: " + strObjName);
490 System.out.println("DEBUG: InstrumentZigbeeDevice: Port number: " + commHan.getComPort(strZigbeeGWAddressKey));
491 System.out.println("DEBUG: InstrumentZigbeeDevice: Device address: " + strZigbeeGWAddress + "\n\n");
493 // Transfer the address
494 for(int iRow=0; iRow<iRows; iRow++) {
495 arrFieldValues = setInstrumenter.fieldValues(iRow);
496 // Get device address
497 String strZBDevAddress = (String) arrFieldValues[0];
498 // Send policy to Zigbee gateway - TODO: Need to clear policy first?
499 zbConfig.setPolicy(strIoTSlaveObjectHostAdd, commHan.getComPort(strZigbeeGWAddressKey), strZBDevAddress);
500 // Send address one by one
501 if(strLanguage.equals(STR_JAVA)) {
502 Message msgGetIoTSetZBObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ZB_DEV_IOTSET_OBJECT, strZBDevAddress);
503 commMasterToSlave(msgGetIoTSetZBObj, "Get IoTSet objects!", inStream, outStream);
504 } else // TODO: Implement IoTSet Zigbee for C++
507 zbConfig.closeConnection();
508 // Reinitialize IoTSet on device object
509 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
514 * A private method to instrument IoTSet of addresses
516 * @params strFieldIdentifier String field name + object ID
517 * @params strFieldName String field name
518 * @params inStream ObjectInputStream communication
519 * @params inStream ObjectOutputStream communication
520 * @params strLanguage String language
523 private void instrumentIoTSetAddress(String strFieldIdentifier, String strFieldName,
524 InputStream inStream, OutputStream outStream, String strLanguage)
525 throws IOException, ClassNotFoundException, InterruptedException {
527 // Get information from the set
528 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
529 // Create a new IoTSet
530 if(strLanguage.equals(STR_JAVA)) {
531 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
532 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream);
535 int iRows = listObject.size();
536 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
537 // Transfer the address
538 for(int iRow=0; iRow<iRows; iRow++) {
539 arrFieldValues = listObject.get(iRow);
540 // Get device address
541 String strAddress = (String) arrFieldValues[0];
542 // Send address one by one
543 if(strLanguage.equals(STR_JAVA)) {
544 Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT, strAddress);
545 commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream);
546 } else // TODO: Implement IoTSet Address for C++
549 // Reinitialize IoTSet on device object
550 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
551 "Reinitialize IoTSet fields!", inStream, outStream);
556 * A private method to instrument an object on a specific machine and setting up policies
558 * @params strFieldObjectID String field object ID
559 * @params strLanguage String language
562 private void instrumentObject(String strFieldObjectID, String strLanguage) throws IOException {
564 // Extract the interface name for RMI
565 // e.g. ProximitySensorInterface, TempSensorInterface, etc.
567 String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
568 strObjClassInterfaceName = parseConfigFile(strObjCfgFile, STR_INTERFACE_CLS_CFG);
569 strObjStubClsIntfaceName = parseConfigFile(strObjCfgFile, STR_INT_STUB_CLS_CFG);
570 // Create an object name, e.g. ProximitySensorImplPS1
571 strObjName = strObjClassName + strFieldObjectID;
572 // Check first if host exists
573 if(commHan.objectExists(strObjName)) {
574 // If this object exists already ...
575 // Re-read IoTSlave object hostname for further reference
576 strIoTSlaveObjectHostAdd = commHan.getHostAddress(strObjName);
577 RuntimeOutput.print("IoTMaster: Object with name: " + strObjName + " has existed!", BOOL_VERBOSE);
579 // If this is a new object ... then create one
580 // Get host address for IoTSlave from LoadBalancer
581 //strIoTSlaveObjectHostAdd = lbIoT.selectHost();
582 strIoTSlaveObjectHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
583 if (strIoTSlaveControllerHostAdd == null)
584 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
585 RuntimeOutput.print("IoTMaster: Object name: " + strObjName, BOOL_VERBOSE);
586 // Add port connection and get port numbers
587 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
588 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strObjName);
589 commHan.addActiveControllerObject(strFieldObjectID, strObjName, strObjClassName, strObjClassInterfaceName,
590 strObjStubClsIntfaceName, strIoTSlaveObjectHostAdd, arrFieldValues, arrFieldClasses);
591 // ROUTING POLICY: IoTMaster and device/controller object
592 // Master-slave communication
593 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
594 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
595 // ROUTING POLICY: Send the same routing policy to both the hosts
596 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
597 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
598 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTMasterHostAdd,
599 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
600 // Need to accommodate callback functions here - open ports for TCP
601 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd,
602 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
603 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd,
604 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
605 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd,
606 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
607 // Instrument the IoTSet declarations inside the class file
608 instrumentObjectIoTSet(strFieldObjectID, strLanguage);
610 // Send routing policy to router for controller object
611 // ROUTING POLICY: RMI communication - RMI registry and stub ports
612 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
613 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
614 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
615 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
616 // Send the same set of routing policies to compute nodes
617 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
618 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
619 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
620 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
621 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
622 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
623 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
624 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
629 * A private method to set router policies for IoTDeviceAddress objects
631 * @params strFieldIdentifier String field name + object ID
632 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
633 * @params strIoTSlaveObjectHostAdd String slave host address
636 private void setRouterPolicyIoTSetDevice(String strFieldIdentifier, Map.Entry<String,Object> map,
637 String strIoTSlaveObjectHostAdd) {
639 // Get information from the set
640 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
641 int iRows = setInstrumenter.numberOfRows();
642 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
643 // Transfer the address
644 for(int iRow=0; iRow<iRows; iRow++) {
645 arrFieldValues = setInstrumenter.fieldValues(iRow);
646 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
647 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
648 String strDeviceAddress = null;
649 String strDeviceAddressKey = null;
650 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
651 strDeviceAddress = strIoTSlaveObjectHostAdd;
652 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
653 } else { // Concatenate object name and IP address to give unique key - for a case where there is one device for multiple drivers
654 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
655 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
657 int iDestDeviceDriverPort = (int) arrFieldValues[1];
658 String strProtocol = (String) arrFieldValues[2];
659 // Add the port connection into communication handler - if it's not assigned yet
660 if (commHan.getComPort(strDeviceAddressKey) == null)
661 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
662 boolean bDstPortWildCard = false;
663 // Recognize this and allocate different ports for it
664 if (arrFieldValues.length > 3) {
665 bDstPortWildCard = (boolean) arrFieldValues[4];
666 if (bDstPortWildCard) { // This needs a unique source port
667 String strUniqueDev = strDeviceAddressKey + ":" + iRow;
668 commHan.addAdditionalPort(strUniqueDev);
673 System.out.println("\n\n DEBUG: InstrumentPolicySetDevice: Object Name: " + strObjName);
674 System.out.println("DEBUG: InstrumentPolicySetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey));
675 System.out.println("DEBUG: InstrumentPolicySetDevice: Device address: " + strDeviceAddressKey + "\n\n");
677 // Send routing policy to router for device drivers and devices
678 // ROUTING POLICY: RMI communication - RMI registry and stub ports
679 if((iDestDeviceDriverPort == -1) && (!strProtocol.equals(STR_NO_PROTOCOL))) {
680 // Port number -1 means that we don't set the policy strictly to port number level
681 // "nopro" = no protocol specified for just TCP or just UDP (can be both used as well)
682 // ROUTING POLICY: Device driver and device
683 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
684 // ROUTING POLICY: Send to the compute node where the device driver is
685 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
686 } else if((iDestDeviceDriverPort == -1) && (strProtocol.equals(STR_NO_PROTOCOL))) {
687 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
688 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
689 } else if(strProtocol.equals(STR_TCPGW_PROTOCOL)) {
690 // This is a TCP protocol that connects, e.g. a phone to our runtime system
691 // that provides a gateway access (accessed through destination port number)
692 commHan.addDevicePort(iDestDeviceDriverPort);
693 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
694 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
695 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
696 routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
698 // Other port numbers...
699 commHan.addDevicePort(iDestDeviceDriverPort);
700 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol,
701 commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
702 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol,
703 commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
709 * A private method to set router policies for IoTAddress objects
711 * @params strFieldIdentifier String field name + object ID
712 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
713 * @params strHostAddress String host address
716 private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry<String,Object> map,
717 String strHostAddress) {
719 // Get information from the set
720 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
721 int iRows = setInstrumenter.numberOfRows();
722 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
723 // Transfer the address
724 for(int iRow=0; iRow<iRows; iRow++) {
725 arrFieldValues = setInstrumenter.fieldValues(iRow);
726 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
727 // Get device address
728 String strAddress = (String) arrFieldValues[0];
729 // Setting up router policies for HTTP/HTTPs
730 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress);
731 routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress);
736 * A private method to instrument an object's IoTSet and IoTRelation field to up policies
738 * Mostly the IoTSet fields would contain IoTDeviceAddress objects
740 * @params strFieldObjectID String field object ID
741 * @params strLanguage String language
744 private void instrumentObjectIoTSet(String strFieldObjectID, String strLanguage) throws IOException {
746 // If this is a new object ... then create one
747 // Instrument the class source code and look for IoTSet for device addresses
748 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
749 HashMap<String,Object> hmObjectFieldObjects = null;
750 if(strLanguage.equals(STR_JAVA)) {
751 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT;
752 FileInputStream fis = new FileInputStream(strObjectClassNamePath);
753 ClassReader cr = new ClassReader(fis);
754 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
755 // We need Object ID to instrument IoTDeviceAddress
756 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE);
759 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
760 hmObjectFieldObjects = crim.getFieldObjects();
762 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
763 CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strObjectClassNamePath, strFieldObjectID, BOOL_VERBOSE);
764 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
765 hmObjectFieldObjects = crim.getFieldObjects();
767 // Get the object and the class names
768 // Build objects for IoTSet and IoTRelation fields in the device object classes
769 RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " +
770 strFieldObjectID, BOOL_VERBOSE);
771 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
772 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
773 // Iterate over HashMap and choose between processing
774 String strFieldName = map.getKey();
775 String strClassName = map.getValue().getClass().getName();
776 String strFieldIdentifier = strFieldName + strFieldObjectID;
777 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
778 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
779 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
780 // Instrument the normal IoTDeviceAddress
781 setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
782 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
783 // Instrument the IoTAddress
784 setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
785 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
786 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
787 RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..",
790 String strErrMsg = "IoTMaster: Device driver object" +
791 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
792 " or IoTSet<IoTZigbeeAddress>!";
793 throw new Error(strErrMsg);
796 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
797 throw new Error(strErrMsg);
804 * A private method to send files to a Java slave driver
806 * @params serverSocket ServerSocket
807 * @params _inStream InputStream
808 * @params _outStream OutputStream
809 * @params strObjName String
810 * @params strObjClassName String
811 * @params strObjClassInterfaceName String
812 * @params strObjStubClsIntfaceName String
813 * @params strIoTSlaveObjectHostAdd String
814 * @params strFieldObjectID String
815 * @params arrFieldValues Object[]
816 * @params arrFieldClasses Class[]
819 private void sendFileToJavaSlaveDriver(ServerSocket serverSocket, InputStream _inStream, OutputStream _outStream,
820 String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
821 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
822 throws IOException, ClassNotFoundException {
824 ObjectInputStream inStream = (ObjectInputStream) _inStream;
825 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
826 // Create message to transfer file first
827 String sFileName = strObjClassName + STR_JAR_FILE_EXT;
828 String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
829 File file = new File(sPath);
830 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()),
831 "Sending file!", inStream, outStream);
832 // Send file - JAR file for object creation
833 sendFile(serverSocket.accept(), sPath, file.length());
834 Message msgReply = (Message) inStream.readObject();
835 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
836 // Pack object information to create object on a IoTSlave
837 Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd,
838 strObjClassName, strObjName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
839 commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses);
841 commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream);
846 * A private method to send files to a Java slave driver
850 private void sendFileToCppSlaveDriver(String strObjClassName, String strIoTSlaveObjectHostAdd)
851 throws IOException, ClassNotFoundException {
853 // Create message to transfer file first
854 String sFileName = strObjClassName + STR_ZIP_FILE_EXT;
855 String sFile = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
856 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_SLAVE_DIR;
857 runCommand(strCmdSend);
858 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
860 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
861 STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
862 runCommand(strCmdUnzip);
863 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
869 * Construct command line for Java IoTSlave
873 private String getCmdJavaDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
875 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " sudo java " +
876 STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_RMI_HOSTNAME +
877 strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
878 commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
879 commHan.getRMIStubPort(strObjName) + " >& " + STR_LOG_FILE_PATH + strObjName + ".log &";
884 * Construct command line for C++ IoTSlave
888 private String getCmdCppDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
890 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
891 STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
892 commHan.getComPort(strObjName) + " " + strObjName;
897 * A private method to create an object on a specific machine
899 * @params strObjName String object name
900 * @params strObjClassName String object class name
901 * @params strObjClassInterfaceName String object class interface name
902 * @params strIoTSlaveObjectHostAdd String IoTSlave host address
903 * @params strFieldObjectID String field object ID
904 * @params arrFieldValues Array of field values
905 * @params arrFieldClasses Array of field classes
908 private void createObject(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
909 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
910 throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException {
913 String sCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
914 String strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE + "_" + strObjName);
915 if(strLanguageDriver == null) // Read just the field LANGUAGE if the first read is null
916 strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE);
917 if(strLanguageDriver == null) // Check nullness for the second time - report if it is still null
918 throw new Error("IoTMaster: Language specification missing in config file: " + sCfgFile);
923 start = System.currentTimeMillis();
925 // Construct ssh command line
926 // e.g. ssh rtrimana@dw-2.eecs.uci.edu cd <path>;
927 // java -cp $CLASSPATH:./*.jar
928 // -Djava.rmi.server.codebase=file:./*.jar
929 // iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 &
930 // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa
931 String strSSHCommand = null;
932 if(strLanguageDriver.equals(STR_JAVA))
933 strSSHCommand = getCmdJavaDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
934 else if(strLanguageDriver.equals(STR_CPP))
935 strSSHCommand = getCmdCppDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
937 throw new Error("IoTMaster: Language specification not recognized: " + strLanguageDriver);
938 RuntimeOutput.print("IoTMaster: Language for " + strObjName + " is " + strLanguageDriver, BOOL_VERBOSE);
940 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
941 // Start a new thread to start a new JVM
942 createThread(strSSHCommand);
943 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjName));
944 Socket socket = serverSocket.accept();
945 //InputStream inStream = new ObjectInputStream(socket.getInputStream());
946 //OutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
947 InputStream inStream = null;
948 OutputStream outStream = null;
949 if(strLanguageDriver.equals(STR_JAVA)) {
950 inStream = new ObjectInputStream(socket.getInputStream());
951 outStream = new ObjectOutputStream(socket.getOutputStream());
952 } else { // At this point the language is certainly C++, otherwise would've complained above
953 inStream = new BufferedInputStream(socket.getInputStream());
954 outStream = new BufferedOutputStream(socket.getOutputStream());
959 result = System.currentTimeMillis()-start;
960 System.out.println("\n\n ==> Time needed to start JVM for " + strObjName + ": " + result + "\n\n");
963 start = System.currentTimeMillis();
965 if(strLanguageDriver.equals(STR_JAVA)) {
966 sendFileToJavaSlaveDriver(serverSocket, inStream, outStream, strObjName,
967 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
968 strIoTSlaveObjectHostAdd, strFieldObjectID, arrFieldValues, arrFieldClasses);
970 sendFileToCppSlaveDriver(strObjClassName, strIoTSlaveObjectHostAdd);
971 createObjectCpp(strObjName, strObjClassName, strObjClassInterfaceName, strIoTSlaveObjectHostAdd,
972 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses,
973 outStream, inStream);
977 result = System.currentTimeMillis()-start;
978 System.out.println("\n\n ==> Time needed to send JAR file for " + strObjName + ": " + result + "\n\n");
981 start = System.currentTimeMillis();
983 // Instrument the class source code and look for IoTSet for device addresses
984 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
985 RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " + strFieldObjectID, BOOL_VERBOSE);
986 // Get the object and the class names
987 // Build objects for IoTSet and IoTRelation fields in the device object classes
988 Object crimObj = mapClassNameToCrim.get(strObjClassName + strFieldObjectID);
989 HashMap<String,Object> hmObjectFieldObjects = null;
990 if (crimObj instanceof ClassRuntimeInstrumenterMaster) {
991 ClassRuntimeInstrumenterMaster crim = (ClassRuntimeInstrumenterMaster) crimObj;
992 hmObjectFieldObjects = crim.getFieldObjects();
993 } else if (crimObj instanceof CRuntimeInstrumenterMaster) {
994 CRuntimeInstrumenterMaster crim = (CRuntimeInstrumenterMaster) crimObj;
995 hmObjectFieldObjects = crim.getFieldObjects();
997 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
998 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
999 // Iterate over HashMap and choose between processing
1000 String strFieldName = map.getKey();
1001 String strClassName = map.getValue().getClass().getName();
1002 String strFieldIdentifier = strFieldName + strFieldObjectID;
1003 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
1004 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1005 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
1006 // Instrument the normal IoTDeviceAddress
1007 synchronized(this) {
1008 instrumentIoTSetDevice(strFieldIdentifier, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1010 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
1011 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
1012 synchronized(this) {
1013 instrumentIoTSetZBDevice(map, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1015 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
1016 // Instrument the IoTAddress
1017 synchronized(this) {
1018 instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream, strLanguageDriver);
1021 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
1022 " or IoTSet<IoTZigbeeAddress>!";
1023 throw new Error(strErrMsg);
1026 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
1027 throw new Error(strErrMsg);
1031 // TODO: Change this later
1032 if(strLanguageDriver.equals(STR_JAVA)) {
1033 ObjectOutputStream oStream = (ObjectOutputStream) outStream;
1034 oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
1035 } else { // C++ side for now will be running continuously because it's an infinite loop (not in a separate thread)
1036 createDriverObjectCpp(outStream, inStream);
1037 //endSessionCpp(outStream);
1041 result = System.currentTimeMillis()-start;
1042 System.out.println("\n\n ==> Time needed to create object " + strObjName + " and instrument IoTDeviceAddress: " + result + "\n\n");
1048 serverSocket.close();
1053 * A private method to create controller objects
1057 private void createDriverObjects() throws InterruptedException {
1059 // Create a list of threads
1060 List<Thread> threads = new ArrayList<Thread>();
1061 // Get the list of active controller objects and loop it
1062 List<String> listActiveControllerObject = commHan.getActiveControllerObjectList();
1063 for(String strObjName : listActiveControllerObject) {
1065 ObjectCreationInfo objCrtInfo = commHan.getObjectCreationInfo(strObjName);
1066 Thread objectThread = new Thread(new Runnable() {
1068 synchronized(this) {
1070 createObject(strObjName, objCrtInfo.getObjectClassName(), objCrtInfo.getObjectClassInterfaceName(),
1071 objCrtInfo.getObjectStubClassInterfaceName(), objCrtInfo.getIoTSlaveObjectHostAdd(),
1072 commHan.getFieldObjectID(strObjName), commHan.getArrayFieldValues(strObjName),
1073 commHan.getArrayFieldClasses(strObjName));
1074 } catch (IOException |
1075 ClassNotFoundException |
1076 InterruptedException ex) {
1077 ex.printStackTrace();
1082 threads.add(objectThread);
1083 objectThread.start();
1086 for (Thread thread : threads) {
1089 } catch (InterruptedException ex) {
1090 ex.printStackTrace();
1097 * A private method to instrument IoTSet
1099 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
1100 * @params strFieldName String field name
1101 * @params strLanguage String language
1104 private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName, String strLanguage)
1105 throws IOException, ClassNotFoundException, InterruptedException {
1107 // Get information from the set
1108 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1109 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTSET);
1111 int iRows = setInstrumenter.numberOfRows();
1112 for(int iRow=0; iRow<iRows; iRow++) {
1113 // Get field classes and values
1114 arrFieldClasses = setInstrumenter.fieldClasses(iRow);
1115 arrFieldValues = setInstrumenter.fieldValues(iRow);
1116 // Get object ID and class name
1117 String strObjID = setInstrumenter.fieldObjectID(iRow);
1118 strObjClassName = setInstrumenter.fieldEntryType(strObjID);
1119 // Call the method to create an object
1120 instrumentObject(strObjID, strLanguage);
1121 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1122 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
1123 commHan.getRMIStubPort(strObjName));
1129 * A private method to instrument IoTRelation
1131 * @params Map.Entry<String,Object> Entry of map IoTRelation instrumentation
1132 * @params strFieldName String field name
1133 * @params strLanguage String language
1136 private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName, String strLanguage)
1137 throws IOException, ClassNotFoundException, InterruptedException {
1139 // Get information from the set
1140 RelationInstrumenter relationInstrumenter = (RelationInstrumenter) map.getValue();
1141 int iRows = relationInstrumenter.numberOfRows();
1142 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTRELATION);
1144 for(int iRow=0; iRow<iRows; iRow++) {
1145 // Operate on the first set first
1146 arrFieldClasses = relationInstrumenter.firstFieldClasses(iRow);
1147 arrFieldValues = relationInstrumenter.firstFieldValues(iRow);
1148 String strObjID = relationInstrumenter.firstFieldObjectID(iRow);
1149 strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID);
1150 // Call the method to create an object
1151 instrumentObject(strObjID, strLanguage);
1152 // Get the first object controller host address
1153 String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1154 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1155 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1156 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
1157 // Operate on the second set
1158 arrFieldClasses = relationInstrumenter.secondFieldClasses(iRow);
1159 arrFieldValues = relationInstrumenter.secondFieldValues(iRow);
1160 strObjID = relationInstrumenter.secondFieldObjectID(iRow);
1161 strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID);
1162 // Call the method to create an object
1163 instrumentObject(strObjID, strLanguage);
1164 // Get the second object controller host address
1165 String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1166 objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1167 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1168 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
1169 // ROUTING POLICY: first and second controller objects in IoTRelation
1170 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd,
1171 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1172 // ROUTING POLICY: Send the same routing policy to both the hosts
1173 routerConfig.configureHostMainPolicies(strFirstIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1174 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1175 routerConfig.configureHostMainPolicies(strSecondIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1176 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1181 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1183 * @params inStream ObjectInputStream communication
1184 * @params outStream ObjectOutputStream communication
1187 private void initializeSetsAndRelationsJava(InputStream inStream, OutputStream outStream)
1188 throws IOException, ClassNotFoundException {
1189 // Get list of fields
1190 List<String> strFields = objInitHand.getListOfFields();
1191 // Iterate on HostAddress
1192 for(String str : strFields) {
1193 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1194 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1195 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1196 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, str);
1197 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet!", inStream, outStream);
1198 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1199 for (ObjectInitInfo objInitInfo : listObject) {
1200 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1201 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(),
1202 objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(),
1203 objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
1204 "Get IoTSet object!", inStream, outStream);
1207 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1208 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
1209 "Renitialize IoTSet field!", inStream, outStream);
1210 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1211 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1212 Message msgCrtIoTRel = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTRELATION, str);
1213 commMasterToSlave(msgCrtIoTRel, "Create new IoTRelation!", inStream, outStream);
1214 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1215 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1216 Iterator it = listSecondObject.iterator();
1217 for (ObjectInitInfo objInitInfo : listObject) {
1218 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1219 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT,
1220 objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(),
1221 objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1222 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
1223 "Get IoTRelation first object!", inStream, outStream);
1224 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1225 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1226 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT,
1227 objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(),
1228 objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1229 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort()),
1230 "Get IoTRelation second object!", inStream, outStream);
1232 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1233 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD),
1234 "Renitialize IoTRelation field!", inStream, outStream);
1240 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1242 * @params inStream ObjectInputStream communication
1243 * @params outStream ObjectOutputStream communication
1246 private void initializeSetsAndRelationsCpp(InputStream inStream, OutputStream outStream)
1247 throws IOException, ClassNotFoundException {
1248 // Get list of fields
1249 List<String> strFields = objInitHand.getListOfFields();
1250 // Iterate on HostAddress
1251 for(String str : strFields) {
1252 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1253 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1254 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1255 createNewIoTSetCpp(str, outStream, inStream);
1256 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1257 for (ObjectInitInfo objInitInfo : listObject) {
1258 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1259 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(),
1260 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1261 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
1263 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1264 reinitializeIoTSetFieldCpp(outStream, inStream);
1265 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1266 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1267 // TODO: createNewIoTRelation needs to be created here!
1268 createNewIoTRelationCpp(str, outStream, inStream);
1269 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1270 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1271 Iterator it = listSecondObject.iterator();
1272 for (ObjectInitInfo objInitInfo : listObject) {
1273 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1274 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(),
1275 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1276 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
1277 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1278 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1279 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT, objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(),
1280 objSecObj.getObjectClassName(), objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1281 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), outStream, inStream);
1283 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1284 reinitializeIoTRelationFieldCpp(outStream, inStream);
1290 * A method to set router basic policies at once
1292 * @param strRouter String router name
1295 private void setRouterBasicPolicies(String strRouter) {
1297 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1298 routerConfig.configureRouterICMPPolicies(strRouter, strMonitorHost);
1299 routerConfig.configureRouterDHCPPolicies(strRouter);
1300 routerConfig.configureRouterDNSPolicies(strRouter);
1301 routerConfig.configureRouterSSHPolicies(strRouter, strMonitorHost);
1302 routerConfig.configureRejectPolicies(strRouter);
1306 * A method to set host basic policies at once
1308 * @param strHost String host name
1311 private void setHostBasicPolicies(String strHost) {
1313 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1314 routerConfig.configureHostDHCPPolicies(strHost);
1315 routerConfig.configureHostDNSPolicies(strHost);
1316 if (strHost.equals(strMonitorHost)) {
1317 // Check if this is the monitoring host
1318 routerConfig.configureHostICMPPolicies(strHost);
1319 routerConfig.configureHostSSHPolicies(strHost);
1321 routerConfig.configureHostICMPPolicies(strHost, strMonitorHost);
1322 routerConfig.configureHostSSHPolicies(strHost, strMonitorHost);
1324 // Apply SQL allowance policies to master host
1325 if (strHost.equals(strIoTMasterHostAdd)) {
1326 routerConfig.configureHostSQLPolicies(strHost);
1328 routerConfig.configureRejectPolicies(strHost);
1332 * A method to create a thread for policy deployment
1334 * @param strRouterAddress String router address to configure
1335 * @param setHostAddresses Set of strings for host addresses to configure
1338 private void createPolicyThreads(String strRouterAddress, Set<String> setHostAddresses) throws IOException {
1340 // Create a list of threads
1341 List<Thread> threads = new ArrayList<Thread>();
1342 // Start threads for hosts
1343 for(String strAddress : setHostAddresses) {
1344 Thread policyThread = new Thread(new Runnable() {
1346 synchronized(this) {
1347 routerConfig.sendHostPolicies(strAddress);
1351 threads.add(policyThread);
1352 policyThread.start();
1353 RuntimeOutput.print("Deploying policies for: " + strAddress, BOOL_VERBOSE);
1355 // A thread for router
1356 Thread policyThread = new Thread(new Runnable() {
1358 synchronized(this) {
1359 routerConfig.sendRouterPolicies(strRouterAddress);
1363 threads.add(policyThread);
1364 policyThread.start();
1365 RuntimeOutput.print("Deploying policies on router: " + strRouterAddress, BOOL_VERBOSE);
1367 for (Thread thread : threads) {
1370 } catch (InterruptedException ex) {
1371 ex.printStackTrace();
1378 * A method to send files to Java IoTSlave
1380 * @params strObjControllerName String
1381 * @params serverSocket ServerSocket
1382 * @params inStream ObjectInputStream communication
1383 * @params outStream ObjectOutputStream communication
1386 private void sendFileToJavaSlave(String strObjControllerName, ServerSocket serverSocket,
1387 InputStream _inStream, OutputStream _outStream) throws IOException, ClassNotFoundException {
1389 ObjectInputStream inStream = (ObjectInputStream) _inStream;
1390 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
1392 String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT;
1393 String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1394 strControllerJarName;
1395 File file = new File(strControllerJarNamePath);
1396 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()),
1397 "Sending file!", inStream, outStream);
1398 // Send file - Class file for object creation
1399 sendFile(serverSocket.accept(), strControllerJarNamePath, file.length());
1400 Message msgReply = (Message) inStream.readObject();
1401 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1402 // Send .zip file if additional zip file is specified
1403 String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT;
1404 String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile;
1405 String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG);
1406 if (strAdditionalFile.equals(STR_YES)) {
1407 String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT;
1408 String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1409 strControllerCmpName;
1410 file = new File(strControllerCmpNamePath);
1411 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()),
1412 "Sending file!", inStream, outStream);
1413 // Send file - Class file for object creation
1414 sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length());
1415 msgReply = (Message) inStream.readObject();
1416 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1422 * A method to send files to C++ IoTSlave
1425 * TODO: Need to look into this (as of now, file transferred retains the "data" format,
1426 * hence it is unreadable from outside world
1428 private void sendFileToCppSlave(String sFilePath, String sFileName, Socket fileSocket,
1429 InputStream inStream, OutputStream outStream) throws IOException {
1431 sendCommCode(IoTCommCode.TRANSFER_FILE, outStream, inStream);
1433 sendString(sFileName, outStream); recvAck(inStream);
1434 File file = new File(sFilePath + sFileName);
1435 int iFileLen = toIntExact(file.length());
1436 RuntimeOutput.print("IoTMaster: Sending file " + sFileName + " with length " + iFileLen + " bytes...", BOOL_VERBOSE);
1438 sendInteger(iFileLen, outStream); recvAck(inStream);
1439 RuntimeOutput.print("IoTMaster: Sent file size!", BOOL_VERBOSE);
1440 byte[] bytFile = new byte[iFileLen];
1441 InputStream inFileStream = new FileInputStream(file);
1442 RuntimeOutput.print("IoTMaster: Opened file!", BOOL_VERBOSE);
1444 OutputStream outFileStream = fileSocket.getOutputStream();
1445 RuntimeOutput.print("IoTMaster: Got output stream!", BOOL_VERBOSE);
1447 while ((iCount = inFileStream.read(bytFile)) > 0) {
1448 outFileStream.write(bytFile, 0, iCount);
1450 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
1456 * A method to send files to C++ IoTSlave (now master using Process() to start
1457 * file transfer using scp)
1461 private void sendFileToCppSlave(String sFilePath, String sFileName) throws IOException {
1463 // Construct shell command to transfer file
1464 String sFile = sFilePath + sFileName;
1465 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_SLAVE_DIR;
1466 runCommand(strCmdSend);
1467 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
1469 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1470 STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
1471 runCommand(strCmdUnzip);
1472 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
1477 * runCommand() method runs shell command
1479 * @param strCommand String that contains command line
1482 private void runCommand(String strCommand) {
1485 Runtime runtime = Runtime.getRuntime();
1486 Process process = runtime.exec(strCommand);
1488 } catch (IOException ex) {
1489 System.out.println("RouterConfig: IOException: " + ex.getMessage());
1490 ex.printStackTrace();
1491 } catch (InterruptedException ex) {
1492 System.out.println("RouterConfig: InterruptException: " + ex.getMessage());
1493 ex.printStackTrace();
1499 * Construct command line for Java IoTSlave
1503 private String getCmdJavaIoTSlave(String strObjControllerName) {
1505 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1506 STR_RUNTIME_DIR + " sudo java " + STR_JVM_INIT_HEAP_SIZE + " " +
1507 STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " +
1508 STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
1509 commHan.getComPort(strObjControllerName) + " " +
1510 commHan.getRMIRegPort(strObjControllerName) + " " +
1511 commHan.getRMIStubPort(strObjControllerName) + " >& " +
1512 STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1517 * Construct command line for C++ IoTSlave
1521 private String getCmdCppIoTSlave(String strObjControllerName) {
1523 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1524 STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
1525 commHan.getComPort(strObjControllerName) + " " + strObjControllerName;
1530 * sendInteger() sends an integer in bytes
1532 public void sendInteger(int intSend, OutputStream outStream) throws IOException {
1534 BufferedOutputStream output = (BufferedOutputStream) outStream;
1535 // Transform integer into bytes
1536 ByteBuffer bb = ByteBuffer.allocate(INT_SIZE);
1538 // Send the byte array
1539 output.write(bb.array(), 0, INT_SIZE);
1545 * recvInteger() receives integer in bytes
1547 public int recvInteger(InputStream inStream) throws IOException {
1549 BufferedInputStream input = (BufferedInputStream) inStream;
1550 // Wait until input is available
1551 while(input.available() == 0);
1552 // Read integer - 4 bytes
1553 byte[] recvInt = new byte[INT_SIZE];
1554 input.read(recvInt, 0, INT_SIZE);
1555 int retVal = ByteBuffer.wrap(recvInt).getInt();
1562 * recvString() receives String in bytes
1564 public String recvString(InputStream inStream) throws IOException {
1566 BufferedInputStream input = (BufferedInputStream) inStream;
1567 int strLen = recvInteger(inStream);
1568 // Wait until input is available
1569 while(input.available() == 0);
1570 // Read String per strLen
1571 byte[] recvStr = new byte[strLen];
1572 input.read(recvStr, 0, strLen);
1573 String retVal = new String(recvStr);
1580 * sendString() sends a String in bytes
1582 public void sendString(String strSend, OutputStream outStream) throws IOException {
1584 BufferedOutputStream output = (BufferedOutputStream) outStream;
1585 // Transform String into bytes
1586 byte[] strSendBytes = strSend.getBytes();
1587 int strLen = strSend.length();
1588 // Send the string length first
1589 sendInteger(strLen, outStream);
1590 // Send the byte array
1591 output.write(strSendBytes, 0, strLen);
1597 * Convert integer to enum
1599 public IoTCommCode getCode(int intCode) throws IOException {
1601 IoTCommCode[] commCode = IoTCommCode.values();
1602 IoTCommCode retCode = commCode[intCode];
1611 public synchronized boolean recvAck(InputStream inStream) throws IOException {
1613 int intAck = recvInteger(inStream);
1614 IoTCommCode codeAck = getCode(intAck);
1615 if (codeAck == IoTCommCode.ACKNOWLEDGED)
1625 public void sendEndTransfer(OutputStream outStream) throws IOException {
1627 int endCode = IoTCommCode.END_TRANSFER.ordinal();
1628 sendInteger(endCode, outStream);
1633 * Send communication code to C++
1635 public void sendCommCode(IoTCommCode inpCommCode, OutputStream outStream, InputStream inStream) throws IOException {
1638 IoTCommCode commCode = inpCommCode;
1639 int intCode = commCode.ordinal();
1640 // TODO: delete this later
1641 System.out.println("DEBUG: Sending " + commCode + " with ordinal: " + intCode);
1642 sendInteger(intCode, outStream); recvAck(inStream);
1647 * Create a main controller object for C++
1649 public void createMainObjectCpp(String strObjControllerName, OutputStream outStream, InputStream inStream) throws IOException {
1651 sendCommCode(IoTCommCode.CREATE_MAIN_OBJECT, outStream, inStream);
1652 String strMainObjName = strObjControllerName;
1653 sendString(strMainObjName, outStream); recvAck(inStream);
1654 RuntimeOutput.print("IoTMaster: Create a main object: " + strMainObjName, BOOL_VERBOSE);
1659 * A helper function that converts Class into String
1661 * @param strDataType String MySQL data type
1664 public String getClassConverted(Class<?> cls) {
1666 if (cls == String.class) {
1668 } else if (cls == int.class) {
1677 * A helper function that converts Object into String for transfer to C++ slave
1679 * @param obj Object to be converted
1680 * @param strClassType String Java Class type
1683 public String getObjectConverted(Object obj) {
1685 if (obj instanceof String) {
1686 return (String) obj;
1687 } else if (obj instanceof Integer) {
1688 return Integer.toString((Integer) obj);
1696 * Create a driver object for C++
1698 public void createObjectCpp(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strIoTSlaveObjectHostAdd,
1699 Integer iRMIRegistryPort, Integer iRMIStubPort, Object[] arrFieldValues, Class[] arrFieldClasses,
1700 OutputStream outStream, InputStream inStream) throws IOException {
1702 sendCommCode(IoTCommCode.CREATE_OBJECT, outStream, inStream);
1703 RuntimeOutput.print("IoTMaster: Send request to create a driver object... ", BOOL_VERBOSE);
1704 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjName, BOOL_VERBOSE);
1705 sendString(strObjName, outStream); recvAck(inStream);
1706 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjClassName, BOOL_VERBOSE);
1707 sendString(strObjClassName, outStream); recvAck(inStream);
1708 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjClassInterfaceName, BOOL_VERBOSE);
1709 sendString(strObjStubClsIntfaceName, outStream); recvAck(inStream);
1710 RuntimeOutput.print("IoTMaster: Driver object skeleton class name: " + strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
1711 sendString(strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, outStream); recvAck(inStream);
1712 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1713 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1714 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1715 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1716 int numOfArgs = arrFieldValues.length;
1717 RuntimeOutput.print("IoTMaster: Send constructor arguments! Number of arguments: " + numOfArgs, BOOL_VERBOSE);
1718 sendInteger(numOfArgs, outStream); recvAck(inStream);
1719 for(Object obj : arrFieldValues) {
1720 String str = getObjectConverted(obj);
1721 sendString(str, outStream); recvAck(inStream);
1723 RuntimeOutput.print("IoTMaster: Send constructor argument classes!", BOOL_VERBOSE);
1724 for(Class cls : arrFieldClasses) {
1725 String str = getClassConverted(cls);
1726 sendString(str, outStream); recvAck(inStream);
1732 * Create new IoTSet for C++
1734 public void createNewIoTSetCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1736 sendCommCode(IoTCommCode.CREATE_NEW_IOTSET, outStream, inStream);
1737 RuntimeOutput.print("IoTMaster: Creating new IoTSet...", BOOL_VERBOSE);
1738 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1739 sendString(strObjFieldName, outStream); recvAck(inStream);
1744 * Create new IoTRelation for C++
1746 public void createNewIoTRelationCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1748 sendCommCode(IoTCommCode.CREATE_NEW_IOTRELATION, outStream, inStream);
1749 RuntimeOutput.print("IoTMaster: Creating new IoTRelation...", BOOL_VERBOSE);
1750 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1751 sendString(strObjFieldName, outStream); recvAck(inStream);
1756 * Get a IoTDeviceAddress object for C++
1758 public void getDeviceIoTSetObjectCpp(OutputStream outStream, InputStream inStream,
1759 String strDeviceAddress, int iSourcePort, int iDestPort, boolean bSourceWildCard, boolean bDestWildCard) throws IOException {
1761 sendCommCode(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, outStream, inStream);
1762 RuntimeOutput.print("IoTMaster: Getting IoTDeviceAddress...", BOOL_VERBOSE);
1763 sendString(strDeviceAddress, outStream); recvAck(inStream);
1764 sendInteger(iSourcePort, outStream); recvAck(inStream);
1765 sendInteger(iDestPort, outStream); recvAck(inStream);
1766 int iSourceWildCard = (bSourceWildCard ? 1 : 0);
1767 sendInteger(iSourceWildCard, outStream); recvAck(inStream);
1768 int iDestWildCard = (bDestWildCard ? 1 : 0);
1769 sendInteger(iDestWildCard, outStream); recvAck(inStream);
1770 RuntimeOutput.print("IoTMaster: Send device address: " + strDeviceAddress, BOOL_VERBOSE);
1775 * Get a IoTSet content object for C++
1777 public void getIoTSetRelationObjectCpp(IoTCommCode iotCommCode, String strIoTSlaveHostAddress, String strObjectName, String strObjectClassName,
1778 String strObjectClassInterfaceName, String strObjectStubClassInterfaceName, int iRMIRegistryPort, int iRMIStubPort,
1779 OutputStream outStream, InputStream inStream) throws IOException {
1781 sendCommCode(iotCommCode, outStream, inStream);
1782 RuntimeOutput.print("IoTMaster: Getting IoTSet object content...", BOOL_VERBOSE);
1784 RuntimeOutput.print("IoTMaster: Send host address: " + strIoTSlaveHostAddress, BOOL_VERBOSE);
1785 sendString(strIoTSlaveHostAddress, outStream); recvAck(inStream);
1786 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjectName, BOOL_VERBOSE);
1787 sendString(strObjectName, outStream); recvAck(inStream);
1788 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjectClassName, BOOL_VERBOSE);
1789 sendString(strObjectClassName, outStream); recvAck(inStream);
1790 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjectClassInterfaceName, BOOL_VERBOSE);
1791 sendString(strObjectClassInterfaceName, outStream); recvAck(inStream);
1792 RuntimeOutput.print("IoTMaster: Driver object stub class name: " + strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
1793 sendString(strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, outStream); recvAck(inStream);
1794 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1795 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1796 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1797 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1802 * Reinitialize IoTRelation field for C++
1804 private void reinitializeIoTRelationFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1806 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTRelation field!", BOOL_VERBOSE);
1807 sendCommCode(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD, outStream, inStream);
1808 RuntimeOutput.print("IoTMaster: Reinitialize IoTRelation field!", BOOL_VERBOSE);
1813 * Reinitialize IoTSet field for C++
1815 private void reinitializeIoTSetFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1817 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTSet field!", BOOL_VERBOSE);
1818 sendCommCode(IoTCommCode.REINITIALIZE_IOTSET_FIELD, outStream, inStream);
1819 RuntimeOutput.print("IoTMaster: Reinitialize IoTSet field!", BOOL_VERBOSE);
1824 * Create driver object for C++
1826 private void createDriverObjectCpp(OutputStream outStream, InputStream inStream) throws IOException {
1828 sendCommCode(IoTCommCode.CREATE_DRIVER_OBJECT, outStream, inStream);
1829 RuntimeOutput.print("IoTMaster: Send command to create driver object!", BOOL_VERBOSE);
1834 * Invoke init() for C++
1836 private void invokeInitMethodCpp(OutputStream outStream, InputStream inStream) throws IOException {
1838 sendCommCode(IoTCommCode.INVOKE_INIT_METHOD, outStream, inStream);
1839 RuntimeOutput.print("IoTMaster: Invoke init method!", BOOL_VERBOSE);
1844 * End session for C++
1846 public void endSessionCpp(OutputStream outStream) throws IOException {
1848 // Send message to end session
1849 IoTCommCode endSessionCode = IoTCommCode.END_SESSION;
1850 int intCode = endSessionCode.ordinal();
1851 sendInteger(intCode, outStream);
1852 //RuntimeOutput.print("IoTMaster: Send request to create a main object: " + strObjName, BOOL_VERBOSE);
1853 RuntimeOutput.print("IoTMaster: Send request to end session!", BOOL_VERBOSE);
1858 * A method to assign objects to multiple JVMs, including
1859 * the controller/device object that uses other objects
1860 * in IoTSet and IoTRelation
1864 private void createObjects() {
1871 // Extract hostname for this IoTMaster from MySQL DB
1872 strIoTMasterHostAdd = routerConfig.getIPFromMACAddress(STR_MASTER_MAC_ADD);
1873 // Loop as we can still find controller/device classes
1874 for(int i=0; i<strObjectNames.length; i++) {
1876 start = System.currentTimeMillis();
1878 // Assign a new list of PrintWriter objects
1879 routerConfig.renewPrintWriter();
1880 // Get controller names one by one
1881 String strObjControllerName = strObjectNames[i];
1882 // Use LoadBalancer to assign a host address
1883 //strIoTSlaveControllerHostAdd = lbIoT.selectHost();
1884 strIoTSlaveControllerHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
1885 if (strIoTSlaveControllerHostAdd == null)
1886 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
1887 // == START INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1888 // Add port connection and get port numbers
1889 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
1890 commHan.addPortConnection(strIoTSlaveControllerHostAdd, strObjControllerName);
1891 // ROUTING POLICY: IoTMaster and main controller object
1892 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
1893 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1894 // ROUTING POLICY: Send the same routing policy to both the hosts
1895 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
1896 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1897 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd,
1898 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1900 String strControllerCfg = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
1901 STR_LANGUAGE_CONTROLLER = parseConfigFile(strControllerCfg, STR_LANGUAGE);
1902 if(STR_LANGUAGE_CONTROLLER == null)
1903 throw new Error("IoTMaster: Language specification missing in config file: " + strControllerCfg);
1904 // Construct ssh command line and create a controller thread for e.g. AcmeProximity
1905 String strSSHCommand = null;
1906 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
1907 strSSHCommand = getCmdJavaIoTSlave(strObjControllerName);
1908 else if(STR_LANGUAGE_CONTROLLER.equals(STR_CPP))
1909 strSSHCommand = getCmdCppIoTSlave(strObjControllerName);
1911 throw new Error("IoTMaster: Language specification not recognized: " + STR_LANGUAGE_CONTROLLER);
1912 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
1913 createThread(strSSHCommand);
1914 // Wait for connection
1915 // Create a new socket for communication
1916 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjControllerName));
1917 Socket socket = serverSocket.accept();
1918 InputStream inStream = null;
1919 OutputStream outStream = null;
1920 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
1921 inStream = new ObjectInputStream(socket.getInputStream());
1922 outStream = new ObjectOutputStream(socket.getOutputStream());
1923 } else { // At this point the language is certainly C++, otherwise would've complained above
1924 inStream = new BufferedInputStream(socket.getInputStream());
1925 outStream = new BufferedOutputStream(socket.getOutputStream());
1928 RuntimeOutput.print("IoTMaster: Communication established!", BOOL_VERBOSE);
1931 result = System.currentTimeMillis()-start;
1932 System.out.println("\n\n ==> From start until after SSH for main controller: " + result);
1934 start = System.currentTimeMillis();
1936 // Send files for every controller class
1937 // e.g. AcmeProximity.jar and AcmeProximity.zip
1938 String strControllerClassName = strObjControllerName + STR_CLS_FILE_EXT;
1939 String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1940 strControllerClassName;
1942 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
1943 sendFileToJavaSlave(strObjControllerName, serverSocket, inStream, outStream);
1944 // Create main controller/device object
1945 commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName),
1946 "Create main object!", inStream, outStream);
1948 String strControllerZipFile = strObjControllerName + STR_ZIP_FILE_EXT;
1949 String strControllerFilePath = STR_CONT_PATH + strObjControllerName + "/";
1950 sendFileToCppSlave(strControllerFilePath, strControllerZipFile);
1951 createMainObjectCpp(strObjControllerName, outStream, inStream);
1955 result = System.currentTimeMillis()-start;
1956 System.out.println("\n\n ==> From IoTSlave start until main controller object is created: " + result);
1957 System.out.println(" ==> Including file transfer times!\n\n");
1959 start = System.currentTimeMillis();
1961 // == END INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1962 // Instrumenting one file
1963 RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE);
1964 RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE);
1965 HashMap<String,Object> hmControllerFieldObjects = null;
1966 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
1967 FileInputStream fis = new FileInputStream(strControllerClassNamePath);
1968 ClassReader cr = new ClassReader(fis);
1969 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
1970 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE);
1973 hmControllerFieldObjects = crim.getFieldObjects();
1975 String strControllerConfigFile = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
1976 CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strControllerConfigFile, null, BOOL_VERBOSE);
1977 hmControllerFieldObjects = crim.getFieldObjects();
1979 // Get the object and the class names
1980 // Build objects for IoTSet and IoTRelation fields in the controller/device classes
1981 //HashMap<String,Object> hmControllerFieldObjects = crim.getFieldObjects();
1982 for(Map.Entry<String,Object> map : hmControllerFieldObjects.entrySet()) {
1983 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
1984 // Iterate over HashMap and choose between processing
1985 // SetInstrumenter vs. RelationInstrumenter
1986 String strFieldName = map.getKey();
1987 String strClassName = map.getValue().getClass().getName();
1988 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
1989 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1990 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
1991 String strErrMsg = "IoTMaster: Controller object" +
1992 " cannot have IoTSet<IoTDeviceAddress>!";
1993 throw new Error(strErrMsg);
1994 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
1995 String strErrMsg = "IoTMaster: Controller object" +
1996 " cannot have IoTSet<ZigbeeAddress>!";
1997 throw new Error(strErrMsg);
1998 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
1999 // Instrument the IoTAddress
2000 setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd);
2001 instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream, STR_LANGUAGE_CONTROLLER);
2004 instrumentIoTSet(map, strFieldName, STR_LANGUAGE_CONTROLLER);
2006 } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) {
2007 instrumentIoTRelation(map, strFieldName, STR_LANGUAGE_CONTROLLER);
2011 result = System.currentTimeMillis()-start;
2012 System.out.println("\n\n ==> Time needed to instrument device driver objects: " + result + "\n\n");
2013 System.out.println(" ==> #Objects: " + commHan.getActiveControllerObjectList().size() + "\n\n");
2016 start = System.currentTimeMillis();
2018 // ROUTING POLICY: Deploy basic policies if this is the last controller
2019 if (i == strObjectNames.length-1) {
2020 // ROUTING POLICY: implement basic policies to reject all other irrelevant traffics
2021 for(String s: commHan.getHosts()) {
2022 setHostBasicPolicies(s);
2024 // We retain all the basic policies for router,
2025 // but we delete the initial allowance policies for internal all TCP and UDP communications
2026 setRouterBasicPolicies(STR_ROUTER_ADD);
2028 // Close access to policy files and deploy policies
2029 routerConfig.close();
2030 // Deploy the policy
2031 HashSet<String> setAddresses = new HashSet<String>(commHan.getHosts());
2032 setAddresses.add(strIoTMasterHostAdd);
2033 createPolicyThreads(STR_ROUTER_ADD, setAddresses);
2036 result = System.currentTimeMillis()-start;
2037 System.out.println("\n\n ==> Time needed to send policy files and deploy them : " + result + "\n\n");
2040 start = System.currentTimeMillis();
2042 // Separating object creations and Set/Relation initializations
2043 createDriverObjects();
2046 result = System.currentTimeMillis()-start;
2047 System.out.println("\n\n ==> Time needed to instantiate objects: " + result + "\n\n");
2049 start = System.currentTimeMillis();
2051 // Sets and relations initializations
2052 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2053 initializeSetsAndRelationsJava(inStream, outStream);
2055 initializeSetsAndRelationsCpp(inStream, outStream);;
2058 result = System.currentTimeMillis()-start;
2059 System.out.println("\n\n ==> Time needed to initialize sets and relations: " + result + "\n\n");
2061 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2062 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD
2063 commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD), "Invoke init() method!", inStream, outStream);
2065 invokeInitMethodCpp(outStream, inStream);
2066 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS
2067 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2068 ObjectOutputStream oStream = (ObjectOutputStream) outStream;
2069 oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
2070 } else // C++ side will wait until the program finishes, it's not generating a separate thread for now
2071 //endSessionCpp(outStream);
2075 serverSocket.close();
2076 commHan.printLists();
2077 lbIoT.printHostInfo();
2080 } catch (IOException |
2081 InterruptedException |
2082 ClassNotFoundException ex) {
2083 System.out.println("IoTMaster: Exception: "
2085 ex.printStackTrace();
2089 public static void main(String args[]) {
2091 // Detect the available controller/device classes
2092 // Input args[] should be used to list the controllers/devices
2093 // e.g. java IoTMaster AcmeProximity AcmeThermostat AcmeVentController
2094 IoTMaster iotMaster = new IoTMaster(args);
2096 iotMaster.parseIoTMasterConfigFile();
2097 // Initialize CommunicationHandler, LoadBalancer, and RouterConfig
2098 iotMaster.initLiveDataStructure();
2100 iotMaster.createObjects();