/home/dko/projects/mobilec/tags/MobileC-v1.10.2/MobileC-v1.10.2/src/df.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 /* 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 }

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