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 #include <errno.h> 00024 #include <sys/file.h> 00025 00026 extern int errno; 00027 00028 /* 00029 * On Solaris no flock function exists, 00030 * we must implenet it here 00031 */ 00032 #ifdef SOLARIS 00033 00034 #define LOCK_SH 1 00035 #define LOCK_EX 2 00036 #define LOCK_NB 4 00037 #define LOCK_UN 8 00038 00039 static int 00040 flock(int fd, int operation) 00041 { 00042 struct flock flock; 00043 00044 switch (operation & ~LOCK_NB) { 00045 case LOCK_SH: 00046 flock.l_type = F_RDLCK; 00047 break; 00048 case LOCK_EX: 00049 flock.l_type = F_WRLCK; 00050 break; 00051 case LOCK_UN: 00052 flock.l_type = F_UNLCK; 00053 break; 00054 default: 00055 errno = EINVAL; 00056 return -1; 00057 } 00058 00059 flock.l_whence = 0; 00060 flock.l_start = 0; 00061 flock.l_len = 0; 00062 00063 return fcntl(fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &flock); 00064 } 00065 #endif 00066 00076 00083 OSyncEnv *osync_group_get_env(OSyncGroup *group) 00084 { 00085 return group->env; 00086 } 00087 00094 void *osync_group_get_data(OSyncGroup *group) 00095 { 00096 return group->data; 00097 } 00098 00105 void osync_group_set_data(OSyncGroup *group, void *data) 00106 { 00107 group->data = data; 00108 } 00109 00116 long long int osync_group_create_member_id(OSyncGroup *group) 00117 { 00118 char *filename = NULL; 00119 long long int i = 0; 00120 do { 00121 i++; 00122 if (filename) 00123 g_free(filename); 00124 filename = g_strdup_printf("%s/%lli", group->configdir, i); 00125 } while (g_file_test(filename, G_FILE_TEST_EXISTS)); 00126 g_free(filename); 00127 return i; 00128 } 00129 00136 OSyncFormatEnv *osync_group_get_format_env(OSyncGroup *group) 00137 { 00138 g_assert(group); 00139 return group->conv_env; 00140 } 00141 00152 osync_bool osync_group_load_members(OSyncGroup *group, const char *path, OSyncError **error) 00153 { 00154 GDir *dir = NULL; 00155 GError *gerror = NULL; 00156 char *filename = NULL; 00157 00158 dir = g_dir_open(path, 0, &gerror); 00159 if (!dir) { 00160 osync_debug("OSGRP", 3, "Unable to open group configdir %s", gerror->message); 00161 osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Unable to open group configdir %s", gerror->message); 00162 g_error_free (gerror); 00163 return FALSE; 00164 } 00165 00166 const gchar *de = NULL; 00167 while ((de = g_dir_read_name(dir))) { 00168 filename = g_strdup_printf ("%s/%s", osync_group_get_configdir(group), de); 00169 if (!g_file_test(filename, G_FILE_TEST_IS_DIR) || g_file_test(filename, G_FILE_TEST_IS_SYMLINK) || g_pattern_match_simple(".*", de) || !strcmp("db", de)) { 00170 g_free(filename); 00171 continue; 00172 } 00173 00174 if (!osync_member_load(group, filename, error)) { 00175 osync_debug("OSGRP", 0, "Unable to load one of the members"); 00176 g_free(filename); 00177 g_dir_close(dir); 00178 return FALSE; 00179 } 00180 g_free(filename); 00181 } 00182 g_dir_close(dir); 00183 return TRUE; 00184 } 00185 00195 00204 OSyncGroup *osync_group_new(OSyncEnv *env) 00205 { 00206 OSyncGroup *group = g_malloc0(sizeof(OSyncGroup)); 00207 group->conv_env = osync_conv_env_new(env); 00208 00209 if (env) { 00210 osync_env_append_group(env, group); 00211 group->env = env; 00212 } 00213 00214 return group; 00215 } 00216 00224 void osync_group_free(OSyncGroup *group) 00225 { 00226 g_assert(group); 00227 00228 if (group->conv_env) 00229 osync_conv_env_free(group->conv_env); 00230 00231 if (group->lock_fd) 00232 osync_group_unlock(group, FALSE); 00233 00234 while (osync_group_nth_member(group, 0)) 00235 osync_member_free(osync_group_nth_member(group, 0)); 00236 00237 if (group->env) 00238 osync_env_remove_group(group->env, group); 00239 00240 if (group->name) 00241 g_free(group->name); 00242 00243 if (group->configdir) 00244 g_free(group->configdir); 00245 00246 g_free(group); 00247 } 00248 00267 OSyncLockState osync_group_lock(OSyncGroup *group) 00268 { 00269 osync_trace(TRACE_ENTRY, "osync_group_lock(%p)", group); 00270 g_assert(group); 00271 g_assert(group->configdir); 00272 00273 osync_bool exists = FALSE; 00274 osync_bool locked = FALSE; 00275 00276 if (group->lock_fd) { 00277 osync_trace(TRACE_EXIT, "osync_group_lock: OSYNC_LOCKED, lock_fd existed"); 00278 return OSYNC_LOCKED; 00279 } 00280 00281 char *lockfile = g_strdup_printf("%s/lock", group->configdir); 00282 osync_debug("GRP", 4, "locking file %s", lockfile); 00283 00284 if (g_file_test(lockfile, G_FILE_TEST_EXISTS)) { 00285 osync_debug("GRP", 4, "locking group: file exists"); 00286 exists = TRUE; 00287 } 00288 00289 if ((group->lock_fd = open(lockfile, O_CREAT | O_WRONLY, 00700)) == -1) { 00290 group->lock_fd = 0; 00291 osync_debug("GRP", 1, "error opening file: %s", strerror(errno)); 00292 g_free(lockfile); 00293 osync_trace(TRACE_EXIT_ERROR, "osync_group_lock: %s", strerror(errno)); 00294 return OSYNC_LOCK_STALE; 00295 } else { 00296 00297 /* Set FD_CLOEXEC flags for the lock file descriptor. We don't want the 00298 * subprocesses created by plugins or the engine to keep holding the lock 00299 */ 00300 int oldflags = fcntl(group->lock_fd, F_GETFD); 00301 if (oldflags == -1) { 00302 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, "Unable to get fd flags"); 00303 return OSYNC_LOCK_STALE; 00304 } 00305 00306 if (fcntl(group->lock_fd, F_SETFD, oldflags|FD_CLOEXEC) == -1) { 00307 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, "Unable to set fd flags"); 00308 return OSYNC_LOCK_STALE; 00309 } 00310 00311 if (flock(group->lock_fd, LOCK_EX | LOCK_NB) == -1) { 00312 if (errno == EWOULDBLOCK) { 00313 osync_debug("GRP", 4, "locking group: is locked2"); 00314 locked = TRUE; 00315 close(group->lock_fd); 00316 group->lock_fd = 0; 00317 } else 00318 osync_debug("GRP", 1, "error setting lock: %s", strerror(errno)); 00319 } else 00320 osync_debug("GRP", 4, "Successfully locked"); 00321 } 00322 g_free(lockfile); 00323 00324 if (!exists) { 00325 osync_trace(TRACE_EXIT, "osync_group_lock: OSYNC_LOCK_OK"); 00326 return OSYNC_LOCK_OK; 00327 } else { 00328 if (locked) { 00329 osync_trace(TRACE_EXIT, "osync_group_lock: OSYNC_LOCKED"); 00330 return OSYNC_LOCKED; 00331 } else { 00332 osync_trace(TRACE_EXIT, "osync_group_lock: OSYNC_LOCK_STALE"); 00333 return OSYNC_LOCK_STALE; 00334 } 00335 } 00336 } 00337 00348 void osync_group_unlock(OSyncGroup *group, osync_bool remove) 00349 { 00350 g_assert(group); 00351 g_assert(group->configdir); 00352 osync_debug("GRP", 4, "unlocking group %s", group->name); 00353 00354 if (!group->lock_fd) { 00355 osync_debug("GRP", 1, "You have to lock the group before unlocking"); 00356 return; 00357 } 00358 00359 if (flock(group->lock_fd, LOCK_UN) == -1) { 00360 osync_debug("GRP", 1, "error releasing lock: %s", strerror(errno)); 00361 return; 00362 } 00363 00364 fsync(group->lock_fd); 00365 close(group->lock_fd); 00366 00367 group->lock_fd = 0; 00368 00369 if (remove) { 00370 char *lockfile = g_strdup_printf("%s/lock", group->configdir); 00371 unlink(lockfile); 00372 g_free(lockfile); 00373 } 00374 } 00375 00384 void osync_group_set_name(OSyncGroup *group, const char *name) 00385 { 00386 g_assert(group); 00387 if (group->name) 00388 g_free(group->name); 00389 group->name = g_strdup(name); 00390 } 00391 00400 const char *osync_group_get_name(OSyncGroup *group) 00401 { 00402 g_assert(group); 00403 return group->name; 00404 } 00405 00415 osync_bool osync_group_save(OSyncGroup *group, OSyncError **error) 00416 { 00417 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, group, error); 00418 g_assert(group); 00419 osync_assert_msg(group->env, "You must specify a Environment prior to saving the group"); 00420 00421 if (!group->configdir) { 00422 group->id = _osync_env_create_group_id(group->env); 00423 group->configdir = g_strdup_printf("%s/group%lli", group->env->groupsdir, group->id); 00424 } 00425 00426 char *filename = NULL; 00427 osync_debug("OSGRP", 3, "Trying to open configdirectory %s to save group %s", group->configdir, group->name); 00428 int i; 00429 00430 if (!g_file_test(group->configdir, G_FILE_TEST_IS_DIR)) { 00431 osync_debug("OSGRP", 3, "Creating group configdirectory %s", group->configdir); 00432 if (mkdir(group->configdir, 0700)) { 00433 osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Unable to create directory for group %s\n", group->name); 00434 goto error; 00435 } 00436 } 00437 00438 filename = g_strdup_printf ("%s/syncgroup.conf", group->configdir); 00439 osync_debug("OSGRP", 3, "Saving group to file %s", filename); 00440 00441 xmlDocPtr doc; 00442 00443 doc = xmlNewDoc((xmlChar*)"1.0"); 00444 doc->children = xmlNewDocNode(doc, NULL, (xmlChar*)"syncgroup", NULL); 00445 00446 //The filters 00447 GList *f; 00448 for (f = group->filters; f; f = f->next) { 00449 OSyncFilter *filter = f->data; 00450 xmlNodePtr child = xmlNewTextChild(doc->children, NULL, (xmlChar*)"filter", NULL); 00451 00452 if (filter->sourcememberid) { 00453 char *sourcememberid = g_strdup_printf("%lli", filter->sourcememberid); 00454 xmlNewTextChild(child, NULL, (xmlChar*)"sourcemember", (xmlChar*)sourcememberid); 00455 g_free(sourcememberid); 00456 } 00457 if (filter->destmemberid) { 00458 char *destmemberid = g_strdup_printf("%lli", filter->destmemberid); 00459 xmlNewTextChild(child, NULL, (xmlChar*)"destmember", (xmlChar*)destmemberid); 00460 g_free(destmemberid); 00461 } 00462 if (filter->sourceobjtype) 00463 xmlNewTextChild(child, NULL, (xmlChar*)"sourceobjtype", (xmlChar*)filter->sourceobjtype); 00464 if (filter->destobjtype) 00465 xmlNewTextChild(child, NULL, (xmlChar*)"destobjtype", (xmlChar*)filter->destobjtype); 00466 if (filter->detectobjtype) 00467 xmlNewTextChild(child, NULL, (xmlChar*)"detectobjtype", (xmlChar*)filter->detectobjtype); 00468 if (filter->action) { 00469 char *action = g_strdup_printf("%i", filter->action); 00470 xmlNewTextChild(child, NULL, (xmlChar*)"action", (xmlChar*)action); 00471 g_free(action); 00472 } 00473 if (filter->function_name) 00474 xmlNewTextChild(child, NULL, (xmlChar*)"function_name", (xmlChar*)filter->function_name); 00475 if (filter->config) 00476 xmlNewTextChild(child, NULL, (xmlChar*)"config", (xmlChar*)filter->config); 00477 } 00478 00479 xmlNewTextChild(doc->children, NULL, (xmlChar*)"groupname", (xmlChar*)group->name); 00480 00481 char *tmstr = g_strdup_printf("%i", (int)group->last_sync); 00482 xmlNewTextChild(doc->children, NULL, (xmlChar*)"last_sync", (xmlChar*)tmstr); 00483 g_free(tmstr); 00484 00485 xmlSaveFile(filename, doc); 00486 xmlFreeDoc(doc); 00487 g_free(filename); 00488 00489 for (i = 0; i < osync_group_num_members(group); i++) { 00490 OSyncMember *member = osync_group_nth_member(group, i); 00491 if (!osync_member_save(member, error)) 00492 goto error; 00493 } 00494 00495 osync_trace(TRACE_EXIT, "%s", __func__); 00496 return TRUE; 00497 00498 error: 00499 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00500 return FALSE; 00501 } 00502 00512 osync_bool osync_group_delete(OSyncGroup *group, OSyncError **error) 00513 { 00514 g_assert(group); 00515 char *delcmd = g_strdup_printf("rm -rf %s", group->configdir); 00516 if (system(delcmd)) { 00517 osync_error_set(error, OSYNC_ERROR_GENERIC, "Failed to delete group. command %s failed", delcmd); 00518 g_free(delcmd); 00519 return FALSE; 00520 } 00521 g_free(delcmd); 00522 osync_group_free(group); 00523 return TRUE; 00524 } 00525 00536 OSyncGroup *osync_group_load(OSyncEnv *env, const char *path, OSyncError **error) 00537 { 00538 g_assert(env); 00539 char *filename = NULL; 00540 char *real_path = NULL; 00541 00542 osync_trace(TRACE_ENTRY, "osync_group_load(%p, %s, %p)", env, path, error); 00543 00544 osync_debug("OSGRP", 3, "Trying to load group from directory %s", path); 00545 00546 if (!g_path_is_absolute(path)) { 00547 real_path = g_strdup_printf("%s/%s", g_get_current_dir(), path); 00548 } else { 00549 real_path = g_strdup(path); 00550 } 00551 filename = g_strdup_printf("%s/syncgroup.conf", real_path); 00552 00553 OSyncGroup *group = osync_group_new(env); 00554 group->configdir = real_path; 00555 00556 xmlDocPtr doc; 00557 xmlNodePtr cur; 00558 xmlNodePtr filternode; 00559 00560 if (!_osync_open_xml_file(&doc, &cur, filename, "syncgroup", error)) { 00561 osync_group_free(group); 00562 g_free(filename); 00563 osync_trace(TRACE_EXIT_ERROR, "osync_group_load"); 00564 return NULL; 00565 } 00566 00567 while (cur != NULL) { 00568 if (!xmlStrcmp(cur->name, (const xmlChar *)"groupname")) 00569 group->name = (char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); 00570 00571 if (!xmlStrcmp(cur->name, (const xmlChar *)"last_sync")) 00572 group->last_sync = (time_t)atoi((char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); 00573 00574 if (!xmlStrcmp(cur->name, (const xmlChar *)"filter")) { 00575 filternode = cur->xmlChildrenNode; 00576 OSyncFilter *filter = osync_filter_new(); 00577 filter->group = group; 00578 00579 while (filternode != NULL) { 00580 if (!xmlStrcmp(filternode->name, (const xmlChar *)"sourceobjtype")) 00581 filter->sourceobjtype = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1); 00582 00583 if (!xmlStrcmp(filternode->name, (const xmlChar *)"destobjtype")) 00584 filter->destobjtype = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1); 00585 00586 if (!xmlStrcmp(filternode->name, (const xmlChar *)"detectobjtype")) 00587 filter->detectobjtype = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1); 00588 00589 if (!xmlStrcmp(filternode->name, (const xmlChar *)"config")) 00590 filter->config = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1); 00591 00592 if (!xmlStrcmp(filternode->name, (const xmlChar *)"function_name")) { 00593 char *str = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1); 00594 if (!str) { 00595 filternode = filternode->next; 00596 continue; 00597 } 00598 osync_filter_update_hook(filter, group, str); 00599 xmlFree(str); 00600 } 00601 00602 if (!xmlStrcmp(filternode->name, (const xmlChar *)"sourcemember")) { 00603 char *str = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1); 00604 if (!str) { 00605 filternode = filternode->next; 00606 continue; 00607 } 00608 filter->sourcememberid = atoll(str); 00609 xmlFree(str); 00610 } 00611 00612 if (!xmlStrcmp(filternode->name, (const xmlChar *)"destmember")) { 00613 char *str = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1); 00614 if (!str) { 00615 filternode = filternode->next; 00616 continue; 00617 } 00618 filter->destmemberid = atoll(str); 00619 xmlFree(str); 00620 } 00621 00622 if (!xmlStrcmp(filternode->name, (const xmlChar *)"action")) { 00623 char *str = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1); 00624 if (!str) { 00625 filternode = filternode->next; 00626 continue; 00627 } 00628 filter->action = atoi(str); 00629 xmlFree(str); 00630 } 00631 filternode = filternode->next; 00632 } 00633 osync_filter_register(group, filter); 00634 } 00635 cur = cur->next; 00636 } 00637 xmlFreeDoc(doc); 00638 g_free(filename); 00639 00640 //Check for sanity 00641 if (!group->name) { 00642 osync_error_set(error, OSYNC_ERROR_MISCONFIGURATION, "Loaded a group without a name"); 00643 osync_debug("OSGRP", 0, "Loaded a group without a name"); 00644 osync_group_free(group); 00645 osync_trace(TRACE_EXIT_ERROR, "osync_group_load"); 00646 return NULL; 00647 } 00648 00649 if (!osync_group_load_members(group, real_path, error)) { 00650 osync_group_free(group); 00651 osync_trace(TRACE_EXIT_ERROR, "osync_group_load"); 00652 return NULL; 00653 } 00654 00655 osync_trace(TRACE_EXIT, "osync_group_load"); 00656 return group; 00657 } 00658 00667 void osync_group_reset(OSyncGroup *group) 00668 { 00669 OSyncError *error = NULL; 00670 osync_db_reset_group(group, &error); 00671 00672 GList *m = NULL; 00673 for (m = group->members; m; m = m->next) { 00674 OSyncMember *member = m->data; 00675 osync_db_reset_member(member, &error); 00676 } 00677 } 00678 00687 void osync_group_add_member(OSyncGroup *group, OSyncMember *member) 00688 { 00689 g_assert(group); 00690 group->members = g_list_append(group->members, member); 00691 } 00692 00699 void osync_group_remove_member(OSyncGroup *group, OSyncMember *member) 00700 { 00701 g_assert(group); 00702 group->members = g_list_remove(group->members, member); 00703 } 00704 00714 OSyncMember *osync_group_nth_member(OSyncGroup *group, int nth) 00715 { 00716 g_assert(group); 00717 return (OSyncMember *)g_list_nth_data(group->members, nth); 00718 } 00719 00728 int osync_group_num_members(OSyncGroup *group) 00729 { 00730 g_assert(group); 00731 return g_list_length(group->members); 00732 } 00733 00742 const char *osync_group_get_configdir(OSyncGroup *group) 00743 { 00744 g_assert(group); 00745 return group->configdir; 00746 } 00747 00755 void osync_group_set_configdir(OSyncGroup *group, const char *directory) 00756 { 00757 g_assert(group); 00758 if (group->configdir) 00759 g_free(group->configdir); 00760 group->configdir = g_strdup(directory); 00761 } 00762 00773 void osync_group_set_slow_sync(OSyncGroup *group, const char *objtypestr, osync_bool slow_sync) 00774 { 00775 osync_trace(TRACE_ENTRY, "%s(%p, %s, %i)", __func__, group, objtypestr, slow_sync); 00776 00777 g_assert(group); 00778 OSyncFormatEnv *conv_env = group->conv_env; 00779 00780 //FIXME Remove the slow_sync bool since you are not allowed to reset 00781 //the slow-sync manually anyways. 00782 00783 //FIXME Race Condition!!! 00784 if (!osync_group_get_slow_sync(group, objtypestr)) { 00785 if (osync_conv_objtype_is_any(objtypestr)) { 00786 GList *element; 00787 for (element = conv_env->objtypes; element; element = element->next) { 00788 OSyncObjType *objtype = element->data; 00789 objtype->needs_slow_sync = slow_sync; 00790 } 00791 } else { 00792 OSyncObjType *objtype = osync_conv_find_objtype(conv_env, objtypestr); 00793 g_assert(objtype); 00794 objtype->needs_slow_sync = slow_sync; 00795 } 00796 } 00797 00798 osync_trace(TRACE_EXIT, "%s", __func__); 00799 } 00800 00809 void osync_group_reset_slow_sync(OSyncGroup *group, const char *objtypestr) 00810 { 00811 osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, group, objtypestr); 00812 g_assert(group); 00813 OSyncFormatEnv *conv_env = group->conv_env; 00814 00815 if (osync_conv_objtype_is_any(objtypestr)) { 00816 GList *element; 00817 for (element = conv_env->objtypes; element; element = element->next) { 00818 OSyncObjType *objtype = element->data; 00819 objtype->needs_slow_sync = FALSE; 00820 } 00821 } else { 00822 OSyncObjType *objtype = osync_conv_find_objtype(conv_env, objtypestr); 00823 g_assert(objtype); 00824 objtype->needs_slow_sync = FALSE; 00825 } 00826 00827 osync_trace(TRACE_EXIT, "%s", __func__); 00828 } 00829 00839 osync_bool osync_group_get_slow_sync(OSyncGroup *group, const char *objtype) 00840 { 00841 osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, group, objtype); 00842 00843 g_assert(group); 00844 OSyncFormatEnv *env = group->conv_env; 00845 g_assert(env); 00846 00847 OSyncObjType *osync_objtype = osync_conv_find_objtype(env, "data"); 00848 if (osync_objtype && osync_objtype->needs_slow_sync) { 00849 osync_trace(TRACE_EXIT, "%s: Data objtype needs slow-sync", __func__); 00850 return TRUE; 00851 } 00852 osync_objtype = osync_conv_find_objtype(env, objtype); 00853 g_assert(osync_objtype); 00854 00855 osync_trace(TRACE_EXIT, "%s: %i", __func__, osync_objtype->needs_slow_sync); 00856 return osync_objtype->needs_slow_sync; 00857 } 00858 00870 osync_bool osync_group_objtype_enabled(OSyncGroup *group, const char *objtype) 00871 { 00872 //FIXME We should actually return a 3-state here. 00873 //0 if none is enabled 00874 //"0.5" if some are enabled, some are not 00875 //1 if all are enabled 00876 g_assert(group); 00877 GList *m; 00878 for (m = group->members; m; m = m->next) { 00879 OSyncMember *member = m->data; 00880 if (osync_member_objtype_enabled(member, objtype)) 00881 return TRUE; 00882 } 00883 return FALSE; 00884 } 00885 00899 void osync_group_set_objtype_enabled(OSyncGroup *group, const char *objtypestr, osync_bool enabled) 00900 { 00901 g_assert(group); 00902 GList *m; 00903 for (m = group->members; m; m = m->next) { 00904 OSyncMember *member = m->data; 00905 00906 /*TODO: What this function should do if we don't have 00907 * any objtype sink information? 00908 * It can't return error currently. We should either 00909 * require that the plugin is instanced, or change the function 00910 * interface. As changing the function interface require more 00911 * care, currently the function is marked as requiring the plugin to be instanced 00912 */ 00913 if (!osync_member_require_sink_info(member, NULL)) { 00914 osync_debug("OSGRP", 0, "%s: No sink information, can't load plugin, and I can't return error"); 00915 continue; 00916 } 00917 00918 osync_member_set_objtype_enabled(member, objtypestr, enabled); 00919 } 00920 } 00921 00928 int osync_group_num_filters(OSyncGroup *group) 00929 { 00930 g_assert(group); 00931 return g_list_length(group->filters); 00932 } 00933 00944 OSyncFilter *osync_group_nth_filter(OSyncGroup *group, int nth) 00945 { 00946 g_assert(group); 00947 return g_list_nth_data(group->filters, nth); 00948 } 00949 00954 void osync_group_flush_filters(OSyncGroup *group) 00955 { 00956 g_assert(group); 00957 while (group->filters) { 00958 OSyncFilter *f = g_list_nth_data(group->filters, 0); 00959 osync_filter_free(f); 00960 00961 /* Delete the first item */ 00962 group->filters = g_list_delete_link(group->filters, group->filters); 00963 } 00964 } 00965 00976 osync_bool osync_group_open_changelog(OSyncGroup *group, char ***uids, char ***objtype, long long int **memberids, int **changetypes, OSyncError **error) 00977 { 00978 return osync_db_open_changelog(group, uids, objtype, memberids, changetypes, error); 00979 } 00980 00988 osync_bool osync_group_save_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error) 00989 { 00990 return osync_db_save_changelog(group, change, error); 00991 } 00992 01000 osync_bool osync_group_remove_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error) 01001 { 01002 return osync_db_remove_changelog(group, change, error); 01003 } 01004 01012 void osync_group_set_last_synchronization(OSyncGroup *group, time_t last_sync) 01013 { 01014 osync_trace(TRACE_ENTRY, "%s(%p, not shown)", __func__, last_sync); 01015 osync_assert_msg(group, "Group missing"); 01016 01017 group->last_sync = last_sync; 01018 01019 osync_trace(TRACE_EXIT, "%s", __func__); 01020 } 01021 01029 time_t osync_group_get_last_synchronization(OSyncGroup *group) 01030 { 01031 osync_assert_msg(group, "Group missing"); 01032 return group->last_sync; 01033 } 01034