Index: vtcross/trunk/src/service_management_layer/sml_demo.cpp
===================================================================
--- vtcross/trunk/src/service_management_layer/sml_demo.cpp	(revision 200)
+++ vtcross/trunk/src/service_management_layer/sml_demo.cpp	(revision 278)
@@ -1,19 +1,26 @@
-/* Virginia Tech Cognitive Radio Open Source Systems
- * Virginia Tech, 2009
- *
- * TODO LICENSE INFORMATION GOES HERE
- */
-
-/* TODO DESCRIPTION OF FILE.
- *
- * This file is a temporary demo of a service management layer using some of 
- * our socket communication functions. This is *not* an actual implementation 
- * of our defined ServiceManagement class.
- */
-
-
 #include <cstdlib>
 #include <cstring>
 #include <stdint.h>
+#include <string>
+#include <stdlib.h> 
+
+#include <arpa/inet.h>
+#include <iostream>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "sqlite3.h"
+
+
+
+//#include "tinyxml.h"
+//#include "tinyxml.cpp"
+//#include "tinystr.h"
 
 #include "vtcross/common.h"
@@ -25,18 +32,112 @@
 
 
-int32_t 
-main(int32_t argc, char *argv[])
-{
-    if(argc < 3)
-       ERROR(1, "Usage: %s hostname port\n", argv[0]);
+
+/*#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+//#include <iostream>
+#include <stdlib.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <sqlite3ext.h>*/
+
+//#include "common.h"
+
+//using namespace std;
+
+
+int main(int argc, char *argv[])
+{   
+    int shell = CreateTCPServerSocket(1979);
+    //sleep(2);
+    int temp = AcceptTCPConnection(shell); 
+   // SendMessage(temp, "list_services");
+    sleep(1);
+    int FD = ClientSocket("127.0.0.1", "2036"); 
+    SendMessage(FD, "register_engine_cognitive");   
+    SendMessage(FD, "register_service");
+    SendMessage(FD, "test_srv"); 
+    SendMessage(FD, "list_services");
+    int FD2 = ClientSocket("127.0.0.1", "2036"); 
+    SendMessage(FD2, "register_engine_cognitive");   
+    SendMessage(FD2, "register_service");
+    SendMessage(FD2, "test_srv1"); 
+    SendMessage(FD2, "register_service");
+    SendMessage(FD2, "test_srv2");
+    SendMessage(FD2, "list_services");
+    sleep(1);
+    printf("preread1\n");
+
+    char buffer[256];
+    memset(buffer, 0, 256);
+
+    SendMessage(temp, "set_active_mission");
+    SendMessage(temp, "0"); 
+    SendMessage(temp, "request_optimization");
+    SendMessage(temp, "params");
+    ReadMessage(FD, buffer);
+    printf("preread2\n");
+    printf("-----buffer1= %s-------\n", buffer);
+    ReadMessage(FD, buffer);
+    printf("-----buffer2= %s-------\n", buffer);
+    memset(buffer, 0, 256);
+    ReadMessage(FD, buffer);
+    printf("-----buffer3= %s-------\n", buffer);
+    SendMessage(FD, "ACK");
+    SendMessage(FD, "temp");
+    SendMessage(FD, "raw_data");
+    ReadMessage(FD2, buffer);
+    printf("-----buffer4= %s-------\n", buffer);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer5= %s-------\n", buffer);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer6= %s-------\n", buffer);
+    SendMessage(FD2, "ACK");
+    ReadMessage(FD2, buffer);
+    printf("-----buffer7= %s-------\n", buffer);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer8= %s-------\n", buffer);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer9= %s-------\n", buffer);
+    SendMessage(FD2, "ACK");
+    SendMessage(FD2, "trans");
+    ReadMessage(temp, buffer);
+    printf("-----buffer10= %s-------\n", buffer);
+    SendMessage(temp, "ACK");
+    /*ReadMessage(FD, buffer);
+    printf("-----buffer1= %s-------\n", buffer);
+    ReadMessage(FD, buffer);
+    printf("-----buffer2= %s-------\n", buffer);
+    memset(buffer, 0, 256);
+    ReadMessage(FD, buffer);
+    printf("-----buffer3= %s-------\n", buffer);
+    SendMessage(FD, "ACK");
+    SendMessage(FD, "true");
+    SendMessage(FD, "data");
+    ReadMessage(FD2, buffer);
+    printf("-----buffer4= %s-------\n", buffer);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer5= %s-------\n", buffer);
+    memset(buffer, 0, 256);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer6= %s-------\n", buffer);
+    SendMessage(FD2, "ACK");
+    SendMessage(FD2, "trans");
+    ReadMessage(temp, buffer);
+    printf("-----buffer7= %s-------\n", buffer);
+    SendMessage(temp, "ACK");*/
+   
     
-    ServiceManagementLayer sml;
 
-    LOG("Waiting for signal...\n");
-    while(1) {
-//        policyEngine.WaitForSignal();
-    }
-
-    return 0;
+    //SendMessage(temp, "list_services");  
+    while(true){   
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(temp, buffer);
+    printf("------%s------\n", buffer);}
+   /*memset(buffer, 0, 256);
+    ReadMessage(temp, buffer);
+    printf("------%s------\n", buffer);*/
 }
-
Index: vtcross/trunk/src/service_management_layer/Makefile.am
===================================================================
--- vtcross/trunk/src/service_management_layer/Makefile.am	(revision 200)
+++ vtcross/trunk/src/service_management_layer/Makefile.am	(revision 278)
@@ -6,4 +6,5 @@
 
 sml_demo_SOURCES = ServiceManagementLayer.cpp sml_demo.cpp
-sml_demo_LDADD = ../lib/socketcomm/libsocketcomm.a
+sml_demo_LDADD = -ldl -lpthread -lsqlite3  ../lib/tinyxml/libtinyxml.a ../lib/socketcomm/libsocketcomm.a
 
+
Index: vtcross/trunk/src/service_management_layer/ServiceManagementLayer.cpp
===================================================================
--- vtcross/trunk/src/service_management_layer/ServiceManagementLayer.cpp	(revision 206)
+++ vtcross/trunk/src/service_management_layer/ServiceManagementLayer.cpp	(revision 278)
@@ -5,18 +5,89 @@
  */
 
-/* DESCRIPTION OF FILE.
- */
-
-
-#include <cstdlib>
+/* Inter-component communication handled by sockets and FD's.  
+ * Server support has been completely implemented and tested.
+ *
+ * Services are stored in a SQLite DB by the ID of the CE that registered them.  Service
+ * support has been completely implemented and tested.
+ *
+ * Missions are loaded from an XML file, connected with services provided by components,
+ * and run.  See the documentation for the "PerformActiveMission" below for important 
+ * info.  
+ */
+
+//TODO Add nested conditional support
+//TODO Verify update functionality
+//TODO Better shutdown
+//TODO Verify Deregister services
+//TODO printf's
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
 #include <cstring>
 #include <stdint.h>
 
 #include "vtcross/common.h"
-#include "vtcross/components.h"
+
+#include "components.h"
 #include "vtcross/containers.h"
 #include "vtcross/debug.h"
 #include "vtcross/error.h"
 #include "vtcross/socketcomm.h"
+#include <cstring>
+#include <stdint.h>
+#include <math.h>
+
+#include <arpa/inet.h>
+#include <iostream>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "tinyxml/tinyxml.h"
+#include "tinyxml/tinystr.h"
+
+#include "sqlite3.h"
+
+typedef struct services_s *services_DB;
+typedef struct data_s *data_DB;
+
+using namespace std;
+
+struct services_s {
+    char filename[64];
+    char tablename[64];
+    char command[2048];
+    sqlite3 *db; 
+    unsigned int num_columns;
+};
+
+struct data_s {
+    char filename[64];
+    char tablename[64];
+    char command[2048];
+    sqlite3 *db; 
+    unsigned int num_columns;
+};
+
+services_DB _services_DB;
+data_DB _data_DB;
+const char *_SML_Config;
+
+//Callback function used internally by some of the SQLite3 commands
+int callback(void *notUsed, int argc, char **argv, char **azColName){
+    int i;
+    for(i=0; i<argc; i++){
+        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
+    }
+    printf("\n");
+    return 0;
+}
+
 
 
@@ -25,24 +96,177 @@
     LOG("Creating Service Management Layer.\n");
     shellSocketFD = -1;
-    LoadConfiguration();
-}
-
-
+    numberOfCognitiveEngines = 0;
+    CE_Present = false;
+    cogEngSrv = 1;
+}
+
+//Free and clear the DB's associated with this SML in the destructor
+//Note that exiting with an error condition will cause SML to not be destructed,
+// resulting in the DB's staying in memory until the destructor is encountered in future executions
 ServiceManagementLayer::~ServiceManagementLayer()
 {
-}
-
-
-ServiceManagementLayer::ServiceManagementLayer(const char* serverName, \
-        const char* serverPort)
+    char *errorMsg;
+    strcpy(_services_DB->command, "drop table ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "ServiceManagementLayer::Destructor services 'drop table' error: %s\n", errorMsg);
+    strcpy(_services_DB->command, "vacuum");
+    rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "ServiceManagementLayer::Destructor services 'vacuum' error: %s\n", errorMsg);
+    free(_services_DB);
+
+    strcpy(_data_DB->command, "drop table ");
+    strcat(_data_DB->command, _data_DB->tablename);
+    rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "ServiceManagementLayer::Destructor data 'drop table' error: %s\n", errorMsg);
+    strcpy(_data_DB->command, "vacuum");
+    rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "ServiceManagementLayer::Destructor data 'vacuum' error: %s\n", errorMsg);
+    free(_data_DB);
+}
+
+//Note that sizes of CE_List, miss, and service are hardcoded for now.
+//Also, their sizes are hardcoded into the code in various places; a fix for a future version.
+ServiceManagementLayer::ServiceManagementLayer(const char* SML_Config, \
+	const char* serverName, const char* serverPort)
 {
     LOG("Creating Service Management Layer.\n");
+    _SML_Config = SML_Config;
 
     ConnectToShell(serverName, serverPort);
-
-    LoadConfiguration();
-}
-
-
+    CE_List = (CE_Reg *) malloc(10*sizeof(struct CE_Reg));
+    CE_List = new CE_Reg[10];
+
+    miss = new Mission[10];
+    for(int i = 0; i < 10; i++)
+    	miss[i].services = new Service[20];
+
+    Current_ID = 0;
+
+    LoadConfiguration(SML_Config, miss);
+    CreateServicesDB();
+    CreateDataDB();
+}
+
+/* CALLED BY: constructor
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Create and initialize a DB to hold the services registered by components
+ */
+void
+ServiceManagementLayer::CreateServicesDB()
+{
+    _services_DB = (services_DB) malloc(sizeof(struct services_s));
+    char *errorMsg;
+
+    // create database
+
+    // copy filename
+    unsigned int i=0;
+    strcpy(_services_DB->filename, "Services_Table");
+
+    // execute create database command
+    // database handle
+    //_services_DB->db = NULL;
+    sqlite3_open(_services_DB->filename, &(_services_DB->db));
+    char* cols[] = {(char *)"ID_Num", (char *)"Service_Name"};
+
+    // create table
+
+    // copy tablename
+    strcpy(_services_DB->tablename, "Services");
+
+    // number of columns in the table
+    _services_DB->num_columns = 2;
+
+    // generate command
+    strcpy(_services_DB->command, "CREATE TABLE ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    strcat(_services_DB->command, "(");
+    strcat(_services_DB->command, cols[0]);
+    strcat(_services_DB->command, " INT, ");
+    strcat(_services_DB->command, cols[1]);
+    strcat(_services_DB->command, " TEXT");
+    strcat(_services_DB->command, ");");
+
+    // execute create table command
+  sqlite3_stmt *ppStmt;  /* OUT: Statement handle */
+  const char *pzTail;     /* OUT: Pointer to unused portion of zSql */
+
+    int rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command, 128, &ppStmt, &pzTail);
+    if( rc!=SQLITE_OK && rc!=101 )
+        printf("ServiceManagementLayer::CreateServicesDB 'prepare_stmt' error %d\n", rc);
+    rc = sqlite3_step(ppStmt);
+    if( rc!=SQLITE_OK && rc!=101 )
+        printf("ServiceManagementLayer::CreateServicesDB 'step' error %d\n");
+}
+
+/* CALLED BY: constructor
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Create and initialize a DB to hold the data sent by components
+ */
+void
+ServiceManagementLayer::CreateDataDB()
+{
+    _data_DB = (data_DB) malloc(sizeof(struct data_s));
+    char *errorMsg;
+
+    // create database
+
+    // copy filename
+    unsigned int i=0;
+    strcpy(_data_DB->filename, "Data_Table");
+
+    // execute create database command
+    // database handle
+    //_services_DB->db = NULL;
+    sqlite3_open(_data_DB->filename, &(_data_DB->db));
+    char* cols[] = {(char *)"Tag", (char *)"Data"};
+
+    // create table
+
+    // copy tablename
+    strcpy(_data_DB->tablename, "Data");
+
+    // number of columns in the table
+    _data_DB->num_columns = 2;
+
+    // generate command
+    strcpy(_data_DB->command, "CREATE TABLE ");
+    strcat(_data_DB->command, _data_DB->tablename);
+    strcat(_data_DB->command, "(");
+    strcat(_data_DB->command, cols[0]);
+    //First column is the name of the data (coresponding to the name of the output/input pair)
+    //It is the primary key so any subsequent data with the same name will replace the row
+    strcat(_data_DB->command, " TEXT PRIMARY KEY ON CONFLICT REPLACE, ");
+    strcat(_data_DB->command, cols[1]);
+    strcat(_data_DB->command, " TEXT");
+    strcat(_data_DB->command, ");");
+
+    // execute create table command
+  sqlite3_stmt *ppStmt;  /* OUT: Statement handle */
+  const char *pzTail;     /* OUT: Pointer to unused portion of zSql */
+
+    int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, 128, &ppStmt, &pzTail);
+    if( rc!=SQLITE_OK && rc!=101 )
+        printf("ServiceManagementLayer::CreateDataDB 'prepare_stmt' error %d\n", rc);
+    rc = sqlite3_step(ppStmt);
+    if( rc!=SQLITE_OK && rc!=101 )
+        printf("ServiceManagementLayer::CreateDataDB 'step' error %d\n");
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Sends a message identifying this component as an SML to the Shell
+ */
 void 
 ServiceManagementLayer::SendComponentType()
@@ -52,5 +276,13 @@
 }
 
-
+/* CALLED BY: constructor
+ * INPUTS: |serverName| the IPv4 name of the server (127.0.0.1 for localhost)
+ *	   |serverPort| the port on the server to connect to
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Connecting to the shell takes 2 steps
+ * 1) Establish a client socket for communication
+ * 2) Run the initial Registration/handshake routine
+ */
 void 
 ServiceManagementLayer::ConnectToShell(const char* serverName, \
@@ -58,56 +290,98 @@
 {
     shellSocketFD = ClientSocket(serverName, serverPort);
-
     RegisterComponent();
 }
 
-
-void 
-ServiceManagementLayer::WaitForSignal()
-{
-    char buffer[256];
-
-    while(true) {
-        memset(buffer, 0, 256);
-       
-        ReadMessage(shellSocketFD, buffer);
-
-        // TODO
-        // If we send integer op codes rather than strings, this process will be
-        // MUCH faster since instead of donig string compares we can simply
-        // switch on the integer value...
-        if(strcmp(buffer, "register_service") == 0) {
-            if(strcmp(buffer, "policy_geo") == 0) {
-            }
-            else if(strcmp(buffer, "policy_time") == 0) {
-            }
-            else if(strcmp(buffer, "policy_spectrum") == 0) {
-            }
-            else if(strcmp(buffer, "policy_spacial") == 0) {
-            }
+/* CALLED BY: StartSMLServer
+ * INPUTS: |ID| The ID number of the CE that has a message wating
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Called whenever a socket is identified as being ready for communication
+ *              This funciton reads the message and calls the appropriate helper
+ */ 
+void
+ServiceManagementLayer::MessageHandler(int32_t ID)
+{
+    char buffer[256];	
+    memset(buffer, 0, 256);  
+    int32_t _FD;  
+    
+    if(ID != -1)
+	_FD = CE_List[ID].FD;
+    else 
+	_FD = shellSocketFD;
+    ReadMessage(_FD, buffer);
+    
+    //--------Policy Engine Stuff - no policy engine support in this version-------//
+
+    //printf("********* %s **********\n", buffer);
+    // TODO
+    // If we send integer op codes rather than strings, this process will be
+    // MUCH faster since instead of donig string compares we can simply
+    // switch on the integer value...
+    /*if(strcmp(buffer, "register_service") == 0) {
+        if(strcmp(buffer, "policy_geo") == 0) {
         }
-        else if(strcmp(buffer, "deregister_service") == 0) {
-            if(strcmp(buffer, "policy_geo") == 0) {
-            }
-            else if(strcmp(buffer, "policy_time") == 0) {
-            }
-            else if(strcmp(buffer, "policy_spectrum") == 0) {
-            }
-            else if(strcmp(buffer, "policy_spacial") == 0) {
-            }
+        else if(strcmp(buffer, "policy_time") == 0) {
         }
-        else if(strcmp(buffer, "query_component_type") == 0) {
-            SendComponentType();
+        else if(strcmp(buffer, "policy_spectrum") == 0) {
         }
-        else if(strcmp(buffer, "reset_sml") == 0) {
-            Reset();
+        else if(strcmp(buffer, "policy_spacial") == 0) {
         }
-        else if(strcmp(buffer, "shutdown_sml") == 0) {
-            Shutdown();
+    }
+    else if(strcmp(buffer, "deregister_service") == 0) {
+        if(strcmp(buffer, "policy_geo") == 0) {
         }
-    }
-}
-
-
+        else if(strcmp(buffer, "policy_time") == 0) {
+        }
+        else if(strcmp(buffer, "policy_spectrum") == 0) {
+        }
+        else if(strcmp(buffer, "policy_spacial") == 0) {
+        }
+    }*/
+
+    //Go down the list to call the appropriate function
+    if(strcmp(buffer, "query_component_type") == 0) {
+        SendComponentType();
+    }
+    else if(strcmp(buffer, "reset_sml") == 0) {
+        Reset();
+    }
+    else if(strcmp(buffer, "shutdown_sml") == 0) {
+        Shutdown();
+    }
+    else if(strcmp(buffer, "register_engine_cognitive") == 0) {
+     	RegisterCognitiveEngine(ID);
+    }
+    else if(strcmp(buffer, "register_service") == 0) {
+ 	ReceiveServices(ID);
+    }
+    else if(strcmp(buffer, "send_component_type") == 0) {
+ 	SendComponentType();
+    }
+    else if(strcmp(buffer, "list_services") == 0) {
+ 	ListServices();
+    }
+    else if(strcmp(buffer, "set_active_mission") == 0) {
+	SetActiveMission();
+    }
+    else if(strcmp(buffer, "request_optimization") == 0) {
+	PerformActiveMission();
+    }
+    else if(strcmp(buffer, "deregister_engine_cognitive") == 0) {
+	DeregisterCognitiveEngine(ID);
+    }
+    else if(strcmp(buffer, "deregister_service") == 0) {
+	DeregisterServices(ID);
+    }
+}
+
+//TODO Finish
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Deregisters the component from the Shell.
+ */ 
 void 
 ServiceManagementLayer::Shutdown()
@@ -116,13 +390,24 @@
 }
 
-
+//TODO Finish
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Deregisters the component from the Shell
+ */
 void 
 ServiceManagementLayer::Reset()
 {
     DeregisterComponent();
-    LoadConfiguration();
-}
-
-
+    ReloadConfiguration();
+}
+
+/* CALLED BY: ConnectToShell
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Sends the registration message to the Shell
+ */
 void 
 ServiceManagementLayer::RegisterComponent()
@@ -132,5 +417,10 @@
 }
 
-
+/* CALLED BY: Shutdown
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Closes the client socket with the shell, sends a deregstration message
+ */
 void 
 ServiceManagementLayer::DeregisterComponent()
@@ -146,45 +436,1047 @@
 
 
+/* CALLED BY: RegisterCognitiveEngine
+ * INPUTS: |ID| The ID number of the component where the data is to be transfered to
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Streams config data directly from the shell to the CE, and checks
+ * for an "ack" message from the CE after every sent message 
+ * to know when to stop communication.
+ */
+
+//Modified to check the incoming message buffer rather than the outgoing message buffer to avoid a portion of the delay
 void 
-ServiceManagementLayer::TransferRadioConfiguration()
-{
-}
-
-
+ServiceManagementLayer::TransferRadioConfiguration(int32_t ID)
+{
+    struct timeval selTimeout;
+    fd_set sockSet;
+    int32_t rc = 0;
+    char buffer[256];
+    //Send data until the CE sends an ACK message back
+    while(rc!=0){
+        memset(buffer, 0, 256);
+	//Receive data from Shell
+	ReadMessage(shellSocketFD, buffer);
+	//Send data to CE
+	SendMessage(CE_List[ID].FD, buffer);
+        FD_ZERO(&sockSet);
+        FD_SET(shellSocketFD, &sockSet);
+        selTimeout.tv_sec = 0;
+        selTimeout.tv_usec = 50000;
+        //Check if there is a message on the shell ready to be processed
+        rc=select(shellSocketFD + 1, &sockSet, NULL, NULL, &selTimeout);
+    }
+    memset(buffer, 0, 256);
+    ReadMessage(CE_List[ID].FD, buffer);
+    SendMessage(shellSocketFD, buffer);
+}
+
+
+/* CALLED BY: RegisterCognitiveEngine
+ * INPUTS: |ID| The ID number of the component where the data is to be transfered to
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Simmilar to TransferRadioConfig, just with Experience data
+ */
+
+//Modified to check the incoming message buffer rather than the outgoing message buffer to avoid a portion of the delay
 void 
-ServiceManagementLayer::TransferExperience()
-{
-}
-
-
+ServiceManagementLayer::TransferExperience(int32_t ID)
+{
+    struct timeval selTimeout;
+    fd_set sockSet;
+    int32_t rc = 0;
+    char buffer[256];
+    //Send data until the CE sends an ACK message back
+    while(rc!=0){
+        memset(buffer, 0, 256);
+	//Receive data from Shell
+	ReadMessage(shellSocketFD, buffer);
+	//Send data to CE
+	SendMessage(CE_List[ID].FD, buffer);
+        FD_ZERO(&sockSet);
+        FD_SET(shellSocketFD, &sockSet);
+        selTimeout.tv_sec = 0;
+        selTimeout.tv_usec = 50000;
+        //Check if there is a message on the shell ready to be processed
+        rc=select(shellSocketFD + 1, &sockSet, NULL, NULL, &selTimeout);
+    }
+    memset(buffer, 0, 256);
+    ReadMessage(CE_List[ID].FD, buffer);
+    SendMessage(shellSocketFD, buffer);
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: |ID| The ID number of the component where service is located
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Inserts a service into the DB with the ID of the component where it exists
+ */
 void 
-ServiceManagementLayer::ReceiveServices()
-{
-}
-
-
+ServiceManagementLayer::ReceiveServices(int32_t ID)
+{
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(CE_List[ID].FD, buffer);
+    char* cols[] = {(char *)"ID_Num", (char *)"Service_Name"};
+    
+    // generate command
+    strcpy(_services_DB->command, "insert into ");
+    strcat(_services_DB->command, _services_DB->tablename); 
+    strcat(_services_DB->command, " (");
+    strcat(_services_DB->command, cols[0]);
+    strcat(_services_DB->command, ", ");
+    strcat(_services_DB->command, cols[1]);
+    strcat(_services_DB->command, ") ");
+    strcat(_services_DB->command, " values(");
+    sprintf(_services_DB->command, "%s%d", _services_DB->command, ID);
+    strcat(_services_DB->command, ", '");
+    strcat(_services_DB->command, buffer);
+    strcat(_services_DB->command, "');");
+    
+    //printf("search command: %s\n", _services_DB->command);
+    // execute add command
+    char *errorMsg;
+    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "ServiceManagementLayer::RecieveServices DB Error %s\n", errorMsg);
+    char *outBuffer;
+    sprintf(outBuffer, "SML: Registering service '%s' from component number '%d'\n", buffer, ID);
+    LOG(outBuffer);
+
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: This method associates the services that components provide with the services that are requested in the mission
+ * Each service in the mission is given the ID and FD of a component that has registered to provide that service 
+ * Deregistration is okay until this method is called without a reload, but if deregistration occurs after this
+ * method is called it needs to be called again even if other engines also provide the services
+ */
 void 
 ServiceManagementLayer::SetActiveMission()
 {
-}
-
-
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(shellSocketFD, buffer);
+    int32_t missID = atoi(buffer);
+    for(activeMission = 0; activeMission < 10; activeMission++)
+    {
+	//Find the active mission by comparing mission ID's
+	if(miss[activeMission].missionID == missID)
+	    break;
+    }
+    //For each service in the mission
+    for(int i = 0; i < miss[activeMission].numServices; i++)
+    {	
+	//Check whether the current service is an actual service or a conditional
+	if(miss[activeMission].services[i].name.compare("if") && miss[activeMission].services[i].name.compare("while")){
+	    //If it is a service, search the database of registered services to find the ID of the component that registered it
+    	    strcpy(_services_DB->command, "select ");
+   	    strcat(_services_DB->command, _services_DB->tablename);
+    	    strcat(_services_DB->command, ".* from ");
+    	    strcat(_services_DB->command, _services_DB->tablename);
+    	    strcat(_services_DB->command, " where Service_Name==");
+	    sprintf(_services_DB->command, "%s'%s';", _services_DB->command, miss[activeMission].services[i].name.c_str());
+	
+            sqlite3_stmt * pStatement;
+            int rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command, -1, &pStatement, NULL);
+            if (rc == SQLITE_OK){ 
+                if (sqlite3_step(pStatement) == SQLITE_ROW)
+	             miss[activeMission].services[i].componentID =  sqlite3_column_int(pStatement, 0); 
+                else {
+	            printf("services_DB:: Mission requires service not provided by any connected component.\n");
+		    rc=31337;
+	        }
+             } else {
+	        printf("services_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_services_DB->command);
+            }
+
+            sqlite3_finalize(pStatement);
+	    miss[activeMission].services[i].socketFD = CE_List[miss[activeMission].services[i].componentID].FD;
+	    //Set the FD and ID of the service to refer to the component where the service exists
+	}
+	//Nothing to be done for conditionals at this stage
+    }
+
+
+    //printf("\nhere ---%d, %d---\n", miss[activeMission].services[0].componentID, miss[activeMission].services[1].componentID);
+}
+
+/* CALLED BY: PerformActiveMission
+ * INPUTS: |sourceID| ID of the service that is being processed
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: This is a helper method for the "PerformActiveMission" function
+ * NOTE: This function has changed durrastically from the previous implementation
+ * Takes an ID of a service
+ * For that service, finds inputs in DB and forwords those on to the engine after sending comm-starting messages
+ * Afterwords, listenes for the outputs so that it can store those in the database for future services or the overall output
+ */
+void
+ServiceManagementLayer::TransactData(int32_t sourceID)
+{
+    printf("TransactData Occuring\n");
+    char buffer[256];
+    std::string data;
+    char* cols[] = {(char *)"Tag", (char *)"Data"};
+    int i = 0;
+    fd_set sockSet;
+    struct timeval selTimeout;
+    //Transmission starting messages
+    SendMessage(miss[activeMission].services[sourceID].socketFD, "request_optimization_service");
+    SendMessage(miss[activeMission].services[sourceID].socketFD, miss[activeMission].services[sourceID].name.c_str());
+    //Find and load the input data
+    while(i < 3 && !miss[activeMission].services[sourceID].input[i].empty()){
+	//printf("pulling input data out of DB for ID#=%d\n", sourceID);
+        strcpy(_data_DB->command, "select ");
+   	strcat(_data_DB->command, _data_DB->tablename);
+    	strcat(_data_DB->command, ".* from ");
+    	strcat(_data_DB->command, _data_DB->tablename);
+    	strcat(_data_DB->command, " where Tag==");
+	sprintf(_data_DB->command, "%s'%s';", _data_DB->command, miss[activeMission].services[sourceID].input[i].c_str());
+        sqlite3_stmt * pStatement;
+        int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL);
+        if (rc == SQLITE_OK){ 
+            if (sqlite3_step(pStatement) == SQLITE_ROW)
+	         data.append((const char*) sqlite3_column_text(pStatement, 1)); 
+            else {
+	            printf("data_DB:: Data not yet in DB.\n");
+		    rc=31337;
+	    }
+        } 
+	else {
+	    printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command);
+        }
+
+        sqlite3_finalize(pStatement);
+	char *data_ch = (char *) data.c_str();
+	//Tokenize the data and pass it along
+	char *token = strtok(data_ch, "@");
+	while(token){
+	    SendMessage(miss[activeMission].services[sourceID].socketFD, token);
+	    token = strtok(NULL, "@");
+	}
+	//printf("done pulling input data out of DB for ID#=%d\n", sourceID);
+	i++;
+    }
+
+    int32_t j = 0;
+    FD_ZERO(&sockSet);
+    FD_SET(miss[activeMission].services[sourceID].socketFD, &sockSet);
+    //TODO neccessary?
+    selTimeout.tv_sec = 5;
+    selTimeout.tv_usec = 0;
+    //Use select command to force wait for processing to finish
+    select(miss[activeMission].services[sourceID].socketFD + 1, &sockSet, NULL, NULL, &selTimeout);
+    while(j < 3 && !miss[activeMission].services[sourceID].output[j].empty()){
+	int rc;
+        data.clear();
+	while(true){
+	    //Read the data incrementally and deliminate it with the "@" symbol
+	    memset(buffer, 0, 256);
+	    ReadMessage(miss[activeMission].services[sourceID].socketFD, buffer);
+	    if(strcmp(buffer, "output_finished")==0)
+		break;
+	    data.append(buffer);
+	    data.append("@");;
+	}
+	printf("SML: putting output data into DB for ID#=%d\n", sourceID);
+
+	strcpy(_data_DB->command, "insert or replace into ");
+    	strcat(_data_DB->command, _data_DB->tablename); 
+      	strcat(_data_DB->command, " (");
+    	strcat(_data_DB->command, cols[0]);
+    	strcat(_data_DB->command, ", ");
+	strcat(_data_DB->command, cols[1]);
+	strcat(_data_DB->command, ") ");
+	strcat(_data_DB->command, " values('");	
+	strcat(_data_DB->command, miss[activeMission].services[sourceID].output[j].c_str());
+	strcat(_data_DB->command, "', '");
+	strcat(_data_DB->command, data.c_str());
+	strcat(_data_DB->command, "');");
+    	char *errorMsg;
+   	rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
+   	if( rc!=SQLITE_OK && rc!=101 )
+   	    fprintf(stderr, "SQL error: %s\n", errorMsg);
+        printf("SML: done putting ouptut data into DB for ID#='%d', data=%s\n", sourceID, data.c_str());
+	j++;
+    }
+    printf("done transact data!\n");
+
+
+    printf("\n\n\n");
+    // generate commandi
+    strcpy(_data_DB->command, "select ");
+    strcat(_data_DB->command, _data_DB->tablename);
+    strcat(_data_DB->command, ".* from ");
+    strcat(_data_DB->command, _data_DB->tablename);
+    strcat(_data_DB->command, ";");
+
+    // execute print (select all)  command    
+    char *errorMsg;
+    int rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "SQL error: %s\n", errorMsg);
+    printf("database %s, table %s:\n", _data_DB->filename, _data_DB->tablename);
+    printf("\n\n\n");
+}
+
+
+
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: This function works by first sending the inputs from the shell to the appropriate components
+ * The first service should begin immeadiately, as should any others who have all of their input paramaters
+ * When they complete, the output path is found and the data is transfered as it becomes available
+ * Presumably at this point the second function has all of it's paramaters, so it begins to compute, and the cycle repeats
+ * If the generated output is an overall output, it is sent on to the shell
+ * "if" and "while" statements are handled by setting up a faux service that has a true input, a false input, and a boolean flag
+ * If the true input is non-NULL and the flag is true, the statements execute
+ * Likewise, if the false input is non-NULL and the flag is false, the statements execute
+ * These flags are set during execution any time one of these faux services' inputs appear in an output statement  
+ *  
+ * 
+ * Rules for active missions (currently)
+ * -Three inputs/outputs per service and per mission
+ * -Inputs simply define a path, so multiple variables can be transmitted over the same input
+ * -Each component that sends data must include the "output_finished" statement after each output is finished sending it's data
+ * -All ordering constraints have been relaxed in this version; all data is stored locally and only sent when requested
+ * -If support fully implemented
+ * -Conditions must be boolean flags
+ * -Flags are set by putting either the character string "true" or "false" on the buffer
+ * -IMPORTANT: DB uses '@' to seperate individual statements; using '@' in the data stream will result in incorrect behavior
+ */
+void
+ServiceManagementLayer::PerformActiveMission()
+{
+    int i = 0;
+    std::string data;
+    std::string input;
+    std::string check;
+    char buffer[256];
+    fd_set sockSet;
+    char* cols[] = {(char *)"Tag", (char *)"Data"};
+    struct timeval selTimeout;
+    //Get the inputs
+    while(i < 3 && !miss[activeMission].input[i].empty()){
+	    //New data being added to DB
+	printf("inserting data from shell\n");
+	int rc;
+	while(true){
+	    memset(buffer, 0, 256);
+	    ReadMessage(shellSocketFD, buffer);
+	    if(strcmp(buffer, "input_finished")==0)
+		break;
+	    data.append(buffer);
+	    data.append("@");
+	    /*FD_ZERO(&sockSet);
+	    FD_SET(miss[activeMission].services[sourceID].socketFD, &sockSet);
+	    selTimeout.tv_sec = 0;
+	    selTimeout.tv_usec = 50000;
+	    //Check if there is a message on the CE socket ready to be processed
+	    rc=select(miss[activeMission].services[sourceID].socketFD + 1, &sockSet, NULL, NULL, &selTimeout);*/
+	}//while(rc!=0);;
+
+	strcpy(_data_DB->command, "insert into ");
+    	strcat(_data_DB->command, _data_DB->tablename); 
+      	strcat(_data_DB->command, " (");
+    	strcat(_data_DB->command, cols[0]);
+    	strcat(_data_DB->command, ", ");
+	strcat(_data_DB->command, cols[1]);
+	strcat(_data_DB->command, ") ");
+	strcat(_data_DB->command, " values('");
+	strcat(_data_DB->command, miss[activeMission].input[i].c_str());
+	strcat(_data_DB->command, "', '");
+	strcat(_data_DB->command, data.c_str());
+	strcat(_data_DB->command, "');");
+    	char *errorMsg;
+   	rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
+   	if( rc!=SQLITE_OK && rc!=101 )
+   	    fprintf(stderr, "SQL error: %s\n", errorMsg);
+        printf("SML: finished adding data from shell on input %d\n", i);
+        i++;
+
+    }
+    i=0;
+    data.clear();
+    while(i < miss[activeMission].numServices)
+    {
+	if(miss[activeMission].services[i].name.compare("if")==0)
+	{
+	    printf("if detected\n");
+	    input.clear();
+	    check.clear();
+	    if(!miss[activeMission].services[i].input[0].empty()){
+		input=miss[activeMission].services[i].input[0];
+		check = "true@";
+	    }
+	    else{
+		input=miss[activeMission].services[i].input[1];
+		check = "false@";
+	    }
+            printf("input=%s\n", input.c_str());
+
+            strcpy(_data_DB->command, "SELECT ");
+   	    strcat(_data_DB->command, _data_DB->tablename);
+	    strcat(_data_DB->command, ".* from ");
+	    strcat(_data_DB->command, _data_DB->tablename);
+    	    strcat(_data_DB->command, " where Tag==");
+	    sprintf(_data_DB->command, "%s'%s';", _data_DB->command, input.c_str());
+            sqlite3_stmt * pStatement;
+            int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL);
+            if (rc == SQLITE_OK){ 
+                if (sqlite3_step(pStatement) == SQLITE_ROW)
+	             data = (const char *) sqlite3_column_text(pStatement, 1); 
+                else {
+	                printf("1 data_DB:: Data not yet in DB. %d\n", i);
+		        rc=31337;
+	        }
+            } else {
+	        printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command);
+            }
+
+    	    sqlite3_finalize(pStatement);
+	    printf("data=%s, check=%s\n", data.c_str(), check.c_str());
+	    if(data.compare(check)==0){
+		printf("if taken\n");
+		for(int k = i + 1; k <= i + miss[activeMission].services[i].num_conds; k++)
+		    TransactData(k);
+	    }
+	    else{
+		i+=miss[activeMission].services[i].num_conds;
+		printf("if not taken %d\n", miss[activeMission].services[i].num_conds);
+	    }
+	}
+	else if(miss[activeMission].services[i].name.compare("while")==0)
+	{
+	    printf("while detected\n");
+	    while(true){
+		    data.clear();
+	            input.clear();
+	            check.clear();
+		    if(!miss[activeMission].services[i].input[0].empty()){
+			input=miss[activeMission].services[i].input[0];
+			check = "true@";
+		    }
+		    else{
+			input=miss[activeMission].services[i].input[1];
+			check = "false@";
+		    }
+		    strcpy(_data_DB->command, "select ");
+	   	    strcat(_data_DB->command, _data_DB->tablename);
+	    	    strcat(_data_DB->command, ".* from ");
+	    	    strcat(_data_DB->command, _data_DB->tablename);
+	    	    strcat(_data_DB->command, " where Tag==");
+		    sprintf(_data_DB->command, "%s'%s';", _data_DB->command, input.c_str());
+		    sqlite3_stmt * pStatement;
+		    int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL);
+		    if (rc == SQLITE_OK){ 
+		        if (sqlite3_step(pStatement) == SQLITE_ROW)
+			    data = (const char *) sqlite3_column_text(pStatement, 1); 
+		        else 
+			    printf("1 data_DB:: Data not yet in DB. %d\n", i);
+		    } 
+		    else {
+			printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command);
+		    }
+
+	    	    sqlite3_finalize(pStatement);
+		    printf("data=%s, check=%s\n", data.c_str(), check.c_str());
+		    if(data.compare(check)==0){
+			printf("while taken\n");
+			for(int k = i + 1; k <= i + miss[activeMission].services[i].num_conds; k++)
+			    TransactData(k);
+		    }
+		    else{
+			i+=miss[activeMission].services[i].num_conds;
+			printf("while not taken %d\n", miss[activeMission].services[i].num_conds);
+			break;
+		    }
+	    }
+	}
+	else{
+	    TransactData(i);}
+	i++;
+    }
+    i=0;
+    data.clear();
+    //get the ouptuts
+    while(i < 3 && !miss[activeMission].output[i].empty()){
+	printf("sending output data to shell\n");
+        strcpy(_data_DB->command, "select ");
+   	strcat(_data_DB->command, _data_DB->tablename);
+    	strcat(_data_DB->command, ".* from ");
+    	strcat(_data_DB->command, _data_DB->tablename);
+    	strcat(_data_DB->command, " where Tag==");
+	sprintf(_data_DB->command, "%s'%s';", _data_DB->command, miss[activeMission].output[i].c_str());
+        sqlite3_stmt * pStatement;
+        int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL);
+        if (rc == SQLITE_OK){ 
+            if (sqlite3_step(pStatement) == SQLITE_ROW)
+	         data.append((const char*) sqlite3_column_text(pStatement, 1)); 
+            else {
+	            printf("data_DB:: Data not yet in DB.\n");
+		    rc=31337;
+	    }
+        } 
+	else {
+	    printf("services_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command);
+        }
+        sqlite3_finalize(pStatement);
+	char *data_ch = (char *) data.c_str();
+	char *token = strtok(data_ch, "@");
+	while(token){
+	    SendMessage(shellSocketFD, token);
+	    token = strtok(NULL, "@");
+	}
+	i++;
+	printf("done sending output data to shell\n");
+    }
+}
+
+
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Print a list of the services currently registered and the ID's of the components that registered them
+ */
 void 
 ServiceManagementLayer::ListServices()
 {
-}
-
-
+    // generate commandi
+    strcpy(_services_DB->command, "select ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    strcat(_services_DB->command, ".* from ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    strcat(_services_DB->command, ";");
+
+    // execute print (select all)  command    
+    char *errorMsg;
+    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "SQL error: %s\n", errorMsg);
+    printf("database %s, table %s:\n", _services_DB->filename, _services_DB->tablename);
+}
+
+/* CALLED BY: Reset
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Clear and reinitialize the mission array, then reload the configuration file
+ */
 void 
 ServiceManagementLayer::ReloadConfiguration()
 {
     LOG("ServiceManagementLayer:: Reloading Configuration.\n");
-}
-
-
+    free(miss);
+    miss = new Mission[10];
+    for(int i = 0; i < 10; i++)
+    	miss[i].services = new Service[20];
+    LoadConfiguration(_SML_Config, miss);
+}
+
+/* CALLED BY: constructor
+ * INPUTS: |SML_Config| Address (either relitive or full) of the XML file containing mission data
+ * 	   |mList| Mission array to be modified 
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: IMPORTANT - See formatting instructions for correct parsing of data
+ * Can currently handle 3 inputs and 3 outputs per service, but easily expandable
+ * Also, can handle one layer of nested conditional statements, but could
+ * be expanded to meet additional needs.  Only support now is for straight bool flags,
+ * but support could be added for more complex conditionals later.
+ * 
+ * Components assigned to mission during "set active mission" stage so that
+ * components can still continue to register after the configuration is loaded
+ */
 void 
-ServiceManagementLayer::LoadConfiguration()
-{
-    LOG("ServiceManagementLayer:: Loading Configuration.\n");
-}
-
+ServiceManagementLayer::LoadConfiguration(const char *SML_Config, Mission* &mList)
+{
+    TiXmlElement *pMission;
+    TiXmlElement *pService;
+    TiXmlElement *pChild0, *pChild1, *pChild2, *pChild3;
+    TiXmlHandle hRoot(0);
+    //printf("ServiceManagementLayer:: Loading Configuration.\n");
+    TiXmlDocument doc(".");
+    doc.LoadFile(SML_Config);
+    bool loadOkay = doc.LoadFile();
+    if(!loadOkay)
+        printf("Loading SML configuration failed: %s\n", SML_Config);
+
+    TiXmlHandle hDoc(&doc);
+    
+    pMission = hDoc.FirstChildElement().Element();
+
+    if(!pMission) 
+        printf("No valid root!");
+
+    hRoot = TiXmlHandle(pMission);
+    pService = pMission->FirstChildElement();
+    int32_t mission_num = 0;
+    //Iterate through the missions
+    for(pChild0 = pMission->FirstChildElement(); pChild0 ; \
+        pChild0 = pChild0->NextSiblingElement()) 
+    {
+	int32_t service_num = 0;
+	uint16_t cond_array[] = {0, 0};
+	//printf("mission_num = %d\n", mission_num);
+	memset(cond_array, 0, 2);
+	
+    	for(pChild1  = pChild0->FirstChildElement(); pChild1; \
+      	    pChild1  = pChild1->NextSiblingElement()) 
+    	{
+	    int32_t conditional_0 = service_num;
+	    for(pChild2 = pChild1->FirstChildElement(); \
+		pChild2; pChild2 = pChild2->NextSiblingElement())
+	    {
+		service_num++;
+		int32_t conditional_1 = service_num;
+		for(pChild3 = pChild2->FirstChildElement(); \
+		    pChild3; pChild3 = pChild3 ->NextSiblingElement())
+		{
+		    service_num++;
+		    mList[mission_num].services[service_num].name = pChild3->Attribute("name");
+                    if(pChild3->Attribute("input1"))
+			mList[mission_num].services[service_num].input[0] = pChild3->Attribute("input1");
+                    if(pChild3->Attribute("input2"))
+			mList[mission_num].services[service_num].input[1] = pChild3->Attribute("input2");
+                    if(pChild3->Attribute("input3"))
+			mList[mission_num].services[service_num].input[2] = pChild3->Attribute("input3");
+                    if(pChild3->Attribute("output1"))
+			mList[mission_num].services[service_num].output[0] = pChild3->Attribute("output1");
+                    if(pChild3->Attribute("output2"))
+			mList[mission_num].services[service_num].output[1] = pChild3->Attribute("output2");
+                    if(pChild3->Attribute("output3"))
+			mList[mission_num].services[service_num].output[2] = pChild3->Attribute("output3");
+		    cond_array[1]++;
+		}
+
+		if(conditional_1 != service_num){
+		    mList[mission_num].services[conditional_1].name = pChild2->Value();
+                    if(pChild2->Attribute("input_t"))
+			mList[mission_num].services[conditional_1].input[0] = pChild2->Attribute("input_t");
+                    if(pChild2->Attribute("input_f"))
+			mList[mission_num].services[conditional_1].input[1] = pChild2->Attribute("input_f");
+		}
+		else{
+		    mList[mission_num].services[conditional_1].name = pChild2->Attribute("name");
+                    if(pChild2->Attribute("input1"))
+			mList[mission_num].services[service_num].input[0] = pChild2->Attribute("input1");
+                    if(pChild2->Attribute("input2"))
+			mList[mission_num].services[service_num].input[1] = pChild2->Attribute("input2");
+                    if(pChild2->Attribute("input3"))
+			mList[mission_num].services[service_num].input[2] = pChild2->Attribute("input3");
+                    if(pChild2->Attribute("output1"))
+			mList[mission_num].services[service_num].output[0] = pChild2->Attribute("output1");
+                    if(pChild2->Attribute("output2"))
+			mList[mission_num].services[service_num].output[1] = pChild2->Attribute("output2");
+                    if(pChild2->Attribute("output3"))
+			mList[mission_num].services[service_num].output[2] = pChild2->Attribute("output3");
+		}
+
+		mList[mission_num].services[conditional_1].num_conds = cond_array[1];
+		cond_array[1] = 0;
+		cond_array[0]++;
+	    }
+	    if(conditional_0 != service_num){
+		mList[mission_num].services[conditional_0].name = pChild1->Value();
+                    if(pChild1->Attribute("input_t"))
+			mList[mission_num].services[conditional_0].input[0] = pChild1->Attribute("input_t");
+                    if(pChild1->Attribute("input_f"))
+			mList[mission_num].services[conditional_0].input[1] = pChild1->Attribute("input_f");
+		//printf("---input_t=%s\n", mList[mission_num].services[conditional_0].input[0].c_str());
+	    }
+	    else{
+		mList[mission_num].services[conditional_0].name = pChild1->Attribute("name");
+                if(pChild1->Attribute("input1"))
+	            mList[mission_num].services[service_num].input[0] = pChild1->Attribute("input1");
+                if(pChild1->Attribute("input2"))
+		    mList[mission_num].services[service_num].input[1] = pChild1->Attribute("input2");
+                if(pChild1->Attribute("input3"))
+		    mList[mission_num].services[service_num].input[2] = pChild1->Attribute("input3");
+                if(pChild1->Attribute("output1"))
+		    mList[mission_num].services[service_num].output[0] = pChild1->Attribute("output1");
+                if(pChild1->Attribute("output2"))
+		    mList[mission_num].services[service_num].output[1] = pChild1->Attribute("output2");
+                if(pChild1->Attribute("output3"))
+		    mList[mission_num].services[service_num].output[2] = pChild1->Attribute("output3");
+	    }
+
+	    mList[mission_num].services[conditional_0].num_conds = cond_array[0];
+            cond_array[0] = 0;
+	    service_num++;
+	}
+	//for(int i = 0; i < service_num; i++)
+	 //printf("%d, input1=%s, output1=%s\n", i, mList[mission_num].services[i].input[0].c_str(), mList[mission_num].services[i].output[0].c_str());
+
+	mList[mission_num].numServices = service_num;
+	mList[mission_num].name = pChild0->Attribute("name");
+	mList[mission_num].missionID = atoi(pChild0->Attribute("id"));
+        if(pChild0->Attribute("input1"))
+	    mList[mission_num].input[0] = pChild0->Attribute("input1");
+        if(pChild0->Attribute("input2"))
+	    mList[mission_num].input[1] = pChild0->Attribute("input2");
+        if(pChild0->Attribute("input3"))
+	    mList[mission_num].input[2] = pChild0->Attribute("input3");
+        if(pChild0->Attribute("output1"))
+	    mList[mission_num].output[0] = pChild0->Attribute("output1");
+        if(pChild0->Attribute("output2"))
+	    mList[mission_num].output[1] = pChild0->Attribute("output2");
+        if(pChild0->Attribute("output3"))
+	    mList[mission_num].output[2] = pChild0->Attribute("output3");
+	//printf("mis, input1=%s, output1=%s\n", mList[mission_num].input[0].c_str(), mList[mission_num].output[0].c_str());
+	mission_num++;
+    }
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: |ID| The ID number of the engine to be registered
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Sends a registration message onto the shell and sends the ACK back to the component
+ */
+void
+ServiceManagementLayer::RegisterCognitiveEngine(int32_t ID)
+{
+    SendMessage(shellSocketFD, "register_engine_cognitive");
+    LOG("ServiceManagementLayer:: CE registration message forwarded to shell.\n");
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(shellSocketFD, buffer);
+    SendMessage(CE_List[ID].FD, buffer);
+
+    //TODO UNCOMMENT!!!
+    //TODO UNCOMMENT!!!
+    /*TransferRadioConfiguration(ID);
+    memset(buffer, 0, 256);
+    TransferExperience(ID);
+    memset(buffer, 0, 256);*/
+    numberOfCognitiveEngines++;
+    CE_Present = true;
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: |ID| The ID number of the engine to have it's services deregistered
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Deletes individual services from the DB
+ * NOTE THAT this function only needs to be called if service deregistration is going
+ * to be done at a different time than component deregistration; it is handled
+ * more efficiently and directly during that deregistration process.
+ */
+void 
+ServiceManagementLayer::DeregisterServices(int32_t ID)
+{
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(CE_List[ID].FD, buffer); 
+    strcpy(_services_DB->command, "DELETE FROM ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    strcat(_services_DB->command, " WHERE ID_Num IN (SELECT");
+    sprintf(_services_DB->command, " %s %d",_services_DB->command, ID);
+    strcat(_services_DB->command, " FROM ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    strcat(_services_DB->command, " WHERE Service_Name");
+    strcat(_services_DB->command, "==");
+    sprintf(_services_DB->command, "%s'%s');", _services_DB->command, buffer);
+    char *errorMsg;
+    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "SQL error: %s\n", errorMsg);
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: |ID| The ID number of the engine to have it's services deregistered
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Deletes the contact info for the cognitive engine, forwards a deregistration message to the shell
+ * Also, deletes the services from the DB
+ */
+void 
+ServiceManagementLayer::DeregisterCognitiveEngine(int32_t ID)
+{
+    LOG("ServiceManagementLayer:: CE deregistration message forwarded to shell.\n");
+
+    numberOfCognitiveEngines--;
+    if(numberOfCognitiveEngines == 0)
+        CE_Present = false;
+
+    SendMessage(shellSocketFD, "deregister_engine_cognitive");
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(shellSocketFD, buffer);
+    SendMessage(CE_List[ID].FD, buffer);
+    if(strcmp("deregister_ack", buffer) != 0) {
+	ERROR(1, "SML:: Failed to close CE socket\n");
+    }
+
+    //Deregister the services
+    strcpy(_services_DB->command, "DELETE FROM ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    strcat(_services_DB->command, " WHERE ");
+    strcat(_services_DB->command, "ID_Num");
+    strcat(_services_DB->command, "==");
+    sprintf(_services_DB->command, "%s%d;", _services_DB->command, ID);
+    char *errorMsg;
+    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "SQL error: %s\n", errorMsg);
+
+
+    CE_List[ID].FD = -1;
+    CE_List[ID].ID_num = -1;
+
+    LOG("Cognitive Radio Shell:: CE Socket closed for engine #%d.\n", ID);
+}
+
+
+/* CALLED BY: test class
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Sets up a server socket and listens for communication on either that or the shell socket
+ */
+void
+ServiceManagementLayer::StartSMLServer()
+{
+    struct timeval selTimeout;
+    int32_t running = 1;
+    int32_t port, rc, new_sd = 1;
+    int32_t desc_ready = 1;
+    int32_t timeout = 10;
+		//If there is, call the MessageHandler with the Shell_Msg code of -1
+    fd_set sockSet, shellSet;
+
+    cogEngSrv = CreateTCPServerSocket(2044);
+    int32_t maxDescriptor = cogEngSrv;
+
+    if(InitializeTCPServerPort(cogEngSrv) == -1)
+        ERROR(1,"Error initializing primary port\n");
+
+    int i = 10000000;  //TODO change to "running" if endpoint can be reached
+    while (i>0) {
+        i--;
+        /* Zero socket descriptor vector and set for server sockets */
+        /* This must be reset every time select() is called */
+        FD_ZERO(&sockSet);
+        FD_SET(cogEngSrv, &sockSet);
+        for(int k = 0; k < Current_ID; k++){
+	    if(CE_List[k].ID_num != -1)
+	        FD_SET(CE_List[k].FD, &sockSet);
+	}
+	    //printf("k=%d, CID=%d\n", k, CE_List[k].FD);
+
+        /* Timeout specification */
+        /* This must be reset every time select() is called */
+        selTimeout.tv_sec = 0;       /* timeout (secs.) */
+        selTimeout.tv_usec = 0;            /* 0 microseconds */
+	//Changed both to zero so that select will check messages from the shell instead of blocking
+	//when there is no command from the CE's to be processed
+
+        //Check if there is a message on the socket waiting to be read
+	rc = select(maxDescriptor + 1, &sockSet, NULL, NULL, &selTimeout); 
+        //printf("rc=%d\n", rc);
+        if(rc == 0){
+            //LOG("No echo requests for %i secs...Server still alive\n", timeout);
+	
+            FD_ZERO(&shellSet);
+            FD_SET(shellSocketFD, &shellSet);
+            selTimeout.tv_sec = 0;
+            selTimeout.tv_usec = 0;
+            //Check if there is a message on the shell socket ready to be processed
+            int rc2 = select(shellSocketFD + 1, &shellSet, NULL, NULL, &selTimeout);
+            //printf("rc2=%d\n", rc2);
+		//If there is, call the MessageHandler with the Shell_Msg code of -1
+	    if(FD_ISSET(shellSocketFD, &shellSet)){
+		//printf("shell_msg, %d\n", rc2);
+	        MessageHandler(-1);}
+	}
+        else { 
+            desc_ready = rc;
+            for(port = 0; port <= maxDescriptor && desc_ready > 0; port++) {
+                if(FD_ISSET(port, &sockSet)) {
+                    desc_ready -= 1;
+
+                    //Check if request is new or on an existing open descriptor
+                    if(port == cogEngSrv) { 
+			//If new, assign it a descriptor and give it an ID
+                        new_sd = AcceptTCPConnection(port);
+			 
+                        if(new_sd < 0) 
+                            break;
+
+                        CE_List[Current_ID].FD = new_sd;
+			CE_List[Current_ID].ID_num = Current_ID;
+                        MessageHandler(Current_ID);
+			Current_ID++;
+	
+			FD_SET(new_sd,&sockSet);
+                        if(new_sd > maxDescriptor) 
+                           maxDescriptor = new_sd;
+                    } 
+                    else {
+			//If old, figure out which ID it coresponds to and handle it accordingly
+			for(int16_t z = 0; z < Current_ID; z++)
+			{
+				if(CE_List[z].FD == port){
+					MessageHandler(z);}
+			}
+                    }
+                }
+            }
+	}
+    }        
+
+    /* Close sockets */
+    close(cogEngSrv);
+
+    //delete &cogEngSrv;
+    return;
+}
+
+
+
+
+    /*TiXmlElement *pMission;
+    TiXmlElement *pService;
+    TiXmlElement *pChild0, *pChild1, *pChild2, *pChild3;
+    TiXmlHandle hRoot(0);
+    //printf("ServiceManagementLayer:: Loading Configuration.\n");
+    TiXmlDocument doc(".");
+    doc.LoadFile(SML_Config);
+    bool loadOkay = doc.LoadFile();
+    if(!loadOkay)
+        printf("Loading SML configuration failed: %s\n", SML_Config);
+
+    TiXmlHandle hDoc(&doc);
+    
+    pMission = hDoc.FirstChildElement().Element();
+
+    if(!pMission) 
+        printf("No valid root!");
+
+    hRoot = TiXmlHandle(pMission);
+    pService = pMission->FirstChildElement();
+    int32_t mission_num = 0;
+    //Iterate through the missions
+    for(pChild0 = pMission->FirstChildElement(); pChild0 ; \
+        pChild0 = pChild0->NextSiblingElement()) 
+    {
+	int32_t service_num = 0;
+	uint16_t cond_array[] = {0, 0};
+	//printf("mission_num = %d\n", mission_num);
+	memset(cond_array, 0, 2);
+	
+    	for(pChild1  = pChild0->FirstChildElement(); pChild1; \
+      	    pChild1  = pChild1->NextSiblingElement()) 
+    	{
+	    int32_t conditional_0 = service_num;
+	    for(pChild2 = pChild1->FirstChildElement(); \
+		pChild2; pChild2 = pChild2->NextSiblingElement())
+	    {
+		service_num++;
+		int32_t conditional_1 = service_num;
+		for(pChild3 = pChild2->FirstChildElement(); \
+		    pChild3; pChild3 = pChild3 ->NextSiblingElement())
+		{
+		    service_num++;
+		    mList[mission_num].services[service_num].name = pChild3->Attribute("name");
+                    if(pChild3->Attribute("input1"))
+			mList[mission_num].services[service_num].input[0] = pChild3->Attribute("input1");
+                    if(pChild3->Attribute("input2"))
+			mList[mission_num].services[service_num].input[1] = pChild3->Attribute("input2");
+                    if(pChild3->Attribute("input3"))
+			mList[mission_num].services[service_num].input[2] = pChild3->Attribute("input3");
+                    if(pChild3->Attribute("output1"))
+			mList[mission_num].services[service_num].output[0] = pChild3->Attribute("output1");
+                    if(pChild3->Attribute("output2"))
+			mList[mission_num].services[service_num].output[1] = pChild3->Attribute("output2");
+                    if(pChild3->Attribute("output3"))
+			mList[mission_num].services[service_num].output[2] = pChild3->Attribute("output3");
+		    cond_array[1]++;
+		}
+
+		if(conditional_1 != service_num){
+		    mList[mission_num].services[conditional_1].name = pChild2->Value();
+                    if(pChild2->Attribute("input_t"))
+			mList[mission_num].services[conditional_1].input[0] = pChild2->Attribute("input_t");
+                    if(pChild2->Attribute("input_f"))
+			mList[mission_num].services[conditional_1].input[1] = pChild2->Attribute("input_f");
+		}
+		else{
+		    mList[mission_num].services[service_num].name = pChild2->Attribute("name");
+                    if(pChild2->Attribute("input1"))
+			mList[mission_num].services[service_num].input[0] = pChild2->Attribute("input1");
+                    if(pChild2->Attribute("input2"))
+			mList[mission_num].services[service_num].input[1] = pChild2->Attribute("input2");
+                    if(pChild2->Attribute("input3"))
+			mList[mission_num].services[service_num].input[2] = pChild2->Attribute("input3");
+                    if(pChild2->Attribute("output1"))
+			mList[mission_num].services[service_num].output[0] = pChild2->Attribute("output1");
+                    if(pChild2->Attribute("output2"))
+			mList[mission_num].services[service_num].output[1] = pChild2->Attribute("output2");
+                    if(pChild2->Attribute("output3"))
+			mList[mission_num].services[service_num].output[2] = pChild2->Attribute("output3");
+		}
+
+		mList[mission_num].services[conditional_1].num_conds = cond_array[1];
+		cond_array[1] = 0;
+		cond_array[0]++;
+	    }
+	    if(conditional_0 != service_num){
+		mList[mission_num].services[conditional_0].name = pChild1->Value();
+                if(pChild1->Attribute("input_t"))
+		    mList[mission_num].services[conditional_0].input[0] = pChild1->Attribute("input_t");
+                if(pChild1->Attribute("input_f"))
+		    mList[mission_num].services[conditional_0].input[1] = pChild1->Attribute("input_f");
+		printf("if detected %s, %s\n", pChild1->Attribute("input_f"), pChild1->Attribute("input_t"));
+	    }
+	    else{
+		mList[mission_num].services[service_num].name = pChild1->Attribute("name");
+                if(pChild1->Attribute("input1"))
+	            mList[mission_num].services[service_num].input[0] = pChild1->Attribute("input1");
+                if(pChild1->Attribute("input2"))
+		    mList[mission_num].services[service_num].input[1] = pChild1->Attribute("input2");
+                if(pChild1->Attribute("input3"))
+		    mList[mission_num].services[service_num].input[2] = pChild1->Attribute("input3");
+                if(pChild1->Attribute("output1"))
+		    mList[mission_num].services[service_num].output[0] = pChild1->Attribute("output1");
+                if(pChild1->Attribute("output2"))
+		    mList[mission_num].services[service_num].output[1] = pChild1->Attribute("output2");
+                if(pChild1->Attribute("output3"))
+		    mList[mission_num].services[service_num].output[2] = pChild1->Attribute("output3");
+	    }
+
+	    mList[mission_num].services[conditional_0].num_conds = cond_array[0];
+	    //printf("hello\n");
+	    
+            cond_array[0] = 0;
+	    service_num++;
+	}
+	for(int i = 0; i < service_num; i++)
+		printf("input1=%s, output1=%s\n", mList[mission_num].services[i].input[0].c_str(), mList[mission_num].services[service_num].output[0].c_str());
+
+	mList[mission_num].numServices = service_num;
+	mList[mission_num].name = pChild0->Attribute("name");
+	mList[mission_num].missionID = atoi(pChild0->Attribute("id"));
+        if(pChild0->Attribute("input1"))
+	    mList[mission_num].input[0] = pChild0->Attribute("input1");
+        if(pChild0->Attribute("input2"))
+	    mList[mission_num].input[1] = pChild0->Attribute("input2");
+        if(pChild0->Attribute("input3"))
+	    mList[mission_num].input[2] = pChild0->Attribute("input3");
+        if(pChild0->Attribute("output1"))
+	    mList[mission_num].output[0] = pChild0->Attribute("output1");
+        if(pChild0->Attribute("output2"))
+	    mList[mission_num].output[1] = pChild0->Attribute("output2");
+        if(pChild0->Attribute("output3"))
+	    mList[mission_num].output[2] = pChild0->Attribute("output3");
+	printf("input1=%s, outpu1=%s\n", mList[mission_num].input[0].c_str(), mList[mission_num].output[0].c_str());
+	mission_num++;
+    }*/
