root/vtcross/branches/wrodgers/src/service_management_layer/ServiceManagementLayer.cpp @ 275

Revision 275, 52.6 KB (checked in by wrodgers, 15 years ago)

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

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