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_SHELL_FILE_EXT = ".sh";
116 private static final String STR_SO_FILE_EXT = ".so";
117 private static final String STR_ZIP_FILE_EXT = ".zip";
118 private static final String STR_TCP_PROTOCOL = "tcp";
119 private static final String STR_UDP_PROTOCOL = "udp";
120 private static final String STR_TCPGW_PROTOCOL = "tcpgw";
121 private static final String STR_NO_PROTOCOL = "nopro";
122 private static final String STR_SELF_MAC_ADD = "00:00:00:00:00:00";
123 private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS";
124 private static final String STR_INT_STUB_CLS_CFG = "INTERFACE_STUB_CLASS";
125 private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE";
126 private static final String STR_LANGUAGE = "LANGUAGE";
127 private static final String STR_YES = "Yes";
128 private static final String STR_NO = "No";
129 private static final String STR_JAVA = "Java";
130 private static final String STR_CPP = "C++";
131 private static final String STR_SSH = "ssh";
132 private static final String STR_SCP = "scp";
133 private static final String STR_IOTSLAVE_CPP = "./IoTSlave.o";
134 private static final String STR_SHELL_HEADER = "#!/bin/sh";
135 private static final String STR_JAVA_PATH = "/usr/bin/java";
137 private static int INT_SIZE = 4; // send length in the size of integer (4 bytes)
140 * Runtime class name constants - not to be configured by users
142 private static final String STR_REL_INSTRUMENTER_CLS = "iotruntime.master.RelationInstrumenter";
143 private static final String STR_SET_INSTRUMENTER_CLS = "iotruntime.master.SetInstrumenter";
144 private static final String STR_IOT_SLAVE_CLS = "iotruntime.slave.IoTSlave";
145 private static final String STR_IOT_DEV_ADD_CLS = "IoTDeviceAddress";
146 private static final String STR_IOT_ZB_ADD_CLS = "IoTZigbeeAddress";
147 private static final String STR_IOT_ADD_CLS = "IoTAddress";
153 public IoTMaster(String[] argObjNms) {
159 objAddInitHand = null;
160 strObjectNames = argObjNms;
162 strObjClassName = null;
163 strObjClassInterfaceName = null;
164 strObjStubClsIntfaceName = null;
165 strIoTMasterHostAdd = null;
166 strIoTSlaveControllerHostAdd = null;
167 strIoTSlaveObjectHostAdd = null;
168 arrFieldClasses = null;
169 arrFieldValues = null;
171 mapClassNameToCrim = null;
172 // Connection with C++ IoTSlave
173 serverSocketCpp = null;
178 STR_MASTER_MAC_ADD = null;
179 STR_IOT_CODE_PATH = null;
180 STR_CONT_PATH = null;
181 STR_RUNTIME_DIR = null;
182 STR_SLAVE_DIR = null;
185 STR_RMI_HOSTNAME = null;
186 STR_LOG_FILE_PATH = null;
188 STR_ROUTER_ADD = null;
189 STR_MONITORING_HOST = null;
190 STR_ZB_GATEWAY_ADDRESS = null;
191 STR_ZB_GATEWAY_PORT = null;
192 STR_ZB_IOTMASTER_PORT = null;
193 STR_JVM_INIT_HEAP_SIZE = null;
194 STR_JVM_MAX_HEAP_SIZE = null;
195 STR_LANGUAGE_CONTROLLER = null;
196 BOOL_VERBOSE = false;
200 * A method to initialize CommunicationHandler, LoadBalancer, RouterConfig and ObjectInitHandler
204 private void initLiveDataStructure() {
206 commHan = new CommunicationHandler(BOOL_VERBOSE);
207 lbIoT = new LoadBalancer(BOOL_VERBOSE);
208 lbIoT.setupLoadBalancer();
209 routerConfig = new RouterConfig();
210 routerConfig.getAddressList(STR_ROUTER_ADD);
211 objInitHand = new ObjectInitHandler(BOOL_VERBOSE);
212 objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE);
213 mapClassNameToCrim = new HashMap<String,Object>();
217 * getPrintWriter() gets a new PrintWriter for a new object
219 * @param strObjectName String object name
220 * @return PrintWriter
222 private PrintWriter getPrintWriter(String strObjectName) {
224 FileWriter fw = null;
226 fw = new FileWriter(strObjectName);
227 } catch (IOException ex) {
228 ex.printStackTrace();
230 PrintWriter printWriter = new PrintWriter(new BufferedWriter(fw));
235 * A method to initialize constants from config file
239 private void parseIoTMasterConfigFile() {
240 // Parse configuration file
241 Properties prop = new Properties();
242 String strCfgFileName = STR_IOT_MASTER_NAME + STR_CFG_FILE_EXT;
243 File file = new File(strCfgFileName);
244 FileInputStream fis = null;
246 fis = new FileInputStream(file);
249 } catch (IOException ex) {
250 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
251 ex.printStackTrace();
253 // Initialize constants from config file
254 STR_MASTER_MAC_ADD = prop.getProperty("MAC_ADDRESS");
255 STR_IOT_CODE_PATH = prop.getProperty("IOT_CODE_PATH");
256 STR_CONT_PATH = prop.getProperty("CONTROLLERS_CODE_PATH");
257 STR_RUNTIME_DIR = prop.getProperty("RUNTIME_DIR");
258 STR_SLAVE_DIR = prop.getProperty("SLAVE_DIR");
259 STR_CLS_PATH = prop.getProperty("CLASS_PATH");
260 STR_RMI_PATH = prop.getProperty("RMI_PATH");
261 STR_RMI_HOSTNAME = prop.getProperty("RMI_HOSTNAME");
262 STR_LOG_FILE_PATH = prop.getProperty("LOG_FILE_PATH");
263 STR_USERNAME = prop.getProperty("USERNAME");
264 STR_ROUTER_ADD = prop.getProperty("ROUTER_ADD");
265 STR_MONITORING_HOST = prop.getProperty("MONITORING_HOST");
266 STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS");
267 STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT");
268 STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT");
269 STR_JVM_INIT_HEAP_SIZE = prop.getProperty("JVM_INIT_HEAP_SIZE");
270 STR_JVM_MAX_HEAP_SIZE = prop.getProperty("JVM_MAX_HEAP_SIZE");
271 STR_SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX");
272 STR_STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX");
273 if(prop.getProperty("VERBOSE").equals(STR_YES)) {
277 RuntimeOutput.print("IoTMaster: Extracting information from config file: " + strCfgFileName, BOOL_VERBOSE);
278 RuntimeOutput.print("STR_MASTER_MAC_ADD=" + STR_MASTER_MAC_ADD, BOOL_VERBOSE);
279 RuntimeOutput.print("STR_IOT_CODE_PATH=" + STR_IOT_CODE_PATH, BOOL_VERBOSE);
280 RuntimeOutput.print("STR_CONT_PATH=" + STR_CONT_PATH, BOOL_VERBOSE);
281 RuntimeOutput.print("STR_RUNTIME_DIR=" + STR_RUNTIME_DIR, BOOL_VERBOSE);
282 RuntimeOutput.print("STR_SLAVE_DIR=" + STR_SLAVE_DIR, BOOL_VERBOSE);
283 RuntimeOutput.print("STR_CLS_PATH=" + STR_CLS_PATH, BOOL_VERBOSE);
284 RuntimeOutput.print("STR_RMI_PATH=" + STR_RMI_PATH, BOOL_VERBOSE);
285 RuntimeOutput.print("STR_RMI_HOSTNAME=" + STR_RMI_HOSTNAME, BOOL_VERBOSE);
286 RuntimeOutput.print("STR_LOG_FILE_PATH=" + STR_LOG_FILE_PATH, BOOL_VERBOSE);
287 RuntimeOutput.print("STR_USERNAME=" + STR_USERNAME, BOOL_VERBOSE);
288 RuntimeOutput.print("STR_ROUTER_ADD=" + STR_ROUTER_ADD, BOOL_VERBOSE);
289 RuntimeOutput.print("STR_MONITORING_HOST=" + STR_MONITORING_HOST, BOOL_VERBOSE);
290 RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE);
291 RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE);
292 RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE);
293 RuntimeOutput.print("STR_JVM_INIT_HEAP_SIZE=" + STR_JVM_INIT_HEAP_SIZE, BOOL_VERBOSE);
294 RuntimeOutput.print("STR_JVM_MAX_HEAP_SIZE=" + STR_JVM_MAX_HEAP_SIZE, BOOL_VERBOSE);
295 RuntimeOutput.print("STR_SKEL_CLASS_SUFFIX=" + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
296 RuntimeOutput.print("STR_STUB_CLASS_SUFFIX=" + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
297 RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE);
298 RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE);
302 * A method to parse information from a config file
304 * @param strCfgFileName Config file name
305 * @param strCfgField Config file field name
308 private String parseConfigFile(String strCfgFileName, String strCfgField) {
309 // Parse configuration file
310 Properties prop = new Properties();
311 File file = new File(strCfgFileName);
312 FileInputStream fis = null;
314 fis = new FileInputStream(file);
317 } catch (IOException ex) {
318 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
319 ex.printStackTrace();
321 System.out.println("IoTMaster: Reading " + strCfgField +
322 " from config file: " + strCfgFileName + " with value: " +
323 prop.getProperty(strCfgField, null));
324 // NULL is returned if the property isn't found
325 return prop.getProperty(strCfgField, null);
329 * A method to send files from IoTMaster
331 * @param filesocket File socket object
332 * @param sFileName File name
333 * @param lFLength File length
336 private void sendFile(Socket filesocket, String sFileName, long lFLength) throws IOException {
338 File file = new File(sFileName);
339 byte[] bytFile = new byte[toIntExact(lFLength)];
340 InputStream inFileStream = new FileInputStream(file);
342 OutputStream outFileStream = filesocket.getOutputStream();
344 while ((iCount = inFileStream.read(bytFile)) > 0) {
345 outFileStream.write(bytFile, 0, iCount);
348 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
352 * A method to create a thread
354 * @param sSSHCmd SSH command
357 private void createThread(String sSSHCmd) throws IOException {
359 // Start a new thread to start a new JVM
361 Runtime runtime = Runtime.getRuntime();
362 Process process = runtime.exec(sSSHCmd);
364 RuntimeOutput.print("Executing: " + sSSHCmd, BOOL_VERBOSE);
368 * A method to send command from master and receive reply from slave
370 * @params msgSend Message object
371 * @params strPurpose String that prints purpose message
372 * @params inStream Input stream
373 * @params outStream Output stream
376 private void commMasterToSlave(Message msgSend, String strPurpose,
377 InputStream _inStream, OutputStream _outStream)
378 throws IOException, ClassNotFoundException {
380 // Send message/command from master
381 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
382 outStream.writeObject(msgSend);
383 RuntimeOutput.print("IoTMaster: Send message: " + strPurpose, BOOL_VERBOSE);
385 // Get reply from slave as acknowledgment
386 ObjectInputStream inStream = (ObjectInputStream) _inStream;
387 Message msgReply = (Message) inStream.readObject();
388 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
392 * A private method to instrument IoTSet device
394 * @params strFieldIdentifier String field name + object ID
395 * @params strFieldName String field name
396 * @params strIoTSlaveObjectHostAdd String slave host address
397 * @params inStream ObjectInputStream communication
398 * @params inStream ObjectOutputStream communication
399 * @params strLanguage String language
402 private void instrumentIoTSetDevice(String strFieldIdentifier, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
403 InputStream inStream, OutputStream outStream, String strLanguage)
404 throws IOException, ClassNotFoundException, InterruptedException {
406 // Get information from the set
407 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
408 // Create a new IoTSet
409 if(strLanguage.equals(STR_JAVA)) {
410 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
411 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream);
413 createNewIoTSetCpp(strFieldName, outStream, inStream);
414 int iRows = listObject.size();
415 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
416 // Transfer the address
417 for(int iRow=0; iRow<iRows; iRow++) {
418 arrFieldValues = listObject.get(iRow);
419 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
420 String strDeviceAddress = null;
421 String strDeviceAddressKey = null;
422 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
423 strDeviceAddress = strIoTSlaveObjectHostAdd;
424 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
426 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
427 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
429 int iDestDeviceDriverPort = (int) arrFieldValues[1];
430 String strProtocol = (String) arrFieldValues[2];
431 // Check for wildcard feature
432 boolean bSrcPortWildCard = false;
433 boolean bDstPortWildCard = false;
434 if (arrFieldValues.length > 3) {
435 bSrcPortWildCard = (boolean) arrFieldValues[3];
436 bDstPortWildCard = (boolean) arrFieldValues[4];
438 // Add the port connection into communication handler - if it's not assigned yet
439 if (commHan.getComPort(strDeviceAddressKey) == null) {
440 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
444 System.out.println("\n\n DEBUG: InstrumentSetDevice: Object Name: " + strObjName);
445 System.out.println("DEBUG: InstrumentSetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey));
446 System.out.println("DEBUG: InstrumentSetDevice: Device address: " + strDeviceAddressKey + "\n\n");
448 // Send address one by one
449 if(strLanguage.equals(STR_JAVA)) {
450 Message msgGetIoTSetObj = null;
451 if (bDstPortWildCard) {
452 String strUniqueDev = strDeviceAddressKey + ":" + iRow;
453 msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
454 strDeviceAddress, commHan.getAdditionalPort(strUniqueDev), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
456 msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
457 strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
458 commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream);
460 getDeviceIoTSetObjectCpp(outStream, inStream, strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort,
461 bSrcPortWildCard, bDstPortWildCard);
463 // Reinitialize IoTSet on device object
464 if(strLanguage.equals(STR_JAVA))
465 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
467 reinitializeIoTSetFieldCpp(outStream, inStream);
472 * A private method to instrument IoTSet Zigbee device
474 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
475 * @params strFieldName String field name
476 * @params strIoTSlaveObjectHostAdd String slave host address
477 * @params inStream ObjectInputStream communication
478 * @params inStream ObjectOutputStream communication
479 * @params strLanguage String language
482 private void instrumentIoTSetZBDevice(Map.Entry<String,Object> map, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
483 InputStream inStream, OutputStream outStream, String strLanguage)
484 throws IOException, ClassNotFoundException, InterruptedException {
486 // Get information from the set
487 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
488 // Create a new IoTSet
489 if(strLanguage.equals(STR_JAVA)) {
490 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
491 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream);
492 } else // TODO: will need to implement IoTSet Zigbee for C++ later
494 // Prepare ZigbeeConfig
495 String strZigbeeGWAddress = routerConfig.getIPFromMACAddress(STR_ZB_GATEWAY_ADDRESS);
496 String strZigbeeGWAddressKey = strObjName + "-" + strZigbeeGWAddress;
497 int iZigbeeGWPort = Integer.parseInt(STR_ZB_GATEWAY_PORT);
498 int iZigbeeIoTMasterPort = Integer.parseInt(STR_ZB_IOTMASTER_PORT);
499 commHan.addDevicePort(iZigbeeIoTMasterPort);
500 ZigbeeConfig zbConfig = new ZigbeeConfig(strZigbeeGWAddress, iZigbeeGWPort, iZigbeeIoTMasterPort,
502 // Add the port connection into communication handler - if it's not assigned yet
503 if (commHan.getComPort(strZigbeeGWAddressKey) == null) {
504 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddressKey);
506 int iRows = setInstrumenter.numberOfRows();
507 RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE);
510 System.out.println("\n\n DEBUG: InstrumentZigbeeDevice: Object Name: " + strObjName);
511 System.out.println("DEBUG: InstrumentZigbeeDevice: Port number: " + commHan.getComPort(strZigbeeGWAddressKey));
512 System.out.println("DEBUG: InstrumentZigbeeDevice: Device address: " + strZigbeeGWAddress + "\n\n");
514 // Transfer the address
515 for(int iRow=0; iRow<iRows; iRow++) {
516 arrFieldValues = setInstrumenter.fieldValues(iRow);
517 // Get device address
518 String strZBDevAddress = (String) arrFieldValues[0];
519 // Send policy to Zigbee gateway - TODO: Need to clear policy first?
520 zbConfig.setPolicy(strIoTSlaveObjectHostAdd, commHan.getComPort(strZigbeeGWAddressKey), strZBDevAddress);
521 // Send address one by one
522 if(strLanguage.equals(STR_JAVA)) {
523 Message msgGetIoTSetZBObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ZB_DEV_IOTSET_OBJECT, strZBDevAddress);
524 commMasterToSlave(msgGetIoTSetZBObj, "Get IoTSet objects!", inStream, outStream);
525 } else // TODO: Implement IoTSet Zigbee for C++
528 zbConfig.closeConnection();
529 // Reinitialize IoTSet on device object
530 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
535 * A private method to instrument IoTSet of addresses
537 * @params strFieldIdentifier String field name + object ID
538 * @params strFieldName String field name
539 * @params inStream ObjectInputStream communication
540 * @params inStream ObjectOutputStream communication
541 * @params strLanguage String language
544 private void instrumentIoTSetAddress(String strFieldIdentifier, String strFieldName,
545 InputStream inStream, OutputStream outStream, String strLanguage)
546 throws IOException, ClassNotFoundException, InterruptedException {
548 // Get information from the set
549 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
550 // Create a new IoTSet
551 if(strLanguage.equals(STR_JAVA)) {
552 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
553 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream);
556 int iRows = listObject.size();
557 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
558 // Transfer the address
559 for(int iRow=0; iRow<iRows; iRow++) {
560 arrFieldValues = listObject.get(iRow);
561 // Get device address
562 String strAddress = (String) arrFieldValues[0];
563 // Send address one by one
564 if(strLanguage.equals(STR_JAVA)) {
565 Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT, strAddress);
566 commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream);
567 } else // TODO: Implement IoTSet Address for C++
570 // Reinitialize IoTSet on device object
571 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
572 "Reinitialize IoTSet fields!", inStream, outStream);
577 * A private method to instrument an object on a specific machine and setting up policies
579 * @params strFieldObjectID String field object ID
580 * @params strLanguage String language
583 private void instrumentObject(String strFieldObjectID, String strLanguage) throws IOException {
585 // Extract the interface name for RMI
586 // e.g. ProximitySensorInterface, TempSensorInterface, etc.
588 String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
589 strObjClassInterfaceName = parseConfigFile(strObjCfgFile, STR_INTERFACE_CLS_CFG);
590 strObjStubClsIntfaceName = parseConfigFile(strObjCfgFile, STR_INT_STUB_CLS_CFG);
591 // Create an object name, e.g. ProximitySensorImplPS1
592 strObjName = strObjClassName + strFieldObjectID;
593 // Check first if host exists
594 if(commHan.objectExists(strObjName)) {
595 // If this object exists already ...
596 // Re-read IoTSlave object hostname for further reference
597 strIoTSlaveObjectHostAdd = commHan.getHostAddress(strObjName);
598 RuntimeOutput.print("IoTMaster: Object with name: " + strObjName + " has existed!", BOOL_VERBOSE);
600 // If this is a new object ... then create one
601 // Get host address for IoTSlave from LoadBalancer
602 //strIoTSlaveObjectHostAdd = lbIoT.selectHost();
603 strIoTSlaveObjectHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
604 if (strIoTSlaveControllerHostAdd == null)
605 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
606 RuntimeOutput.print("IoTMaster: Object name: " + strObjName, BOOL_VERBOSE);
607 // Add port connection and get port numbers
608 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
609 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strObjName);
610 commHan.addActiveControllerObject(strFieldObjectID, strObjName, strObjClassName, strObjClassInterfaceName,
611 strObjStubClsIntfaceName, strIoTSlaveObjectHostAdd, arrFieldValues, arrFieldClasses);
612 // ROUTING POLICY: IoTMaster and device/controller object
613 // Master-slave communication
614 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
615 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
616 // ROUTING POLICY: Send the same routing policy to both the hosts
617 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
618 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
619 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTMasterHostAdd,
620 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
621 // Need to accommodate callback functions here - open ports for TCP
622 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd,
623 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
624 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd,
625 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
626 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd,
627 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
628 // Instrument the IoTSet declarations inside the class file
629 instrumentObjectIoTSet(strFieldObjectID, strLanguage);
631 // Send routing policy to router for controller object
632 // ROUTING POLICY: RMI communication - RMI registry and stub ports
633 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
634 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
635 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
636 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
637 // Send the same set of routing policies to compute nodes
638 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
639 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
640 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
641 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
642 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
643 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
644 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
645 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
650 * A private method to set router policies for IoTDeviceAddress objects
652 * @params strFieldIdentifier String field name + object ID
653 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
654 * @params strIoTSlaveObjectHostAdd String slave host address
657 private void setRouterPolicyIoTSetDevice(String strFieldIdentifier, Map.Entry<String,Object> map,
658 String strIoTSlaveObjectHostAdd) {
660 // Get information from the set
661 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
662 int iRows = setInstrumenter.numberOfRows();
663 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
664 // Transfer the address
665 for(int iRow=0; iRow<iRows; iRow++) {
666 arrFieldValues = setInstrumenter.fieldValues(iRow);
667 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
668 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
669 String strDeviceAddress = null;
670 String strDeviceAddressKey = null;
671 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
672 strDeviceAddress = strIoTSlaveObjectHostAdd;
673 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
674 } else { // Concatenate object name and IP address to give unique key - for a case where there is one device for multiple drivers
675 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
676 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
678 int iDestDeviceDriverPort = (int) arrFieldValues[1];
679 String strProtocol = (String) arrFieldValues[2];
680 // Add the port connection into communication handler - if it's not assigned yet
681 if (commHan.getComPort(strDeviceAddressKey) == null)
682 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
683 boolean bDstPortWildCard = false;
684 // Recognize this and allocate different ports for it
685 if (arrFieldValues.length > 3) {
686 bDstPortWildCard = (boolean) arrFieldValues[4];
687 if (bDstPortWildCard) { // This needs a unique source port
688 String strUniqueDev = strDeviceAddressKey + ":" + iRow;
689 commHan.addAdditionalPort(strUniqueDev);
694 System.out.println("\n\n DEBUG: InstrumentPolicySetDevice: Object Name: " + strObjName);
695 System.out.println("DEBUG: InstrumentPolicySetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey));
696 System.out.println("DEBUG: InstrumentPolicySetDevice: Device address: " + strDeviceAddressKey + "\n\n");
698 // Send routing policy to router for device drivers and devices
699 // ROUTING POLICY: RMI communication - RMI registry and stub ports
700 if((iDestDeviceDriverPort == -1) && (!strProtocol.equals(STR_NO_PROTOCOL))) {
701 // Port number -1 means that we don't set the policy strictly to port number level
702 // "nopro" = no protocol specified for just TCP or just UDP (can be both used as well)
703 // ROUTING POLICY: Device driver and device
704 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
705 // ROUTING POLICY: Send to the compute node where the device driver is
706 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
707 } else if((iDestDeviceDriverPort == -1) && (strProtocol.equals(STR_NO_PROTOCOL))) {
708 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
709 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
710 } else if(strProtocol.equals(STR_TCPGW_PROTOCOL)) {
711 // This is a TCP protocol that connects, e.g. a phone to our runtime system
712 // that provides a gateway access (accessed through destination port number)
713 commHan.addDevicePort(iDestDeviceDriverPort);
714 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
715 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
716 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
717 routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
719 // Other port numbers...
720 commHan.addDevicePort(iDestDeviceDriverPort);
721 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol,
722 commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
723 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol,
724 commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
730 * A private method to set router policies for IoTAddress objects
732 * @params strFieldIdentifier String field name + object ID
733 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
734 * @params strHostAddress String host address
737 private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry<String,Object> map,
738 String strHostAddress) {
740 // Get information from the set
741 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
742 int iRows = setInstrumenter.numberOfRows();
743 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
744 // Transfer the address
745 for(int iRow=0; iRow<iRows; iRow++) {
746 arrFieldValues = setInstrumenter.fieldValues(iRow);
747 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
748 // Get device address
749 String strAddress = (String) arrFieldValues[0];
750 // Setting up router policies for HTTP/HTTPs
751 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress);
752 routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress);
757 * A private method to instrument an object's IoTSet and IoTRelation field to up policies
759 * Mostly the IoTSet fields would contain IoTDeviceAddress objects
761 * @params strFieldObjectID String field object ID
762 * @params strLanguage String language
765 private void instrumentObjectIoTSet(String strFieldObjectID, String strLanguage) throws IOException {
767 // If this is a new object ... then create one
768 // Instrument the class source code and look for IoTSet for device addresses
769 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
770 HashMap<String,Object> hmObjectFieldObjects = null;
771 if(strLanguage.equals(STR_JAVA)) {
772 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT;
773 FileInputStream fis = new FileInputStream(strObjectClassNamePath);
774 ClassReader cr = new ClassReader(fis);
775 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
776 // We need Object ID to instrument IoTDeviceAddress
777 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE);
780 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
781 hmObjectFieldObjects = crim.getFieldObjects();
783 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
784 CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strObjectClassNamePath, strFieldObjectID, BOOL_VERBOSE);
785 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
786 hmObjectFieldObjects = crim.getFieldObjects();
788 // Get the object and the class names
789 // Build objects for IoTSet and IoTRelation fields in the device object classes
790 RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " +
791 strFieldObjectID, BOOL_VERBOSE);
792 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
793 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
794 // Iterate over HashMap and choose between processing
795 String strFieldName = map.getKey();
796 String strClassName = map.getValue().getClass().getName();
797 String strFieldIdentifier = strFieldName + strFieldObjectID;
798 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
799 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
800 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
801 // Instrument the normal IoTDeviceAddress
802 setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
803 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
804 // Instrument the IoTAddress
805 setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
806 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
807 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
808 RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..",
811 String strErrMsg = "IoTMaster: Device driver object" +
812 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
813 " or IoTSet<IoTZigbeeAddress>!";
814 throw new Error(strErrMsg);
817 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
818 throw new Error(strErrMsg);
825 * A private method to send files to a Java slave driver
827 * @params serverSocket ServerSocket
828 * @params _inStream InputStream
829 * @params _outStream OutputStream
830 * @params strObjName String
831 * @params strObjClassName String
832 * @params strObjClassInterfaceName String
833 * @params strObjStubClsIntfaceName String
834 * @params strIoTSlaveObjectHostAdd String
835 * @params strFieldObjectID String
836 * @params arrFieldValues Object[]
837 * @params arrFieldClasses Class[]
840 private void sendFileToJavaSlaveDriver(ServerSocket serverSocket, InputStream _inStream, OutputStream _outStream,
841 String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
842 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
843 throws IOException, ClassNotFoundException {
845 ObjectInputStream inStream = (ObjectInputStream) _inStream;
846 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
847 // Create message to transfer file first
848 String sFileName = strObjClassName + STR_JAR_FILE_EXT;
849 String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
850 File file = new File(sPath);
851 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()),
852 "Sending file!", inStream, outStream);
853 // Send file - JAR file for object creation
854 sendFile(serverSocket.accept(), sPath, file.length());
855 Message msgReply = (Message) inStream.readObject();
856 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
857 // Pack object information to create object on a IoTSlave
858 Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd,
859 strObjClassName, strObjName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
860 commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses);
862 commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream);
867 * A private method to send files to a Java slave driver
871 private void sendFileToCppSlaveDriver(String strObjClassName, String strIoTSlaveObjectHostAdd)
872 throws IOException, ClassNotFoundException {
874 // Create message to transfer file first
875 String sFileName = strObjClassName + STR_ZIP_FILE_EXT;
876 String sFile = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
877 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_SLAVE_DIR;
878 runCommand(strCmdSend);
879 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
881 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
882 STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
883 runCommand(strCmdUnzip);
884 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
890 * Construct command line for Java IoTSlave
894 /*private String getCmdJavaDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
896 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " sudo java " +
897 STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_RMI_HOSTNAME +
898 strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
899 commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
900 commHan.getRMIStubPort(strObjName) + " >& " + STR_LOG_FILE_PATH + strObjName + ".log &";
902 private String getCmdJavaDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
904 // Create an Shell executable
905 String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " +
906 STR_RMI_HOSTNAME + strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
907 commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
908 commHan.getRMIStubPort(strObjName) + " > " + STR_LOG_FILE_PATH + strObjName + ".log &";
909 String shellFile = "./" + strObjName + STR_SHELL_FILE_EXT;
910 createWrapperShellScript(strJavaCommand, shellFile);
911 // Send the file to the compute node
912 String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_RUNTIME_DIR;
913 runCommand(strCmdSend);
914 System.out.println("IoTMaster: Sending shell file: " + strCmdSend);
915 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile;
920 * Construct command line for C++ IoTSlave
924 private String getCmdCppDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
926 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
927 STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
928 commHan.getComPort(strObjName) + " " + strObjName;
933 * createWrapperShellScript() gets a wrapper shell script
935 * @param strCommand String command
936 * @param strObjectName String object name
937 * @return PrintWriter
939 private void createWrapperShellScript(String strCommand, String strFileName) {
941 PrintWriter printWriter = getPrintWriter(strFileName);
942 printWriter.println(strCommand);
944 runCommand("chmod 755 " + strFileName);
949 * A private method to create an object on a specific machine
951 * @params strObjName String object name
952 * @params strObjClassName String object class name
953 * @params strObjClassInterfaceName String object class interface name
954 * @params strIoTSlaveObjectHostAdd String IoTSlave host address
955 * @params strFieldObjectID String field object ID
956 * @params arrFieldValues Array of field values
957 * @params arrFieldClasses Array of field classes
960 private void createObject(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
961 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
962 throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException {
965 String sCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
966 String strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE + "_" + strObjName);
967 if(strLanguageDriver == null) // Read just the field LANGUAGE if the first read is null
968 strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE);
969 if(strLanguageDriver == null) // Check nullness for the second time - report if it is still null
970 throw new Error("IoTMaster: Language specification missing in config file: " + sCfgFile);
975 start = System.currentTimeMillis();
977 // Construct ssh command line
978 // e.g. ssh rtrimana@dw-2.eecs.uci.edu cd <path>;
979 // java -cp $CLASSPATH:./*.jar
980 // -Djava.rmi.server.codebase=file:./*.jar
981 // iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 &
982 // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa
983 String strSSHCommand = null;
984 if(strLanguageDriver.equals(STR_JAVA))
985 strSSHCommand = getCmdJavaDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
986 else if(strLanguageDriver.equals(STR_CPP))
987 strSSHCommand = getCmdCppDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
989 throw new Error("IoTMaster: Language specification not recognized: " + strLanguageDriver);
990 RuntimeOutput.print("IoTMaster: Language for " + strObjName + " is " + strLanguageDriver, BOOL_VERBOSE);
992 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
993 // Start a new thread to start a new JVM
994 createThread(strSSHCommand);
995 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjName));
996 Socket socket = serverSocket.accept();
997 //InputStream inStream = new ObjectInputStream(socket.getInputStream());
998 //OutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
999 InputStream inStream = null;
1000 OutputStream outStream = null;
1001 if(strLanguageDriver.equals(STR_JAVA)) {
1002 inStream = new ObjectInputStream(socket.getInputStream());
1003 outStream = new ObjectOutputStream(socket.getOutputStream());
1004 } else { // At this point the language is certainly C++, otherwise would've complained above
1005 inStream = new BufferedInputStream(socket.getInputStream());
1006 outStream = new BufferedOutputStream(socket.getOutputStream());
1011 result = System.currentTimeMillis()-start;
1012 System.out.println("\n\n ==> Time needed to start JVM for " + strObjName + ": " + result + "\n\n");
1015 start = System.currentTimeMillis();
1017 if(strLanguageDriver.equals(STR_JAVA)) {
1018 sendFileToJavaSlaveDriver(serverSocket, inStream, outStream, strObjName,
1019 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1020 strIoTSlaveObjectHostAdd, strFieldObjectID, arrFieldValues, arrFieldClasses);
1022 sendFileToCppSlaveDriver(strObjClassName, strIoTSlaveObjectHostAdd);
1023 createObjectCpp(strObjName, strObjClassName, strObjClassInterfaceName, strIoTSlaveObjectHostAdd,
1024 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses,
1025 outStream, inStream);
1029 result = System.currentTimeMillis()-start;
1030 System.out.println("\n\n ==> Time needed to send JAR file for " + strObjName + ": " + result + "\n\n");
1033 start = System.currentTimeMillis();
1035 // Instrument the class source code and look for IoTSet for device addresses
1036 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
1037 RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " + strFieldObjectID, BOOL_VERBOSE);
1038 // Get the object and the class names
1039 // Build objects for IoTSet and IoTRelation fields in the device object classes
1040 Object crimObj = mapClassNameToCrim.get(strObjClassName + strFieldObjectID);
1041 HashMap<String,Object> hmObjectFieldObjects = null;
1042 if (crimObj instanceof ClassRuntimeInstrumenterMaster) {
1043 ClassRuntimeInstrumenterMaster crim = (ClassRuntimeInstrumenterMaster) crimObj;
1044 hmObjectFieldObjects = crim.getFieldObjects();
1045 } else if (crimObj instanceof CRuntimeInstrumenterMaster) {
1046 CRuntimeInstrumenterMaster crim = (CRuntimeInstrumenterMaster) crimObj;
1047 hmObjectFieldObjects = crim.getFieldObjects();
1049 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
1050 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
1051 // Iterate over HashMap and choose between processing
1052 String strFieldName = map.getKey();
1053 String strClassName = map.getValue().getClass().getName();
1054 String strFieldIdentifier = strFieldName + strFieldObjectID;
1055 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
1056 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1057 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
1058 // Instrument the normal IoTDeviceAddress
1059 synchronized(this) {
1060 instrumentIoTSetDevice(strFieldIdentifier, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1062 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
1063 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
1064 synchronized(this) {
1065 instrumentIoTSetZBDevice(map, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1067 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
1068 // Instrument the IoTAddress
1069 synchronized(this) {
1070 instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream, strLanguageDriver);
1073 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
1074 " or IoTSet<IoTZigbeeAddress>!";
1075 throw new Error(strErrMsg);
1078 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
1079 throw new Error(strErrMsg);
1083 // TODO: Change this later
1084 if(strLanguageDriver.equals(STR_JAVA)) {
1085 ObjectOutputStream oStream = (ObjectOutputStream) outStream;
1086 oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
1087 } else { // C++ side for now will be running continuously because it's an infinite loop (not in a separate thread)
1088 createDriverObjectCpp(outStream, inStream);
1089 //endSessionCpp(outStream);
1093 result = System.currentTimeMillis()-start;
1094 System.out.println("\n\n ==> Time needed to create object " + strObjName + " and instrument IoTDeviceAddress: " + result + "\n\n");
1100 serverSocket.close();
1105 * A private method to create controller objects
1109 private void createDriverObjects() throws InterruptedException {
1111 // Create a list of threads
1112 List<Thread> threads = new ArrayList<Thread>();
1113 // Get the list of active controller objects and loop it
1114 List<String> listActiveControllerObject = commHan.getActiveControllerObjectList();
1115 for(String strObjName : listActiveControllerObject) {
1117 ObjectCreationInfo objCrtInfo = commHan.getObjectCreationInfo(strObjName);
1118 Thread objectThread = new Thread(new Runnable() {
1120 synchronized(this) {
1122 createObject(strObjName, objCrtInfo.getObjectClassName(), objCrtInfo.getObjectClassInterfaceName(),
1123 objCrtInfo.getObjectStubClassInterfaceName(), objCrtInfo.getIoTSlaveObjectHostAdd(),
1124 commHan.getFieldObjectID(strObjName), commHan.getArrayFieldValues(strObjName),
1125 commHan.getArrayFieldClasses(strObjName));
1126 } catch (IOException |
1127 ClassNotFoundException |
1128 InterruptedException ex) {
1129 ex.printStackTrace();
1134 threads.add(objectThread);
1135 objectThread.start();
1138 for (Thread thread : threads) {
1141 } catch (InterruptedException ex) {
1142 ex.printStackTrace();
1149 * A private method to instrument IoTSet
1151 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
1152 * @params strFieldName String field name
1153 * @params strLanguage String language
1156 private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName, String strLanguage)
1157 throws IOException, ClassNotFoundException, InterruptedException {
1159 // Get information from the set
1160 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1161 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTSET);
1163 int iRows = setInstrumenter.numberOfRows();
1164 for(int iRow=0; iRow<iRows; iRow++) {
1165 // Get field classes and values
1166 arrFieldClasses = setInstrumenter.fieldClasses(iRow);
1167 arrFieldValues = setInstrumenter.fieldValues(iRow);
1168 // Get object ID and class name
1169 String strObjID = setInstrumenter.fieldObjectID(iRow);
1170 strObjClassName = setInstrumenter.fieldEntryType(strObjID);
1171 // Call the method to create an object
1172 instrumentObject(strObjID, strLanguage);
1173 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1174 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
1175 commHan.getRMIStubPort(strObjName));
1181 * A private method to instrument IoTRelation
1183 * @params Map.Entry<String,Object> Entry of map IoTRelation instrumentation
1184 * @params strFieldName String field name
1185 * @params strLanguage String language
1188 private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName, String strLanguage)
1189 throws IOException, ClassNotFoundException, InterruptedException {
1191 // Get information from the set
1192 RelationInstrumenter relationInstrumenter = (RelationInstrumenter) map.getValue();
1193 int iRows = relationInstrumenter.numberOfRows();
1194 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTRELATION);
1196 for(int iRow=0; iRow<iRows; iRow++) {
1197 // Operate on the first set first
1198 arrFieldClasses = relationInstrumenter.firstFieldClasses(iRow);
1199 arrFieldValues = relationInstrumenter.firstFieldValues(iRow);
1200 String strObjID = relationInstrumenter.firstFieldObjectID(iRow);
1201 strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID);
1202 // Call the method to create an object
1203 instrumentObject(strObjID, strLanguage);
1204 // Get the first object controller host address
1205 String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1206 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1207 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1208 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
1209 // Operate on the second set
1210 arrFieldClasses = relationInstrumenter.secondFieldClasses(iRow);
1211 arrFieldValues = relationInstrumenter.secondFieldValues(iRow);
1212 strObjID = relationInstrumenter.secondFieldObjectID(iRow);
1213 strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID);
1214 // Call the method to create an object
1215 instrumentObject(strObjID, strLanguage);
1216 // Get the second object controller host address
1217 String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1218 objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1219 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1220 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
1221 // ROUTING POLICY: first and second controller objects in IoTRelation
1222 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd,
1223 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1224 // ROUTING POLICY: Send the same routing policy to both the hosts
1225 routerConfig.configureHostMainPolicies(strFirstIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1226 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1227 routerConfig.configureHostMainPolicies(strSecondIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1228 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1233 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1235 * @params inStream ObjectInputStream communication
1236 * @params outStream ObjectOutputStream communication
1239 private void initializeSetsAndRelationsJava(InputStream inStream, OutputStream outStream)
1240 throws IOException, ClassNotFoundException {
1241 // Get list of fields
1242 List<String> strFields = objInitHand.getListOfFields();
1243 // Iterate on HostAddress
1244 for(String str : strFields) {
1245 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1246 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1247 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1248 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, str);
1249 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet!", inStream, outStream);
1250 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1251 for (ObjectInitInfo objInitInfo : listObject) {
1252 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1253 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(),
1254 objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(),
1255 objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
1256 "Get IoTSet object!", inStream, outStream);
1259 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1260 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
1261 "Renitialize IoTSet field!", inStream, outStream);
1262 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1263 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1264 Message msgCrtIoTRel = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTRELATION, str);
1265 commMasterToSlave(msgCrtIoTRel, "Create new IoTRelation!", inStream, outStream);
1266 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1267 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1268 Iterator it = listSecondObject.iterator();
1269 for (ObjectInitInfo objInitInfo : listObject) {
1270 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1271 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT,
1272 objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(),
1273 objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1274 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
1275 "Get IoTRelation first object!", inStream, outStream);
1276 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1277 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1278 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT,
1279 objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(),
1280 objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1281 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort()),
1282 "Get IoTRelation second object!", inStream, outStream);
1284 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1285 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD),
1286 "Renitialize IoTRelation field!", inStream, outStream);
1292 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1294 * @params inStream ObjectInputStream communication
1295 * @params outStream ObjectOutputStream communication
1298 private void initializeSetsAndRelationsCpp(InputStream inStream, OutputStream outStream)
1299 throws IOException, ClassNotFoundException {
1300 // Get list of fields
1301 List<String> strFields = objInitHand.getListOfFields();
1302 // Iterate on HostAddress
1303 for(String str : strFields) {
1304 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1305 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1306 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1307 createNewIoTSetCpp(str, outStream, inStream);
1308 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1309 for (ObjectInitInfo objInitInfo : listObject) {
1310 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1311 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(),
1312 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1313 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
1315 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1316 reinitializeIoTSetFieldCpp(outStream, inStream);
1317 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1318 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1319 // TODO: createNewIoTRelation needs to be created here!
1320 createNewIoTRelationCpp(str, outStream, inStream);
1321 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1322 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1323 Iterator it = listSecondObject.iterator();
1324 for (ObjectInitInfo objInitInfo : listObject) {
1325 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1326 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(),
1327 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1328 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
1329 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1330 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1331 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT, objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(),
1332 objSecObj.getObjectClassName(), objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1333 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), outStream, inStream);
1335 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1336 reinitializeIoTRelationFieldCpp(outStream, inStream);
1342 * A method to set router basic policies at once
1344 * @param strRouter String router name
1347 private void setRouterBasicPolicies(String strRouter) {
1349 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1350 routerConfig.configureRouterICMPPolicies(strRouter, strMonitorHost);
1351 routerConfig.configureRouterDHCPPolicies(strRouter);
1352 routerConfig.configureRouterDNSPolicies(strRouter);
1353 routerConfig.configureRouterSSHPolicies(strRouter, strMonitorHost);
1354 routerConfig.configureRejectPolicies(strRouter);
1358 * A method to set host basic policies at once
1360 * @param strHost String host name
1363 private void setHostBasicPolicies(String strHost) {
1365 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1366 routerConfig.configureHostDHCPPolicies(strHost);
1367 routerConfig.configureHostDNSPolicies(strHost);
1368 if (strHost.equals(strMonitorHost)) {
1369 // Check if this is the monitoring host
1370 routerConfig.configureHostICMPPolicies(strHost);
1371 routerConfig.configureHostSSHPolicies(strHost);
1373 routerConfig.configureHostICMPPolicies(strHost, strMonitorHost);
1374 routerConfig.configureHostSSHPolicies(strHost, strMonitorHost);
1376 // Apply SQL allowance policies to master host
1377 if (strHost.equals(strIoTMasterHostAdd)) {
1378 routerConfig.configureHostSQLPolicies(strHost);
1380 routerConfig.configureRejectPolicies(strHost);
1384 * A method to create a thread for policy deployment
1386 * @param strRouterAddress String router address to configure
1387 * @param setHostAddresses Set of strings for host addresses to configure
1390 private void createPolicyThreads(String strRouterAddress, Set<String> setHostAddresses) throws IOException {
1392 // Create a list of threads
1393 List<Thread> threads = new ArrayList<Thread>();
1394 // Start threads for hosts
1395 for(String strAddress : setHostAddresses) {
1396 Thread policyThread = new Thread(new Runnable() {
1398 synchronized(this) {
1399 routerConfig.sendHostPolicies(strAddress);
1403 threads.add(policyThread);
1404 policyThread.start();
1405 RuntimeOutput.print("Deploying policies for: " + strAddress, BOOL_VERBOSE);
1407 // A thread for router
1408 Thread policyThread = new Thread(new Runnable() {
1410 synchronized(this) {
1411 routerConfig.sendRouterPolicies(strRouterAddress);
1415 threads.add(policyThread);
1416 policyThread.start();
1417 RuntimeOutput.print("Deploying policies on router: " + strRouterAddress, BOOL_VERBOSE);
1419 for (Thread thread : threads) {
1422 } catch (InterruptedException ex) {
1423 ex.printStackTrace();
1430 * A method to send files to Java IoTSlave
1432 * @params strObjControllerName String
1433 * @params serverSocket ServerSocket
1434 * @params inStream ObjectInputStream communication
1435 * @params outStream ObjectOutputStream communication
1438 private void sendFileToJavaSlave(String strObjControllerName, ServerSocket serverSocket,
1439 InputStream _inStream, OutputStream _outStream) throws IOException, ClassNotFoundException {
1441 ObjectInputStream inStream = (ObjectInputStream) _inStream;
1442 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
1444 String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT;
1445 String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1446 strControllerJarName;
1447 File file = new File(strControllerJarNamePath);
1448 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()),
1449 "Sending file!", inStream, outStream);
1450 // Send file - Class file for object creation
1451 sendFile(serverSocket.accept(), strControllerJarNamePath, file.length());
1452 Message msgReply = (Message) inStream.readObject();
1453 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1454 // Send .zip file if additional zip file is specified
1455 String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT;
1456 String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile;
1457 String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG);
1458 if (strAdditionalFile.equals(STR_YES)) {
1459 String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT;
1460 String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1461 strControllerCmpName;
1462 file = new File(strControllerCmpNamePath);
1463 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()),
1464 "Sending file!", inStream, outStream);
1465 // Send file - Class file for object creation
1466 sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length());
1467 msgReply = (Message) inStream.readObject();
1468 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1474 * A method to send files to C++ IoTSlave
1477 * TODO: Need to look into this (as of now, file transferred retains the "data" format,
1478 * hence it is unreadable from outside world
1480 private void sendFileToCppSlave(String sFilePath, String sFileName, Socket fileSocket,
1481 InputStream inStream, OutputStream outStream) throws IOException {
1483 sendCommCode(IoTCommCode.TRANSFER_FILE, outStream, inStream);
1485 sendString(sFileName, outStream); recvAck(inStream);
1486 File file = new File(sFilePath + sFileName);
1487 int iFileLen = toIntExact(file.length());
1488 RuntimeOutput.print("IoTMaster: Sending file " + sFileName + " with length " + iFileLen + " bytes...", BOOL_VERBOSE);
1490 sendInteger(iFileLen, outStream); recvAck(inStream);
1491 RuntimeOutput.print("IoTMaster: Sent file size!", BOOL_VERBOSE);
1492 byte[] bytFile = new byte[iFileLen];
1493 InputStream inFileStream = new FileInputStream(file);
1494 RuntimeOutput.print("IoTMaster: Opened file!", BOOL_VERBOSE);
1496 OutputStream outFileStream = fileSocket.getOutputStream();
1497 RuntimeOutput.print("IoTMaster: Got output stream!", BOOL_VERBOSE);
1499 while ((iCount = inFileStream.read(bytFile)) > 0) {
1500 outFileStream.write(bytFile, 0, iCount);
1502 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
1508 * A method to send files to C++ IoTSlave (now master using Process() to start
1509 * file transfer using scp)
1513 private void sendFileToCppSlave(String sFilePath, String sFileName) throws IOException {
1515 // Construct shell command to transfer file
1516 String sFile = sFilePath + sFileName;
1517 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_SLAVE_DIR;
1518 runCommand(strCmdSend);
1519 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
1521 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1522 STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
1523 runCommand(strCmdUnzip);
1524 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
1529 * runCommand() method runs shell command
1531 * @param strCommand String that contains command line
1534 private void runCommand(String strCommand) {
1537 Runtime runtime = Runtime.getRuntime();
1538 Process process = runtime.exec(strCommand);
1540 } catch (IOException ex) {
1541 System.out.println("RouterConfig: IOException: " + ex.getMessage());
1542 ex.printStackTrace();
1543 } catch (InterruptedException ex) {
1544 System.out.println("RouterConfig: InterruptException: " + ex.getMessage());
1545 ex.printStackTrace();
1551 * Construct command line for Java IoTSlave
1555 /*private String getCmdJavaIoTSlave(String strObjControllerName) {
1557 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1558 STR_RUNTIME_DIR + " sudo java " + STR_JVM_INIT_HEAP_SIZE + " " +
1559 STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " +
1560 STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
1561 commHan.getComPort(strObjControllerName) + " " +
1562 commHan.getRMIRegPort(strObjControllerName) + " " +
1563 commHan.getRMIStubPort(strObjControllerName) + " >& " +
1564 STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1566 private String getCmdJavaIoTSlave(String strObjControllerName) {
1568 // Create an Shell executable
1569 String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_JVM_INIT_HEAP_SIZE + " " +
1570 STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " +
1571 strIoTMasterHostAdd + " " + commHan.getComPort(strObjControllerName) + " " +
1572 commHan.getRMIRegPort(strObjControllerName) + " " + commHan.getRMIStubPort(strObjControllerName) +
1573 " > " + STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1574 String shellFile = "./" + strObjControllerName + STR_SHELL_FILE_EXT;
1575 createWrapperShellScript(strJavaCommand, shellFile);
1576 // Send the file to the compute node
1577 String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_RUNTIME_DIR;
1578 runCommand(strCmdSend);
1579 System.out.println("IoTMaster: Sending main controller shell file: " + strCmdSend);
1580 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile;
1585 * Construct command line for C++ IoTSlave
1589 private String getCmdCppIoTSlave(String strObjControllerName) {
1591 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1592 STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
1593 commHan.getComPort(strObjControllerName) + " " + strObjControllerName;
1598 * sendInteger() sends an integer in bytes
1600 public void sendInteger(int intSend, OutputStream outStream) throws IOException {
1602 BufferedOutputStream output = (BufferedOutputStream) outStream;
1603 // Transform integer into bytes
1604 ByteBuffer bb = ByteBuffer.allocate(INT_SIZE);
1606 // Send the byte array
1607 output.write(bb.array(), 0, INT_SIZE);
1613 * recvInteger() receives integer in bytes
1615 public int recvInteger(InputStream inStream) throws IOException {
1617 BufferedInputStream input = (BufferedInputStream) inStream;
1618 // Wait until input is available
1619 while(input.available() == 0);
1620 // Read integer - 4 bytes
1621 byte[] recvInt = new byte[INT_SIZE];
1622 input.read(recvInt, 0, INT_SIZE);
1623 int retVal = ByteBuffer.wrap(recvInt).getInt();
1630 * recvString() receives String in bytes
1632 public String recvString(InputStream inStream) throws IOException {
1634 BufferedInputStream input = (BufferedInputStream) inStream;
1635 int strLen = recvInteger(inStream);
1636 // Wait until input is available
1637 while(input.available() == 0);
1638 // Read String per strLen
1639 byte[] recvStr = new byte[strLen];
1640 input.read(recvStr, 0, strLen);
1641 String retVal = new String(recvStr);
1648 * sendString() sends a String in bytes
1650 public void sendString(String strSend, OutputStream outStream) throws IOException {
1652 BufferedOutputStream output = (BufferedOutputStream) outStream;
1653 // Transform String into bytes
1654 byte[] strSendBytes = strSend.getBytes();
1655 int strLen = strSend.length();
1656 // Send the string length first
1657 sendInteger(strLen, outStream);
1658 // Send the byte array
1659 output.write(strSendBytes, 0, strLen);
1665 * Convert integer to enum
1667 public IoTCommCode getCode(int intCode) throws IOException {
1669 IoTCommCode[] commCode = IoTCommCode.values();
1670 IoTCommCode retCode = commCode[intCode];
1679 public synchronized boolean recvAck(InputStream inStream) throws IOException {
1681 int intAck = recvInteger(inStream);
1682 IoTCommCode codeAck = getCode(intAck);
1683 if (codeAck == IoTCommCode.ACKNOWLEDGED)
1693 public void sendEndTransfer(OutputStream outStream) throws IOException {
1695 int endCode = IoTCommCode.END_TRANSFER.ordinal();
1696 sendInteger(endCode, outStream);
1701 * Send communication code to C++
1703 public void sendCommCode(IoTCommCode inpCommCode, OutputStream outStream, InputStream inStream) throws IOException {
1706 IoTCommCode commCode = inpCommCode;
1707 int intCode = commCode.ordinal();
1708 // TODO: delete this later
1709 System.out.println("DEBUG: Sending " + commCode + " with ordinal: " + intCode);
1710 sendInteger(intCode, outStream); recvAck(inStream);
1715 * Create a main controller object for C++
1717 public void createMainObjectCpp(String strObjControllerName, OutputStream outStream, InputStream inStream) throws IOException {
1719 sendCommCode(IoTCommCode.CREATE_MAIN_OBJECT, outStream, inStream);
1720 String strMainObjName = strObjControllerName;
1721 sendString(strMainObjName, outStream); recvAck(inStream);
1722 RuntimeOutput.print("IoTMaster: Create a main object: " + strMainObjName, BOOL_VERBOSE);
1727 * A helper function that converts Class into String
1729 * @param strDataType String MySQL data type
1732 public String getClassConverted(Class<?> cls) {
1734 if (cls == String.class) {
1736 } else if (cls == int.class) {
1745 * A helper function that converts Object into String for transfer to C++ slave
1747 * @param obj Object to be converted
1748 * @param strClassType String Java Class type
1751 public String getObjectConverted(Object obj) {
1753 if (obj instanceof String) {
1754 return (String) obj;
1755 } else if (obj instanceof Integer) {
1756 return Integer.toString((Integer) obj);
1764 * Create a driver object for C++
1766 public void createObjectCpp(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strIoTSlaveObjectHostAdd,
1767 Integer iRMIRegistryPort, Integer iRMIStubPort, Object[] arrFieldValues, Class[] arrFieldClasses,
1768 OutputStream outStream, InputStream inStream) throws IOException {
1770 sendCommCode(IoTCommCode.CREATE_OBJECT, outStream, inStream);
1771 RuntimeOutput.print("IoTMaster: Send request to create a driver object... ", BOOL_VERBOSE);
1772 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjName, BOOL_VERBOSE);
1773 sendString(strObjName, outStream); recvAck(inStream);
1774 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjClassName, BOOL_VERBOSE);
1775 sendString(strObjClassName, outStream); recvAck(inStream);
1776 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjClassInterfaceName, BOOL_VERBOSE);
1777 sendString(strObjStubClsIntfaceName, outStream); recvAck(inStream);
1778 RuntimeOutput.print("IoTMaster: Driver object skeleton class name: " + strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
1779 sendString(strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, outStream); recvAck(inStream);
1780 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1781 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1782 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1783 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1784 int numOfArgs = arrFieldValues.length;
1785 RuntimeOutput.print("IoTMaster: Send constructor arguments! Number of arguments: " + numOfArgs, BOOL_VERBOSE);
1786 sendInteger(numOfArgs, outStream); recvAck(inStream);
1787 for(Object obj : arrFieldValues) {
1788 String str = getObjectConverted(obj);
1789 sendString(str, outStream); recvAck(inStream);
1791 RuntimeOutput.print("IoTMaster: Send constructor argument classes!", BOOL_VERBOSE);
1792 for(Class cls : arrFieldClasses) {
1793 String str = getClassConverted(cls);
1794 sendString(str, outStream); recvAck(inStream);
1800 * Create new IoTSet for C++
1802 public void createNewIoTSetCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1804 sendCommCode(IoTCommCode.CREATE_NEW_IOTSET, outStream, inStream);
1805 RuntimeOutput.print("IoTMaster: Creating new IoTSet...", BOOL_VERBOSE);
1806 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1807 sendString(strObjFieldName, outStream); recvAck(inStream);
1812 * Create new IoTRelation for C++
1814 public void createNewIoTRelationCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1816 sendCommCode(IoTCommCode.CREATE_NEW_IOTRELATION, outStream, inStream);
1817 RuntimeOutput.print("IoTMaster: Creating new IoTRelation...", BOOL_VERBOSE);
1818 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1819 sendString(strObjFieldName, outStream); recvAck(inStream);
1824 * Get a IoTDeviceAddress object for C++
1826 public void getDeviceIoTSetObjectCpp(OutputStream outStream, InputStream inStream,
1827 String strDeviceAddress, int iSourcePort, int iDestPort, boolean bSourceWildCard, boolean bDestWildCard) throws IOException {
1829 sendCommCode(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, outStream, inStream);
1830 RuntimeOutput.print("IoTMaster: Getting IoTDeviceAddress...", BOOL_VERBOSE);
1831 sendString(strDeviceAddress, outStream); recvAck(inStream);
1832 sendInteger(iSourcePort, outStream); recvAck(inStream);
1833 sendInteger(iDestPort, outStream); recvAck(inStream);
1834 int iSourceWildCard = (bSourceWildCard ? 1 : 0);
1835 sendInteger(iSourceWildCard, outStream); recvAck(inStream);
1836 int iDestWildCard = (bDestWildCard ? 1 : 0);
1837 sendInteger(iDestWildCard, outStream); recvAck(inStream);
1838 RuntimeOutput.print("IoTMaster: Send device address: " + strDeviceAddress, BOOL_VERBOSE);
1843 * Get a IoTSet content object for C++
1845 public void getIoTSetRelationObjectCpp(IoTCommCode iotCommCode, String strIoTSlaveHostAddress, String strObjectName, String strObjectClassName,
1846 String strObjectClassInterfaceName, String strObjectStubClassInterfaceName, int iRMIRegistryPort, int iRMIStubPort,
1847 OutputStream outStream, InputStream inStream) throws IOException {
1849 sendCommCode(iotCommCode, outStream, inStream);
1850 RuntimeOutput.print("IoTMaster: Getting IoTSet object content...", BOOL_VERBOSE);
1852 RuntimeOutput.print("IoTMaster: Send host address: " + strIoTSlaveHostAddress, BOOL_VERBOSE);
1853 sendString(strIoTSlaveHostAddress, outStream); recvAck(inStream);
1854 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjectName, BOOL_VERBOSE);
1855 sendString(strObjectName, outStream); recvAck(inStream);
1856 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjectClassName, BOOL_VERBOSE);
1857 sendString(strObjectClassName, outStream); recvAck(inStream);
1858 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjectClassInterfaceName, BOOL_VERBOSE);
1859 sendString(strObjectClassInterfaceName, outStream); recvAck(inStream);
1860 RuntimeOutput.print("IoTMaster: Driver object stub class name: " + strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
1861 sendString(strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, outStream); recvAck(inStream);
1862 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1863 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1864 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1865 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1870 * Reinitialize IoTRelation field for C++
1872 private void reinitializeIoTRelationFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1874 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTRelation field!", BOOL_VERBOSE);
1875 sendCommCode(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD, outStream, inStream);
1876 RuntimeOutput.print("IoTMaster: Reinitialize IoTRelation field!", BOOL_VERBOSE);
1881 * Reinitialize IoTSet field for C++
1883 private void reinitializeIoTSetFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1885 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTSet field!", BOOL_VERBOSE);
1886 sendCommCode(IoTCommCode.REINITIALIZE_IOTSET_FIELD, outStream, inStream);
1887 RuntimeOutput.print("IoTMaster: Reinitialize IoTSet field!", BOOL_VERBOSE);
1892 * Create driver object for C++
1894 private void createDriverObjectCpp(OutputStream outStream, InputStream inStream) throws IOException {
1896 sendCommCode(IoTCommCode.CREATE_DRIVER_OBJECT, outStream, inStream);
1897 RuntimeOutput.print("IoTMaster: Send command to create driver object!", BOOL_VERBOSE);
1902 * Invoke init() for C++
1904 private void invokeInitMethodCpp(OutputStream outStream, InputStream inStream) throws IOException {
1906 sendCommCode(IoTCommCode.INVOKE_INIT_METHOD, outStream, inStream);
1907 RuntimeOutput.print("IoTMaster: Invoke init method!", BOOL_VERBOSE);
1912 * End session for C++
1914 public void endSessionCpp(OutputStream outStream) throws IOException {
1916 // Send message to end session
1917 IoTCommCode endSessionCode = IoTCommCode.END_SESSION;
1918 int intCode = endSessionCode.ordinal();
1919 sendInteger(intCode, outStream);
1920 //RuntimeOutput.print("IoTMaster: Send request to create a main object: " + strObjName, BOOL_VERBOSE);
1921 RuntimeOutput.print("IoTMaster: Send request to end session!", BOOL_VERBOSE);
1926 * A method to assign objects to multiple JVMs, including
1927 * the controller/device object that uses other objects
1928 * in IoTSet and IoTRelation
1932 private void createObjects() {
1939 // Extract hostname for this IoTMaster from MySQL DB
1940 strIoTMasterHostAdd = routerConfig.getIPFromMACAddress(STR_MASTER_MAC_ADD);
1941 // Loop as we can still find controller/device classes
1942 for(int i=0; i<strObjectNames.length; i++) {
1944 start = System.currentTimeMillis();
1946 // Assign a new list of PrintWriter objects
1947 routerConfig.renewPrintWriter();
1948 // Get controller names one by one
1949 String strObjControllerName = strObjectNames[i];
1950 // Use LoadBalancer to assign a host address
1951 //strIoTSlaveControllerHostAdd = lbIoT.selectHost();
1952 strIoTSlaveControllerHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
1953 if (strIoTSlaveControllerHostAdd == null)
1954 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
1955 // == START INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1956 // Add port connection and get port numbers
1957 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
1958 commHan.addPortConnection(strIoTSlaveControllerHostAdd, strObjControllerName);
1959 // ROUTING POLICY: IoTMaster and main controller object
1960 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
1961 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1962 // ROUTING POLICY: Send the same routing policy to both the hosts
1963 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
1964 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1965 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd,
1966 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1968 String strControllerCfg = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
1969 STR_LANGUAGE_CONTROLLER = parseConfigFile(strControllerCfg, STR_LANGUAGE);
1970 if(STR_LANGUAGE_CONTROLLER == null)
1971 throw new Error("IoTMaster: Language specification missing in config file: " + strControllerCfg);
1972 // Construct ssh command line and create a controller thread for e.g. AcmeProximity
1973 String strSSHCommand = null;
1974 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
1975 strSSHCommand = getCmdJavaIoTSlave(strObjControllerName);
1976 else if(STR_LANGUAGE_CONTROLLER.equals(STR_CPP))
1977 strSSHCommand = getCmdCppIoTSlave(strObjControllerName);
1979 throw new Error("IoTMaster: Language specification not recognized: " + STR_LANGUAGE_CONTROLLER);
1980 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
1981 createThread(strSSHCommand);
1982 // Wait for connection
1983 // Create a new socket for communication
1984 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjControllerName));
1985 Socket socket = serverSocket.accept();
1986 InputStream inStream = null;
1987 OutputStream outStream = null;
1988 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
1989 inStream = new ObjectInputStream(socket.getInputStream());
1990 outStream = new ObjectOutputStream(socket.getOutputStream());
1991 } else { // At this point the language is certainly C++, otherwise would've complained above
1992 inStream = new BufferedInputStream(socket.getInputStream());
1993 outStream = new BufferedOutputStream(socket.getOutputStream());
1996 RuntimeOutput.print("IoTMaster: Communication established!", BOOL_VERBOSE);
1999 result = System.currentTimeMillis()-start;
2000 System.out.println("\n\n ==> From start until after SSH for main controller: " + result);
2002 start = System.currentTimeMillis();
2004 // Send files for every controller class
2005 // e.g. AcmeProximity.jar and AcmeProximity.zip
2006 String strControllerClassName = strObjControllerName + STR_CLS_FILE_EXT;
2007 String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" +
2008 strControllerClassName;
2010 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2011 sendFileToJavaSlave(strObjControllerName, serverSocket, inStream, outStream);
2012 // Create main controller/device object
2013 commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName),
2014 "Create main object!", inStream, outStream);
2016 String strControllerZipFile = strObjControllerName + STR_ZIP_FILE_EXT;
2017 String strControllerFilePath = STR_CONT_PATH + strObjControllerName + "/";
2018 sendFileToCppSlave(strControllerFilePath, strControllerZipFile);
2019 createMainObjectCpp(strObjControllerName, outStream, inStream);
2023 result = System.currentTimeMillis()-start;
2024 System.out.println("\n\n ==> From IoTSlave start until main controller object is created: " + result);
2025 System.out.println(" ==> Including file transfer times!\n\n");
2027 start = System.currentTimeMillis();
2029 // == END INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
2030 // Instrumenting one file
2031 RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE);
2032 RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE);
2033 HashMap<String,Object> hmControllerFieldObjects = null;
2034 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2035 FileInputStream fis = new FileInputStream(strControllerClassNamePath);
2036 ClassReader cr = new ClassReader(fis);
2037 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
2038 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE);
2041 hmControllerFieldObjects = crim.getFieldObjects();
2043 String strControllerConfigFile = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
2044 CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strControllerConfigFile, null, BOOL_VERBOSE);
2045 hmControllerFieldObjects = crim.getFieldObjects();
2047 // Get the object and the class names
2048 // Build objects for IoTSet and IoTRelation fields in the controller/device classes
2049 //HashMap<String,Object> hmControllerFieldObjects = crim.getFieldObjects();
2050 for(Map.Entry<String,Object> map : hmControllerFieldObjects.entrySet()) {
2051 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
2052 // Iterate over HashMap and choose between processing
2053 // SetInstrumenter vs. RelationInstrumenter
2054 String strFieldName = map.getKey();
2055 String strClassName = map.getValue().getClass().getName();
2056 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
2057 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
2058 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
2059 String strErrMsg = "IoTMaster: Controller object" +
2060 " cannot have IoTSet<IoTDeviceAddress>!";
2061 throw new Error(strErrMsg);
2062 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
2063 String strErrMsg = "IoTMaster: Controller object" +
2064 " cannot have IoTSet<ZigbeeAddress>!";
2065 throw new Error(strErrMsg);
2066 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
2067 // Instrument the IoTAddress
2068 setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd);
2069 instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream, STR_LANGUAGE_CONTROLLER);
2072 instrumentIoTSet(map, strFieldName, STR_LANGUAGE_CONTROLLER);
2074 } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) {
2075 instrumentIoTRelation(map, strFieldName, STR_LANGUAGE_CONTROLLER);
2079 result = System.currentTimeMillis()-start;
2080 System.out.println("\n\n ==> Time needed to instrument device driver objects: " + result + "\n\n");
2081 System.out.println(" ==> #Objects: " + commHan.getActiveControllerObjectList().size() + "\n\n");
2084 start = System.currentTimeMillis();
2086 // ROUTING POLICY: Deploy basic policies if this is the last controller
2087 if (i == strObjectNames.length-1) {
2088 // ROUTING POLICY: implement basic policies to reject all other irrelevant traffics
2089 for(String s: commHan.getHosts()) {
2090 setHostBasicPolicies(s);
2092 // We retain all the basic policies for router,
2093 // but we delete the initial allowance policies for internal all TCP and UDP communications
2094 setRouterBasicPolicies(STR_ROUTER_ADD);
2096 // Close access to policy files and deploy policies
2097 routerConfig.close();
2098 // Deploy the policy
2099 HashSet<String> setAddresses = new HashSet<String>(commHan.getHosts());
2100 setAddresses.add(strIoTMasterHostAdd);
2101 createPolicyThreads(STR_ROUTER_ADD, setAddresses);
2104 result = System.currentTimeMillis()-start;
2105 System.out.println("\n\n ==> Time needed to send policy files and deploy them : " + result + "\n\n");
2108 start = System.currentTimeMillis();
2110 // Separating object creations and Set/Relation initializations
2111 createDriverObjects();
2114 result = System.currentTimeMillis()-start;
2115 System.out.println("\n\n ==> Time needed to instantiate objects: " + result + "\n\n");
2117 start = System.currentTimeMillis();
2119 // Sets and relations initializations
2120 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2121 initializeSetsAndRelationsJava(inStream, outStream);
2123 initializeSetsAndRelationsCpp(inStream, outStream);;
2126 result = System.currentTimeMillis()-start;
2127 System.out.println("\n\n ==> Time needed to initialize sets and relations: " + result + "\n\n");
2129 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2130 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD
2131 commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD), "Invoke init() method!", inStream, outStream);
2133 invokeInitMethodCpp(outStream, inStream);
2134 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS
2135 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2136 ObjectOutputStream oStream = (ObjectOutputStream) outStream;
2137 oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
2138 } else // C++ side will wait until the program finishes, it's not generating a separate thread for now
2139 //endSessionCpp(outStream);
2143 serverSocket.close();
2144 commHan.printLists();
2145 lbIoT.printHostInfo();
2148 } catch (IOException |
2149 InterruptedException |
2150 ClassNotFoundException ex) {
2151 System.out.println("IoTMaster: Exception: "
2153 ex.printStackTrace();
2157 public static void main(String args[]) {
2159 // Detect the available controller/device classes
2160 // Input args[] should be used to list the controllers/devices
2161 // e.g. java IoTMaster AcmeProximity AcmeThermostat AcmeVentController
2162 IoTMaster iotMaster = new IoTMaster(args);
2164 iotMaster.parseIoTMasterConfigFile();
2165 // Initialize CommunicationHandler, LoadBalancer, and RouterConfig
2166 iotMaster.initLiveDataStructure();
2168 iotMaster.createObjects();