root/vtcross/trunk/src/service_management_layer/ServiceManagementLayer.cpp @ 285

Revision 285, 54.7 KB (checked in by wrodgers, 15 years ago)

updating SML demo

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