/home/dko/projects/mobilec/trunk/src/agent.c

Go to the documentation of this file.
00001 /*[
00002  * Copyright (c) 2007 Integration Engineering Laboratory
00003                       University of California, Davis
00004  *
00005  * Permission to use, copy, and distribute this software and its
00006  * documentation for any purpose with or without fee is hereby granted,
00007  * provided that the above copyright notice appear in all copies and
00008  * that both that copyright notice and this permission notice appear
00009  * in supporting documentation.
00010  *
00011  * Permission to modify the software is granted, but not the right to
00012  * distribute the complete modified source code.  Modifications are to
00013  * be distributed as patches to the released version.  Permission to
00014  * distribute binaries produced by compiling modified sources is granted,
00015  * provided you
00016  *   1. distribute the corresponding source modifications from the
00017  *    released version in the form of a patch file along with the binaries,
00018  *   2. add special version identification to distinguish your version
00019  *    in addition to the base release version number,
00020  *   3. provide your name and address as the primary contact for the
00021  *    support of your modified version, and
00022  *   4. retain our contact information in regard to use of the base
00023  *    software.
00024  * Permission to distribute the released version of the source code along
00025  * with corresponding source modifications in the form of a patch file is
00026  * granted with same provisions 2 through 4 for binary distributions.
00027  *
00028  * This software is provided "as is" without express or implied warranty
00029  * to the extent permitted by applicable law.
00030 ]*/
00031 
00032 #ifndef _WIN32
00033 #include <unistd.h>
00034 #endif
00035 
00036 #include <embedch.h>
00037 
00038 #include "include/libmc.h"
00039 #include "include/agent.h"
00040 #include "include/mc_platform.h"
00041 #include "include/message.h"
00042 #include "include/agent_lib.h"
00043 #include "include/interpreter_variable_data.h"
00044 #include "include/xml_parser.h"
00045 
00046 int agent_AddPersistentVariable(agent_p agent, int task_num, const char* var_name)
00047 {
00048   int i;
00049   int size;
00050   int data_type_size;
00051   int progress;
00052   interpreter_variable_data_t *agent_variable_data;
00053   agent_variable_data = (interpreter_variable_data_t*)malloc(sizeof(interpreter_variable_data_t));
00054   agent_variable_data->name = strdup(var_name);
00055 
00056   /* Get the array data type */
00057   agent_variable_data->data_type = Ch_DataType(
00058       agent->agent_interp,
00059       var_name );
00060   /* Make sure the variable exists */
00061   if (agent_variable_data->data_type == CH_UNDEFINETYPE) {
00062     free(agent_variable_data);
00063     fprintf(stderr, "Warning: agent %s attempted saving of invalid variable, %s. %s:%d\n",
00064         agent->name, var_name, __FILE__, __LINE__);
00065     return MC_ERR;
00066   }
00067   /* Get the array dimension */
00068   agent_variable_data->array_dim = Ch_ArrayDim(
00069       agent->agent_interp,
00070       var_name );
00071   /* Get the array extents */
00072   agent_variable_data->array_extent = (int*)malloc(
00073       sizeof(int) * agent_variable_data->array_dim );
00074   for (i=0; i<agent_variable_data->array_dim; i++) {
00075     agent_variable_data->array_extent[i] = 
00076       Ch_ArrayExtent(
00077           agent->agent_interp,
00078           var_name,
00079           i );
00080   }
00081   /* Finally, allocate and point returnData to the right place. */
00082   size = 1;
00083   for (i=0; i < agent_variable_data->array_dim; i++) {
00084     size *= agent_variable_data->array_extent[i];
00085   }
00086 
00087   /* Now get the data type size */
00088   CH_DATATYPE_SIZE(agent_variable_data->data_type, data_type_size);
00089 
00090   agent_variable_data->data = (void*)malloc(size * data_type_size);
00091   CHECK_NULL(agent_variable_data->data, exit(0));
00092   /* Copy the data over from the agent */
00093   /* For now, only support statically allocated global vars. */
00094   progress = agent->datastate->task_progress;
00095   i = 0;
00096 
00097   if (agent_variable_data->array_dim == 0) {
00098     memcpy(
00099         agent_variable_data->data,
00100         (void*)Ch_GlobalSymbolAddrByName(
00101           agent->agent_interp,
00102           var_name),
00103         size*data_type_size
00104         );
00105 
00106   } else {
00107     memcpy(
00108         agent_variable_data->data,
00109         (void*)Ch_GlobalSymbolAddrByName(
00110           agent->agent_interp,
00111           var_name),
00112         size*data_type_size
00113         );
00114   }
00115   agent_variable_data->size = size*data_type_size;
00116   
00117   /* Make sure that the variable is not already in the agent's list already. */
00118   agent_variable_list_Remove(
00119       agent->datastate->tasks[task_num]->agent_variable_list, 
00120       var_name);
00121   agent_variable_list_Add(
00122       agent->datastate->tasks[task_num]->agent_variable_list, 
00123       agent_variable_data);
00124   return 0;
00125 }
00126 
00127   agent_p
00128 agent_Copy(const agent_p agent)
00129 {
00130   agent_p cp_agent;
00131   cp_agent = (agent_p)malloc(sizeof(agent_t));
00132 
00133   MUTEX_LOCK(agent->lock);
00134   /* id */
00135   cp_agent->id = agent->id;
00136   /* name */
00137   cp_agent->name = (char*)malloc
00138     (
00139      sizeof(char) * 
00140      (strlen(agent->name) + 1)
00141     );
00142   strcpy(cp_agent->name, agent->name);
00143   /* connect_id: Not Needed */
00144   /* arrival_time */
00145   cp_agent->arrival_time = agent->arrival_time;
00146   /*owner*/
00147   cp_agent->owner = (char*)malloc
00148     (
00149      sizeof(char) * 
00150      (strlen(agent->owner) + 1)
00151     );
00152   strcpy(cp_agent->owner, agent->owner);
00153   /*home*/
00154   cp_agent->home = (char*)malloc
00155     (
00156      sizeof(char) * 
00157      (strlen(agent->home) + 1)
00158     );
00159   strcpy(cp_agent->home, agent->home);
00160   /*home_port*/
00161   cp_agent->home_port = agent->home_port;
00162   /*datastate*/
00163   cp_agent->datastate = agent_datastate_Copy(agent->datastate);
00164   /* Agent is an orphan */
00165   cp_agent->orphan = 1;
00166   /*agent_type*/
00167   cp_agent->agent_type = agent->agent_type;
00168   /*agent_status*/
00169   cp_agent->agent_status = agent->agent_status;
00170   /*return_data*/
00171   cp_agent->return_data = agent->return_data;
00172   /*agent_interp*/
00173   cp_agent->agent_interp = NULL;
00174   /*agent_thread*/
00175   cp_agent->agent_thread = NULL;
00176   /*run_lock*/
00177   cp_agent->run_lock = (MUTEX_T*)malloc(sizeof(MUTEX_T));
00178   MUTEX_INIT(cp_agent->run_lock);
00179   /*agent_persistent*/
00180   cp_agent->agent_persistent = agent->agent_persistent;
00181   
00182   /*lock*/
00183   cp_agent->lock = (MUTEX_T*)malloc(sizeof(MUTEX_T));
00184   MUTEX_INIT(cp_agent->lock);
00185 
00186   return cp_agent;
00187 }
00188 
00189 agent_p
00190 agent_New(void)
00191 {
00192   agent_p agent;
00193   agent = (agent_p)malloc(sizeof(agent_t));
00194   if(agent==NULL) {
00195     fprintf(stderr, "Memory error at %s:%d\n",
00196         __FILE__, __LINE__);
00197     return NULL;
00198   }
00199   /* Just init everything to zero */
00200   memset(agent, 0, sizeof(agent_t));
00201 
00202   /* Lets go ahead and allocate the threading stuff */
00203   MUTEX_NEW(agent->run_lock);
00204   MUTEX_INIT(agent->run_lock);
00205 
00206   MUTEX_NEW(agent->lock);
00207   MUTEX_INIT(agent->lock);
00208 
00209   return agent;
00210 }
00211 
00212   agent_p 
00213 agent_Initialize(
00214     struct mc_platform_s *mc_platform,
00215     message_p message,
00216     int id)
00217 {
00218   agent_p agent; 
00219   int err_code;
00220 
00221   /* malloc memory for the agent */
00222   agent = (MCAgent_t)malloc(sizeof(agent_t));
00223   memset(agent, 0, sizeof(agent_t));
00224 
00225   /* Set up general agent data access mutex */
00226   agent->lock = (MUTEX_T*)malloc(sizeof(MUTEX_T));
00227   MUTEX_INIT(agent->lock);
00228 
00229   /* Set up run_lock mutex */
00230   agent->run_lock = (MUTEX_T*)malloc(sizeof(MUTEX_T));
00231   MUTEX_INIT(agent->run_lock);
00232 
00233   /* set flags and variables for the agent */
00234   agent->id = id;
00235 #ifndef _WIN32
00236   agent->arrival_time = time(NULL);
00237 #else
00238   GetSystemTime( &(agent->arrival_time) );
00239 #endif
00240 
00241   /* set flags */
00242   agent->orphan = 0;
00243   agent->agent_script_ready = 1;
00244   agent->agent_pipe_ready_to_read = 0;
00245   agent->agent_ready_to_send = 0;
00246   agent->agent_pipe_active = 0;
00247 
00248   /* set the agent thread to null until activated */
00249   agent->agent_thread = NULL;
00250   agent->agent_thread_id = 0;
00251 
00252   /* Set up an empty mailbox */
00253   agent->mailbox = agent_mailbox_New();
00254 
00255   /* parse the xml */
00256   agent->datastate = agent_datastate_New();
00257   agent->datastate->xml_agent_root = message->xml_payload;
00258   agent->datastate->xml_root = message->xml_root;
00259   message->agent_xml_flag = 1;
00260   
00261   if (agent->datastate->xml_agent_root != NULL) {
00262     switch(message->message_type) {
00263       case MOBILE_AGENT:
00264         agent->agent_type = MC_REMOTE_AGENT;
00265         if( (err_code = agent_xml_parse(agent))) {
00266           fprintf(stderr, "error code %d. %s:%d\n",
00267               err_code, __FILE__, __LINE__ );
00268           agent_Destroy(agent);
00269           return NULL;
00270         }
00271         if (mc_platform->default_agentstatus != -1) {
00272           agent->agent_status = mc_platform->default_agentstatus;
00273         }
00274         break;
00275       case RETURN_MSG:
00276         agent->agent_type = MC_RETURN_AGENT;
00277         if( (err_code = agent_xml_parse(agent))) {
00278           fprintf(stderr, "error code %d. %s:%d\n",
00279               err_code, __FILE__, __LINE__ );
00280           agent_Destroy(agent);
00281           return NULL;
00282         }
00283         break;
00284       default:
00285         fprintf(stderr, "Invalid agent type: %d %s:%d\n",
00286             agent->agent_type, __FILE__, __LINE__ );
00287     }
00288   } else {
00289     mc_platform->err = MC_ERR_PARSE;
00290     /* Free up memory. */
00291     MUTEX_DESTROY(agent->lock);
00292     free(agent->lock);
00293     MUTEX_DESTROY(agent->run_lock);
00294     free(agent->run_lock);
00295 
00296     free(agent);
00297     return NULL;
00298   }
00299 
00300   /* In the future we will compare the current tasks server name to 
00301      the one on the server, presently this is not implemented */
00302 
00303   /* set the CH exectution flag */
00304   /* FIXME: This should be in the xml parser */
00305   /*if (agent->datastate->tasks[agent->datastate->task_progress]->init_agent_status != -1) {
00306     agent->agent_status = agent->datastate->tasks[agent->datastate->task_progress]->init_agent_status;
00307     } else {
00308     agent->agent_status = mc_platform->default_agentstatus;
00309     }
00310     */
00311   agent->agent_status = MC_WAIT_CH;
00312 
00313   agent->mc_platform = mc_platform;
00314 
00315   /* return */
00316   return agent;
00317 }
00318 
00319   int
00320 agent_Destroy(agent_p agent)
00321 {
00322   if (agent == NULL) {
00323     return MC_SUCCESS;
00324   }
00325   MUTEX_LOCK(agent->lock);
00326   if (agent->name != NULL) {
00327     free(agent->name);
00328   }
00329   if (agent->owner != NULL) {
00330     free(agent->owner);
00331   }
00332   if (agent->home != NULL) {
00333     free(agent->home);
00334   }
00335   /* Terminate the agent datastate memory */
00336   MUTEX_DESTROY(agent->lock);
00337   if (agent->agent_status == MC_AGENT_NEUTRAL) {
00338     if ((agent->agent_interp) != NULL) {
00339       Ch_End(agent->agent_interp);
00340     }
00341   }
00342   free(agent->lock);
00343   agent_datastate_Destroy(agent->datastate);
00344   free(agent->agent_thread);
00345   free(agent->run_lock);
00346   agent_mailbox_Destroy(agent->mailbox);
00347   /* deallocate the agent */
00348   free(agent);
00349   agent = NULL;
00350   return MC_SUCCESS;
00351 }
00352 
00353   extern void 
00354 agent_RunChScript(agent_p agent, mc_platform_p mc_platform)
00355 {
00356 #ifndef _WIN32
00357   pthread_attr_t attr;
00358   pthread_attr_init(&attr);
00359   if(mc_platform->stack_size[MC_THREAD_AGENT] != -1) {
00360     pthread_attr_setstacksize
00361       (
00362        &attr, 
00363        mc_platform->stack_size[MC_THREAD_AGENT]
00364       );
00365   }
00366   pthread_attr_setdetachstate /* Automatically reclaim thread memory for this thread */
00367     (
00368      &attr,
00369      PTHREAD_CREATE_DETACHED
00370     );
00371 #else
00372   int stack_size;
00373   if (mc_platform->stack_size[MC_THREAD_AGENT] < 1) {
00374           stack_size = mc_platform->stack_size[MC_THREAD_AGENT]+1;
00375   } else {
00376           stack_size = mc_platform->stack_size[MC_THREAD_AGENT];
00377   }
00378 #endif
00379   if(agent->agent_thread == NULL) 
00380   {
00381     agent->agent_thread = (THREAD_T *)malloc(sizeof(THREAD_T));
00382   }
00383 
00384   agent->agent_status = MC_AGENT_ACTIVE;
00385   agent->mc_platform = mc_platform;
00386 
00387   THREAD_CREATE(agent->agent_thread,
00388       agent_RunChScriptThread,
00389       agent );
00390 
00391   return;
00392 }
00393 
00394 #ifndef _WIN32
00395   void* 
00396 agent_RunChScriptThread(void * ChAgent)
00397 #else
00398   DWORD WINAPI 
00399 agent_RunChScriptThread(void* ChAgent)
00400 #endif
00401 {
00402 #ifndef _WIN32
00403   int fd;
00404 #endif
00405   MCAgent_t agent;
00406   mc_platform_p mc_platform;
00407   int i,n;
00408   FILE *TEMP_FILE;
00409   char *temp_store_file;
00410   char *ChShellArg[2];
00411   void *result;
00412   int progress;
00413   char *tmp_buf;
00414 
00415   /* set up the agent object */
00416   agent = (MCAgent_t)ChAgent;
00417   progress = agent->datastate->task_progress;
00418   mc_platform = agent->mc_platform;
00419 
00420   /* check to see if the agent is null */
00421   if(ChAgent == NULL)
00422   {
00423     printf("ERROR, AGENT NULL \n");
00424 #ifndef _WIN32
00425     return NULL;
00426 #else
00427     return 0;
00428 #endif
00429   }
00430   /* We need to check for custom interp_options. If any
00431    * value is null, then we pass null on to Ch_Initialize. */
00432   if( ((MCAgent_t)ChAgent)->mc_platform->interp_options == NULL ) {
00433 
00434     if(Ch_Initialize(&(((MCAgent_t)ChAgent)->agent_interp), 
00435           NULL))
00436     {
00437       printf("CH INIT ERROR \n");
00438       exit(EXIT_FAILURE);
00439     }
00440   } else {
00441     if(Ch_Initialize(&(((MCAgent_t)ChAgent)->agent_interp), 
00442           ((MCAgent_t)ChAgent)->mc_platform->interp_options))
00443     {
00444       printf("CH INIT ERROR \n");
00445       exit(EXIT_FAILURE);
00446     }
00447   }
00448 
00449   /* Declare special variables for holding the agent id and name */
00450   tmp_buf = malloc(sizeof(char) * 200);
00451   tmp_buf[0] = '\0';
00452   sprintf(tmp_buf, "int mc_agent_id=%d;", (int)agent->id);
00453   Ch_DeclareVar(
00454       agent->agent_interp,
00455       tmp_buf
00456       );
00457 
00458   tmp_buf[0] = '\0';
00459   sprintf(tmp_buf,
00460       "char mc_agent_name[]=\"%s\";",
00461       agent->name
00462       );
00463   Ch_DeclareVar(
00464       agent->agent_interp,
00465       tmp_buf
00466       );
00467 
00468   tmp_buf[0] = '\0';
00469   sprintf(tmp_buf, "void* mc_current_agent = (void*)%d;", (int)agent);
00470   Ch_DeclareVar(
00471       agent->agent_interp,
00472       tmp_buf
00473       );
00474 
00475   tmp_buf[0] = '\0';
00476   sprintf(tmp_buf, "char mc_host_name[] = \"%s\";",
00477       agent->mc_platform->hostname );
00478   Ch_DeclareVar(
00479       agent->agent_interp,
00480       tmp_buf
00481       );
00482 
00483   tmp_buf[0] = '\0';
00484   sprintf(tmp_buf, "int mc_host_port = %d;\n",
00485       agent->mc_platform->port );
00486   Ch_DeclareVar(
00487       agent->agent_interp,
00488       tmp_buf
00489       );
00490 
00491   tmp_buf[0] = '\0';
00492   sprintf(tmp_buf, "int mc_task_progress = %d;\n",
00493       agent->datastate->task_progress);
00494   Ch_DeclareVar(
00495       agent->agent_interp,
00496       tmp_buf
00497       );
00498 
00499   tmp_buf[0] = '\0';
00500   sprintf(tmp_buf, "int mc_num_tasks = %d;\n",
00501       agent->datastate->number_of_tasks );
00502   Ch_DeclareVar(
00503       agent->agent_interp,
00504       tmp_buf
00505       );
00506 
00507   /* Declare standard error code enum */
00508   tmp_buf[0] = '\0';
00509   sprintf(tmp_buf, "enum error_code_e {MC_SUCCESS = 0, MC_ERR, MC_ERR_CONNECT, MC_ERR_PARSE, MC_ERR_EMPTY, MC_ERR_INVALID, MC_ERR_INVALID_ARGS, MC_ERR_NOT_FOUND, MC_ERR_MEMORY, MC_ERR_SEND, MC_WARN_DUPLICATE };" );
00510   Ch_DeclareVar(
00511       agent->agent_interp,
00512       tmp_buf
00513       );
00514 
00515   tmp_buf[0] = '\0';
00516   sprintf(tmp_buf, "enum MC_SteerCommand_e {MC_RUN = 0, MC_SUSPEND, MC_RESTART, MC_STOP};" );
00517   Ch_DeclareVar(
00518       agent->agent_interp,
00519       tmp_buf
00520       );
00521 
00522   tmp_buf[0] = '\0';
00523   sprintf(tmp_buf, "enum mc_AgentStatus_e { MC_WAIT_CH, MC_WAIT_MESSGSEND, MC_AGENT_ACTIVE, MC_AGENT_NEUTRAL, MC_AGENT_SUSPENDED, MC_WAIT_FINISHED};"); 
00524   Ch_DeclareVar(
00525       agent->agent_interp,
00526       tmp_buf
00527       );
00528 
00529   free(tmp_buf);
00530   /* Add the MCAgent_t typedef */
00531   Ch_DeclareVar(
00532       agent->agent_interp,
00533       "void* MCAgent_t;"
00534       );
00535   Ch_DeclareTypedef(
00536       agent->agent_interp,
00537       "MCAgent_t"
00538       );
00539 
00540   /* Following are the declarations of the agent-space api functions. */
00541   Ch_DeclareFunc(
00542       agent->agent_interp,
00543       "int mc_AclDestroy(void* acl_message);",
00544       (ChFuncdl_t)MC_AclDestroy_chdl
00545       );
00546   Ch_DeclareFunc(
00547       agent->agent_interp,
00548       "void* mc_AclNew(void);",
00549       (ChFuncdl_t)MC_AclNew_chdl
00550       );
00551   Ch_DeclareFunc(
00552       agent->agent_interp,
00553       "void* mc_AclPost(void* agent, void* acl_message);",
00554       (ChFuncdl_t)MC_AclPost_chdl
00555       );
00556   Ch_DeclareFunc(
00557       agent->agent_interp,
00558       "void* mc_AclRetrieve(void* agent);",
00559       (ChFuncdl_t)MC_AclRetrieve_chdl
00560       );
00561   Ch_DeclareFunc(
00562       agent->agent_interp,
00563       "void* mc_AclReply(void* acl_message);",
00564       (ChFuncdl_t)MC_AclReply_chdl
00565       );
00566   Ch_DeclareFunc(
00567       agent->agent_interp,
00568       "int mc_AclSend(void* acl_message);",
00569       (ChFuncdl_t)MC_AclSend_chdl
00570       );
00571   Ch_DeclareFunc(
00572       agent->agent_interp,
00573       "void* mc_AclWaitRetrieve(void* agent);",
00574       (ChFuncdl_t)MC_AclWaitRetrieve_chdl
00575       );
00576   /* begin Acl Helper Functions */
00577   Ch_DeclareFunc(
00578       agent->agent_interp,
00579       "int mc_AclSetPerformative(void* acl_message, int performative);",
00580       (ChFuncdl_t)MC_AclSetPerformative_chdl
00581       );
00582   Ch_DeclareFunc(
00583       agent->agent_interp,
00584       "int mc_AclSetSender(void* acl_message, char* name, char* address);",
00585       (ChFuncdl_t)MC_AclSetSender_chdl
00586       );
00587   Ch_DeclareFunc(
00588       agent->agent_interp,
00589       "int mc_AclAddReceiver(void* acl_message, char* name, char* address);",
00590       (ChFuncdl_t)MC_AclAddReceiver_chdl
00591       );
00592   Ch_DeclareFunc(
00593       agent->agent_interp,
00594       "int mc_AclAddReplyTo(void* acl_message, char* name, char* address);",
00595       (ChFuncdl_t)MC_AclAddReplyTo_chdl
00596       );
00597   Ch_DeclareFunc(
00598       agent->agent_interp,
00599       "int mc_AclSetContent(void* acl_message, char* content);",
00600       (ChFuncdl_t)MC_AclSetContent_chdl
00601       );
00602   /* end Acl Helper Functions */
00603   Ch_DeclareFunc(
00604       agent->agent_interp,
00605       "int mc_AddAgent(void* agent);",
00606       (ChFuncdl_t)MC_AddAgent_chdl
00607       );
00608   Ch_DeclareFunc(
00609       agent->agent_interp,
00610       "const void* mc_AgentVariableRetrieve(void* agent, const char* var_name, int task_num);",
00611       (ChFuncdl_t)MC_AgentVariableRetrieve_chdl
00612       );
00613   Ch_DeclareFunc(
00614       agent->agent_interp,
00615       "int mc_AgentVariableSave(void* agent, const char* var_name);",
00616       (ChFuncdl_t)MC_AgentVariableSave_chdl
00617       );
00618   Ch_DeclareFunc(
00619       agent->agent_interp,
00620       "int mc_Barrier(int id);",
00621       (ChFuncdl_t)MC_Barrier_chdl
00622       );
00623   Ch_DeclareFunc(
00624       agent->agent_interp,
00625       "int mc_BarrierDelete(int id);",
00626       (ChFuncdl_t)MC_BarrierDelete_chdl
00627       );
00628   Ch_DeclareFunc(
00629       agent->agent_interp,
00630       "int mc_BarrierInit(int id, int num_procs);",
00631       (ChFuncdl_t)MC_BarrierInit_chdl
00632       );
00633   Ch_DeclareFunc(
00634       agent->agent_interp,
00635       "int mc_CallAgentFunc(MCAgent_t agent, const char* funcName, void* returnVal, void* arg_struct);",
00636       (ChFuncdl_t)MC_CallAgentFunc_chdl
00637       );
00638   Ch_DeclareFunc(
00639       agent->agent_interp,
00640       "MCAgent_t mc_ComposeAgent(const char* name, *home, *owner, *code, *return_var_name, *server, int persistent);",
00641       (ChFuncdl_t)MC_ComposeAgent_chdl
00642       );
00643   Ch_DeclareFunc(
00644       agent->agent_interp,
00645       "int mc_CondBroadcast(int id);",
00646       (ChFuncdl_t)MC_CondBroadcast_chdl
00647       );
00648   Ch_DeclareFunc(
00649       agent->agent_interp,
00650       "int mc_CondSignal(int id);",
00651       (ChFuncdl_t)MC_CondSignal_chdl
00652       );
00653   Ch_DeclareFunc(
00654       agent->agent_interp,
00655       "int mc_CondReset(int id);",
00656       (ChFuncdl_t)MC_CondReset_chdl 
00657       );
00658   Ch_DeclareFunc(
00659       agent->agent_interp,
00660       "int mc_CondWait(int id);",
00661       (ChFuncdl_t)MC_CondWait_chdl 
00662       );
00663   Ch_DeclareFunc(
00664       agent->agent_interp,
00665       "int mc_DeleteAgent(MCAgent_t agent);",
00666       (ChFuncdl_t)MC_DeleteAgent_chdl 
00667       );
00668   Ch_DeclareFunc(
00669       agent->agent_interp,
00670       "int mc_DeregisterService(int agentID, char* serviceName);",
00671       (ChFuncdl_t)MC_DeregisterService_chdl
00672       );
00673   Ch_DeclareFunc(
00674       agent->agent_interp,
00675       "int mc_DestroyServiceSearchResult( char** agentName, char** serviceName, int* agentID, int numResult);",
00676       (ChFuncdl_t)MC_DestroyServiceSearchResult_chdl 
00677       );
00678   Ch_DeclareFunc(
00679       agent->agent_interp,
00680       "int mc_End(void);",
00681       (ChFuncdl_t)MC_End_chdl
00682       );
00683   Ch_DeclareFunc(
00684       agent->agent_interp,
00685       "void *mc_FindAgentByID(int id);",
00686       (ChFuncdl_t)MC_FindAgentByID_chdl
00687       );
00688   Ch_DeclareFunc(
00689       agent->agent_interp,
00690       "void *mc_FindAgentByName(const char *name);",
00691       (ChFuncdl_t)MC_FindAgentByName_chdl
00692       );
00693   /* FIXME -- This block of code does not work: Ch does not
00694    * understand 'time_t' */
00695   /*
00696   Ch_DeclareFunc(
00697       agent->agent_interp,
00698       "time_t mc_GetAgentArrivalTime(void* agent);",
00699       (ChFuncdl_t)MC_GetAgentArrivalTime_chdl
00700       );
00701       */
00702   Ch_DeclareFunc(
00703       agent->agent_interp,
00704       "int MC_GetAgentID(void* agent);",
00705       (ChFuncdl_t)MC_GetAgentStatus_chdl
00706       );
00707   Ch_DeclareFunc(
00708       agent->agent_interp,
00709       "char* MC_GetAgentName(void* agent);",
00710       (ChFuncdl_t)MC_GetAgentStatus_chdl
00711       );
00712   Ch_DeclareFunc(
00713       agent->agent_interp,
00714       "int mc_GetAgentStatus(void* agent);",
00715       (ChFuncdl_t)MC_GetAgentStatus_chdl
00716       );
00717   Ch_DeclareFunc(
00718       agent->agent_interp,
00719       "char *mc_GetAgentXMLString(void* agent);",
00720       (ChFuncdl_t)MC_GetAgentXMLString_chdl
00721       );
00722 
00723 #ifndef _WIN32
00724   Ch_DeclareFunc(
00725       agent->agent_interp,
00726       "int mc_gettimeofday(void* tv);",
00727       (ChFuncdl_t)MC_GetTimeOfDay_chdl
00728       );
00729 #endif
00730 
00731   Ch_DeclareFunc(
00732       agent->agent_interp,
00733       "int mc_HaltAgency(void);",
00734       (ChFuncdl_t)MC_HaltAgency_chdl
00735       );
00736   Ch_DeclareFunc(
00737       agent->agent_interp,
00738       "int mc_MutexLock(int id);",
00739       (ChFuncdl_t)MC_MutexLock_chdl
00740       );
00741   Ch_DeclareFunc(
00742       agent->agent_interp,
00743       "int mc_MutexUnlock(int id);",
00744       (ChFuncdl_t)MC_MutexUnlock_chdl
00745       );
00746   Ch_DeclareFunc(
00747       agent->agent_interp,
00748       "int mc_PrintAgentCode(void* agent);",
00749       (ChFuncdl_t)MC_PrintAgentCode_chdl
00750       );
00751   Ch_DeclareFunc(
00752       agent->agent_interp,
00753       "int mc_ResumeAgency(void);",
00754       (ChFuncdl_t)MC_ResumeAgency_chdl
00755       );
00756   Ch_DeclareFunc(
00757       agent->agent_interp,
00758       "int mc_SearchForService(const char* searchString, char*** agentNames, char*** serviceNames, int** agentIDs, int* numResults);",
00759       (ChFuncdl_t)MC_SearchForService_chdl
00760       );
00761   Ch_DeclareFunc(
00762       agent->agent_interp,
00763       "int mc_SendSteerCommand(enum MC_SteerCommand_e command);",
00764       (ChFuncdl_t)MC_SendSteerCommand_chdl
00765       );
00766   Ch_DeclareFunc(
00767       agent->agent_interp,
00768       "int mc_RegisterService(MCAgent_t agent, char **serviceNames, int numServices);",
00769       (ChFuncdl_t)MC_RegisterService_chdl
00770       );
00771   Ch_DeclareFunc(
00772       agent->agent_interp,
00773       "void *mc_RetrieveAgent(void);",
00774       (ChFuncdl_t)MC_RetrieveAgent_chdl
00775       );
00776   Ch_DeclareFunc(
00777       agent->agent_interp,
00778       "char *mc_RetrieveAgentCode(void* agent);",
00779       (ChFuncdl_t)MC_RetrieveAgentCode_chdl
00780       );
00781   Ch_DeclareFunc(
00782       agent->agent_interp,
00783       "int mc_SemaphoreWait(int id);",
00784       (ChFuncdl_t)MC_SemaphoreWait_chdl
00785       );
00786   Ch_DeclareFunc(
00787       agent->agent_interp,
00788       "int mc_SemaphorePost(int id);",
00789       (ChFuncdl_t)MC_SemaphorePost_chdl
00790       );
00791   Ch_DeclareFunc(
00792       agent->agent_interp,
00793       "int mc_SendAgentMigrationMessage(char *message, char *hostname, int port);",
00794       (ChFuncdl_t)MC_SendAgentMigrationMessage_chdl
00795       );
00796   Ch_DeclareFunc(
00797       agent->agent_interp,
00798       "int mc_SendAgentMigrationMessageFile(char *filename, char *hostname, int port);",
00799       (ChFuncdl_t)MC_SendAgentMigrationMessageFile_chdl
00800       );
00801   Ch_DeclareFunc(
00802       agent->agent_interp,
00803       "int mc_SetAgentStatus(void* agent, int status);",
00804       (ChFuncdl_t)MC_SetAgentStatus_chdl
00805       );
00806   Ch_DeclareFunc(
00807       agent->agent_interp,
00808       "int mc_SetDefaultAgentStatus(int status);",
00809       (ChFuncdl_t)MC_SetDefaultAgentStatus_chdl
00810       );
00811   Ch_DeclareFunc(
00812       agent->agent_interp,
00813       "int mc_SyncDelete(int id);",
00814       (ChFuncdl_t)MC_SyncDelete_chdl 
00815       );
00816   Ch_DeclareFunc(
00817       agent->agent_interp,
00818       "int mc_SyncInit(int id);",
00819       (ChFuncdl_t)MC_SyncInit_chdl 
00820       );
00821   Ch_DeclareFunc(
00822       agent->agent_interp,
00823       "int mc_TerminateAgent(void* agent);",
00824       (ChFuncdl_t)MC_TerminateAgent_chdl
00825       );
00826   Ch_DeclareFunc(
00827       agent->agent_interp,
00828       "int mc_GetAgentID(void* agent);",
00829       (ChFuncdl_t)MC_GetAgentID_chdl
00830       );
00831   Ch_DeclareFunc(
00832       agent->agent_interp,
00833       "char *mc_GetAgentName(void* agent);",
00834       (ChFuncdl_t)MC_GetAgentName_chdl
00835       );
00836   /* Originally, we hope to use append runscript if the buffer for code is less than 5120 bytes.
00837      Otherwise we must open a file and save the data to the filename.
00838      However, since the mobile agent codes for testing are complete programs 
00839      which contain preprocessing directives like "#include" and are larger than 51 bytes, we use
00840      the following statement to save the data to a file instead of putting it into the buffer. 
00841 
00842 FIXME: This is silly
00843 */
00844   if(strlen(agent->datastate->agent_code) < 51)
00845   {
00846     if(Ch_AppendRunScript(
00847           ((MCAgent_t)ChAgent)->agent_interp, 
00848           ((MCAgent_t)ChAgent)->datastate->agent_code))
00849     {
00850       printf("CH Failure \n");
00851       exit(EXIT_FAILURE);
00852     }
00853     if(Ch_CallFuncByName(((MCAgent_t)ChAgent)->agent_interp, "main", NULL))
00854     {
00855       printf("CH2 failure \n");
00856       exit(EXIT_FAILURE);
00857     }
00858   }
00859   else
00860   {
00861 
00862 #ifndef _WIN32
00863     /* save the agent to an external file %agentname%%d%d */
00864     temp_store_file = (char *)malloc(sizeof(char)*30);
00865 
00866     strcpy(temp_store_file, "agentchscriptXXXXXX");
00867     fd = mkstemp(temp_store_file);
00868     if (fd == -1) {
00869       fprintf(stderr, "Could not create temporary file:%s. %s:%d\n",
00870           temp_store_file,
00871           __FILE__,
00872           __LINE__ );
00873       exit(EXIT_FAILURE);
00874     }
00875     close(fd);
00876 #else
00877     temp_store_file = _tempnam(".", "agentchscript");
00878 #endif
00879     TEMP_FILE = fopen(temp_store_file, "w");
00880     
00881     /* write the data to a ch-file */
00882     n = fwrite(
00883         (void *)agent->datastate->agent_code, 
00884         sizeof(char), 
00885         strlen(agent->datastate->agent_code), 
00886         TEMP_FILE);
00887 
00888     fclose(TEMP_FILE);
00889 
00890     /* set the Ch Shell arguments as appropriate */
00891     ChShellArg[0] = temp_store_file;
00892     ChShellArg[1] = NULL;
00893     MUTEX_LOCK(agent->run_lock);
00894     Ch_RunScript(agent->agent_interp, ChShellArg); 
00895     MUTEX_UNLOCK(agent->run_lock);
00896 
00897     /*        if(Ch_CallFuncByName(((MCAgent_t)ChAgent)->agent_interp, "main", NULL))
00898               {
00899               printf("CH2 failure \n");
00900               exit(EXIT_FAILURE);
00901               } */
00902 
00903     /* remove the temp file after its usage */
00904     remove(temp_store_file);
00905 #ifndef _WIN32
00906     free(temp_store_file);
00907 #endif
00908   }
00909 
00910   /* now add the data element returned from the Ch execution into the agent data structure */
00911   if(strcmp(agent->datastate->tasks[progress]->var_name, "no-return"))
00912   {
00913     result = interpreter_variable_data_InitializeFromAgent(agent);
00914     /* Free old result extracted from XML agent */
00915     interpreter_variable_data_Destroy(
00916         agent->datastate->tasks[progress]->agent_return_data
00917         );
00918     /* Replace with new freshly calculated one */
00919     agent->datastate->tasks[progress]->agent_return_data = 
00920       result;
00921   } else {
00922     interpreter_variable_data_Destroy(
00923         agent->datastate->tasks[progress]->agent_return_data );
00924     agent->datastate->tasks[progress]->agent_return_data = NULL;
00925   }
00926 
00927   /* This is where we want to save all of the agent variables that the agent
00928    * wishes to keep for its trip. */
00929   for(i = 0; i < agent->datastate->tasks[progress]->num_saved_variables; i++) {
00930     agent_variable_list_Add(
00931         agent->datastate->tasks[progress]->agent_variable_list,
00932         interpreter_variable_data_Initialize(
00933           agent,
00934           agent->datastate->tasks[progress]->saved_variables[i] )
00935         );
00936   }
00937 
00938   if (agent->datastate->persistent || 
00939       agent->datastate->tasks[progress]->persistent ) {
00940     /* TODO: We need a large while loop here that waits on a condition 
00941        variable. Upon waking up, we will need to check a 'mailbox' for
00942        a struct containing
00943        1. A message/command
00944        2. A void* to generic data
00945        3. The size of the data.
00946        It should then execute the command, and check to see if the
00947        persistent flag is still set. If it is, loop again. 
00948        */
00949     /* For now, let us just not end the Ch interpreter and set the 
00950      * agent_status to MC_AGENT_NEUTRAL to cause it to hang. */
00951     ((MCAgent_t) ChAgent)->agent_status = MC_AGENT_NEUTRAL;
00952   } else {
00953     if ((((MCAgent_t)ChAgent)->agent_interp) != NULL) {
00954       Ch_End(((MCAgent_t)ChAgent)->agent_interp);
00955     }
00956 
00957     /* Perform some housekeeping regarding agent status */
00958     if (
00959         (agent->datastate->task_progress ==
00960          (agent->datastate->number_of_tasks-1))
00961        ) 
00962     {
00963       /* If the agent is done... */
00964       ((MCAgent_t) ChAgent)->agent_status = MC_WAIT_FINISHED;
00965       /* If _any_ of the tasks have return data, we should generate
00966        * a return message. */
00967       for(i = 0; 
00968           i < agent->datastate->number_of_tasks;
00969           i++)
00970       {
00971         if (agent->datastate->tasks[i]->agent_return_data != NULL) {
00972           ((MCAgent_t) ChAgent)->agent_status = MC_WAIT_MESSGSEND;
00973         }
00974       }
00975     }
00976     else {
00977       ((MCAgent_t) ChAgent)->agent_status = MC_WAIT_MESSGSEND; 
00978     }
00979   }
00980 
00981   /* close the task, indicating that it has been completed */
00982   agent->datastate->
00983     tasks[agent->datastate->task_progress]->task_completed = 1;
00984   agent->datastate->task_progress++;
00985 
00986   if (
00987       (agent->datastate->task_progress >= agent->datastate->number_of_tasks)
00988      )
00989   {
00990     agent->agent_type = MC_RETURN_AGENT;
00991   }
00992 
00993   SIGNAL(
00994       mc_platform->MC_signal_cond,
00995       mc_platform->MC_signal_lock,
00996       mc_platform->MC_signal = MC_EXEC_AGENT;
00997       );
00998 
00999   MUTEX_LOCK( mc_platform->MC_signal_lock);
01000   MUTEX_UNLOCK( mc_platform->MC_signal_lock );
01001   MUTEX_LOCK(mc_platform->ams->runflag_lock);
01002   mc_platform->ams->run = 1;
01003   COND_SIGNAL(mc_platform->ams->runflag_cond);
01004   MUTEX_UNLOCK(mc_platform->ams->runflag_lock);
01005 
01006 #ifndef _WIN32
01007   pthread_exit(ChAgent);  
01008 #else
01009   return 0;
01010 #endif
01011 }

Generated on Mon Jun 23 16:01:09 2008 for Mobile-C by  doxygen 1.5.4