00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00030
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
00298
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
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
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
00781
00782
00783
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
00873
00874
00875
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
00907
00908
00909
00910
00911
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
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