Perfecting IoTSlave for C++; Found one issue with SSH/Java process execution in which...
[iot2.git] / iotjava / iotruntime / cpp / iotslave / IoTSlave.cpp
index d950a0362f6a7503b0c525e39e83c825286a7374..2761fb1d8c63891f2085df7f657f3763dd0baa3f 100644 (file)
@@ -3,8 +3,11 @@
 
 #include "IoTSlave.hpp"
 
+#include "Lifxtest.cpp"
+
 IoTSlave::IoTSlave(string _serverAddress, int _serverPort, string _objectName) {
 
+       isDriverObject = false;         // Default to false
        serverAddress = _serverAddress;
        serverPort = _serverPort;
        objectName = _objectName;
@@ -20,6 +23,18 @@ IoTSlave::~IoTSlave() {
                delete socket;
                socket = NULL;
        }
+       /*if (objMainCls != NULL) {
+               delete objMainCls;
+               objMainCls = NULL;
+       }
+       if (objSkelCls != NULL) {
+               delete objSkelCls;
+               objSkelCls = NULL;
+       }*/
+       for (IoTSet<void*>* iotset : vecIoTSet) {
+               delete iotset;
+               iotset = NULL;
+       }
        closeFile();
 }
 
@@ -99,7 +114,7 @@ void IoTSlave::closeFile() {
 }
 
 
-void IoTSlave::instantiateObject(string objectClassName) {
+void IoTSlave::getObjectHandler(string objectClassName) {
 
        // Object handling
        string strObj = FILEPATH + objectClassName + SOEXT;
@@ -111,7 +126,8 @@ void IoTSlave::instantiateObject(string objectClassName) {
        }
        writeToFile("Object handled!");
        // Create handler
-       create_object = (create_t*) dlsym(handle, CREATEFUNCTION.c_str());
+       string createFunction = CREATEFUNCTION + objectClassName;
+       create_object = (create_t*) dlsym(handle, createFunction.c_str());
        const char* dlsym_error = dlerror();
     if (dlsym_error) {
         cerr << "Cannot load symbol create: " << dlsym_error << '\n';
@@ -120,7 +136,8 @@ void IoTSlave::instantiateObject(string objectClassName) {
     }
        writeToFile("Object factory created for " + objectClassName);
        // Destroy handler
-    destroy_object = (destroy_t*) dlsym(handle, DESTROYFUNCTION.c_str());
+       string destroyFunction = DESTROYFUNCTION + objectClassName;
+    destroy_object = (destroy_t*) dlsym(handle, destroyFunction.c_str());
     dlsym_error = dlerror();
     if (dlsym_error) {
         cerr << "Cannot load symbol destroy: " << dlsym_error << '\n';
@@ -128,6 +145,107 @@ void IoTSlave::instantiateObject(string objectClassName) {
         exit(1);
     }
        writeToFile("Object destroyer created for " + objectClassName);
+       // Create initializer
+       string initFunction = INITFUNCTION + objectClassName;
+    init_object = (init_t*) dlsym(handle, initFunction.c_str());
+    dlsym_error = dlerror();
+    if (dlsym_error) {
+        cerr << "Cannot load symbol init: " << dlsym_error << '\n';
+               writeToFile("Cannot load symbol init!");
+        exit(1);
+    }
+       writeToFile("Object initializer created for " + objectClassName);
+}
+
+
+// Run init_object function
+void IoTSlave::runInitObject(IoTSlave* iotslave) {
+
+       iotslave->init_object(iotslave->objMainCls);
+}
+
+
+// Instantiate main object!
+// Use handler obtained by getObjectHandler() and instantiate object!
+void IoTSlave::instantiateMainObject() {
+
+       // IoTDeviceAddress + other arguments
+       int paramSize = vecIoTSet.size();
+       void* params[paramSize];
+       for(int i=0; i<vecIoTSet.size(); i++) {
+               params[i] = vecIoTSet[i];       // Just the first object is taken in this case
+       }
+       writeToFile("Vector IoTSet size: " + to_string(vecIoTSet.size()));
+       objMainCls = create_object(params);
+       writeToFile("Object created for " + mainObjectName);
+       init_object(objMainCls);
+       //thread th1 (&IoTSlave::runInitObject, this, this);
+       //th1.detach();
+       //thread th1 (&IoTSlave::runInitObject, this, this);
+       //th1.join();
+       writeToFile("Initialized object " + mainObjectName);
+}
+
+
+// Instantiate driver object!
+// Use handler obtained by getObjectHandler() and instantiate object!
+void IoTSlave::instantiateDriverObject() {
+
+       // IoTDeviceAddress + other arguments
+       int paramSize = vecIoTSet.size() + args.size();
+       void* params[paramSize];
+       for(int i=0; i<vecIoTSet.size(); i++) {
+               params[i] = vecIoTSet[i];       // Just the first object is taken in this case
+       }
+       writeToFile("Vector IoTSet size: " + to_string(vecIoTSet.size()));
+       writeToFile("Arg size: " + to_string(args.size()));
+       int countArg = vecIoTSet.size();        // Start from after the address set
+       // Iterate over arguments
+       for(int i=0; i<args.size(); i++) {
+               params[countArg] = getObjectConverted(params[countArg], args[i], argClasses[i]);
+               countArg++; 
+       }
+       objMainCls = create_object(params);
+       // Delete unused object after conversion and instantiation
+       for(int i=1; i<paramSize; i++) {
+               if (argClasses[i-1].compare(STRINGCLASS) == 0) {                
+                       delete (string*) params[i];
+               } else if (argClasses[i-1].compare(INTCLASS) == 0)
+                       delete (int*) params[i];
+       }               
+       writeToFile("Object created for " + objectClassName);
+}
+
+
+// Use handler obtained by getObjectHandler() and instantiate skeleton object!
+void IoTSlave::instantiateSkelObject() {
+
+       void* params[SKELPARAMSIZE];
+       params[0] = objMainCls;
+       string callbackAddress = LOCALHOST;
+       params[1] = &callbackAddress;
+       params[2] = &objectStubPort;
+       writeToFile("Skeleton Object " + objectSkelClass + " created for " + objectClassName);
+       // After this, this slave needs to be killed using "pkill IoTSlave" because it's waiting in an infinite while-loop
+       objSkelCls = create_object(params);
+}
+
+
+// Use handler obtained by getObjectHandler() and instantiate stub object!
+void IoTSlave::instantiateStubObject() {
+
+       void* params[STUBPARAMSIZE];
+       params[0] = &objectStubPort;
+       params[1] = &hostAddress;
+       string callbackAddress = LOCALHOST;
+       params[2] = &callbackAddress;
+       int rev = 0;
+       params[3] = &rev;
+       bool result = false;
+       params[4] = &result;
+       params[5] = &ports;
+       writeToFile("Stub Object " + objectStubClass + " created for " + objectClassName);
+       objStubCls = create_object(params);
 }
 
 
@@ -212,45 +330,144 @@ string IoTSlave::recvString() {
 void IoTSlave::createObject() {
 
        writeToFile("Creating a driver object now...");
-       sendAck();
        // Receiving object info
        objectName = recvString(); sendAck();
-       writeToFile("Driver object name: " + objectName);
+       writeToFile("=> Driver object name: " + objectName);
        objectClassName = recvString(); sendAck();
-       writeToFile("Driver object class name: " + objectClassName);
+       writeToFile("=> Driver object class name: " + objectClassName);
        objectInterfaceName = recvString(); sendAck();
-       writeToFile("Driver object interface name: " + objectInterfaceName);
+       writeToFile("=> Driver object interface name: " + objectInterfaceName);
        objectSkelClass = recvString(); sendAck();
-       writeToFile("Driver object skeleton class name: " + objectSkelClass);
+       writeToFile("=> Driver object skeleton class name: " + objectSkelClass);
        objectRegPort = recvInteger(); sendAck();
-       writeToFile("Driver object registry port: " + to_string(objectRegPort));
+       writeToFile("=> Driver object registry port: " + to_string(objectRegPort));
        objectStubPort = recvInteger(); sendAck();
-       writeToFile("Driver object stub port: " + to_string(objectStubPort));
+       writeToFile("=> Driver object stub port: " + to_string(objectStubPort));
        int numOfArgs = recvInteger(); sendAck();
        for (int i = 0; i < numOfArgs; i++) {
                string arg = recvString(); sendAck();
                args.push_back(arg);
-               writeToFile("Got argument: " + arg);
+               writeToFile("==> Got argument: " + arg);
        }
        for (int i = 0; i < numOfArgs; i++) {
                string argClass = recvString(); sendAck();
-               args.push_back(argClass);
-               writeToFile("Got argument class: " + argClass);
+               argClasses.push_back(argClass);
+               writeToFile("==> Got argument class: " + argClass);
        }
        // We are just receiving object information here
        // Instantiation will be done when IoTDeviceAddress has been sent
-       //instantiateObject(objectClassName);
 }
 
 
+// Create a new IoTSet object to hold objects
 void IoTSlave::createNewIoTSet() {
 
-
+       objectFieldName = recvString(); sendAck();
+       // Instantiating new IoTSet object
+       isetObject = new unordered_set<void*>();
+       writeToFile("Creating new IoTSet for field: " + objectFieldName);
 }
 
 
+// Get IoTDeviceAddress object reference and put it inside IoTSet object
 void IoTSlave::getDeviceIoTSetObject() {
 
+       writeToFile("Getting IoTDeviceAddress... ");
+       // Get the IoTDeviceAddress info
+       hostAddress = recvString(); sendAck();
+       writeToFile("=> Host address: " + hostAddress);
+       int sourcePort = recvInteger(); sendAck();
+       writeToFile("=> Source port: " + to_string(sourcePort));
+       int destPort = recvInteger(); sendAck();
+       writeToFile("=> Destination port: " + to_string(destPort));
+       bool sourcePortWildCard = (bool) recvInteger(); sendAck();
+       writeToFile("=> Is source port wild card? " + to_string(sourcePortWildCard));
+       bool destPortWildCard = (bool) recvInteger(); sendAck();
+       writeToFile("=> Is destination port wild card? " + to_string(destPortWildCard));
+       // Create IoTDeviceAddress      
+       IoTDeviceAddress* objDeviceAddress = new IoTDeviceAddress(hostAddress, sourcePort, destPort, 
+               sourcePortWildCard, destPortWildCard);
+       // Insert it into isetObject!
+       isetObject->insert(objDeviceAddress);
+       writeToFile("=> Inserting IoTDeviceAddress into set...");
+       writeToFile("==> Now we have " + to_string(isetObject->size()) + " object(s)!");
+       // Set flag to true;
+       isDriverObject = true;
+}
+
+
+// Get IoTSet object content reference and put it inside IoTSet object
+// This is basically the stub objects
+void IoTSlave::getIoTSetObject() {
+
+       writeToFile("Getting IoTSet object... ");
+       // Get the IoTDeviceAddress info
+       hostAddress = recvString(); sendAck();
+       writeToFile("=> Host address: " + hostAddress);
+       objectName = recvString(); sendAck();
+       writeToFile("=> Driver object name: " + objectName);
+       objectClassName = recvString(); sendAck();
+       writeToFile("=> Driver object class name: " + objectClassName);
+       objectInterfaceName = recvString(); sendAck();
+       writeToFile("=> Driver object interface name: " + objectInterfaceName);
+       objectStubClass = recvString(); sendAck();
+       writeToFile("=> Driver object stub class name: " + objectStubClass);
+       objectRegPort = recvInteger(); sendAck();
+       writeToFile("=> Driver object registry port: " + to_string(objectRegPort));
+       objectStubPort = recvInteger(); sendAck();
+       writeToFile("=> Driver object stub port: " + to_string(objectStubPort));
+       int numOfPorts = recvInteger(); sendAck();
+       for (int i = 0; i < numOfPorts; i++) {
+               int port = recvInteger(); sendAck();
+               ports.push_back(port);
+               writeToFile("==> Got a new port: " + to_string(port));
+       }
+       // Create Stub object
+       unordered_map<string,void*>::const_iterator itr = mapObjNameStub.find(objectName);
+       if (itr != mapObjNameStub.end()) {      // Stub has been created earlier
+               writeToFile("=> Stub has been created! Getting back reference...");
+               objStubCls = itr->second;
+       } else {        // Instantiate a new stub and map it
+               writeToFile("=> Stub has not been created! Creating a new stub...");
+               getObjectHandler(objectStubClass);
+               instantiateStubObject();
+               mapObjNameStub.insert(make_pair(objectName,objStubCls));
+               writeToFile("=> Map has: " + to_string(mapObjNameStub.size()) + " members");
+       }
+       // Insert it into isetObject!
+       isetObject->insert(objStubCls);
+       writeToFile("=> Inserting stub object into set...");
+       writeToFile("==> Now we have " + to_string(isetObject->size()) + " object(s)!");
+}
+
+
+// Reinitialize IoTSet field!
+void IoTSlave::reinitializeIoTSetField() {
+
+       writeToFile("Reinitialize IoTSet field...");
+       iotsetObject = new IoTSet<void*>(isetObject);
+       // Collect IoTSet field first in a vector
+       vecIoTSet.push_back(iotsetObject);
+
+       // Create object if this is for driver object
+       if (isDriverObject) {
+               // Instantiate driver object
+               getObjectHandler(objectClassName);
+               instantiateDriverObject();
+               // Instantiate skeleton object
+               getObjectHandler(objectSkelClass);
+               instantiateSkelObject();
+       }
+}
+
+
+// Invoke init() method in main controller
+void IoTSlave::invokeInitMethod() {
+
+       writeToFile("Invoke init() method for: " + mainObjectName);
+       // Instantiate main controller object
+       getObjectHandler(mainObjectName);
+       instantiateMainObject();
 
 }
 
@@ -258,9 +475,10 @@ void IoTSlave::getDeviceIoTSetObject() {
 // Create a main object, e.g. Lifxtest
 void IoTSlave::createMainObject() {
 
-       writeToFile("Creating main object: " + objectName);
-       string mainObject = recvString();
-       sendAck();
+       mainObjectName = recvString(); sendAck();
+       writeToFile("Creating main object: " + mainObjectName);
+       // Just receive the name of the class object here
+       // We will instantiate the object after we get the set/relation objects
 }
 
 
@@ -286,9 +504,9 @@ void IoTSlave::commIoTMaster() {
        writeToFile("Starting main loop...");
        // Main iteration/loop
        while(true) {
-               IoTCommCode message = (IoTCommCode) recvInteger();
+               IoTCommCode message = (IoTCommCode) recvInteger(); sendAck();
                //writeToFile("Message: " + (int) message);
-
+               
                switch(message) {
 
                        case CREATE_OBJECT:
@@ -312,7 +530,7 @@ void IoTSlave::commIoTMaster() {
                                break;
 
                        case GET_IOTSET_OBJECT:
-                               //getIoTSetObject();
+                               getIoTSetObject();
                                break;
 
                        case GET_IOTRELATION_FIRST_OBJECT:
@@ -324,7 +542,7 @@ void IoTSlave::commIoTMaster() {
                                break;
 
                        case REINITIALIZE_IOTSET_FIELD:
-                               //reinitializeIoTSetField();
+                               reinitializeIoTSetField();
                                break;
 
                        case REINITIALIZE_IOTRELATION_FIELD:
@@ -344,7 +562,7 @@ void IoTSlave::commIoTMaster() {
                                break;
 
                        case INVOKE_INIT_METHOD:
-                               //invokeInitMethod();
+                               invokeInitMethod();
                                break;
 
                        case END_SESSION:
@@ -381,7 +599,6 @@ int main(int argc, char *argv[]) {
        int serverPort = atoi(servPort);
        string strObjName = argv[3];
        IoTSlave *iotSlave = new IoTSlave(serverAddress, serverPort, strObjName);
-       //iotSlave->sendInteger(123455);
        iotSlave->sendAck();
        iotSlave->commIoTMaster();