Changeset 275

Show
Ignore:
Timestamp:
06/08/09 16:15:11 (15 years ago)
Author:
wrodgers
Message:

Updated data management, added function descriptions, fixed a few errors

Location:
vtcross/branches/wrodgers/src
Files:
1 added
1 modified
5 copied

Legend:

Unmodified
Added
Removed
  • vtcross/branches/wrodgers/src/include/vtcross/components.h

    r268 r275  
    169169         */ 
    170170        void CreateServicesDB(); 
     171        void CreateDataDB(); 
    171172 
    172173        void PerformActiveMission(); 
    173         void TransactData(int32_t sourceID, int32_t destID); 
     174        void TransactData(int32_t sourceID); 
    174175 
    175176 
  • vtcross/branches/wrodgers/src/service_management_layer/ServiceManagementLayer.cpp

    r206 r275  
    55 */ 
    66 
    7 /* DESCRIPTION OF FILE. 
    8  */ 
     7/* Inter-component communication handled by sockets and FD's.   
     8 * Server support has been completely implemented and tested. 
     9 * 
     10 * Services are stored in a SQLite DB by the ID of the CE that registered them.  Service 
     11 * support has been completely implemented and tested. 
     12 * 
     13 * Missions are loaded from an XML file, connected with services provided by components, 
     14 * and run.  See the documentation for the "PerformActiveMission" below for important  
     15 * info.   
     16 * 
     17 * NOTE THAT the RegisterServices method works differently than it is described in the documentation 
     18 * this will be fixed in a future release 
     19 */ 
     20 
     21//TODO Verify while 
     22//TODO Add nested conditional support 
     23//TODO Verify update functionality 
     24//TODO Better shutdown 
     25 
     26#include <stdlib.h> 
     27#include <string.h> 
     28#include <stdio.h> 
     29#include <cstring> 
     30#include <stdint.h> 
     31 
     32#include "../include/vtcross/common.h" 
     33 
     34#include "../include/vtcross/components.h" 
     35#include "../include/vtcross/containers.h" 
     36#include "../include/vtcross/debug.h" 
     37#include "../include/vtcross/error.h" 
     38#include "../include/vtcross/socketcomm.h" 
     39 
     40/*#include "../../trunk/src/include/vtcross/common.h" 
     41 
     42#include "../../trunk/src/include/vtcross/components.h" 
     43#include "../../trunk/src/include/vtcross/containers.h" 
     44#include "../../trunk/src/include/vtcross/debug.h" 
     45#include "../../trunk/src/include/vtcross/error.h" 
     46#include "../../trunk/src/include/vtcross/socketcomm.h"*/ 
    947 
    1048 
     
    1250#include <cstring> 
    1351#include <stdint.h> 
    14  
    15 #include "vtcross/common.h" 
    16 #include "vtcross/components.h" 
    17 #include "vtcross/containers.h" 
    18 #include "vtcross/debug.h" 
    19 #include "vtcross/error.h" 
    20 #include "vtcross/socketcomm.h" 
     52#include <math.h> 
     53 
     54#include <arpa/inet.h> 
     55#include <iostream> 
     56#include <netinet/in.h> 
     57#include <netdb.h> 
     58#include <fcntl.h> 
     59#include <sys/ioctl.h> 
     60#include <sys/mman.h> 
     61#include <sys/socket.h> 
     62#include <sys/types.h> 
     63#include <sys/wait.h> 
     64 
     65//#include "../../trunk/src/include/tinyxml/tinyxml.h" 
     66//#include "../../trunk/src/include/tinyxml/tinystr.h" 
     67 
     68#include "../include/tinyxml/tinyxml.h" 
     69#include "../include/tinyxml/tinystr.h" 
     70 
     71#include "sqlite3.h" 
     72//#include "sqlite3ext.h" 
     73 
     74typedef struct services_s *services_DB; 
     75typedef struct data_s *data_DB; 
     76 
     77using namespace std; 
     78 
     79struct services_s { 
     80    char filename[64]; 
     81    char tablename[64]; 
     82    char command[2048]; 
     83    sqlite3 *db;  
     84    unsigned int num_columns; 
     85}; 
     86 
     87struct data_s { 
     88    char filename[64]; 
     89    char tablename[64]; 
     90    char command[2048]; 
     91    sqlite3 *db;  
     92    unsigned int num_columns; 
     93}; 
     94 
     95services_DB _services_DB; 
     96data_DB _data_DB; 
     97const char *_SML_Config; 
     98 
     99//Callback function used internally by some of the SQLite3 commands 
     100int callback(void *notUsed, int argc, char **argv, char **azColName){ 
     101    int i; 
     102    for(i=0; i<argc; i++){ 
     103        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); 
     104    } 
     105    printf("\n"); 
     106    return 0; 
     107} 
     108 
    21109 
    22110 
     
    25113    LOG("Creating Service Management Layer.\n"); 
    26114    shellSocketFD = -1; 
    27     LoadConfiguration(); 
    28 } 
    29  
    30  
     115    numberOfCognitiveEngines = 0; 
     116    CE_Present = false; 
     117    cogEngSrv = 1; 
     118} 
     119 
     120//Free and clear the DB's associated with this SML in the destructor 
     121//Note that exiting with an error condition will cause SML to not be destructed, 
     122// resulting in the DB's staying in memory until the destructor is encountered in future executions 
    31123ServiceManagementLayer::~ServiceManagementLayer() 
    32124{ 
    33 } 
    34  
    35  
    36 ServiceManagementLayer::ServiceManagementLayer(const char* serverName, \ 
    37         const char* serverPort) 
     125    char *errorMsg; 
     126    strcpy(_services_DB->command, "drop table "); 
     127    strcat(_services_DB->command, _services_DB->tablename); 
     128    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg); 
     129    if( rc!=SQLITE_OK && rc!=101 ) 
     130        fprintf(stderr, "1SQL error: %s\n", errorMsg); 
     131    strcpy(_services_DB->command, "vacuum"); 
     132    rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg); 
     133    if( rc!=SQLITE_OK && rc!=101 ) 
     134        fprintf(stderr, "1SQL error: %s\n", errorMsg); 
     135    free(_services_DB); 
     136 
     137    strcpy(_data_DB->command, "drop table "); 
     138    strcat(_data_DB->command, _data_DB->tablename); 
     139    rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg); 
     140    if( rc!=SQLITE_OK && rc!=101 ) 
     141        fprintf(stderr, "2SQL error (1): %s\n", errorMsg); 
     142    strcpy(_data_DB->command, "vacuum"); 
     143    rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg); 
     144    if( rc!=SQLITE_OK && rc!=101 ) 
     145        fprintf(stderr, "2SQL error (2): %s\n", errorMsg); 
     146    free(_data_DB); 
     147} 
     148 
     149//Note that sizes of CE_List, miss, and service are hardcoded for now. 
     150//Also, their sizes are hardcoded into the code in various places; a fix for a future version. 
     151ServiceManagementLayer::ServiceManagementLayer(const char* SML_Config, \ 
     152        const char* serverName, const char* serverPort) 
    38153{ 
    39154    LOG("Creating Service Management Layer.\n"); 
     155    _SML_Config = SML_Config; 
    40156 
    41157    ConnectToShell(serverName, serverPort); 
    42  
    43     LoadConfiguration(); 
    44 } 
    45  
    46  
     158    CE_List = (CE_Reg *) malloc(10*sizeof(struct CE_Reg)); 
     159    CE_List = new CE_Reg[10]; 
     160 
     161    miss = new Mission[10]; 
     162    for(int i = 0; i < 10; i++) 
     163        miss[i].services = new Service[20]; 
     164 
     165    Current_ID = 0; 
     166 
     167    LoadConfiguration(SML_Config, miss); 
     168    CreateServicesDB(); 
     169    CreateDataDB(); 
     170} 
     171 
     172/* CALLED BY: constructor 
     173 * INPUTS: <none> 
     174 * OUTPUTS: <none> 
     175 * 
     176 * DESCRIPTION: Create and initialize a DB to hold the services registered by components 
     177 */ 
     178void 
     179ServiceManagementLayer::CreateServicesDB() 
     180{ 
     181    _services_DB = (services_DB) malloc(sizeof(struct services_s)); 
     182    char *errorMsg; 
     183 
     184    // create database 
     185 
     186    // copy filename 
     187    unsigned int i=0; 
     188    strcpy(_services_DB->filename, "Services_Table"); 
     189 
     190    // execute create database command 
     191    // database handle 
     192    //_services_DB->db = NULL; 
     193    sqlite3_open(_services_DB->filename, &(_services_DB->db)); 
     194    char* cols[] = {(char *)"ID_Num", (char *)"Service_Name"}; 
     195 
     196    // create table 
     197 
     198    // copy tablename 
     199    strcpy(_services_DB->tablename, "Services"); 
     200 
     201    // number of columns in the table 
     202    _services_DB->num_columns = 2; 
     203 
     204    // generate command 
     205    strcpy(_services_DB->command, "CREATE TABLE "); 
     206    strcat(_services_DB->command, _services_DB->tablename); 
     207    strcat(_services_DB->command, "("); 
     208    //strcat(_services_DB->command, "SRVID INTEGER PRIMARY KEY, "); 
     209    strcat(_services_DB->command, cols[0]); 
     210    strcat(_services_DB->command, " INT, "); 
     211    strcat(_services_DB->command, cols[1]); 
     212    strcat(_services_DB->command, " TEXT"); 
     213    strcat(_services_DB->command, ");"); 
     214 
     215    // execute create table command 
     216  sqlite3_stmt *ppStmt;  /* OUT: Statement handle */ 
     217  const char *pzTail;     /* OUT: Pointer to unused portion of zSql */ 
     218 
     219    int rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command, 128, &ppStmt, &pzTail); 
     220    if( rc!=SQLITE_OK && rc!=101 ) 
     221        printf("SQL error(1): %d\n", rc); 
     222    rc = sqlite3_step(ppStmt); 
     223    if( rc!=SQLITE_OK && rc!=101 ) 
     224        printf("SQL error(2): %d\n", rc); 
     225} 
     226 
     227/* CALLED BY: constructor 
     228 * INPUTS: <none> 
     229 * OUTPUTS: <none> 
     230 * 
     231 * DESCRIPTION: Create and initialize a DB to hold the data sent by components 
     232 */ 
     233void 
     234ServiceManagementLayer::CreateDataDB() 
     235{ 
     236    _data_DB = (data_DB) malloc(sizeof(struct data_s)); 
     237    char *errorMsg; 
     238 
     239    // create database 
     240 
     241    // copy filename 
     242    unsigned int i=0; 
     243    strcpy(_data_DB->filename, "Data_Table"); 
     244 
     245    // execute create database command 
     246    // database handle 
     247    //_services_DB->db = NULL; 
     248    sqlite3_open(_data_DB->filename, &(_data_DB->db)); 
     249    char* cols[] = {(char *)"Tag", (char *)"Data"}; 
     250 
     251    // create table 
     252 
     253    // copy tablename 
     254    strcpy(_data_DB->tablename, "Data"); 
     255 
     256    // number of columns in the table 
     257    _data_DB->num_columns = 2; 
     258 
     259    // generate command 
     260    strcpy(_data_DB->command, "CREATE TABLE "); 
     261    strcat(_data_DB->command, _data_DB->tablename); 
     262    strcat(_data_DB->command, "("); 
     263    strcat(_data_DB->command, cols[0]); 
     264    //First column is the name of the data (coresponding to the name of the output/input pair) 
     265    //It is the primary key so any subsequent data with the same name will replace the row 
     266    strcat(_data_DB->command, " TEXT PRIMARY KEY ON CONFLICT REPLACE, "); 
     267    strcat(_data_DB->command, cols[1]); 
     268    strcat(_data_DB->command, " TEXT"); 
     269    strcat(_data_DB->command, ");"); 
     270 
     271    // execute create table command 
     272  sqlite3_stmt *ppStmt;  /* OUT: Statement handle */ 
     273  const char *pzTail;     /* OUT: Pointer to unused portion of zSql */ 
     274 
     275    int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, 128, &ppStmt, &pzTail); 
     276    if( rc!=SQLITE_OK && rc!=101 ) 
     277        printf("SQL error(1): %d\n", rc); 
     278    rc = sqlite3_step(ppStmt); 
     279    if( rc!=SQLITE_OK && rc!=101 ) 
     280        printf("SQL error(2): %d\n", rc); 
     281} 
     282 
     283/* CALLED BY: MessageHandler 
     284 * INPUTS: <none> 
     285 * OUTPUTS: <none> 
     286 * 
     287 * DESCRIPTION: Sends a message identifying this component as an SML to the Shell 
     288 */ 
    47289void  
    48290ServiceManagementLayer::SendComponentType() 
     
    52294} 
    53295 
    54  
     296/* CALLED BY: constructor 
     297 * INPUTS: |serverName| the IPv4 name of the server (127.0.0.1 for localhost) 
     298 *         |serverPort| the port on the server to connect to 
     299 * OUTPUTS: <none> 
     300 * 
     301 * DESCRIPTION: Connecting to the shell takes 2 steps 
     302 * 1) Establish a client socket for communication 
     303 * 2) Run the initial Registration/handshake routine 
     304 */ 
    55305void  
    56306ServiceManagementLayer::ConnectToShell(const char* serverName, \ 
     
    58308{ 
    59309    shellSocketFD = ClientSocket(serverName, serverPort); 
    60  
    61310    RegisterComponent(); 
    62311} 
    63312 
    64  
    65 void  
    66 ServiceManagementLayer::WaitForSignal() 
    67 { 
    68     char buffer[256]; 
    69  
    70     while(true) { 
    71         memset(buffer, 0, 256); 
    72         
    73         ReadMessage(shellSocketFD, buffer); 
    74  
    75         // TODO 
    76         // If we send integer op codes rather than strings, this process will be 
    77         // MUCH faster since instead of donig string compares we can simply 
    78         // switch on the integer value... 
    79         if(strcmp(buffer, "register_service") == 0) { 
    80             if(strcmp(buffer, "policy_geo") == 0) { 
    81             } 
    82             else if(strcmp(buffer, "policy_time") == 0) { 
    83             } 
    84             else if(strcmp(buffer, "policy_spectrum") == 0) { 
    85             } 
    86             else if(strcmp(buffer, "policy_spacial") == 0) { 
    87             } 
     313/* CALLED BY: StartSMLServer 
     314 * INPUTS: |ID| The ID number of the CE that has a message wating 
     315 * OUTPUTS: <none> 
     316 * 
     317 * DESCRIPTION: Called whenever a socket is identified as being ready for communication 
     318 *              This funciton reads the message and calls the appropriate helper 
     319 */  
     320void 
     321ServiceManagementLayer::MessageHandler(int32_t ID) 
     322{ 
     323    char buffer[256];    
     324    memset(buffer, 0, 256);   
     325    int32_t _FD;  
     326    //printf("ID= %d\n", ID);  
     327     
     328    if(ID != -1) 
     329        _FD = CE_List[ID].FD; 
     330    else  
     331        _FD = shellSocketFD; 
     332    ReadMessage(_FD, buffer); 
     333    /*//printf("FD=%d, shellFD=%d", _FD, shellSocketFD); 
     334    ssize_t msgLength = recv(_FD, buffer, 256, MSG_PEEK); 
     335    if(msgLength == 0){ 
     336        //printf("Error reading from socket.\n"); 
     337        //sleep(5);      
     338        return; 
     339    } 
     340 
     341 
     342    size_t i; 
     343    for(i = 0; i < 256; i++) { 
     344        if(strcmp(&buffer[i], "\0") == 0) 
     345            break; 
     346    } 
     347    // Read the message into msgBuffer 
     348    recv(_FD, buffer, i + 1, 0);*/ 
     349 
     350    //--------Policy Engine Stuff - no policy engine support in this version-------// 
     351 
     352    //printf("********* %s **********\n", buffer); 
     353    // TODO 
     354    // If we send integer op codes rather than strings, this process will be 
     355    // MUCH faster since instead of donig string compares we can simply 
     356    // switch on the integer value... 
     357    /*if(strcmp(buffer, "register_service") == 0) { 
     358        if(strcmp(buffer, "policy_geo") == 0) { 
    88359        } 
    89         else if(strcmp(buffer, "deregister_service") == 0) { 
    90             if(strcmp(buffer, "policy_geo") == 0) { 
    91             } 
    92             else if(strcmp(buffer, "policy_time") == 0) { 
    93             } 
    94             else if(strcmp(buffer, "policy_spectrum") == 0) { 
    95             } 
    96             else if(strcmp(buffer, "policy_spacial") == 0) { 
    97             } 
     360        else if(strcmp(buffer, "policy_time") == 0) { 
    98361        } 
    99         else if(strcmp(buffer, "query_component_type") == 0) { 
    100             SendComponentType(); 
     362        else if(strcmp(buffer, "policy_spectrum") == 0) { 
    101363        } 
    102         else if(strcmp(buffer, "reset_sml") == 0) { 
    103             Reset(); 
     364        else if(strcmp(buffer, "policy_spacial") == 0) { 
    104365        } 
    105         else if(strcmp(buffer, "shutdown_sml") == 0) { 
    106             Shutdown(); 
     366    } 
     367    else if(strcmp(buffer, "deregister_service") == 0) { 
     368        if(strcmp(buffer, "policy_geo") == 0) { 
    107369        } 
    108     } 
    109 } 
    110  
    111  
     370        else if(strcmp(buffer, "policy_time") == 0) { 
     371        } 
     372        else if(strcmp(buffer, "policy_spectrum") == 0) { 
     373        } 
     374        else if(strcmp(buffer, "policy_spacial") == 0) { 
     375        } 
     376    }*/ 
     377 
     378    //Go down the list to call the appropriate function 
     379    if(strcmp(buffer, "query_component_type") == 0) { 
     380        SendComponentType(); 
     381    } 
     382    else if(strcmp(buffer, "reset_sml") == 0) { 
     383        Reset(); 
     384    } 
     385    else if(strcmp(buffer, "shutdown_sml") == 0) { 
     386        Shutdown(); 
     387    } 
     388    else if(strcmp(buffer, "register_engine_cognitive") == 0) { 
     389        RegisterCognitiveEngine(ID); 
     390    } 
     391    else if(strcmp(buffer, "register_service") == 0) { 
     392        ReceiveServices(ID); 
     393    } 
     394    else if(strcmp(buffer, "send_component_type") == 0) { 
     395        SendComponentType(); 
     396    } 
     397    else if(strcmp(buffer, "list_services") == 0) { 
     398        ListServices(); 
     399    } 
     400    else if(strcmp(buffer, "set_active_mission") == 0) { 
     401        SetActiveMission(); 
     402    } 
     403    else if(strcmp(buffer, "request_optimization") == 0) { 
     404        PerformActiveMission(); 
     405    } 
     406    else if(strcmp(buffer, "deregister_engine_cognitive") == 0) { 
     407        DeregisterServices(ID); 
     408        DeregisterCognitiveEngine(ID); 
     409    } 
     410} 
     411 
     412//TODO Finish 
     413/* CALLED BY: MessageHandler 
     414 * INPUTS: <none> 
     415 * OUTPUTS: <none> 
     416 * 
     417 * DESCRIPTION: Deregisters the component from the Shell. 
     418 */  
    112419void  
    113420ServiceManagementLayer::Shutdown() 
     
    116423} 
    117424 
    118  
     425//TODO Finish 
     426/* CALLED BY: MessageHandler 
     427 * INPUTS: <none> 
     428 * OUTPUTS: <none> 
     429 * 
     430 * DESCRIPTION: Deregisters the component from the Shell 
     431 */ 
    119432void  
    120433ServiceManagementLayer::Reset() 
    121434{ 
    122435    DeregisterComponent(); 
    123     LoadConfiguration(); 
    124 } 
    125  
    126  
     436    LoadConfiguration(_SML_Config, miss); 
     437} 
     438 
     439/* CALLED BY: ConnectToShell 
     440 * INPUTS: <none> 
     441 * OUTPUTS: <none> 
     442 * 
     443 * DESCRIPTION: Sends the registration message to the Shell 
     444 */ 
    127445void  
    128446ServiceManagementLayer::RegisterComponent() 
     
    132450} 
    133451 
    134  
     452/* CALLED BY: Shutdown 
     453 * INPUTS: <none> 
     454 * OUTPUTS: <none> 
     455 * 
     456 * DESCRIPTION: Closes the client socket with the shell, sends a deregstration message 
     457 */ 
    135458void  
    136459ServiceManagementLayer::DeregisterComponent() 
     
    146469 
    147470 
     471/* CALLED BY: RegisterCognitiveEngine 
     472 * INPUTS: |ID| The ID number of the component where the data is to be transfered to 
     473 * OUTPUTS: <none> 
     474 * 
     475 * DESCRIPTION: Streams config data directly from the shell to the CE, and checks 
     476 * for an "ack" message from the CE after every sent message  
     477 * to know when to stop communication. 
     478 */ 
     479 
     480//TODO backwards check instead of forwords check to avoid waiting every data loop? 
    148481void  
    149 ServiceManagementLayer::TransferRadioConfiguration() 
    150 { 
    151 } 
    152  
    153  
     482ServiceManagementLayer::TransferRadioConfiguration(int32_t ID) 
     483{ 
     484    struct timeval selTimeout; 
     485    fd_set sockSet; 
     486    int32_t rc = 0; 
     487    char buffer[256]; 
     488    //Send data until the CE sends an ACK message back 
     489    while(rc==0){ 
     490        memset(buffer, 0, 256); 
     491        //Receive data from Shell 
     492        ReadMessage(shellSocketFD, buffer); 
     493        //Send data to CE 
     494        SendMessage(CE_List[ID].FD, buffer); 
     495        FD_ZERO(&sockSet); 
     496        FD_SET(CE_List[ID].FD, &sockSet); 
     497        selTimeout.tv_sec = 0; 
     498        selTimeout.tv_usec = 50000; 
     499        //Check if there is a message on the CE socket ready to be processed 
     500        rc=select(CE_List[ID].FD + 1, &sockSet, NULL, NULL, &selTimeout); 
     501    } 
     502    memset(buffer, 0, 256); 
     503    ReadMessage(CE_List[ID].FD, buffer); 
     504    SendMessage(shellSocketFD, buffer); 
     505} 
     506 
     507 
     508/* CALLED BY: RegisterCognitiveEngine 
     509 * INPUTS: |ID| The ID number of the component where the data is to be transfered to 
     510 * OUTPUTS: <none> 
     511 * 
     512 * DESCRIPTION: Simmilar to TransferRadioConfig, just with Experience data 
     513 */ 
    154514void  
    155 ServiceManagementLayer::TransferExperience() 
    156 { 
    157 } 
    158  
    159  
     515ServiceManagementLayer::TransferExperience(int32_t ID) 
     516{ 
     517    struct timeval selTimeout; 
     518    fd_set sockSet; 
     519    int32_t rc = 0; 
     520    char buffer[256]; 
     521    //Send data until the CE sends an ACK message back 
     522    while(rc==0){ 
     523        memset(buffer, 0, 256); 
     524        //Receive data from Shell 
     525        ReadMessage(shellSocketFD, buffer); 
     526        //Send data to CE 
     527        SendMessage(CE_List[ID].FD, buffer); 
     528        FD_ZERO(&sockSet); 
     529        FD_SET(CE_List[ID].FD, &sockSet); 
     530        selTimeout.tv_sec = 0; 
     531        selTimeout.tv_usec = 50000; 
     532        //Check if there is a message on the CE socket ready to be processed 
     533        rc = select(CE_List[ID].FD + 1, &sockSet, NULL, NULL, &selTimeout); 
     534    } 
     535    memset(buffer, 0, 256); 
     536    ReadMessage(CE_List[ID].FD, buffer); 
     537    SendMessage(shellSocketFD, buffer); 
     538} 
     539 
     540/* CALLED BY: MessageHandler 
     541 * INPUTS: |ID| The ID number of the component where service is located 
     542 * OUTPUTS: <none> 
     543 * 
     544 * DESCRIPTION: Inserts a service into the DB with the ID of the component where it exists 
     545 */ 
    160546void  
    161 ServiceManagementLayer::ReceiveServices() 
    162 { 
    163 } 
    164  
    165  
     547ServiceManagementLayer::ReceiveServices(int32_t ID) 
     548{ 
     549    char buffer[256]; 
     550    memset(buffer, 0, 256); 
     551    ReadMessage(CE_List[ID].FD, buffer); 
     552    char* cols[] = {(char *)"ID_Num", (char *)"Service_Name"}; 
     553     
     554    // generate command 
     555    //printf("%s\n", _services_DB->command); 
     556    strcpy(_services_DB->command, "insert into "); 
     557    strcat(_services_DB->command, _services_DB->tablename);  
     558    strcat(_services_DB->command, " ("); 
     559    strcat(_services_DB->command, cols[0]); 
     560    strcat(_services_DB->command, ", "); 
     561    strcat(_services_DB->command, cols[1]); 
     562    strcat(_services_DB->command, ") "); 
     563    strcat(_services_DB->command, " values("); 
     564    sprintf(_services_DB->command, "%s%d", _services_DB->command, ID); 
     565    strcat(_services_DB->command, ", '"); 
     566    strcat(_services_DB->command, buffer); 
     567    strcat(_services_DB->command, "');"); 
     568     
     569    //printf("search command: %s\n", _services_DB->command); 
     570    // execute add command 
     571    char *errorMsg; 
     572    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg); 
     573    if( rc!=SQLITE_OK && rc!=101 ) 
     574        fprintf(stderr, "SQL error: %s\n", errorMsg); 
     575    printf("SML: Registering service '%s' from component number '%d'\n", buffer, ID); 
     576 
     577} 
     578 
     579/* CALLED BY: MessageHandler 
     580 * INPUTS: <none> 
     581 * OUTPUTS: <none> 
     582 * 
     583 * DESCRIPTION: This method associates the services that components provide with the services that are requested in the mission 
     584 * Each service in the mission is given the ID and FD of a component that has registered to provide that service  
     585 * Deregistration is okay until this method is called without a reload, but if deregistration occurs after this 
     586 * method is called it needs to be called again even if other engines also provide the services 
     587 */ 
    166588void  
    167589ServiceManagementLayer::SetActiveMission() 
    168590{ 
    169 } 
    170  
    171  
     591    char buffer[256]; 
     592    memset(buffer, 0, 256); 
     593    ReadMessage(shellSocketFD, buffer); 
     594    int32_t missID = atoi(buffer); 
     595    for(activeMission = 0; activeMission < 10; activeMission++) 
     596    { 
     597        //Find the active mission by comparing mission ID's 
     598        if(miss[activeMission].missionID == missID) 
     599            break; 
     600    } 
     601    //For each service in the mission 
     602    for(int i = 0; i < miss[activeMission].numServices; i++) 
     603    {    
     604        //Check whether the current service is an actual service or a conditional 
     605        if(miss[activeMission].services[i].name.compare("if") && miss[activeMission].services[i].name.compare("while")){ 
     606            //If it is a service, search the database of registered services to find the ID of the component that registered it 
     607            strcpy(_services_DB->command, "select "); 
     608            strcat(_services_DB->command, _services_DB->tablename); 
     609            strcat(_services_DB->command, ".* from "); 
     610            strcat(_services_DB->command, _services_DB->tablename); 
     611            strcat(_services_DB->command, " where Service_Name=="); 
     612            sprintf(_services_DB->command, "%s'%s';", _services_DB->command, miss[activeMission].services[i].name.c_str()); 
     613         
     614            sqlite3_stmt * pStatement; 
     615            int rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command, -1, &pStatement, NULL); 
     616            if (rc == SQLITE_OK){  
     617                if (sqlite3_step(pStatement) == SQLITE_ROW) 
     618                     miss[activeMission].services[i].componentID =  sqlite3_column_int(pStatement, 0);  
     619                else { 
     620                    printf("services_DB:: Mission requires service not provided by any connected component.\n"); 
     621                    rc=31337; 
     622                } 
     623             } else { 
     624                printf("services_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_services_DB->command); 
     625            } 
     626 
     627            sqlite3_finalize(pStatement); 
     628            miss[activeMission].services[i].socketFD = CE_List[miss[activeMission].services[i].componentID].FD; 
     629            //Set the FD and ID of the service to refer to the component where the service exists 
     630        } 
     631        //Nothing to be done for conditionals at this stage 
     632    } 
     633 
     634 
     635    printf("\nhere ---%d, %d---\n", miss[activeMission].services[0].componentID, miss[activeMission].services[1].componentID); 
     636} 
     637 
     638/* CALLED BY: PerformActiveMission 
     639 * INPUTS: |sourceID| ID of the service that is being processed 
     640 * OUTPUTS: <none> 
     641 * 
     642 * DESCRIPTION: This is a helper method for the "PerformActiveMission" function 
     643 * NOTE: This function has changed durrastically from the previous implementation 
     644 * Takes an ID of a service 
     645 * For that service, finds inputs in DB and forwords those on to the engine after sending comm-starting messages 
     646 * Afterwords, listenes for the outputs so that it can store those in the database for future services or the overall output 
     647 */ 
     648void 
     649ServiceManagementLayer::TransactData(int32_t sourceID) 
     650{ 
     651    printf("transactData\n"); 
     652    char buffer[256]; 
     653    std::string data; 
     654    char* cols[] = {(char *)"Tag", (char *)"Data"}; 
     655    int i = 0; 
     656    fd_set sockSet; 
     657    struct timeval selTimeout; 
     658    //Transmission starting messages 
     659    SendMessage(miss[activeMission].services[sourceID].socketFD, "request_optimization_service"); 
     660    SendMessage(miss[activeMission].services[sourceID].socketFD, miss[activeMission].services[sourceID].name.c_str()); 
     661    //Find and load the input data 
     662    while(i < 3 && !miss[activeMission].services[sourceID].input[i].empty()){ 
     663        printf("pulling input data out of DB for ID#=%d\n", sourceID); 
     664        strcpy(_data_DB->command, "select "); 
     665        strcat(_data_DB->command, _data_DB->tablename); 
     666        strcat(_data_DB->command, ".* from "); 
     667        strcat(_data_DB->command, _data_DB->tablename); 
     668        strcat(_data_DB->command, " where Tag=="); 
     669        sprintf(_data_DB->command, "%s'%s';", _data_DB->command, miss[activeMission].services[sourceID].input[i].c_str()); 
     670        sqlite3_stmt * pStatement; 
     671        int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL); 
     672        if (rc == SQLITE_OK){  
     673            if (sqlite3_step(pStatement) == SQLITE_ROW) 
     674                 data.append((const char*) sqlite3_column_text(pStatement, 1));  
     675            else { 
     676                    printf("data_DB:: Data not yet in DB.\n"); 
     677                    rc=31337; 
     678            } 
     679        }  
     680        else { 
     681            printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command); 
     682        } 
     683 
     684        sqlite3_finalize(pStatement); 
     685        char *data_ch = (char *) data.c_str(); 
     686        //Tokenize the data and pass it along 
     687        char *token = strtok(data_ch, "@"); 
     688        while(token){ 
     689            SendMessage(miss[activeMission].services[sourceID].socketFD, token); 
     690            token = strtok(NULL, "@"); 
     691        } 
     692        printf("done pulling input data out of DB for ID#=%d\n", sourceID); 
     693        i++; 
     694    } 
     695 
     696    int32_t j = 0; 
     697    FD_ZERO(&sockSet); 
     698    FD_SET(miss[activeMission].services[sourceID].socketFD, &sockSet); 
     699    //TODO neccessary? 
     700    selTimeout.tv_sec = 5; 
     701    selTimeout.tv_usec = 0; 
     702    //Use select command to force wait for processing to finish 
     703    select(miss[activeMission].services[sourceID].socketFD + 1, &sockSet, NULL, NULL, &selTimeout); 
     704    data.clear(); 
     705    while(j < 3 && !miss[activeMission].services[sourceID].output[j].empty()){ 
     706        int rc; 
     707        while(true){ 
     708            //Read the data incrementally and deliminate it with the "@" symbol 
     709            memset(buffer, 0, 256); 
     710            ReadMessage(miss[activeMission].services[sourceID].socketFD, buffer); 
     711            if(strcmp(buffer, "output_finished")==0) 
     712                break; 
     713            data.append(buffer); 
     714            data.append("@"); 
     715        } 
     716        printf("SML: putting output data into DB for ID#=%d\n", sourceID); 
     717 
     718        strcpy(_data_DB->command, "insert or replace into "); 
     719        strcat(_data_DB->command, _data_DB->tablename);  
     720        strcat(_data_DB->command, " ("); 
     721        strcat(_data_DB->command, cols[0]); 
     722        strcat(_data_DB->command, ", "); 
     723        strcat(_data_DB->command, cols[1]); 
     724        strcat(_data_DB->command, ") "); 
     725        strcat(_data_DB->command, " values('");  
     726        strcat(_data_DB->command, miss[activeMission].services[sourceID].output[j].c_str()); 
     727        strcat(_data_DB->command, "', '"); 
     728        strcat(_data_DB->command, data.c_str()); 
     729        strcat(_data_DB->command, "');"); 
     730        char *errorMsg; 
     731        rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg); 
     732        if( rc!=SQLITE_OK && rc!=101 ) 
     733            fprintf(stderr, "SQL error: %s\n", errorMsg); 
     734        printf("SML: done putting ouptut data into DB for ID#='%d'\n", sourceID); 
     735        j++; 
     736    } 
     737    printf("done transact data!\n"); 
     738} 
     739 
     740 
     741 
     742/* CALLED BY: MessageHandler 
     743 * INPUTS: <none> 
     744 * OUTPUTS: <none> 
     745 * 
     746 * DESCRIPTION: This function works by first sending the inputs from the shell to the appropriate components 
     747 * The first service should begin immeadiately, as should any others who have all of their input paramaters 
     748 * When they complete, the output path is found and the data is transfered as it becomes available 
     749 * Presumably at this point the second function has all of it's paramaters, so it begins to compute, and the cycle repeats 
     750 * If the generated output is an overall output, it is sent on to the shell 
     751 * "if" and "while" statements are handled by setting up a faux service that has a true input, a false input, and a boolean flag 
     752 * If the true input is non-NULL and the flag is true, the statements execute 
     753 * Likewise, if the false input is non-NULL and the flag is false, the statements execute 
     754 * These flags are set during execution any time one of these faux services' inputs appear in an output statement   
     755 *   
     756 *  
     757 * Rules for active missions (currently) 
     758 * -Three inputs/outputs per service and per mission 
     759 * -Inputs simply define a path, so multiple variables can be transmitted over the same input 
     760 * -Each component that sends data must include the "output_finished" statement after each output is finished sending it's data 
     761 * -All ordering constraints have been relaxed in this version; all data is stored locally and only sent when requested 
     762 * -If support fully implemented 
     763 * -Conditions must be boolean flags 
     764 * -Flags are set by putting either the character string "true" or "false" on the buffer 
     765 * -IMPORTANT: DB uses '@' to seperate individual statements; using '@' in the data stream will result in incorrect behavior 
     766 */ 
     767void 
     768ServiceManagementLayer::PerformActiveMission() 
     769{ 
     770    //TODO verify while 
     771    int i = 0; 
     772    std::string data; 
     773    std::string input; 
     774    std::string check; 
     775    char buffer[256]; 
     776    fd_set sockSet; 
     777    char* cols[] = {(char *)"Tag", (char *)"Data"}; 
     778    struct timeval selTimeout; 
     779    //Get the inputs 
     780    while(i < 3 && !miss[activeMission].input[i].empty()){ 
     781            //New data being added to DB 
     782        printf("inserting data from shell\n"); 
     783        int rc; 
     784        while(true){ 
     785            memset(buffer, 0, 256); 
     786            ReadMessage(shellSocketFD, buffer); 
     787            if(strcmp(buffer, "input_finished")==0) 
     788                break; 
     789            data.append(buffer); 
     790            data.append("@"); 
     791            /*FD_ZERO(&sockSet); 
     792            FD_SET(miss[activeMission].services[sourceID].socketFD, &sockSet); 
     793            selTimeout.tv_sec = 0; 
     794            selTimeout.tv_usec = 50000; 
     795            //Check if there is a message on the CE socket ready to be processed 
     796            rc=select(miss[activeMission].services[sourceID].socketFD + 1, &sockSet, NULL, NULL, &selTimeout);*/ 
     797        }//while(rc!=0);; 
     798 
     799        strcpy(_data_DB->command, "insert into "); 
     800        strcat(_data_DB->command, _data_DB->tablename);  
     801        strcat(_data_DB->command, " ("); 
     802        strcat(_data_DB->command, cols[0]); 
     803        strcat(_data_DB->command, ", "); 
     804        strcat(_data_DB->command, cols[1]); 
     805        strcat(_data_DB->command, ") "); 
     806        strcat(_data_DB->command, " values('"); 
     807        strcat(_data_DB->command, miss[activeMission].input[i].c_str()); 
     808        strcat(_data_DB->command, "', '"); 
     809        strcat(_data_DB->command, data.c_str()); 
     810        strcat(_data_DB->command, "');"); 
     811        char *errorMsg; 
     812        rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg); 
     813        if( rc!=SQLITE_OK && rc!=101 ) 
     814            fprintf(stderr, "SQL error: %s\n", errorMsg); 
     815        printf("SML: finished adding data from shell on input %d\n", i); 
     816        i++; 
     817 
     818    } 
     819    i=0; 
     820    data.clear(); 
     821    while(i < miss[activeMission].numServices) 
     822    { 
     823        if(miss[activeMission].services[i].name.compare("if")==0) 
     824        { 
     825            printf("if detected\n"); 
     826            input.clear(); 
     827            check.clear(); 
     828            if(!miss[activeMission].services[i].input[0].empty()){ 
     829                input=miss[activeMission].services[i].input[0]; 
     830                check = "true@"; 
     831            } 
     832            else{ 
     833                input=miss[activeMission].services[i].input[1]; 
     834                check = "false@"; 
     835            } 
     836            strcpy(_data_DB->command, "select "); 
     837            strcat(_data_DB->command, _services_DB->tablename); 
     838            strcat(_data_DB->command, ".* from "); 
     839            strcat(_data_DB->command, _services_DB->tablename); 
     840            strcat(_data_DB->command, " where Tag=="); 
     841            sprintf(_data_DB->command, "%s'%s';", _data_DB->command, input.c_str()); 
     842            sqlite3_stmt * pStatement; 
     843            int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL); 
     844            if (rc == SQLITE_OK){  
     845                if (sqlite3_step(pStatement) == SQLITE_ROW) 
     846                     data = (const char *) sqlite3_column_text(pStatement, 1);  
     847                else { 
     848                        printf("1 data_DB:: Data not yet in DB. %d\n", i); 
     849                        rc=31337; 
     850                } 
     851            } else { 
     852                printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command); 
     853            } 
     854 
     855            sqlite3_finalize(pStatement); 
     856            printf("data=%s, check=%s\n", data.c_str(), check.c_str()); 
     857            if(data.compare(check)==0){ 
     858                printf("if taken\n"); 
     859                for(int k = i + 1; k < i + miss[activeMission].services[i].num_conds; k++) 
     860                    TransactData(k); 
     861            } 
     862            else{ 
     863                i+=miss[activeMission].services[i].num_conds; 
     864                printf("if not taken %d\n", miss[activeMission].services[i].num_conds); 
     865            } 
     866        } 
     867        //TODO test while 
     868        else if(miss[activeMission].services[i].name.compare("while")==0) 
     869        { 
     870            printf("while detected\n"); 
     871            input.clear(); 
     872            check.clear(); 
     873            while(true){ 
     874                    if(!miss[activeMission].services[i].input[0].empty()){ 
     875                        input=miss[activeMission].services[i].input[0]; 
     876                        check = "true@"; 
     877                    } 
     878                    else{ 
     879                        input=miss[activeMission].services[i].input[1]; 
     880                        check = "false@"; 
     881                    } 
     882                    strcpy(_data_DB->command, "select "); 
     883                    strcat(_data_DB->command, _services_DB->tablename); 
     884                    strcat(_data_DB->command, ".* from "); 
     885                    strcat(_data_DB->command, _services_DB->tablename); 
     886                    strcat(_data_DB->command, " where Tag=="); 
     887                    sprintf(_data_DB->command, "%s'%s';", _data_DB->command, input.c_str()); 
     888                    sqlite3_stmt * pStatement; 
     889                    int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL); 
     890                    if (rc == SQLITE_OK){  
     891                        if (sqlite3_step(pStatement) == SQLITE_ROW) 
     892                            data = (const char *) sqlite3_column_text(pStatement, 1);  
     893                        else  
     894                            printf("1 data_DB:: Data not yet in DB. %d\n", i); 
     895                    }  
     896                    else { 
     897                        printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command); 
     898                    } 
     899 
     900                    sqlite3_finalize(pStatement); 
     901                    printf("data=%s, check=%s\n", data.c_str(), check.c_str()); 
     902                    if(data.compare(check)==0){ 
     903                        printf("while taken\n"); 
     904                        for(int k = i + 1; k < i + miss[activeMission].services[i].num_conds; k++) 
     905                            TransactData(k); 
     906                    } 
     907                    else{ 
     908                        i+=miss[activeMission].services[i].num_conds; 
     909                        printf("if not taken %d\n", miss[activeMission].services[i].num_conds); 
     910                        break; 
     911                    } 
     912            } 
     913        } 
     914        else{ 
     915            TransactData(i);} 
     916        i++; 
     917    } 
     918    i=0; 
     919    data.clear(); 
     920    //get the ouptuts 
     921    while(i < 3 && !miss[activeMission].output[i].empty()){ 
     922        printf("sending output data to shell\n"); 
     923        strcpy(_data_DB->command, "select "); 
     924        strcat(_data_DB->command, _data_DB->tablename); 
     925        strcat(_data_DB->command, ".* from "); 
     926        strcat(_data_DB->command, _data_DB->tablename); 
     927        strcat(_data_DB->command, " where Tag=="); 
     928        sprintf(_data_DB->command, "%s'%s';", _data_DB->command, miss[activeMission].output[i].c_str()); 
     929        sqlite3_stmt * pStatement; 
     930        int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL); 
     931        if (rc == SQLITE_OK){  
     932            if (sqlite3_step(pStatement) == SQLITE_ROW) 
     933                 data.append((const char*) sqlite3_column_text(pStatement, 1));  
     934            else { 
     935                    printf("data_DB:: Data not yet in DB.\n"); 
     936                    rc=31337; 
     937            } 
     938        }  
     939        else { 
     940            printf("services_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command); 
     941        } 
     942        sqlite3_finalize(pStatement); 
     943        char *data_ch = (char *) data.c_str(); 
     944        char *token = strtok(data_ch, "@"); 
     945        while(token){ 
     946            SendMessage(shellSocketFD, token); 
     947            token = strtok(NULL, "@"); 
     948        } 
     949        i++; 
     950        printf("done sending output data to shell\n"); 
     951    } 
     952} 
     953 
     954 
     955/* CALLED BY: MessageHandler 
     956 * INPUTS: <none> 
     957 * OUTPUTS: <none> 
     958 * 
     959 * DESCRIPTION: Print a list of the services currently registered and the ID's of the components that registered them 
     960 */ 
    172961void  
    173962ServiceManagementLayer::ListServices() 
    174963{ 
    175 } 
    176  
    177  
     964    // generate commandi 
     965    strcpy(_services_DB->command, "select "); 
     966    strcat(_services_DB->command, _services_DB->tablename); 
     967    strcat(_services_DB->command, ".* from "); 
     968    strcat(_services_DB->command, _services_DB->tablename); 
     969    strcat(_services_DB->command, ";"); 
     970 
     971    // execute print (select all)  command     
     972    char *errorMsg; 
     973    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg); 
     974    if( rc!=SQLITE_OK && rc!=101 ) 
     975        fprintf(stderr, "SQL error: %s\n", errorMsg); 
     976    printf("database %s, table %s:\n", _services_DB->filename, _services_DB->tablename); 
     977} 
     978 
     979/* CALLED BY: Reset 
     980 * INPUTS: <none> 
     981 * OUTPUTS: <none> 
     982 * 
     983 * DESCRIPTION: Clear and reinitialize the mission array, then reload the configuration file 
     984 */ 
    178985void  
    179986ServiceManagementLayer::ReloadConfiguration() 
    180987{ 
    181988    LOG("ServiceManagementLayer:: Reloading Configuration.\n"); 
    182 } 
    183  
    184  
     989    free(miss); 
     990    miss = new Mission[10]; 
     991    for(int i = 0; i < 10; i++) 
     992        miss[i].services = new Service[20]; 
     993    LoadConfiguration(_SML_Config, miss); 
     994} 
     995 
     996/* CALLED BY: constructor, Reset 
     997 * INPUTS: |SML_Config| Address (either relitive or full) of the XML file containing mission data 
     998 *         |mList| Mission array to be modified  
     999 * OUTPUTS: <none> 
     1000 * 
     1001 * DESCRIPTION: IMPORTANT - See formatting instructions for correct parsing of data 
     1002 * Can currently handle 3 inputs and 3 outputs per service, but easily expandable 
     1003 * Also, can handle one layer of nested conditional statements, but could 
     1004 * be expanded to meet additional needs.  Only support now is for straight bool flags, 
     1005 * but support could be added for more complex conditionals later. 
     1006 *  
     1007 * Components assigned to mission during "set active mission" stage so that 
     1008 * components can still continue to register after the configuration is loaded 
     1009 */ 
    1851010void  
    186 ServiceManagementLayer::LoadConfiguration() 
    187 { 
    188     LOG("ServiceManagementLayer:: Loading Configuration.\n"); 
    189 } 
    190  
     1011ServiceManagementLayer::LoadConfiguration(const char *SML_Config, Mission* &mList) 
     1012{ 
     1013    TiXmlElement *pMission; 
     1014    TiXmlElement *pService; 
     1015    TiXmlElement *pChild0, *pChild1, *pChild2, *pChild3; 
     1016    TiXmlHandle hRoot(0); 
     1017    //printf("ServiceManagementLayer:: Loading Configuration.\n"); 
     1018    TiXmlDocument doc("."); 
     1019    doc.LoadFile(SML_Config); 
     1020    bool loadOkay = doc.LoadFile(); 
     1021    if(!loadOkay) 
     1022        printf("Loading SML configuration failed: %s\n", SML_Config); 
     1023 
     1024    TiXmlHandle hDoc(&doc); 
     1025     
     1026    pMission = hDoc.FirstChildElement().Element(); 
     1027 
     1028    if(!pMission)  
     1029        printf("No valid root!"); 
     1030 
     1031    hRoot = TiXmlHandle(pMission); 
     1032    pService = pMission->FirstChildElement(); 
     1033    int32_t mission_num = 0; 
     1034    //Iterate through the missions 
     1035    for(pChild0 = pMission->FirstChildElement(); pChild0 ; \ 
     1036        pChild0 = pChild0->NextSiblingElement())  
     1037    { 
     1038        int32_t service_num = 0; 
     1039        uint16_t cond_array[] = {0, 0}; 
     1040        //printf("mission_num = %d\n", mission_num); 
     1041        memset(cond_array, 0, 2); 
     1042         
     1043        for(pChild1  = pChild0->FirstChildElement(); pChild1; \ 
     1044            pChild1  = pChild1->NextSiblingElement())  
     1045        { 
     1046            int32_t conditional_0 = service_num; 
     1047            for(pChild2 = pChild1->FirstChildElement(); \ 
     1048                pChild2; pChild2 = pChild2->NextSiblingElement()) 
     1049            { 
     1050                service_num++; 
     1051                int32_t conditional_1 = service_num; 
     1052                for(pChild3 = pChild2->FirstChildElement(); \ 
     1053                    pChild3; pChild3 = pChild3 ->NextSiblingElement()) 
     1054                { 
     1055                    service_num++; 
     1056                    mList[mission_num].services[service_num].name = pChild3->Attribute("name"); 
     1057                    if(pChild3->Attribute("input1")) 
     1058                        mList[mission_num].services[service_num].input[0] = pChild3->Attribute("input1"); 
     1059                    if(pChild3->Attribute("input2")) 
     1060                        mList[mission_num].services[service_num].input[1] = pChild3->Attribute("input2"); 
     1061                    if(pChild3->Attribute("input3")) 
     1062                        mList[mission_num].services[service_num].input[2] = pChild3->Attribute("input3"); 
     1063                    if(pChild3->Attribute("output1")) 
     1064                        mList[mission_num].services[service_num].output[0] = pChild3->Attribute("output1"); 
     1065                    if(pChild3->Attribute("output2")) 
     1066                        mList[mission_num].services[service_num].output[1] = pChild3->Attribute("output2"); 
     1067                    if(pChild3->Attribute("output3")) 
     1068                        mList[mission_num].services[service_num].output[2] = pChild3->Attribute("output3"); 
     1069                    cond_array[1]++; 
     1070                } 
     1071 
     1072                if(conditional_1 != service_num){ 
     1073                    mList[mission_num].services[conditional_1].name = pChild2->Value(); 
     1074                    if(pChild2->Attribute("input_t")) 
     1075                        mList[mission_num].services[conditional_1].input[0] = pChild2->Attribute("input_t"); 
     1076                    if(pChild2->Attribute("input_f")) 
     1077                        mList[mission_num].services[conditional_1].input[1] = pChild2->Attribute("input_f"); 
     1078                } 
     1079                else{ 
     1080                    mList[mission_num].services[conditional_1].name = pChild2->Attribute("name"); 
     1081                    if(pChild2->Attribute("input1")) 
     1082                        mList[mission_num].services[service_num].input[0] = pChild2->Attribute("input1"); 
     1083                    if(pChild2->Attribute("input2")) 
     1084                        mList[mission_num].services[service_num].input[1] = pChild2->Attribute("input2"); 
     1085                    if(pChild2->Attribute("input3")) 
     1086                        mList[mission_num].services[service_num].input[2] = pChild2->Attribute("input3"); 
     1087                    if(pChild2->Attribute("output1")) 
     1088                        mList[mission_num].services[service_num].output[0] = pChild2->Attribute("output1"); 
     1089                    if(pChild2->Attribute("output2")) 
     1090                        mList[mission_num].services[service_num].output[1] = pChild2->Attribute("output2"); 
     1091                    if(pChild2->Attribute("output3")) 
     1092                        mList[mission_num].services[service_num].output[2] = pChild2->Attribute("output3"); 
     1093                } 
     1094 
     1095                mList[mission_num].services[conditional_1].num_conds = cond_array[1]; 
     1096printf("hello\n"); 
     1097                cond_array[1] = 0; 
     1098                cond_array[0]++; 
     1099            } 
     1100            if(conditional_0 != service_num){ 
     1101                mList[mission_num].services[conditional_0].name = pChild1->Value(); 
     1102                    if(pChild1->Attribute("input_t")) 
     1103                        mList[mission_num].services[conditional_0].input[0] = pChild1->Attribute("input_t"); 
     1104                    if(pChild1->Attribute("input_f")) 
     1105                        mList[mission_num].services[conditional_0].input[1] = pChild1->Attribute("input_f"); 
     1106                printf("---input_t=%s\n", mList[mission_num].services[conditional_0].input[0].c_str()); 
     1107            } 
     1108            else{ 
     1109                mList[mission_num].services[conditional_0].name = pChild1->Attribute("name"); 
     1110                if(pChild1->Attribute("input1")) 
     1111                    mList[mission_num].services[service_num].input[0] = pChild1->Attribute("input1"); 
     1112                if(pChild1->Attribute("input2")) 
     1113                    mList[mission_num].services[service_num].input[1] = pChild1->Attribute("input2"); 
     1114                if(pChild1->Attribute("input3")) 
     1115                    mList[mission_num].services[service_num].input[2] = pChild1->Attribute("input3"); 
     1116                if(pChild1->Attribute("output1")) 
     1117                    mList[mission_num].services[service_num].output[0] = pChild1->Attribute("output1"); 
     1118                if(pChild1->Attribute("output2")) 
     1119                    mList[mission_num].services[service_num].output[1] = pChild1->Attribute("output2"); 
     1120                if(pChild1->Attribute("output3")) 
     1121                    mList[mission_num].services[service_num].output[2] = pChild1->Attribute("output3"); 
     1122            } 
     1123 
     1124            mList[mission_num].services[conditional_0].num_conds = cond_array[0]; 
     1125            //printf("hello\n"); 
     1126            cond_array[0] = 0; 
     1127            service_num++; 
     1128        } 
     1129        for(int i = 0; i < service_num; i++) 
     1130                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()); 
     1131 
     1132        mList[mission_num].numServices = service_num; 
     1133        mList[mission_num].name = pChild0->Attribute("name"); 
     1134        mList[mission_num].missionID = atoi(pChild0->Attribute("id")); 
     1135        if(pChild0->Attribute("input1")) 
     1136            mList[mission_num].input[0] = pChild0->Attribute("input1"); 
     1137        if(pChild0->Attribute("input2")) 
     1138            mList[mission_num].input[1] = pChild0->Attribute("input2"); 
     1139        if(pChild0->Attribute("input3")) 
     1140            mList[mission_num].input[2] = pChild0->Attribute("input3"); 
     1141        if(pChild0->Attribute("output1")) 
     1142            mList[mission_num].output[0] = pChild0->Attribute("output1"); 
     1143        if(pChild0->Attribute("output2")) 
     1144            mList[mission_num].output[1] = pChild0->Attribute("output2"); 
     1145        if(pChild0->Attribute("output3")) 
     1146            mList[mission_num].output[2] = pChild0->Attribute("output3"); 
     1147        printf("mis, input1=%s, output1=%s\n", mList[mission_num].input[0].c_str(), mList[mission_num].output[0].c_str()); 
     1148        mission_num++; 
     1149    } 
     1150} 
     1151 
     1152/* CALLED BY: MessageHandler 
     1153 * INPUTS: |ID| The ID number of the engine to be registered 
     1154 * OUTPUTS: <none> 
     1155 * 
     1156 * DESCRIPTION: Sends a registration message onto the shell and sends the ACK back to the component 
     1157 */ 
     1158void 
     1159ServiceManagementLayer::RegisterCognitiveEngine(int32_t ID) 
     1160{ 
     1161    SendMessage(shellSocketFD, "register_engine_cognitive"); 
     1162    LOG("ServiceManagementLayer:: CE registration message forwarded to shell.\n"); 
     1163    char buffer[256]; 
     1164    memset(buffer, 0, 256); 
     1165    ReadMessage(shellSocketFD, buffer); 
     1166    SendMessage(CE_List[ID].FD, buffer); 
     1167 
     1168    //TODO UNCOMMENT!!! 
     1169    //TODO UNCOMMENT!!! 
     1170    /*TransferRadioConfiguration(ID); 
     1171    memset(buffer, 0, 256); 
     1172    TransferExperience(ID); 
     1173    memset(buffer, 0, 256);*/ 
     1174    numberOfCognitiveEngines++; 
     1175    CE_Present = true; 
     1176} 
     1177 
     1178/* CALLED BY: MessageHandler 
     1179 * INPUTS: |ID| The ID number of the engine to have it's services deregistered 
     1180 * OUTPUTS: <none> 
     1181 * 
     1182 * DESCRIPTION: Deleates the services from the DB coresponding to the component ID 
     1183 */ 
     1184//----NOTE---- 
     1185//The behavior of this method is different than described in the documentation. 
     1186//This function deregisteres all of the services when a component deregistes, 
     1187//whereas the one in the documentation describes a function where an individual 
     1188//service is deregistered.  This may be changed in the future. 
     1189void  
     1190ServiceManagementLayer::DeregisterServices(int32_t ID) 
     1191{ 
     1192    strcpy(_services_DB->command, "DELETE FROM "); 
     1193    strcat(_services_DB->command, _services_DB->tablename); 
     1194    strcat(_services_DB->command, " WHERE "); 
     1195    strcat(_services_DB->command, "ID_Num"); 
     1196    strcat(_services_DB->command, "=="); 
     1197    sprintf(_services_DB->command, "%s%d;", _services_DB->command, ID); 
     1198    char *errorMsg; 
     1199    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg); 
     1200    if( rc!=SQLITE_OK && rc!=101 ) 
     1201        fprintf(stderr, "SQL error: %s\n", errorMsg); 
     1202} 
     1203 
     1204/* CALLED BY: MessageHandler 
     1205 * INPUTS: |ID| The ID number of the engine to have it's services deregistered 
     1206 * OUTPUTS: <none> 
     1207 * 
     1208 * DESCRIPTION: Deletes the contact info for the cognitive engine, forwards a deregistration message to the shell 
     1209 */ 
     1210void  
     1211ServiceManagementLayer::DeregisterCognitiveEngine(int32_t ID) 
     1212{ 
     1213    LOG("ServiceManagementLayer:: CE deregistration message forwarded to shell.\n"); 
     1214 
     1215    numberOfCognitiveEngines--; 
     1216    if(numberOfCognitiveEngines == 0) 
     1217        CE_Present = false; 
     1218 
     1219    SendMessage(shellSocketFD, "deregister_engine_cognitive"); 
     1220    char buffer[256]; 
     1221    memset(buffer, 0, 256); 
     1222    ReadMessage(shellSocketFD, buffer); 
     1223    SendMessage(CE_List[ID].FD, buffer); 
     1224    if(strcmp("deregister_ack", buffer) != 0) { 
     1225        ERROR(1, "SML:: Failed to close CE socket\n"); 
     1226    } 
     1227    CE_List[ID].FD = -1; 
     1228    CE_List[ID].ID_num = -1; 
     1229 
     1230    LOG("Cognitive Radio Shell:: Socket closed.\n"); 
     1231} 
     1232 
     1233 
     1234/* CALLED BY: test class 
     1235 * INPUTS: <none> 
     1236 * OUTPUTS: <none> 
     1237 * 
     1238 * DESCRIPTION: Sets up a server socket and listens for communication on either that or the shell socket 
     1239 */ 
     1240void 
     1241ServiceManagementLayer::StartSMLServer() 
     1242{ 
     1243    struct timeval selTimeout; 
     1244    int32_t running = 1; 
     1245    int32_t port, rc, new_sd = 1; 
     1246    int32_t desc_ready = 1; 
     1247    int32_t timeout = 10; 
     1248                //If there is, call the MessageHandler with the Shell_Msg code of -1 
     1249    fd_set sockSet, shellSet; 
     1250 
     1251    cogEngSrv = CreateTCPServerSocket(2044); 
     1252    int32_t maxDescriptor = cogEngSrv; 
     1253 
     1254    if(InitializeTCPServerPort(cogEngSrv) == -1) 
     1255        ERROR(1,"Error initializing primary port\n"); 
     1256 
     1257    int i = 10000000; 
     1258    while (i>0) { 
     1259        i--; 
     1260        /* Zero socket descriptor vector and set for server sockets */ 
     1261        /* This must be reset every time select() is called */ 
     1262        FD_ZERO(&sockSet); 
     1263        FD_SET(cogEngSrv, &sockSet); 
     1264        for(int k = 0; k < Current_ID; k++){ 
     1265            if(CE_List[k].ID_num != -1) 
     1266                FD_SET(CE_List[k].FD, &sockSet); 
     1267        } 
     1268            //printf("k=%d, CID=%d\n", k, CE_List[k].FD); 
     1269 
     1270        /* Timeout specification */ 
     1271        /* This must be reset every time select() is called */ 
     1272        selTimeout.tv_sec = 0;       /* timeout (secs.) */ 
     1273        selTimeout.tv_usec = 0;            /* 0 microseconds */ 
     1274        //Changed both to zero so that select will check messages from the shell instead of blocking 
     1275        //when there is no command from the CE's to be processed 
     1276 
     1277        //Check if there is a message on the socket waiting to be read 
     1278        rc = select(maxDescriptor + 1, &sockSet, NULL, NULL, &selTimeout);  
     1279        //printf("rc=%d\n", rc); 
     1280        if(rc == 0){ 
     1281            //LOG("No echo requests for %i secs...Server still alive\n", timeout); 
     1282         
     1283            FD_ZERO(&shellSet); 
     1284            FD_SET(shellSocketFD, &shellSet); 
     1285            selTimeout.tv_sec = 0; 
     1286            selTimeout.tv_usec = 0; 
     1287            //Check if there is a message on the shell socket ready to be processed 
     1288            int rc2 = select(shellSocketFD + 1, &shellSet, NULL, NULL, &selTimeout); 
     1289            //printf("rc2=%d\n", rc2); 
     1290                //If there is, call the MessageHandler with the Shell_Msg code of -1 
     1291            if(FD_ISSET(shellSocketFD, &shellSet)){ 
     1292                //printf("shell_msg, %d\n", rc2); 
     1293                MessageHandler(-1);} 
     1294        } 
     1295        else {  
     1296            desc_ready = rc; 
     1297            for(port = 0; port <= maxDescriptor && desc_ready > 0; port++) { 
     1298                if(FD_ISSET(port, &sockSet)) { 
     1299                    desc_ready -= 1; 
     1300 
     1301                    //Check if request is new or on an existing open descriptor 
     1302                    if(port == cogEngSrv) {  
     1303                        //If new, assign it a descriptor and give it an ID 
     1304                        new_sd = AcceptTCPConnection(port); 
     1305                          
     1306                        if(new_sd < 0)  
     1307                            break; 
     1308 
     1309                        CE_List[Current_ID].FD = new_sd; 
     1310                        CE_List[Current_ID].ID_num = Current_ID; 
     1311                        MessageHandler(Current_ID); 
     1312                        Current_ID++; 
     1313         
     1314                        FD_SET(new_sd,&sockSet); 
     1315                        if(new_sd > maxDescriptor)  
     1316                           maxDescriptor = new_sd; 
     1317                    }  
     1318                    else { 
     1319                        //If old, figure out which ID it coresponds to and handle it accordingly 
     1320                        for(int16_t z = 0; z < Current_ID; z++) 
     1321                        { 
     1322                                if(CE_List[z].FD == port){ 
     1323                                        MessageHandler(z);} 
     1324                        } 
     1325                    } 
     1326                } 
     1327            } 
     1328        } 
     1329    }         
     1330 
     1331    /* Close sockets */ 
     1332    close(cogEngSrv); 
     1333 
     1334    //delete &cogEngSrv; 
     1335    return; 
     1336} 
     1337 
     1338 
     1339 
     1340 
     1341    /*TiXmlElement *pMission; 
     1342    TiXmlElement *pService; 
     1343    TiXmlElement *pChild0, *pChild1, *pChild2, *pChild3; 
     1344    TiXmlHandle hRoot(0); 
     1345    //printf("ServiceManagementLayer:: Loading Configuration.\n"); 
     1346    TiXmlDocument doc("."); 
     1347    doc.LoadFile(SML_Config); 
     1348    bool loadOkay = doc.LoadFile(); 
     1349    if(!loadOkay) 
     1350        printf("Loading SML configuration failed: %s\n", SML_Config); 
     1351 
     1352    TiXmlHandle hDoc(&doc); 
     1353     
     1354    pMission = hDoc.FirstChildElement().Element(); 
     1355 
     1356    if(!pMission)  
     1357        printf("No valid root!"); 
     1358 
     1359    hRoot = TiXmlHandle(pMission); 
     1360    pService = pMission->FirstChildElement(); 
     1361    int32_t mission_num = 0; 
     1362    //Iterate through the missions 
     1363    for(pChild0 = pMission->FirstChildElement(); pChild0 ; \ 
     1364        pChild0 = pChild0->NextSiblingElement())  
     1365    { 
     1366        int32_t service_num = 0; 
     1367        uint16_t cond_array[] = {0, 0}; 
     1368        //printf("mission_num = %d\n", mission_num); 
     1369        memset(cond_array, 0, 2); 
     1370         
     1371        for(pChild1  = pChild0->FirstChildElement(); pChild1; \ 
     1372            pChild1  = pChild1->NextSiblingElement())  
     1373        { 
     1374            int32_t conditional_0 = service_num; 
     1375            for(pChild2 = pChild1->FirstChildElement(); \ 
     1376                pChild2; pChild2 = pChild2->NextSiblingElement()) 
     1377            { 
     1378                service_num++; 
     1379                int32_t conditional_1 = service_num; 
     1380                for(pChild3 = pChild2->FirstChildElement(); \ 
     1381                    pChild3; pChild3 = pChild3 ->NextSiblingElement()) 
     1382                { 
     1383                    service_num++; 
     1384                    mList[mission_num].services[service_num].name = pChild3->Attribute("name"); 
     1385                    if(pChild3->Attribute("input1")) 
     1386                        mList[mission_num].services[service_num].input[0] = pChild3->Attribute("input1"); 
     1387                    if(pChild3->Attribute("input2")) 
     1388                        mList[mission_num].services[service_num].input[1] = pChild3->Attribute("input2"); 
     1389                    if(pChild3->Attribute("input3")) 
     1390                        mList[mission_num].services[service_num].input[2] = pChild3->Attribute("input3"); 
     1391                    if(pChild3->Attribute("output1")) 
     1392                        mList[mission_num].services[service_num].output[0] = pChild3->Attribute("output1"); 
     1393                    if(pChild3->Attribute("output2")) 
     1394                        mList[mission_num].services[service_num].output[1] = pChild3->Attribute("output2"); 
     1395                    if(pChild3->Attribute("output3")) 
     1396                        mList[mission_num].services[service_num].output[2] = pChild3->Attribute("output3"); 
     1397                    cond_array[1]++; 
     1398                } 
     1399 
     1400                if(conditional_1 != service_num){ 
     1401                    mList[mission_num].services[conditional_1].name = pChild2->Value(); 
     1402                    if(pChild2->Attribute("input_t")) 
     1403                        mList[mission_num].services[conditional_1].input[0] = pChild2->Attribute("input_t"); 
     1404                    if(pChild2->Attribute("input_f")) 
     1405                        mList[mission_num].services[conditional_1].input[1] = pChild2->Attribute("input_f"); 
     1406                } 
     1407                else{ 
     1408                    mList[mission_num].services[service_num].name = pChild2->Attribute("name"); 
     1409                    if(pChild2->Attribute("input1")) 
     1410                        mList[mission_num].services[service_num].input[0] = pChild2->Attribute("input1"); 
     1411                    if(pChild2->Attribute("input2")) 
     1412                        mList[mission_num].services[service_num].input[1] = pChild2->Attribute("input2"); 
     1413                    if(pChild2->Attribute("input3")) 
     1414                        mList[mission_num].services[service_num].input[2] = pChild2->Attribute("input3"); 
     1415                    if(pChild2->Attribute("output1")) 
     1416                        mList[mission_num].services[service_num].output[0] = pChild2->Attribute("output1"); 
     1417                    if(pChild2->Attribute("output2")) 
     1418                        mList[mission_num].services[service_num].output[1] = pChild2->Attribute("output2"); 
     1419                    if(pChild2->Attribute("output3")) 
     1420                        mList[mission_num].services[service_num].output[2] = pChild2->Attribute("output3"); 
     1421                } 
     1422 
     1423                mList[mission_num].services[conditional_1].num_conds = cond_array[1]; 
     1424                cond_array[1] = 0; 
     1425                cond_array[0]++; 
     1426            } 
     1427            if(conditional_0 != service_num){ 
     1428                mList[mission_num].services[conditional_0].name = pChild1->Value(); 
     1429                if(pChild1->Attribute("input_t")) 
     1430                    mList[mission_num].services[conditional_0].input[0] = pChild1->Attribute("input_t"); 
     1431                if(pChild1->Attribute("input_f")) 
     1432                    mList[mission_num].services[conditional_0].input[1] = pChild1->Attribute("input_f"); 
     1433                printf("if detected %s, %s\n", pChild1->Attribute("input_f"), pChild1->Attribute("input_t")); 
     1434            } 
     1435            else{ 
     1436                mList[mission_num].services[service_num].name = pChild1->Attribute("name"); 
     1437                if(pChild1->Attribute("input1")) 
     1438                    mList[mission_num].services[service_num].input[0] = pChild1->Attribute("input1"); 
     1439                if(pChild1->Attribute("input2")) 
     1440                    mList[mission_num].services[service_num].input[1] = pChild1->Attribute("input2"); 
     1441                if(pChild1->Attribute("input3")) 
     1442                    mList[mission_num].services[service_num].input[2] = pChild1->Attribute("input3"); 
     1443                if(pChild1->Attribute("output1")) 
     1444                    mList[mission_num].services[service_num].output[0] = pChild1->Attribute("output1"); 
     1445                if(pChild1->Attribute("output2")) 
     1446                    mList[mission_num].services[service_num].output[1] = pChild1->Attribute("output2"); 
     1447                if(pChild1->Attribute("output3")) 
     1448                    mList[mission_num].services[service_num].output[2] = pChild1->Attribute("output3"); 
     1449            } 
     1450 
     1451            mList[mission_num].services[conditional_0].num_conds = cond_array[0]; 
     1452            //printf("hello\n"); 
     1453             
     1454            cond_array[0] = 0; 
     1455            service_num++; 
     1456        } 
     1457        for(int i = 0; i < service_num; i++) 
     1458                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()); 
     1459 
     1460        mList[mission_num].numServices = service_num; 
     1461        mList[mission_num].name = pChild0->Attribute("name"); 
     1462        mList[mission_num].missionID = atoi(pChild0->Attribute("id")); 
     1463        if(pChild0->Attribute("input1")) 
     1464            mList[mission_num].input[0] = pChild0->Attribute("input1"); 
     1465        if(pChild0->Attribute("input2")) 
     1466            mList[mission_num].input[1] = pChild0->Attribute("input2"); 
     1467        if(pChild0->Attribute("input3")) 
     1468            mList[mission_num].input[2] = pChild0->Attribute("input3"); 
     1469        if(pChild0->Attribute("output1")) 
     1470            mList[mission_num].output[0] = pChild0->Attribute("output1"); 
     1471        if(pChild0->Attribute("output2")) 
     1472            mList[mission_num].output[1] = pChild0->Attribute("output2"); 
     1473        if(pChild0->Attribute("output3")) 
     1474            mList[mission_num].output[2] = pChild0->Attribute("output3"); 
     1475        printf("input1=%s, outpu1=%s\n", mList[mission_num].input[0].c_str(), mList[mission_num].output[0].c_str()); 
     1476        mission_num++; 
     1477    }*/