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

Revision 279, 53.6 KB (checked in by wrodgers, 15 years ago)

Updated shell to conform with API

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