/home/dko/projects/mobilec/tags/MobileC-v1.10.2/MobileC-v1.10.2/src/agent.c

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

Generated on Fri Jul 11 17:59:44 2008 for Mobile-C by  doxygen 1.5.4