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

Revision 290, 66.7 KB (checked in by wrodgers, 15 years ago)

Works for 3 levels of nested if's. Nested while support still to come. Shell commands implemented for sending data directly to shell.

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