Applying changes for 3rd benchmark (wildcard addresses) in IoTMaster
[iot2.git] / iotjava / iotruntime / master / CommunicationHandler.java
1 package iotruntime.master;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Random;
9 import java.util.Set;
10
11 /** Class CommunicationHandler is a class that maintains
12  *  a data structure that preserves a collection of host name,
13  *  port numbers, and objects that are running
14  *  +-----------------+----+--------+------------------+--------------+----------------+
15  *  | HOST-ADDRESS    | ...|IN-PORT | RMIREGISTRY-PORT | RMISTUB-PORT | ACTIVE OBJECTS |
16  *  +-----------------+----+--------+------------------+--------------+----------------+
17  *  | XXX.XXX.XXX.XXX |    | XXXXX  | XXXXX            | XXXXX        | XXXXXXXXXXXXXX |
18  *  |                 |    | XXXXX  | XXXXX            | XXXXX        | XXXXXXXXXXXXXX |
19  *  |                 |    | XXXXX  | XXXXX            | XXXXX        | XXXXXXXXXXXXXX |
20  *  |                 | ...| ...    | ...              | ...          | ...            |
21  *  +-----------------+----+--------+------------------+--------------+----------------+
22  *  In this case we use ACTIVE OBJECTS names as the key
23  *  So ACTIVE OBJECTS maps to numbers and these numbers map to each other
24  *  entry in hashmaps (HostAddress can be repetitive)
25  *  e.g. ACTIVE OBJECTS ProximitySensorPS0 - 0
26  *                      ProximitySensorPS1 - 1
27  *                      TempSensorTS1      - 2
28  *                      ...
29  *       IN-PORT / RMIREGISTRY-PORT / RMISTUB-PORT / HOST-ADDRESS: 0 - XXXXX
30  *                                                                 1 - XXXXX
31  *                                                                 2 - XXXXX
32  *  +-------------+
33  *  | DEVICE-PORT |
34  *  +-------------+
35  *  | XXXXX       |
36  *  | XXXXX       |
37  *  | XXXXX       |
38  *  | ...         |
39  *  +-------------+
40  *  We add a Set structure to handle all the other ports that are used by devices
41  *  when communicating with their respective drivers
42  *
43  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
44  * @version     1.0
45  * @since       2016-01-07
46  */
47 public final class CommunicationHandler {
48
49         /**
50          * CommunicationHandler class properties
51          * <p>
52          * Random, host name, port number, active objects
53          * HostAdd is the key to the table so we use it
54          * as a key to elements
55          * HostList gives a mapping from hostname to list of objects
56          */
57         private Random random;
58         private List<String> listActiveControllerObj;
59         private List<String> listFieldObjectID;
60         private List<ObjectCreationInfo> listObjCrtInfo;
61         private List<Object[]> listArrFieldValues;
62         private List<Class[]> listArrFieldClasses;
63         private Map<String, Integer> hmActiveObj;
64         private Map<Integer, String> hmHostAdd;
65         private Map<String, ArrayList<String> > hmHostList;
66         private Map<Integer, Integer> hmComPort;
67         private Map<Integer, Integer> hmRMIRegPort;
68         private Map<Integer, Integer> hmRMIStubPort;
69         private Set<Integer> hsDevicePort;
70         private Set<Integer> hsCallbackPort;
71         private Map<Integer, Integer[]> hmCallbackPort;
72         private Map<Integer, Integer> hmAdditionalPort;
73         private int iNumOfObjects;
74         private int iNumOfHosts;
75         private boolean bVerbose;
76
77         /**
78          * CommunicationHandler class constants
79          */
80         private final int INT_MAX_PORT = 65535;
81         private final int INT_MIN_PORT = 10000;
82
83         /**
84          * Empty constructor
85          */
86         public CommunicationHandler(boolean _bVerbose) {
87
88                 random = new Random();
89                 listActiveControllerObj = new ArrayList<String>();
90                 listFieldObjectID = new ArrayList<String>();
91                 listObjCrtInfo = new ArrayList<ObjectCreationInfo>();
92                 listArrFieldValues = new ArrayList<Object[]>();
93                 listArrFieldClasses = new ArrayList<Class[]>();
94                 hmActiveObj = new HashMap<String, Integer>();
95                 hmHostAdd = new HashMap<Integer, String>();
96                 hmHostList = new HashMap<String, ArrayList<String>>();
97                 hmComPort = new HashMap<Integer, Integer>();
98                 hmRMIRegPort = new HashMap<Integer, Integer>();
99                 hmRMIStubPort = new HashMap<Integer, Integer>();
100                 hsDevicePort = new HashSet<Integer>();
101                 hsCallbackPort = new HashSet<Integer>();
102                 hmCallbackPort = new HashMap<Integer, Integer[]>();
103                 hmAdditionalPort = new HashMap<Integer, Integer>();
104                 iNumOfObjects = 0;
105                 iNumOfHosts = 0;
106                 bVerbose = _bVerbose;
107                 RuntimeOutput.print("CommunicationHandler: Creating a new CommunicationHandler object!", bVerbose);
108         }
109
110         /**
111          * Method addPortConnection()
112          * <p>
113          * Add a new connection then generate new in-port and out-port numbers
114          *
115          * @param   sHAddress                   String host address
116          * @param   sAObject                    String active object name
117          * @return  void
118          */
119         public void addPortConnection(String sHAddress, String sAObject) {
120
121                 // Increment counter first before we add objects as we start from 0
122                 // Objects are named uniquely so we record this and match with the host
123                 // Hostname occurrence can be repetitive as there can be more than
124                 // one host on one compute node
125
126                 // Add a new object in the list of objects
127                 hmActiveObj.put(sAObject, iNumOfObjects);
128
129                 // Check host existence in our data structure
130                 // Add a new host and a new object
131                 if(hmHostList.containsKey(sHAddress) == false) {
132                         iNumOfHosts++;
133                         hmHostList.put(sHAddress, new ArrayList<String>());
134                 }
135                 hmHostList.get(sHAddress).add(sAObject);
136
137                 // Map object to host
138                 hmHostAdd.put(iNumOfObjects, sHAddress);
139
140                 int iComPort = 0;
141                 do {
142                         iComPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
143                         // Check port existence in HashMap
144                 } while (portIsAvailable(iComPort) == false);
145                 hmComPort.put(iNumOfObjects, iComPort);
146
147                 int iRMIRegPort = 0;
148                 do {
149                         iRMIRegPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
150                         // Check port existence in HashMap
151                 } while (portIsAvailable(iRMIRegPort) == false);
152                 hmRMIRegPort.put(iNumOfObjects, iRMIRegPort);
153
154                 int iRMIStubPort = 0;
155                 do {
156                         iRMIStubPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
157                         // Check port existence in HashMap
158                 } while (portIsAvailable(iRMIStubPort) == false);
159                 hmRMIStubPort.put(iNumOfObjects, iRMIStubPort);
160
161                 iNumOfObjects++;
162         }
163
164         /**
165          * A private method to add a new active controller object
166          *
167          * @params  strFieldObjectID                    String field object ID
168          * @params  strObjName                                  String object name
169          * @params  strObjClassName                     String object class name
170          * @params  strObjClassInterfaceName    String object class interface name
171          * @params  strIoTSlaveObjectHostAdd    String IoTSlave host address
172          * @params  arrFieldValues                              Array of field values
173          * @params  arrFieldClasses                             Array of field classes
174          * @return  void
175          */
176         public void addActiveControllerObject(String strFieldObjectID, String strObjName, String strObjClassName,
177                 String strObjClassInterfaceName, String strObjStubClsIntfaceName, String strIoTSlaveObjectHostAdd, Object[] arrFieldValues, 
178                 Class[] arrFieldClasses) {
179
180                 listActiveControllerObj.add(strObjName);
181                 listFieldObjectID.add(strFieldObjectID);
182                 listArrFieldValues.add(arrFieldValues);
183                 listArrFieldClasses.add(arrFieldClasses);
184                 ObjectCreationInfo objCrtInfo = new ObjectCreationInfo(strIoTSlaveObjectHostAdd, strObjName,
185                         strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName);
186                 listObjCrtInfo.add(objCrtInfo);
187         }
188
189
190         /**
191          * Method getCallbackPort()
192          * <p>
193          * Get a new port for new connections for callback objects in the program.
194          * This newly generated port number will be recorded.
195          *
196          * @return  int[]       A set of callback ports
197          */
198         public int[] getCallbackPorts(int numOfPorts) {
199
200                 int[] ports = new int[numOfPorts];
201
202                 for(int i = 0; i < numOfPorts; i++) {
203                         do {
204                                 ports[i] = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
205                                 // Check port existence in HashMap
206                         } while (portIsAvailable(ports[i]) == false);
207                         hsCallbackPort.add(ports[i]);
208                 }
209
210                 return ports;
211         }
212
213
214         /**
215          * Method getCallbackPorts()
216          * <p>
217          * Get a set of new ports for new connections for callback objects in the program.
218          * This newly generated port number will be recorded.
219          *
220          * @return  int[]       A set of callback ports
221          */
222         public Integer[] getCallbackPorts(String sAObject, int numOfPorts) {
223
224                 Integer[] ports = new Integer[numOfPorts];
225                 int iNumOfObject = hmActiveObj.get(sAObject);
226
227                 if (!hmCallbackPort.containsKey(iNumOfObject)) {
228                         for(int i = 0; i < numOfPorts; i++) {
229                                 do {
230                                         ports[i] = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
231                                         // Check port existence in HashMap
232                                 } while (portIsAvailable(ports[i]) == false);
233                                 hsCallbackPort.add(ports[i]);
234                         }
235                         hmCallbackPort.put(iNumOfObject, ports);
236                 } else {
237                         ports = hmCallbackPort.get(iNumOfObject);
238                 }
239
240                 return ports;
241         }
242
243
244         /**
245          * Method addDevicePort()
246          * <p>
247          * Add a port that is used by a device when communicating with its driver
248          * This port will be taken into account when checking for port availability
249          *
250          * @param   iDevPort  Device port number
251          * @return  void
252          */
253         public void addDevicePort(int iDevPort) {
254
255                 hsDevicePort.add(iDevPort);
256
257         }
258
259         /**
260          * Method addAdditionalPort()
261          * <p>
262          * Add a new port for new connections for any objects in the program.
263          * This newly generated port number will be recorded.
264          *
265          * @return  int         One new port
266          */
267         public int addAdditionalPort(String sAObject) {
268
269                 hmActiveObj.put(sAObject, iNumOfObjects);
270
271                 int iAdditionalPort = 0;
272                 do {
273                         iAdditionalPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
274                         // Check port existence in HashMap
275                 } while (portIsAvailable(iAdditionalPort) == false);
276                 hmAdditionalPort.put(iNumOfObjects, iAdditionalPort);
277
278                 iNumOfObjects++;
279
280                 return iAdditionalPort;
281         }
282
283         /**
284          * Method portIsAvailable()
285          * <p>
286          * Checks the availability of the newly generated port.
287          * If port number has been used in any of the lists then
288          * it is not available
289          *
290          * @param   iPortNumber  Device port number
291          * @return  boolean
292          */
293         public boolean portIsAvailable(int iPortNumber) {
294
295                 if (hmComPort.containsValue(iPortNumber) == true) {
296                         return false;
297                 } else if (hmRMIRegPort.containsValue(iPortNumber) == true) {
298                         return false;
299                 } else if (hmRMIStubPort.containsValue(iPortNumber) == true) {
300                         return false;
301                 } else if (hmAdditionalPort.containsValue(iPortNumber) == true) {
302                         return false;
303                 } else if (hsDevicePort.contains(iPortNumber) == true) {
304                         return false;
305                 } else if (hsCallbackPort.contains(iPortNumber) == true) {
306                         return false;
307                 } else {
308                         return true;
309                 }
310         }
311
312         /**
313          * Method getNumOfObjects()
314          *
315          * @return  int
316          */
317         public int getNumOfObjects() {
318
319                 return iNumOfObjects;
320
321         }
322
323         /**
324          * Method getNumOfHosts()
325          *
326          * @return  int
327          */
328         public int getNumOfHosts() {
329
330                 return iNumOfHosts;
331
332         }
333
334         /**
335          * Method objectExists()
336          *
337          * @param   sObjName  String object name
338          * @return  boolean
339          */
340         public boolean objectExists(String sObjName) {
341
342                 return hmActiveObj.containsKey(sObjName);
343
344         }
345
346         /**
347          * Method hostExists()
348          *
349          * @param   sHostName  String host name
350          * @return  boolean
351          */
352         public boolean hostExists(String sHostName) {
353
354                 return hmHostList.containsKey(sHostName);
355
356         }
357
358         /**
359          * Method getHostAddress()
360          * <p>
361          * User finds HostAddress using Object name
362          *
363          * @param   sAObject  String active object name
364          * @return  String
365          */
366         public String getHostAddress(String sAObject) {
367
368                 return hmHostAdd.get(hmActiveObj.get(sAObject));
369
370         }
371
372         /**
373          * Method getHosts()
374          * <p>
375          * User gets the set of hostnames
376          *
377          * @return  String
378          */
379         public Set<String> getHosts() {
380
381                 return hmHostList.keySet();
382
383         }
384
385         /**
386          * Method getComPort()
387          * <p>
388          * User finds In-Port number using Object name
389          *
390          * @param   sAObject  String active object name
391          * @return  Integer
392          */
393         public Integer getComPort(String sAObject) {
394
395                 return hmComPort.get(hmActiveObj.get(sAObject));
396         }
397
398         /**
399          * Method getAdditionalPort()
400          * <p>
401          * User finds a port number using Object name
402          *
403          * @param   sAObject  String active object name
404          * @return  Integer
405          */
406         public Integer getAdditionalPort(String sAObject) {
407
408                 return hmAdditionalPort.get(hmActiveObj.get(sAObject));
409         }
410
411         /**
412          * Method getRMIRegPort()
413          * <p>
414          * User finds Out-Port number using Object name
415          *
416          * @param   sAObject  String active object name
417          * @return  Integer
418          */
419         public Integer getRMIRegPort(String sAObject) {
420
421                 return hmRMIRegPort.get(hmActiveObj.get(sAObject));
422
423         }
424
425         /**
426          * Method getRMIStubPort()
427          * <p>
428          * User finds Out-Port number using Object name
429          *
430          * @param   sAObject  String active object name
431          * @return  Integer
432          */
433         public Integer getRMIStubPort(String sAObject) {
434
435                 return hmRMIStubPort.get(hmActiveObj.get(sAObject));
436
437         }
438
439         /**
440          * Method getFieldObjectID()
441          * <p>
442          * User finds field object ID using Object name
443          *
444          * @param   sAObject  String active object name
445          * @return  String
446          */
447         public String getFieldObjectID(String sAObject) {
448
449                 return listFieldObjectID.get(listActiveControllerObj.indexOf(sAObject));
450
451         }
452
453         /**
454          * Method getObjectCreationInfo()
455          * <p>
456          * User finds ObjectCreationInfo using Object name
457          *
458          * @param   sAObject  String active object name
459          * @return  ObjectCreationInfo
460          */
461         public ObjectCreationInfo getObjectCreationInfo(String sAObject) {
462
463                 return listObjCrtInfo.get(listActiveControllerObj.indexOf(sAObject));
464
465         }
466
467         /**
468          * Method getArrayFieldClasses()
469          * <p>
470          * User finds array of field classes using Object name
471          *
472          * @param   sAObject  String active object name
473          * @return  Class[]
474          */
475         public Class[] getArrayFieldClasses(String sAObject) {
476
477                 return listArrFieldClasses.get(listActiveControllerObj.indexOf(sAObject));
478
479         }
480
481         /**
482          * Method getArrayFieldValues()
483          * <p>
484          * User finds array of field values using Object name
485          *
486          * @param   sAObject  String active object name
487          * @return  Object[]
488          */
489         public Object[] getArrayFieldValues(String sAObject) {
490
491                 return listArrFieldValues.get(listActiveControllerObj.indexOf(sAObject));
492
493         }
494
495         /**
496          * Method getActiveControllerObjectList()
497          *
498          * @return  List<String>
499          */
500         public List<String> getActiveControllerObjectList() {
501
502                 return listActiveControllerObj;
503
504         }
505
506         /**
507          * Method printLists()
508          *
509          * @return  void
510          */
511         public void printLists() {
512
513                 // Iterate on HostAddress
514                 for(String s : hmHostList.keySet()) {
515
516                         for(String str : hmHostList.get(s)) {
517
518                                 int iIndex = hmActiveObj.get(str);
519                                 RuntimeOutput.print("Active Object: " + str, bVerbose);
520                                 RuntimeOutput.print("Communication Port: " + hmComPort.get(iIndex), bVerbose);
521                                 RuntimeOutput.print("RMI Registry Port: " + hmRMIRegPort.get(iIndex), bVerbose);
522                                 RuntimeOutput.print("RMI Stub Port: " + hmRMIStubPort.get(iIndex), bVerbose);
523                                 RuntimeOutput.print("\n", bVerbose);
524                         }
525                 }
526                 for(Integer i : hsCallbackPort)
527                         RuntimeOutput.print("RMI callback Port: " + i, bVerbose);
528                 RuntimeOutput.print("\n", bVerbose);
529
530                 for(int iPort : hsDevicePort) {
531                         RuntimeOutput.print("Device Port: " + iPort, bVerbose);
532                 }
533                 RuntimeOutput.print("\n", bVerbose);
534         }
535 }