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

Generated on Fri May 16 14:49:54 2008 for Mobile-C by  doxygen 1.5.4