OpenSync
0.22
|
00001 /* 00002 * libopensync - A synchronization framework 00003 * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 * 00019 */ 00020 00021 #include "opensync.h" 00022 #include "opensync_internals.h" 00023 00046 00047 /* Get the value of a an OSyncEnv option 00048 * 00049 * Search order: 00050 * - options set using osync_env_set_option() 00051 * - OSYNC_* environment variables 00052 */ 00053 static const char *osync_env_query_option(OSyncEnv *env, const char *name) 00054 { 00055 const char *value; 00056 value = g_hash_table_lookup(env->options, name); 00057 if (value) 00058 return value; 00059 00060 gchar *env_name = g_strdup_printf("OSYNC_%s", name); 00061 value = getenv(env_name); 00062 g_free(env_name); 00063 00064 if (value) 00065 return value; 00066 00067 return NULL; 00068 } 00069 00070 static osync_bool osync_env_query_option_bool(OSyncEnv *env, const char *name) 00071 { 00072 const char *get_value; 00073 if (!(get_value = osync_env_query_option(env, name))) 00074 return FALSE; 00075 if (!strcmp(get_value, "TRUE")) 00076 return TRUE; 00077 return FALSE; 00078 } 00079 00083 void osync_env_export_loaded_modules(OSyncEnv *env) 00084 { 00085 int num_modules = g_list_length(env->modules); 00086 00087 /* build an array for g_strjoinv() */ 00088 gchar **path_array = g_malloc0(sizeof(gchar*)*(num_modules + 1)); 00089 int i; 00090 for (i = 0; i < num_modules; i++) { 00091 GModule *module = g_list_nth_data(env->modules, i); 00092 const gchar *path = g_module_name(module); 00093 /*XXX: casting to non-const, here. Ugly. 00094 * 00095 * We know the elements pointed by path_array won't 00096 * be touched. But isn't g_strjoinv() supposed to get a 00097 * 'const gchar **' instead of a 'gchar **'? 00098 */ 00099 path_array[i] = (gchar*)path; 00100 } 00101 00102 /* Build a ':'-separated list */ 00103 gchar *list_str = g_strjoinv(":", path_array); 00104 setenv("OSYNC_FORMAT_LIST", list_str, 1); 00105 g_free(list_str); 00106 } 00107 00108 static void export_option_to_env(gpointer key, gpointer data, gpointer user_data) 00109 { 00110 const char *name = (const char*)key; 00111 const char *value = (const char*)data; 00112 gchar *env_name = g_strdup_printf("OSYNC_%s", name); 00113 setenv(env_name, value, 1); 00114 g_free(env_name); 00115 } 00116 00120 void osync_env_export_all_options(OSyncEnv *env) 00121 { 00122 g_hash_table_foreach(env->options, export_option_to_env, NULL); 00123 } 00124 00125 static void free_hash(char *key, char *value, void *data) 00126 { 00127 g_free(key); 00128 g_free(value); 00129 } 00130 00139 long long int _osync_env_create_group_id(OSyncEnv *env) 00140 { 00141 char *filename = NULL; 00142 long long int i = 0; 00143 do { 00144 i++; 00145 if (filename) 00146 g_free(filename); 00147 filename = g_strdup_printf("%s/group%lli", env->groupsdir, i); 00148 } while (g_file_test(filename, G_FILE_TEST_EXISTS)); 00149 g_free(filename); 00150 return i; 00151 } 00152 00177 00178 00186 OSyncEnv *osync_env_new(void) 00187 { 00188 OSyncEnv *env = g_malloc0(sizeof(OSyncEnv)); 00189 env->is_initialized = FALSE; 00190 env->options = g_hash_table_new(g_str_hash, g_str_equal); 00191 00192 //Set some defaults 00193 osync_env_set_option(env, "LOAD_GROUPS", "TRUE"); 00194 osync_env_set_option(env, "LOAD_FORMATS", "TRUE"); 00195 osync_env_set_option(env, "LOAD_PLUGINS", "TRUE"); 00196 00197 return env; 00198 } 00199 00207 void osync_env_free(OSyncEnv *env) 00208 { 00209 g_assert(env); 00210 g_hash_table_foreach(env->options, (GHFunc)free_hash, NULL); 00211 g_hash_table_destroy(env->options); 00212 g_free(env); 00213 } 00214 00222 void osync_env_set_option(OSyncEnv *env, const char *name, const char *value) 00223 { 00224 if (value) 00225 g_hash_table_insert(env->options, g_strdup(name), g_strdup(value)); 00226 else 00227 g_hash_table_remove(env->options, name); 00228 } 00229 00240 osync_bool osync_env_initialize(OSyncEnv *env, OSyncError **error) 00241 { 00242 osync_trace(TRACE_ENTRY, "osync_env_initialize(%p, %p)", env, error); 00243 g_assert(env); 00244 00245 if (env->is_initialized) { 00246 osync_error_set(error, OSYNC_ERROR_INITIALIZATION, "Cannot initialize the same environment twice"); 00247 osync_trace(TRACE_EXIT_ERROR, "osync_env_initialize: %s", osync_error_print(error)); 00248 return FALSE; 00249 } 00250 00251 //Load the normal plugins 00252 if (osync_env_query_option_bool(env, "LOAD_PLUGINS")) { 00253 if (!osync_env_load_plugins(env, osync_env_query_option(env, "PLUGINS_DIRECTORY"), error)) { 00254 osync_trace(TRACE_EXIT_ERROR, "osync_env_initialize: %s", osync_error_print(error)); 00255 return FALSE; 00256 } 00257 } 00258 00259 //Load the format plugins 00260 if (osync_env_query_option_bool(env, "LOAD_FORMATS")) { 00261 if (!osync_env_load_formats(env, osync_env_query_option(env, "FORMATS_DIRECTORY"), error)) { 00262 osync_trace(TRACE_EXIT_ERROR, "osync_env_initialize: %s", osync_error_print(error)); 00263 return FALSE; 00264 } 00265 } 00266 00267 //Load groups 00268 if (osync_env_query_option_bool(env, "LOAD_GROUPS")) { 00269 if (!osync_env_load_groups(env, osync_env_query_option(env, "GROUPS_DIRECTORY"), error)) { 00270 osync_trace(TRACE_EXIT_ERROR, "osync_env_initialize: %s", osync_error_print(error)); 00271 return FALSE; 00272 } 00273 } 00274 00275 env->is_initialized = TRUE; 00276 osync_trace(TRACE_EXIT, "osync_env_initialize"); 00277 return TRUE; 00278 } 00279 00289 osync_bool osync_env_finalize(OSyncEnv *env, OSyncError **error) 00290 { 00291 osync_trace(TRACE_ENTRY, "osync_env_finalize(%p, %p)", env, error); 00292 g_assert(env); 00293 00294 if (!env->is_initialized) { 00295 osync_error_set(error, OSYNC_ERROR_INITIALIZATION, "Environment has to be initialized before"); 00296 return FALSE; 00297 } 00298 00299 while (osync_env_nth_group(env, 0)) 00300 osync_group_free(osync_env_nth_group(env, 0)); 00301 00302 GList *plugins = g_list_copy(env->plugins); 00303 GList *p; 00304 for (p = plugins; p; p = p->next) { 00305 OSyncPlugin *plugin = p->data; 00306 osync_plugin_free(plugin); 00307 } 00308 g_list_free(plugins); 00309 00310 //Unload all loaded modules 00311 GList *modules = g_list_copy(env->modules); 00312 for (p = modules; p; p = p->next) { 00313 GModule *module = p->data; 00314 osync_module_unload(env, module); 00315 } 00316 g_list_free(modules); 00317 00318 osync_trace(TRACE_EXIT, "osync_env_finalize"); 00319 return TRUE; 00320 } 00321 00334 osync_bool osync_env_load_formats(OSyncEnv *env, const char *path, OSyncError **error) 00335 { 00336 osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, env, path, error); 00337 osync_bool must_exist = TRUE; 00338 00339 if (!path) { 00340 path = OPENSYNC_FORMATSDIR; 00341 must_exist = FALSE; 00342 } 00343 00344 if (!osync_module_load_dir(env, path, must_exist, error)) { 00345 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00346 return FALSE; 00347 } 00348 00349 osync_trace(TRACE_EXIT, "%s", __func__); 00350 return TRUE; 00351 } 00352 00363 osync_bool osync_env_load_plugins(OSyncEnv *env, const char *path, OSyncError **error) 00364 { 00365 osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, env, path, error); 00366 osync_bool must_exist = TRUE; 00367 00368 if (!path) { 00369 path = OPENSYNC_PLUGINDIR; 00370 must_exist = FALSE; 00371 } 00372 00373 if (!osync_module_load_dir(env, path, must_exist, error)) { 00374 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00375 return FALSE; 00376 } 00377 00378 osync_trace(TRACE_EXIT, "%s", __func__); 00379 return TRUE; 00380 } 00381 00391 OSyncPlugin *osync_env_find_plugin(OSyncEnv *env, const char *name) 00392 { 00393 g_assert(env); 00394 OSyncPlugin *plugin; 00395 int i; 00396 for (i = 0; i < osync_env_num_plugins(env); i++) { 00397 plugin = osync_env_nth_plugin(env, i); 00398 if (g_ascii_strcasecmp(plugin->info.name, name) == 0) { 00399 return plugin; 00400 } 00401 } 00402 return NULL; 00403 } 00404 00413 int osync_env_num_plugins(OSyncEnv *env) 00414 { 00415 return g_list_length(env->plugins); 00416 } 00417 00427 OSyncPlugin *osync_env_nth_plugin(OSyncEnv *env, int nth) 00428 { 00429 return (OSyncPlugin *)g_list_nth_data(env->plugins, nth); 00430 } 00431 00440 osync_bool osync_env_plugin_is_usable(OSyncEnv *env, const char *pluginname, OSyncError **error) 00441 { 00442 osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, env, pluginname, error); 00443 00444 OSyncPlugin *plugin = osync_env_find_plugin(env, pluginname); 00445 if (!plugin) { 00446 osync_error_set(error, OSYNC_ERROR_PLUGIN_NOT_FOUND, "Unable to find plugin \"%s\". This can be caused by unresolved symbols", pluginname); 00447 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00448 return FALSE; 00449 } 00450 00451 if (plugin->info.functions.is_available) { 00452 osync_bool ret = plugin->info.functions.is_available(error); 00453 osync_trace(ret ? TRACE_EXIT : TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00454 return ret; 00455 } 00456 00457 osync_trace(TRACE_EXIT, "%s: TRUE: No is_available function", __func__); 00458 return TRUE; 00459 } 00460 00472 osync_bool osync_env_load_groups(OSyncEnv *env, const char *p, OSyncError **error) 00473 { 00474 GDir *dir; 00475 GError *gerror = NULL; 00476 char *filename = NULL; 00477 char *real_path = NULL; 00478 char *path = g_strdup(p); 00479 00480 if (!path) { 00481 OSyncUserInfo *user = osync_user_new(error); 00482 if (!user) 00483 return FALSE; 00484 path = g_strdup(osync_user_get_confdir(user)); 00485 00486 if (!g_file_test(path, G_FILE_TEST_EXISTS)) { 00487 if (mkdir(path, 0700) == -1) { 00488 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to create group directory at %s: %s", path, strerror(errno)); 00489 g_free(path); 00490 return FALSE; 00491 } 00492 char *enginepath = g_strdup_printf("%s/engines", path); 00493 if (mkdir(enginepath, 0700) == -1) { 00494 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to create engine group directory at %s: %s", enginepath, strerror(errno)); 00495 g_free(path); 00496 g_free(enginepath); 00497 return FALSE; 00498 } 00499 g_free(enginepath); 00500 osync_debug("OSGRP", 3, "Created groups configdir %s\n", path); 00501 } 00502 osync_user_free(user); 00503 } 00504 00505 if (!g_path_is_absolute(path)) { 00506 real_path = g_strdup_printf("%s/%s", g_get_current_dir(), path); 00507 } else { 00508 real_path = g_strdup(path); 00509 } 00510 00511 if (!g_file_test(real_path, G_FILE_TEST_IS_DIR)) { 00512 osync_debug("OSGRP", 0, "%s exists, but is no dir", real_path); 00513 osync_error_set(error, OSYNC_ERROR_INITIALIZATION, "%s exists, but is no dir", real_path); 00514 g_free(real_path); 00515 g_free(path); 00516 return FALSE; 00517 } 00518 00519 dir = g_dir_open(real_path, 0, &gerror); 00520 if (!dir) { 00521 osync_debug("OSGRP", 0, "Unable to open main configdir %s: %s", real_path, gerror->message); 00522 osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Unable to open main configdir %s: %s", real_path, gerror->message); 00523 g_error_free (gerror); 00524 g_free(real_path); 00525 g_free(path); 00526 return FALSE; 00527 } 00528 00529 const gchar *de = NULL; 00530 while ((de = g_dir_read_name(dir))) { 00531 filename = g_strdup_printf ("%s/%s", real_path, de); 00532 00533 if (!g_file_test(filename, G_FILE_TEST_IS_DIR) || g_file_test(filename, G_FILE_TEST_IS_SYMLINK) || !g_pattern_match_simple("group*", de)) { 00534 g_free(filename); 00535 continue; 00536 } 00537 00538 /* Try to open the confdir*/ 00539 OSyncError *error = NULL; 00540 if (!osync_group_load(env, filename, &error)) { 00541 osync_debug("OSGRP", 0, "Unable to load group from %s: %s", filename, error->message); 00542 osync_error_free(&error); 00543 } 00544 00545 g_free(filename); 00546 } 00547 g_free(real_path); 00548 g_dir_close(dir); 00549 00550 env->groupsdir = path; 00551 return TRUE; 00552 } 00553 00563 OSyncGroup *osync_env_find_group(OSyncEnv *env, const char *name) 00564 { 00565 OSyncGroup *group; 00566 int i; 00567 for (i = 0; i < osync_env_num_groups(env); i++) { 00568 group = osync_env_nth_group(env, i); 00569 if (g_ascii_strcasecmp(group->name, name) == 0) { 00570 return group; 00571 } 00572 } 00573 osync_debug("OSPLG", 0, "Couldnt find the group with the name %s", name); 00574 return NULL; 00575 } 00576 00585 void osync_env_append_group(OSyncEnv *env, OSyncGroup *group) 00586 { 00587 env->groups = g_list_append(env->groups, group); 00588 } 00589 00598 void osync_env_remove_group(OSyncEnv *env, OSyncGroup *group) 00599 { 00600 env->groups = g_list_remove(env->groups, group); 00601 } 00602 00611 int osync_env_num_groups(OSyncEnv *env) 00612 { 00613 return g_list_length(env->groups); 00614 } 00615 00625 OSyncGroup *osync_env_nth_group(OSyncEnv *env, int nth) 00626 { 00627 return (OSyncGroup *)g_list_nth_data(env->groups, nth);; 00628 } 00629 00639 00652 osync_bool _osync_open_xml_file(xmlDocPtr *doc, xmlNodePtr *cur, const char *path, const char *topentry, OSyncError **error) 00653 { 00654 if (!g_file_test(path, G_FILE_TEST_EXISTS)) { 00655 osync_debug("OSXML", 1, "File %s does not exist", path); 00656 osync_error_set(error, OSYNC_ERROR_IO_ERROR, "File %s does not exist", path); 00657 return FALSE; 00658 } 00659 00660 *doc = xmlParseFile(path); 00661 00662 if (!*doc) { 00663 osync_debug("OSXML", 1, "Could not open: %s", path); 00664 osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Could not open: %s", path); 00665 return FALSE; 00666 } 00667 00668 *cur = xmlDocGetRootElement(*doc); 00669 00670 if (!*cur) { 00671 osync_debug("OSXML", 0, "%s seems to be empty", path); 00672 osync_error_set(error, OSYNC_ERROR_IO_ERROR, "%s seems to be empty", path); 00673 xmlFreeDoc(*doc); 00674 return FALSE; 00675 } 00676 00677 if (xmlStrcmp((*cur)->name, (const xmlChar *) topentry)) { 00678 osync_debug("OSXML", 0, "%s seems not to be a valid configfile.\n", path); 00679 osync_error_set(error, OSYNC_ERROR_IO_ERROR, "%s seems not to be a valid configfile.\n", path); 00680 xmlFreeDoc(*doc); 00681 return FALSE; 00682 } 00683 00684 *cur = (*cur)->xmlChildrenNode; 00685 return TRUE; 00686 } 00687 00700 osync_bool osync_file_write(const char *filename, const char *data, int size, int mode, OSyncError **oserror) 00701 { 00702 osync_bool ret = FALSE; 00703 GError *error = NULL; 00704 GIOChannel *chan = g_io_channel_new_file(filename, "w", &error); 00705 if (!chan) { 00706 osync_debug("OSYNC", 3, "Unable to open file %s for writing: %s", filename, error->message); 00707 osync_error_set(oserror, OSYNC_ERROR_IO_ERROR, "Unable to open file %s for writing: %s", filename, error->message); 00708 return FALSE; 00709 } 00710 if (mode) { 00711 int fd = g_io_channel_unix_get_fd(chan); 00712 if (fchmod(fd, mode)) { 00713 osync_debug("OSYNC", 3, "Unable to set file permissions %i for file %s", mode, filename); 00714 osync_error_set(oserror, OSYNC_ERROR_IO_ERROR, "Unable to set file permissions %i for file %s", mode, filename); 00715 return FALSE; 00716 } 00717 } 00718 gsize writen; 00719 g_io_channel_set_encoding(chan, NULL, NULL); 00720 if (g_io_channel_write_chars(chan, data, size, &writen, &error) != G_IO_STATUS_NORMAL) { 00721 osync_debug("OSYNC", 3, "Unable to write contents of file %s: %s", filename, error->message); 00722 osync_error_set(oserror, OSYNC_ERROR_IO_ERROR, "Unable to write contents of file %s: %s", filename, error->message); 00723 } else { 00724 g_io_channel_flush(chan, NULL); 00725 ret = TRUE; 00726 } 00727 g_io_channel_shutdown(chan, FALSE, NULL); 00728 g_io_channel_unref(chan); 00729 return ret; 00730 } 00731 00743 osync_bool osync_file_read(const char *filename, char **data, int *size, OSyncError **oserror) 00744 { 00745 osync_bool ret = FALSE; 00746 GError *error = NULL; 00747 gsize sz = 0; 00748 00749 if (!filename) { 00750 osync_debug("OSYNC", 3, "No file open specified"); 00751 osync_error_set(oserror, OSYNC_ERROR_IO_ERROR, "No file to open specified"); 00752 return FALSE; 00753 } 00754 GIOChannel *chan = g_io_channel_new_file(filename, "r", &error); 00755 if (!chan) { 00756 osync_debug("OSYNC", 3, "Unable to read file %s: %s", filename, error->message); 00757 osync_error_set(oserror, OSYNC_ERROR_IO_ERROR, "Unable to open file %s for reading: %s", filename, error->message); 00758 return FALSE; 00759 } 00760 g_io_channel_set_encoding(chan, NULL, NULL); 00761 if (g_io_channel_read_to_end(chan, data, &sz, &error) != G_IO_STATUS_NORMAL) { 00762 osync_debug("OSYNC", 3, "Unable to read contents of file %s: %s", filename, error->message); 00763 osync_error_set(oserror, OSYNC_ERROR_IO_ERROR, "Unable to read contents of file %s: %s", filename, error->message); 00764 } else { 00765 ret = TRUE; 00766 *size = (int)sz; 00767 } 00768 g_io_channel_shutdown(chan, FALSE, NULL); 00769 g_io_channel_unref(chan); 00770 return ret; 00771 } 00772 00781 const char *osync_get_version(void) 00782 { 00783 return VERSION; 00784 } 00785 00796 void *osync_try_malloc0(unsigned int size, OSyncError **error) 00797 { 00798 void *result = g_try_malloc(size); 00799 if (!result) { 00800 osync_error_set(error, OSYNC_ERROR_GENERIC, "No memory left"); 00801 return NULL; 00802 } 00803 memset(result, 0, size); 00804 return result; 00805 } 00806 00807 char *osync_strreplace(const char *input, const char *delimiter, const char *replacement) 00808 { 00809 osync_return_val_if_fail(input != NULL, NULL); 00810 osync_return_val_if_fail(delimiter != NULL, NULL); 00811 osync_return_val_if_fail(replacement != NULL, NULL); 00812 00813 gchar **array = g_strsplit(input, delimiter, 0); 00814 gchar *ret = g_strjoinv(replacement, array); 00815 g_strfreev(array); 00816 00817 return ret; 00818 } 00819 00822 OSyncThread *osync_thread_new(GMainContext *context, OSyncError **error) 00823 { 00824 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, context, error); 00825 00826 OSyncThread *thread = osync_try_malloc0(sizeof(OSyncThread), error); 00827 if (!thread) 00828 goto error; 00829 00830 if (!g_thread_supported ()) g_thread_init (NULL); 00831 00832 thread->started_mutex = g_mutex_new(); 00833 thread->started = g_cond_new(); 00834 thread->context = context; 00835 if (thread->context) 00836 g_main_context_ref(thread->context); 00837 thread->loop = g_main_loop_new(thread->context, FALSE); 00838 00839 osync_trace(TRACE_EXIT, "%s: %p", __func__, thread); 00840 return thread; 00841 00842 error: 00843 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00844 return NULL; 00845 } 00846 00847 void osync_thread_free(OSyncThread *thread) 00848 { 00849 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, thread); 00850 osync_assert(thread); 00851 00852 if (thread->started_mutex) 00853 g_mutex_free(thread->started_mutex); 00854 00855 if (thread->started) 00856 g_cond_free(thread->started); 00857 00858 if (thread->loop) 00859 g_main_loop_unref(thread->loop); 00860 00861 if (thread->context) 00862 g_main_context_unref(thread->context); 00863 00864 g_free(thread); 00865 osync_trace(TRACE_EXIT, "%s", __func__); 00866 } 00867 00868 /*static gpointer osyncThreadStartCallback(gpointer data) 00869 { 00870 OSyncThread *thread = data; 00871 00872 g_mutex_lock(thread->started_mutex); 00873 g_cond_signal(thread->started); 00874 g_mutex_unlock(thread->started_mutex); 00875 00876 g_main_loop_run(thread->loop); 00877 00878 return NULL; 00879 }*/ 00880 00881 static gboolean osyncThreadStopCallback(gpointer data) 00882 { 00883 OSyncThread *thread = data; 00884 00885 g_main_loop_quit(thread->loop); 00886 00887 return FALSE; 00888 } 00889 00890 /*void osync_thread_start(OSyncThread *thread) 00891 { 00892 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, thread); 00893 osync_assert(thread); 00894 00895 //Start the thread 00896 g_mutex_lock(thread->started_mutex); 00897 thread->thread = g_thread_create (osyncThreadStartCallback, thread, TRUE, NULL); 00898 g_cond_wait(thread->started, thread->started_mutex); 00899 g_mutex_unlock(thread->started_mutex); 00900 00901 osync_trace(TRACE_EXIT, "%s", __func__); 00902 }*/ 00903 00904 static gboolean osyncThreadStartCallback(gpointer data) 00905 { 00906 OSyncThread *thread = data; 00907 00908 g_mutex_lock(thread->started_mutex); 00909 g_cond_signal(thread->started); 00910 g_mutex_unlock(thread->started_mutex); 00911 return FALSE; 00912 } 00913 00914 void osync_thread_start(OSyncThread *thread) 00915 { 00916 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, thread); 00917 00918 g_mutex_lock(thread->started_mutex); 00919 GSource *idle = g_idle_source_new(); 00920 g_source_set_callback(idle, osyncThreadStartCallback, thread, NULL); 00921 g_source_attach(idle, thread->context); 00922 thread->thread = g_thread_create ((GThreadFunc)g_main_loop_run, thread->loop, TRUE, NULL); 00923 g_cond_wait(thread->started, thread->started_mutex); 00924 g_mutex_unlock(thread->started_mutex); 00925 00926 osync_trace(TRACE_EXIT, "%s", __func__); 00927 } 00928 00929 void osync_thread_stop(OSyncThread *thread) 00930 { 00931 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, thread); 00932 osync_assert(thread); 00933 00934 GSource *source = g_idle_source_new(); 00935 g_source_set_callback(source, osyncThreadStopCallback, thread, NULL); 00936 g_source_attach(source, thread->context); 00937 00938 g_thread_join(thread->thread); 00939 thread->thread = NULL; 00940 00941 g_source_unref(source); 00942 00943 osync_trace(TRACE_EXIT, "%s", __func__); 00944 } 00945 00946 osync_bool osync_pattern_match(const char *pattern, const char *data, int size) 00947 { 00948 GPatternSpec *spec = g_pattern_spec_new(pattern); 00949 osync_bool result = g_pattern_match(spec, size, data, NULL); 00950 g_pattern_spec_free(spec); 00951 return result; 00952 }