00001 /* SVN FILE INFO 00002 * $Revision: 230 $ : Last Committed Revision 00003 * $Date: 2008年10月24日 15:47:36 -0700 (2008年10月24日) $ : 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, ...);", 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_SaveData(MCAgent_t agent, char* name, int size, void* data);", 00787 (ChFuncdl_t)MC_SaveData_chdl 00788 ); 00789 Ch_DeclareFunc( 00790 agent->agent_interp, 00791 "int mc_SemaphoreWait(int id);", 00792 (ChFuncdl_t)MC_SemaphoreWait_chdl 00793 ); 00794 Ch_DeclareFunc( 00795 agent->agent_interp, 00796 "int mc_SemaphorePost(int id);", 00797 (ChFuncdl_t)MC_SemaphorePost_chdl 00798 ); 00799 Ch_DeclareFunc( 00800 agent->agent_interp, 00801 "int mc_SendAgentMigrationMessage(char *message, char *hostname, int port);", 00802 (ChFuncdl_t)MC_SendAgentMigrationMessage_chdl 00803 ); 00804 Ch_DeclareFunc( 00805 agent->agent_interp, 00806 "int mc_SendAgentMigrationMessageFile(char *filename, char *hostname, int port);", 00807 (ChFuncdl_t)MC_SendAgentMigrationMessageFile_chdl 00808 ); 00809 Ch_DeclareFunc( 00810 agent->agent_interp, 00811 "int mc_SetAgentStatus(void* agent, int status);", 00812 (ChFuncdl_t)MC_SetAgentStatus_chdl 00813 ); 00814 Ch_DeclareFunc( 00815 agent->agent_interp, 00816 "int mc_SetDefaultAgentStatus(int status);", 00817 (ChFuncdl_t)MC_SetDefaultAgentStatus_chdl 00818 ); 00819 Ch_DeclareFunc( 00820 agent->agent_interp, 00821 "int mc_SyncDelete(int id);", 00822 (ChFuncdl_t)MC_SyncDelete_chdl 00823 ); 00824 Ch_DeclareFunc( 00825 agent->agent_interp, 00826 "int mc_SyncInit(int id);", 00827 (ChFuncdl_t)MC_SyncInit_chdl 00828 ); 00829 Ch_DeclareFunc( 00830 agent->agent_interp, 00831 "int mc_TerminateAgent(void* agent);", 00832 (ChFuncdl_t)MC_TerminateAgent_chdl 00833 ); 00834 Ch_DeclareFunc( 00835 agent->agent_interp, 00836 "int mc_GetAgentID(void* agent);", 00837 (ChFuncdl_t)MC_GetAgentID_chdl 00838 ); 00839 Ch_DeclareFunc( 00840 agent->agent_interp, 00841 "char *mc_GetAgentName(void* agent);", 00842 (ChFuncdl_t)MC_GetAgentName_chdl 00843 ); 00844 /* Originally, we hope to use append runscript if the buffer for code is less than 5120 bytes. 00845 Otherwise we must open a file and save the data to the filename. 00846 However, since the mobile agent codes for testing are complete programs 00847 which contain preprocessing directives like "#include" and are larger than 51 bytes, we use 00848 the following statement to save the data to a file instead of putting it into the buffer. 00849 00850 FIXME: This is silly 00851 */ 00852 if(strlen(agent->datastate->agent_code) < 51) 00853 { 00854 if(Ch_AppendRunScript( 00855 ((MCAgent_t)ChAgent)->agent_interp, 00856 ((MCAgent_t)ChAgent)->datastate->agent_code)) 00857 { 00858 printf("CH Failure \n"); 00859 exit(EXIT_FAILURE); 00860 } 00861 if(Ch_CallFuncByName(((MCAgent_t)ChAgent)->agent_interp, "main", NULL)) 00862 { 00863 printf("CH2 failure \n"); 00864 exit(EXIT_FAILURE); 00865 } 00866 } 00867 else 00868 { 00869 00870 #ifndef _WIN32 00871 /* save the agent to an external file %agentname%%d%d */ 00872 temp_store_file = (char *)malloc(sizeof(char)*30); 00873 00874 strcpy(temp_store_file, "agentchscriptXXXXXX"); 00875 fd = mkstemp(temp_store_file); 00876 if (fd == -1) { 00877 fprintf(stderr, "Could not create temporary file:%s. %s:%d\n", 00878 temp_store_file, 00879 __FILE__, 00880 __LINE__ ); 00881 exit(EXIT_FAILURE); 00882 } 00883 close(fd); 00884 #else 00885 temp_store_file = _tempnam(".", "agentchscript"); 00886 #endif 00887 TEMP_FILE = fopen(temp_store_file, "w"); 00888 00889 /* write the data to a ch-file */ 00890 n = fwrite( 00891 (void *)agent->datastate->agent_code, 00892 sizeof(char), 00893 strlen(agent->datastate->agent_code), 00894 TEMP_FILE); 00895 00896 fclose(TEMP_FILE); 00897 00898 /* set the Ch Shell arguments as appropriate */ 00899 ChShellArg[0] = temp_store_file; 00900 ChShellArg[1] = NULL; 00901 MUTEX_LOCK(agent->run_lock); 00902 Ch_RunScript(agent->agent_interp, ChShellArg); 00903 MUTEX_UNLOCK(agent->run_lock); 00904 00905 /* if(Ch_CallFuncByName(((MCAgent_t)ChAgent)->agent_interp, "main", NULL)) 00906 { 00907 printf("CH2 failure \n"); 00908 exit(EXIT_FAILURE); 00909 } */ 00910 00911 /* remove the temp file after its usage */ 00912 remove(temp_store_file); 00913 #ifndef _WIN32 00914 free(temp_store_file); 00915 #endif 00916 } 00917 00918 /* now add the data element returned from the Ch execution into the agent data structure */ 00919 if(strcmp(agent->datastate->tasks[progress]->var_name, "no-return")) 00920 { 00921 result = interpreter_variable_data_InitializeFromAgent(agent); 00922 /* Free old result extracted from XML agent */ 00923 interpreter_variable_data_Destroy( 00924 agent->datastate->tasks[progress]->agent_return_data 00925 ); 00926 /* Replace with new freshly calculated one */ 00927 agent->datastate->tasks[progress]->agent_return_data = 00928 result; 00929 } else { 00930 interpreter_variable_data_Destroy( 00931 agent->datastate->tasks[progress]->agent_return_data ); 00932 agent->datastate->tasks[progress]->agent_return_data = NULL; 00933 } 00934 00935 /* This is where we want to save all of the agent variables that the agent 00936 * wishes to keep for its trip. */ 00937 for(i = 0; i < agent->datastate->tasks[progress]->num_saved_variables; i++) { 00938 agent_variable_list_Add( 00939 agent->datastate->tasks[progress]->agent_variable_list, 00940 interpreter_variable_data_Initialize( 00941 agent, 00942 agent->datastate->tasks[progress]->saved_variables[i] ) 00943 ); 00944 } 00945 00946 if (agent->datastate->persistent || 00947 agent->datastate->tasks[progress]->persistent ) { 00948 /* TODO: We need a large while loop here that waits on a condition 00949 variable. Upon waking up, we will need to check a 'mailbox' for 00950 a struct containing 00951 1. A message/command 00952 2. A void* to generic data 00953 3. The size of the data. 00954 It should then execute the command, and check to see if the 00955 persistent flag is still set. If it is, loop again. 00956 */ 00957 /* For now, let us just not end the Ch interpreter and set the 00958 * agent_status to MC_AGENT_NEUTRAL to cause it to hang. */ 00959 ((MCAgent_t) ChAgent)->agent_status = MC_AGENT_NEUTRAL; 00960 } else { 00961 if ((((MCAgent_t)ChAgent)->agent_interp) != NULL) { 00962 Ch_End(((MCAgent_t)ChAgent)->agent_interp); 00963 } 00964 00965 /* Perform some housekeeping regarding agent status */ 00966 if ( 00967 (agent->datastate->task_progress == 00968 (agent->datastate->number_of_tasks-1)) 00969 ) 00970 { 00971 /* If the agent is done... */ 00972 ((MCAgent_t) ChAgent)->agent_status = MC_WAIT_FINISHED; 00973 /* If _any_ of the tasks have return data, we should generate 00974 * a return message. */ 00975 for(i = 0; 00976 i < agent->datastate->number_of_tasks; 00977 i++) 00978 { 00979 if (agent->datastate->tasks[i]->agent_return_data != NULL) { 00980 ((MCAgent_t) ChAgent)->agent_status = MC_WAIT_MESSGSEND; 00981 } 00982 } 00983 } 00984 else { 00985 ((MCAgent_t) ChAgent)->agent_status = MC_WAIT_MESSGSEND; 00986 } 00987 } 00988 00989 /* close the task, indicating that it has been completed */ 00990 agent->datastate-> 00991 tasks[agent->datastate->task_progress]->task_completed = 1; 00992 agent->datastate->task_progress++; 00993 00994 if ( 00995 (agent->datastate->task_progress >= agent->datastate->number_of_tasks) 00996 ) 00997 { 00998 agent->agent_type = MC_RETURN_AGENT; 00999 } 01000 01001 SIGNAL( 01002 mc_platform->MC_signal_cond, 01003 mc_platform->MC_signal_lock, 01004 mc_platform->MC_signal = MC_EXEC_AGENT; 01005 ); 01006 01007 MUTEX_LOCK( mc_platform->MC_signal_lock); 01008 MUTEX_UNLOCK( mc_platform->MC_signal_lock ); 01009 MUTEX_LOCK(mc_platform->ams->runflag_lock); 01010 mc_platform->ams->run = 1; 01011 COND_SIGNAL(mc_platform->ams->runflag_cond); 01012 MUTEX_UNLOCK(mc_platform->ams->runflag_lock); 01013 01014 #ifndef _WIN32 01015 pthread_exit(ChAgent); 01016 #else 01017 return 0; 01018 #endif 01019 }