00001 /* SVN FILE INFO 00002 * $Revision: 174 $ : Last Committed Revision 00003 * $Date: 2008年06月24日 10:50:29 -0700 (2008年6月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 /* Filename: df.c */ 00036 00037 #include <stdio.h> 00038 #include <stdlib.h> 00039 #ifndef _WIN32 00040 #include <unistd.h> 00041 #endif 00042 #include "include/mc_platform.h" 00043 #include "include/df.h" 00044 00045 /* df functions */ 00046 int 00047 df_Add(struct df_s* df, struct df_node_s* node) 00048 { 00049 int err; 00050 00051 SIGNAL( 00052 df->cond, 00053 df->lock, 00054 00055 err = ListAdd(df->service_list, (void*) node); 00056 if (err == MC_SUCCESS) 00057 df->num_entries++; 00058 ); 00059 return err; 00060 } 00061 00062 int 00063 df_AddRequest(struct df_s* df, struct df_request_list_node_s* node) 00064 { 00065 int err; 00066 00067 SIGNAL( 00068 df->request_list->cond, 00069 df->request_list->lock, 00070 00071 err = ListAdd( 00072 df->request_list->request_list, 00073 (void*)node ); 00074 df->request_list->size++; 00075 ); 00076 return err; 00077 } 00078 00079 int 00080 df_Destroy(df_p df) 00081 { 00082 df_node_p df_node; 00083 MUTEX_LOCK(df->lock); 00084 while ( (df_node = (df_node_p)ListPop(df->service_list)) != NULL) { 00085 df_node_Destroy(df_node); 00086 } 00087 ListTerminate(df->service_list); 00088 df_request_list_Destroy(df->request_list); 00089 MUTEX_DESTROY(df->lock); 00090 COND_DESTROY(df->cond); 00091 free(df->lock); 00092 free(df->cond); 00093 free(df); 00094 return MC_SUCCESS; 00095 } 00096 00097 df_p 00098 df_Initialize(mc_platform_p mc_platform) 00099 { 00100 df_p df; 00101 df = (df_p)malloc(sizeof(df_t)); 00102 00103 df->mc_platform = mc_platform; 00104 00105 /* Mutex Init */ 00106 df->lock = (MUTEX_T*)malloc(sizeof(MUTEX_T)); 00107 MUTEX_INIT(df->lock); 00108 00109 /* Cond Init */ 00110 df->cond = (COND_T*)malloc(sizeof(COND_T)); 00111 COND_INIT(df->cond); 00112 00113 /* Initialize the Service List */ 00114 df->service_list = ListInitialize(); 00115 00116 /* Initialize the Request List */ 00117 df->request_list = df_request_list_New(); 00118 00119 df->num_entries = 0; 00120 df->waiting = 0; 00121 df->waiting_lock = (MUTEX_T*)malloc(sizeof(MUTEX_T)); 00122 MUTEX_INIT(df->waiting_lock); 00123 df->waiting_cond = (COND_T*)malloc(sizeof(COND_T)); 00124 COND_INIT(df->waiting_cond); 00125 return df; 00126 } 00127 00128 int 00129 df_ProcessRequest( 00130 struct mc_platform_s* global 00131 ) 00132 { 00133 int return_code; 00134 int handler_code; 00135 enum df_request_list_index_e request_code; 00136 df_request_list_node_t *request; 00137 if ( 00138 ( 00139 request = df_request_list_Pop( global->df->request_list ) 00140 ) == NULL 00141 ) 00142 { 00143 printf("Empty.\n"); 00144 return MC_ERR_EMPTY; 00145 } 00146 00147 /* Process the request, call the correct handler */ 00148 #define REQUEST(name, string, description) \ 00149 if ( !strcmp(request->command, string ) ) { \ 00150 return_code = MC_SUCCESS; \ 00151 handler_code = request_handler_##name( \ 00152 global, \ 00153 request->data ); \ 00154 request_code = REQUEST_##name; \ 00155 } else 00156 #include "include/df_request.x.h" 00157 #undef REQUEST 00158 { 00159 fprintf(stderr, "No such register command: %s. %s:%d\n", 00160 request->command, 00161 __FILE__, 00162 __LINE__ ); 00163 return MC_ERR_INVALID; 00164 } 00165 00166 return handler_code; 00167 } 00168 00169 /* returns error code. */ 00170 /* Third argument is a return argument: array of matching agent names. */ 00171 /* Fourth argument is a return argument: Number of matching service names. */ 00172 /* Fifth argument is a return argument: Array of matching agent IDs */ 00173 int df_SearchForService( 00174 df_p df, 00175 const char* searchstring, 00176 char*** agent_names, 00177 char*** service_names, 00178 int** agent_ids, 00179 int* num_entries) 00180 { 00181 int i=0; 00182 int j=0; 00183 int found_entries=0; 00184 listNode_p list_node; 00185 df_node_p df_node; 00186 00187 /* check for empty df */ 00188 if(df->num_entries < 1) { 00189 *num_entries = 0; 00190 return MC_ERR_NOT_FOUND; 00191 } 00192 00193 /* Lock the list mutex to prevent simultaneous searches */ 00194 MUTEX_LOCK(df->lock); 00195 /* We'll run the following loop twice. The first time to find 00196 * the number of elements we need to allocate, the second 00197 * to actually assign some values. */ 00198 list_node = df->service_list->listhead; 00199 while (list_node != NULL) { 00200 /* Lock the df_node to prevent deletions/changes from happening 00201 * mid-search */ 00202 MUTEX_LOCK( ((df_node_p)(list_node->node_data))->lock ); 00203 df_node = (df_node_p)list_node->node_data; 00204 for(i = 0; i < df_node->num_services; i++) { 00205 if ( strstr(df_node->service_names[i], searchstring) ) { 00206 /* Found an entry. */ 00207 found_entries++; 00208 } 00209 } 00210 MUTEX_UNLOCK(df_node->lock); 00211 list_node = list_node->next; 00212 } 00213 if (found_entries == 0) { 00214 /* Nothing was found. Unlock mutexes and return */ 00215 MUTEX_UNLOCK(df->lock); 00216 *num_entries = 0; 00217 return MC_ERR_NOT_FOUND; 00218 } 00219 00220 /* Allocate return arguments */ 00221 *agent_names = (char**)malloc(sizeof(char*) * found_entries); 00222 *service_names = (char**)malloc(sizeof(char*) * found_entries); 00223 *agent_ids = (int*)malloc(sizeof(int) * found_entries); 00224 /* Re run the loop */ 00225 list_node = df->service_list->listhead; 00226 while (list_node != NULL) { 00227 /* Lock the df_node to prevent deletions/changes from happening 00228 * mid-search */ 00229 MUTEX_LOCK( ((df_node_p)(list_node->node_data))->lock ); 00230 df_node = (df_node_p)list_node->node_data; 00231 for(i = 0; i < df_node->num_services; i++) { 00232 if ( strstr(df_node->service_names[i], searchstring) ) { 00233 /* Found an entry. */ 00234 /* Copy name into return argument */ 00235 (*agent_names)[j] = (char*)malloc( 00236 sizeof(char) * (strlen(df_node->agent_name)+1) 00237 ); 00238 strcpy((*agent_names)[j], df_node->agent_name); 00239 /* Copy service name into return arg */ 00240 (*service_names)[j] = (char*)malloc( 00241 sizeof(char) * (strlen((df_node->service_names)[i])+1) 00242 ); 00243 strcpy((*service_names)[j], (df_node->service_names)[i]); 00244 /* Copy agent id into return arg */ 00245 (*agent_ids)[j] = df_node->agent_id; 00246 j++; 00247 } 00248 } 00249 MUTEX_UNLOCK(df_node->lock); 00250 list_node = list_node->next; 00251 } 00252 MUTEX_UNLOCK(df->lock); 00253 *num_entries = found_entries; 00254 return MC_SUCCESS; 00255 } 00256 00257 void 00258 df_Start(mc_platform_p mc_platform) 00259 { 00260 #ifndef _WIN32 00261 pthread_attr_t attr; 00262 pthread_attr_init(&attr); 00263 if (mc_platform->stack_size[MC_THREAD_DF] != -1) { 00264 pthread_attr_setstacksize 00265 ( 00266 &attr, 00267 mc_platform->stack_size[MC_THREAD_DF] 00268 ); 00269 } 00270 #else 00271 int stack_size; 00272 if (mc_platform->stack_size[MC_THREAD_DF] < 1) { 00273 /* In windows, 0 is default, not min */ 00274 stack_size = mc_platform->stack_size[MC_THREAD_DF]+1; 00275 } else { 00276 stack_size = mc_platform->stack_size[MC_THREAD_DF]; 00277 } 00278 #endif 00279 THREAD_CREATE 00280 ( 00281 &mc_platform->df->thread, 00282 df_Thread, 00283 mc_platform 00284 ); 00285 } 00286 00287 /* df_request_list_node functions */ 00288 int 00289 df_request_list_node_Destroy(df_request_list_node_p node) 00290 { 00291 MUTEX_DESTROY(node->lock); 00292 free(node->lock); 00293 COND_DESTROY(node->cond); 00294 free(node->cond); 00295 free(node); 00296 return MC_SUCCESS; 00297 } 00298 00299 df_request_list_node_p 00300 df_request_list_node_New(void) 00301 { 00302 df_request_list_node_p node; 00303 node = (df_request_list_node_p) 00304 malloc(sizeof(df_request_list_node_t)); 00305 CHECK_NULL(node, return NULL;); 00306 node->lock = (MUTEX_T*)malloc(sizeof(MUTEX_T)); 00307 MUTEX_INIT(node->lock); 00308 node->cond = (COND_T*)malloc(sizeof(COND_T)); 00309 COND_INIT(node->cond); 00310 node->data_size = 0; 00311 node->command = NULL; 00312 node->data = NULL; 00313 return node; 00314 } 00315 00316 /* df_request_list functions */ 00317 int 00318 df_request_list_Destroy(df_request_list_p df_request_list) 00319 { 00320 df_request_list_node_p node; 00321 while 00322 ( 00323 ( 00324 node = 00325 (df_request_list_node_p)ListPop 00326 ( 00327 df_request_list->request_list 00328 ) 00329 ) != NULL 00330 ) 00331 { 00332 df_request_list_node_Destroy(node); 00333 } 00334 ListTerminate(df_request_list->request_list); 00335 free(df_request_list); 00336 return MC_SUCCESS; 00337 } 00338 00339 df_request_list_p 00340 df_request_list_New(void) 00341 { 00342 df_request_list_p new_list; 00343 new_list = (df_request_list_p)malloc(sizeof(df_request_list_t)); 00344 CHECK_NULL(new_list, return NULL;); 00345 00346 /* Initialize sync */ 00347 new_list->lock = (MUTEX_T*)malloc(sizeof(MUTEX_T)); 00348 CHECK_NULL(new_list->lock, return NULL;); 00349 new_list->cond = (COND_T*)malloc(sizeof(COND_T)); 00350 CHECK_NULL(new_list->cond, return NULL;); 00351 00352 MUTEX_INIT(new_list->lock); 00353 COND_INIT(new_list->cond); 00354 00355 new_list->size=0; 00356 00357 new_list->request_list = ListInitialize(); 00358 if (new_list->request_list == NULL) { 00359 return NULL; 00360 } else 00361 return new_list; 00362 } 00363 00364 df_request_list_node_p 00365 df_request_list_Pop(df_request_list_p requests) 00366 { 00367 df_request_list_node_t *node; 00368 MUTEX_LOCK( requests->lock ); 00369 if (requests->size <= 0) { 00370 MUTEX_UNLOCK( requests->lock ); 00371 return NULL; 00372 } 00373 node = ListPop(requests->request_list); 00374 requests->size--; 00375 MUTEX_UNLOCK( requests->lock ); 00376 return node; 00377 } 00378 00379 /*df_request_search functions */ 00380 df_request_search_p 00381 df_request_search_New(void) 00382 { 00383 df_request_search_p search; 00384 search = (df_request_search_p)malloc(sizeof(df_request_search_t)); 00385 CHECK_NULL(search, return NULL;); 00386 search->lock = (MUTEX_T*)malloc(sizeof(MUTEX_T)); 00387 CHECK_NULL(search->lock, return NULL;); 00388 search->cond = (COND_T*)malloc(sizeof(COND_T)); 00389 CHECK_NULL(search->cond, return NULL;); 00390 MUTEX_INIT(search->lock); 00391 COND_INIT(search->cond); 00392 return search; 00393 } 00394 00395 int 00396 df_request_search_Destroy(df_request_search_p node) 00397 { 00398 MUTEX_DESTROY(node->lock); 00399 free(node->lock); 00400 COND_DESTROY(node->cond); 00401 free(node->cond); 00402 00403 free(node); 00404 return MC_SUCCESS; 00405 } 00406 00407 00408 int 00409 df_node_Destroy(df_node_p df_node) 00410 { 00411 int i; 00412 MUTEX_LOCK(df_node->lock); 00413 free(df_node->agent_name); 00414 for(i = 0; i < df_node->num_services; i++) { 00415 free(df_node->service_names[i]); 00416 } 00417 free(df_node->service_names); 00418 free(df_node); 00419 return MC_SUCCESS; 00420 } 00421 00422 #ifndef _WIN32 00423 void* df_Thread(void* arg) 00424 #else 00425 DWORD WINAPI df_Thread( LPVOID arg ) 00426 #endif 00427 { 00428 int err_code; 00429 mc_platform_p global = (mc_platform_p)arg; 00430 while(1) { 00431 MUTEX_LOCK(global->df->request_list->lock); 00432 MUTEX_LOCK(global->quit_lock); 00433 while 00434 ( 00435 (global->df->request_list->size <= 0) && 00436 !global->quit 00437 ) 00438 { 00439 MUTEX_UNLOCK(global->quit_lock); 00440 /* Set waiting flag on */ 00441 MUTEX_LOCK(global->df->waiting_lock); 00442 global->df->waiting = 1; 00443 COND_BROADCAST(global->df->waiting_cond); 00444 MUTEX_UNLOCK(global->df->waiting_lock); 00445 /* Wait for activity */ 00446 COND_WAIT 00447 ( 00448 global->df->request_list->cond, 00449 global->df->request_list->lock 00450 ); 00451 MUTEX_LOCK(global->quit_lock); 00452 } 00453 /* Set waiting flag off */ 00454 MUTEX_LOCK(global->df->waiting_lock); 00455 global->df->waiting = 0; 00456 COND_BROADCAST(global->df->waiting_cond); 00457 MUTEX_UNLOCK(global->df->waiting_lock); 00458 if 00459 ( 00460 global->df->request_list->size == 0 && global->quit 00461 ) { 00462 MUTEX_UNLOCK(global->quit_lock); 00463 MUTEX_UNLOCK(global->df->request_list->lock); 00464 return 0; 00465 } 00466 MUTEX_UNLOCK(global->quit_lock); 00467 MUTEX_UNLOCK(global->df->request_list->lock); 00468 if ( 00469 (err_code = df_ProcessRequest( 00470 global 00471 )) != MC_SUCCESS ) { 00472 fprintf(stderr, 00473 "Error Code %d: %s:%d\n", 00474 err_code, 00475 __FILE__, 00476 __LINE__ ); 00477 } 00478 } 00479 return 0; 00480 } 00481 00482 00483 00484 00485 /* Request Handlers */ 00486 00487 int request_handler_REGISTER(struct mc_platform_s* global, void* data) 00488 { 00489 /* Insert new struct into DF */ 00490 return df_Add(global->df, (struct df_node_s*)data); 00491 } 00492 00493 int request_handler_SEARCH(struct mc_platform_s* global, void* data) 00494 { 00495 df_request_search_p search; 00496 search = (df_request_search_p)data; 00497 df_SearchForService( 00498 global->df, 00499 search->search_string, 00500 &search->search_results->agent_names, 00501 &search->search_results->service_names, 00502 &search->search_results->agent_ids, 00503 &search->search_results->num_results 00504 ); 00505 SIGNAL(search->cond, 00506 search->lock, 00507 NULL 00508 ); 00509 return MC_SUCCESS; 00510 } 00511 00512 int request_handler_SUBSCRIBE(struct mc_platform_s* global, void* data) 00513 { 00514 return 0; 00515 } 00516 00517 int request_handler_DEREGISTER(struct mc_platform_s* global, void* data) 00518 { 00519 int i, j; 00520 df_deregister_p deregister; 00521 listNode_p node; 00522 df_node_p df_node; 00523 int num_deregistered=0; 00524 df_p df = global->df; 00525 deregister = (df_deregister_p)data; 00526 /* Find and remove all entries matching search terms. */ 00527 MUTEX_LOCK(df->lock); 00528 if (df->service_list->listhead== NULL) { 00529 MUTEX_UNLOCK(df->lock); 00530 return 0; 00531 } 00532 node = df->service_list->listhead; 00533 while (node != NULL) { 00534 df_node = (df_node_p)node->node_data; 00535 if (df_node->agent_id == deregister->agent_id) { 00536 for (i = 0; i < df_node->num_services; i++) { 00537 if (!strcmp( 00538 df_node->service_names[i], 00539 deregister->service_name 00540 ) 00541 ) 00542 { 00543 free(df_node->service_names[i]); 00544 for (j = i; j < df_node->num_services-1; j++) { 00545 df_node->service_names[j] = df_node->service_names[j+1]; 00546 } 00547 df_node->num_services--; 00548 num_deregistered++; 00549 00550 if (df_node->num_services == 0) { 00551 /* Just get rid of the entire node altogether */ 00552 /* FIXME */ 00553 } 00554 } 00555 } 00556 } 00557 node = node->next; 00558 } 00559 MUTEX_UNLOCK(df->lock); 00560 return MC_SUCCESS; 00561 }