OpenSync  0.22
opensync_group.c
1 /*
2  * libopensync - A synchronization framework
3  * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  */
20 
21 #include "opensync.h"
22 #include "opensync_internals.h"
23 #include <errno.h>
24 #include <sys/file.h>
25 
26 extern int errno;
27 
28 /*
29  * On Solaris no flock function exists,
30  * we must implenet it here
31  */
32 #ifdef SOLARIS
33 
34 #define LOCK_SH 1
35 #define LOCK_EX 2
36 #define LOCK_NB 4
37 #define LOCK_UN 8
38 
39 static int
40 flock(int fd, int operation)
41 {
42  struct flock flock;
43 
44  switch (operation & ~LOCK_NB) {
45  case LOCK_SH:
46  flock.l_type = F_RDLCK;
47  break;
48  case LOCK_EX:
49  flock.l_type = F_WRLCK;
50  break;
51  case LOCK_UN:
52  flock.l_type = F_UNLCK;
53  break;
54  default:
55  errno = EINVAL;
56  return -1;
57  }
58 
59  flock.l_whence = 0;
60  flock.l_start = 0;
61  flock.l_len = 0;
62 
63  return fcntl(fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &flock);
64 }
65 #endif
66 
76 
84 {
85  return group->env;
86 }
87 
95 {
96  return group->data;
97 }
98 
105 void osync_group_set_data(OSyncGroup *group, void *data)
106 {
107  group->data = data;
108 }
109 
117 {
118  char *filename = NULL;
119  long long int i = 0;
120  do {
121  i++;
122  if (filename)
123  g_free(filename);
124  filename = g_strdup_printf("%s/%lli", group->configdir, i);
125  } while (g_file_test(filename, G_FILE_TEST_EXISTS));
126  g_free(filename);
127  return i;
128 }
129 
137 {
138  g_assert(group);
139  return group->conv_env;
140 }
141 
152 osync_bool osync_group_load_members(OSyncGroup *group, const char *path, OSyncError **error)
153 {
154  GDir *dir = NULL;
155  GError *gerror = NULL;
156  char *filename = NULL;
157 
158  dir = g_dir_open(path, 0, &gerror);
159  if (!dir) {
160  osync_debug("OSGRP", 3, "Unable to open group configdir %s", gerror->message);
161  osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Unable to open group configdir %s", gerror->message);
162  g_error_free (gerror);
163  return FALSE;
164  }
165 
166  const gchar *de = NULL;
167  while ((de = g_dir_read_name(dir))) {
168  filename = g_strdup_printf ("%s/%s", osync_group_get_configdir(group), de);
169  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)) {
170  g_free(filename);
171  continue;
172  }
173 
174  if (!osync_member_load(group, filename, error)) {
175  osync_debug("OSGRP", 0, "Unable to load one of the members");
176  g_free(filename);
177  g_dir_close(dir);
178  return FALSE;
179  }
180  g_free(filename);
181  }
182  g_dir_close(dir);
183  return TRUE;
184 }
185 
195 
205 {
206  OSyncGroup *group = g_malloc0(sizeof(OSyncGroup));
207  group->conv_env = osync_conv_env_new(env);
208 
209  if (env) {
210  osync_env_append_group(env, group);
211  group->env = env;
212  }
213 
214  return group;
215 }
216 
225 {
226  g_assert(group);
227 
228  if (group->conv_env)
229  osync_conv_env_free(group->conv_env);
230 
231  if (group->lock_fd)
232  osync_group_unlock(group, FALSE);
233 
234  while (osync_group_nth_member(group, 0))
236 
237  if (group->env)
238  osync_env_remove_group(group->env, group);
239 
240  if (group->name)
241  g_free(group->name);
242 
243  if (group->configdir)
244  g_free(group->configdir);
245 
246  g_free(group);
247 }
248 
268 {
269  osync_trace(TRACE_ENTRY, "osync_group_lock(%p)", group);
270  g_assert(group);
271  g_assert(group->configdir);
272 
273  osync_bool exists = FALSE;
274  osync_bool locked = FALSE;
275 
276  if (group->lock_fd) {
277  osync_trace(TRACE_EXIT, "osync_group_lock: OSYNC_LOCKED, lock_fd existed");
278  return OSYNC_LOCKED;
279  }
280 
281  char *lockfile = g_strdup_printf("%s/lock", group->configdir);
282  osync_debug("GRP", 4, "locking file %s", lockfile);
283 
284  if (g_file_test(lockfile, G_FILE_TEST_EXISTS)) {
285  osync_debug("GRP", 4, "locking group: file exists");
286  exists = TRUE;
287  }
288 
289  if ((group->lock_fd = open(lockfile, O_CREAT | O_WRONLY, 00700)) == -1) {
290  group->lock_fd = 0;
291  osync_debug("GRP", 1, "error opening file: %s", strerror(errno));
292  g_free(lockfile);
293  osync_trace(TRACE_EXIT_ERROR, "osync_group_lock: %s", strerror(errno));
294  return OSYNC_LOCK_STALE;
295  } else {
296 
297  /* Set FD_CLOEXEC flags for the lock file descriptor. We don't want the
298  * subprocesses created by plugins or the engine to keep holding the lock
299  */
300  int oldflags = fcntl(group->lock_fd, F_GETFD);
301  if (oldflags == -1) {
302  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, "Unable to get fd flags");
303  return OSYNC_LOCK_STALE;
304  }
305 
306  if (fcntl(group->lock_fd, F_SETFD, oldflags|FD_CLOEXEC) == -1) {
307  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, "Unable to set fd flags");
308  return OSYNC_LOCK_STALE;
309  }
310 
311  if (flock(group->lock_fd, LOCK_EX | LOCK_NB) == -1) {
312  if (errno == EWOULDBLOCK) {
313  osync_debug("GRP", 4, "locking group: is locked2");
314  locked = TRUE;
315  close(group->lock_fd);
316  group->lock_fd = 0;
317  } else
318  osync_debug("GRP", 1, "error setting lock: %s", strerror(errno));
319  } else
320  osync_debug("GRP", 4, "Successfully locked");
321  }
322  g_free(lockfile);
323 
324  if (!exists) {
325  osync_trace(TRACE_EXIT, "osync_group_lock: OSYNC_LOCK_OK");
326  return OSYNC_LOCK_OK;
327  } else {
328  if (locked) {
329  osync_trace(TRACE_EXIT, "osync_group_lock: OSYNC_LOCKED");
330  return OSYNC_LOCKED;
331  } else {
332  osync_trace(TRACE_EXIT, "osync_group_lock: OSYNC_LOCK_STALE");
333  return OSYNC_LOCK_STALE;
334  }
335  }
336 }
337 
348 void osync_group_unlock(OSyncGroup *group, osync_bool remove)
349 {
350  g_assert(group);
351  g_assert(group->configdir);
352  osync_debug("GRP", 4, "unlocking group %s", group->name);
353 
354  if (!group->lock_fd) {
355  osync_debug("GRP", 1, "You have to lock the group before unlocking");
356  return;
357  }
358 
359  if (flock(group->lock_fd, LOCK_UN) == -1) {
360  osync_debug("GRP", 1, "error releasing lock: %s", strerror(errno));
361  return;
362  }
363 
364  fsync(group->lock_fd);
365  close(group->lock_fd);
366 
367  group->lock_fd = 0;
368 
369  if (remove) {
370  char *lockfile = g_strdup_printf("%s/lock", group->configdir);
371  unlink(lockfile);
372  g_free(lockfile);
373  }
374 }
375 
384 void osync_group_set_name(OSyncGroup *group, const char *name)
385 {
386  g_assert(group);
387  if (group->name)
388  g_free(group->name);
389  group->name = g_strdup(name);
390 }
391 
400 const char *osync_group_get_name(OSyncGroup *group)
401 {
402  g_assert(group);
403  return group->name;
404 }
405 
415 osync_bool osync_group_save(OSyncGroup *group, OSyncError **error)
416 {
417  osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, group, error);
418  g_assert(group);
419  osync_assert_msg(group->env, "You must specify a Environment prior to saving the group");
420 
421  if (!group->configdir) {
422  group->id = _osync_env_create_group_id(group->env);
423  group->configdir = g_strdup_printf("%s/group%lli", group->env->groupsdir, group->id);
424  }
425 
426  char *filename = NULL;
427  osync_debug("OSGRP", 3, "Trying to open configdirectory %s to save group %s", group->configdir, group->name);
428  int i;
429 
430  if (!g_file_test(group->configdir, G_FILE_TEST_IS_DIR)) {
431  osync_debug("OSGRP", 3, "Creating group configdirectory %s", group->configdir);
432  if (mkdir(group->configdir, 0700)) {
433  osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Unable to create directory for group %s\n", group->name);
434  goto error;
435  }
436  }
437 
438  filename = g_strdup_printf ("%s/syncgroup.conf", group->configdir);
439  osync_debug("OSGRP", 3, "Saving group to file %s", filename);
440 
441  xmlDocPtr doc;
442 
443  doc = xmlNewDoc((xmlChar*)"1.0");
444  doc->children = xmlNewDocNode(doc, NULL, (xmlChar*)"syncgroup", NULL);
445 
446  //The filters
447  GList *f;
448  for (f = group->filters; f; f = f->next) {
449  OSyncFilter *filter = f->data;
450  xmlNodePtr child = xmlNewTextChild(doc->children, NULL, (xmlChar*)"filter", NULL);
451 
452  if (filter->sourcememberid) {
453  char *sourcememberid = g_strdup_printf("%lli", filter->sourcememberid);
454  xmlNewTextChild(child, NULL, (xmlChar*)"sourcemember", (xmlChar*)sourcememberid);
455  g_free(sourcememberid);
456  }
457  if (filter->destmemberid) {
458  char *destmemberid = g_strdup_printf("%lli", filter->destmemberid);
459  xmlNewTextChild(child, NULL, (xmlChar*)"destmember", (xmlChar*)destmemberid);
460  g_free(destmemberid);
461  }
462  if (filter->sourceobjtype)
463  xmlNewTextChild(child, NULL, (xmlChar*)"sourceobjtype", (xmlChar*)filter->sourceobjtype);
464  if (filter->destobjtype)
465  xmlNewTextChild(child, NULL, (xmlChar*)"destobjtype", (xmlChar*)filter->destobjtype);
466  if (filter->detectobjtype)
467  xmlNewTextChild(child, NULL, (xmlChar*)"detectobjtype", (xmlChar*)filter->detectobjtype);
468  if (filter->action) {
469  char *action = g_strdup_printf("%i", filter->action);
470  xmlNewTextChild(child, NULL, (xmlChar*)"action", (xmlChar*)action);
471  g_free(action);
472  }
473  if (filter->function_name)
474  xmlNewTextChild(child, NULL, (xmlChar*)"function_name", (xmlChar*)filter->function_name);
475  if (filter->config)
476  xmlNewTextChild(child, NULL, (xmlChar*)"config", (xmlChar*)filter->config);
477  }
478 
479  xmlNewTextChild(doc->children, NULL, (xmlChar*)"groupname", (xmlChar*)group->name);
480 
481  char *tmstr = g_strdup_printf("%i", (int)group->last_sync);
482  xmlNewTextChild(doc->children, NULL, (xmlChar*)"last_sync", (xmlChar*)tmstr);
483  g_free(tmstr);
484 
485  xmlSaveFile(filename, doc);
486  xmlFreeDoc(doc);
487  g_free(filename);
488 
489  for (i = 0; i < osync_group_num_members(group); i++) {
490  OSyncMember *member = osync_group_nth_member(group, i);
491  if (!osync_member_save(member, error))
492  goto error;
493  }
494 
495  osync_trace(TRACE_EXIT, "%s", __func__);
496  return TRUE;
497 
498 error:
499  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
500  return FALSE;
501 }
502 
512 osync_bool osync_group_delete(OSyncGroup *group, OSyncError **error)
513 {
514  g_assert(group);
515  char *delcmd = g_strdup_printf("rm -rf %s", group->configdir);
516  if (system(delcmd)) {
517  osync_error_set(error, OSYNC_ERROR_GENERIC, "Failed to delete group. command %s failed", delcmd);
518  g_free(delcmd);
519  return FALSE;
520  }
521  g_free(delcmd);
522  osync_group_free(group);
523  return TRUE;
524 }
525 
536 OSyncGroup *osync_group_load(OSyncEnv *env, const char *path, OSyncError **error)
537 {
538  g_assert(env);
539  char *filename = NULL;
540  char *real_path = NULL;
541 
542  osync_trace(TRACE_ENTRY, "osync_group_load(%p, %s, %p)", env, path, error);
543 
544  osync_debug("OSGRP", 3, "Trying to load group from directory %s", path);
545 
546  if (!g_path_is_absolute(path)) {
547  real_path = g_strdup_printf("%s/%s", g_get_current_dir(), path);
548  } else {
549  real_path = g_strdup(path);
550  }
551  filename = g_strdup_printf("%s/syncgroup.conf", real_path);
552 
553  OSyncGroup *group = osync_group_new(env);
554  group->configdir = real_path;
555 
556  xmlDocPtr doc;
557  xmlNodePtr cur;
558  xmlNodePtr filternode;
559 
560  if (!_osync_open_xml_file(&doc, &cur, filename, "syncgroup", error)) {
561  osync_group_free(group);
562  g_free(filename);
563  osync_trace(TRACE_EXIT_ERROR, "osync_group_load");
564  return NULL;
565  }
566 
567  while (cur != NULL) {
568  if (!xmlStrcmp(cur->name, (const xmlChar *)"groupname"))
569  group->name = (char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
570 
571  if (!xmlStrcmp(cur->name, (const xmlChar *)"last_sync"))
572  group->last_sync = (time_t)atoi((char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
573 
574  if (!xmlStrcmp(cur->name, (const xmlChar *)"filter")) {
575  filternode = cur->xmlChildrenNode;
576  OSyncFilter *filter = osync_filter_new();
577  filter->group = group;
578 
579  while (filternode != NULL) {
580  if (!xmlStrcmp(filternode->name, (const xmlChar *)"sourceobjtype"))
581  filter->sourceobjtype = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
582 
583  if (!xmlStrcmp(filternode->name, (const xmlChar *)"destobjtype"))
584  filter->destobjtype = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
585 
586  if (!xmlStrcmp(filternode->name, (const xmlChar *)"detectobjtype"))
587  filter->detectobjtype = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
588 
589  if (!xmlStrcmp(filternode->name, (const xmlChar *)"config"))
590  filter->config = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
591 
592  if (!xmlStrcmp(filternode->name, (const xmlChar *)"function_name")) {
593  char *str = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
594  if (!str) {
595  filternode = filternode->next;
596  continue;
597  }
598  osync_filter_update_hook(filter, group, str);
599  xmlFree(str);
600  }
601 
602  if (!xmlStrcmp(filternode->name, (const xmlChar *)"sourcemember")) {
603  char *str = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
604  if (!str) {
605  filternode = filternode->next;
606  continue;
607  }
608  filter->sourcememberid = atoll(str);
609  xmlFree(str);
610  }
611 
612  if (!xmlStrcmp(filternode->name, (const xmlChar *)"destmember")) {
613  char *str = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
614  if (!str) {
615  filternode = filternode->next;
616  continue;
617  }
618  filter->destmemberid = atoll(str);
619  xmlFree(str);
620  }
621 
622  if (!xmlStrcmp(filternode->name, (const xmlChar *)"action")) {
623  char *str = (char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
624  if (!str) {
625  filternode = filternode->next;
626  continue;
627  }
628  filter->action = atoi(str);
629  xmlFree(str);
630  }
631  filternode = filternode->next;
632  }
633  osync_filter_register(group, filter);
634  }
635  cur = cur->next;
636  }
637  xmlFreeDoc(doc);
638  g_free(filename);
639 
640  //Check for sanity
641  if (!group->name) {
642  osync_error_set(error, OSYNC_ERROR_MISCONFIGURATION, "Loaded a group without a name");
643  osync_debug("OSGRP", 0, "Loaded a group without a name");
644  osync_group_free(group);
645  osync_trace(TRACE_EXIT_ERROR, "osync_group_load");
646  return NULL;
647  }
648 
649  if (!osync_group_load_members(group, real_path, error)) {
650  osync_group_free(group);
651  osync_trace(TRACE_EXIT_ERROR, "osync_group_load");
652  return NULL;
653  }
654 
655  osync_trace(TRACE_EXIT, "osync_group_load");
656  return group;
657 }
658 
668 {
669  OSyncError *error = NULL;
670  osync_db_reset_group(group, &error);
671 
672  GList *m = NULL;
673  for (m = group->members; m; m = m->next) {
674  OSyncMember *member = m->data;
675  osync_db_reset_member(member, &error);
676  }
677 }
678 
688 {
689  g_assert(group);
690  group->members = g_list_append(group->members, member);
691 }
692 
700 {
701  g_assert(group);
702  group->members = g_list_remove(group->members, member);
703 }
704 
715 {
716  g_assert(group);
717  return (OSyncMember *)g_list_nth_data(group->members, nth);
718 }
719 
729 {
730  g_assert(group);
731  return g_list_length(group->members);
732 }
733 
743 {
744  g_assert(group);
745  return group->configdir;
746 }
747 
755 void osync_group_set_configdir(OSyncGroup *group, const char *directory)
756 {
757  g_assert(group);
758  if (group->configdir)
759  g_free(group->configdir);
760  group->configdir = g_strdup(directory);
761 }
762 
773 void osync_group_set_slow_sync(OSyncGroup *group, const char *objtypestr, osync_bool slow_sync)
774 {
775  osync_trace(TRACE_ENTRY, "%s(%p, %s, %i)", __func__, group, objtypestr, slow_sync);
776 
777  g_assert(group);
778  OSyncFormatEnv *conv_env = group->conv_env;
779 
780  //FIXME Remove the slow_sync bool since you are not allowed to reset
781  //the slow-sync manually anyways.
782 
783  //FIXME Race Condition!!!
784  if (!osync_group_get_slow_sync(group, objtypestr)) {
785  if (osync_conv_objtype_is_any(objtypestr)) {
786  GList *element;
787  for (element = conv_env->objtypes; element; element = element->next) {
788  OSyncObjType *objtype = element->data;
789  objtype->needs_slow_sync = slow_sync;
790  }
791  } else {
792  OSyncObjType *objtype = osync_conv_find_objtype(conv_env, objtypestr);
793  g_assert(objtype);
794  objtype->needs_slow_sync = slow_sync;
795  }
796  }
797 
798  osync_trace(TRACE_EXIT, "%s", __func__);
799 }
800 
809 void osync_group_reset_slow_sync(OSyncGroup *group, const char *objtypestr)
810 {
811  osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, group, objtypestr);
812  g_assert(group);
813  OSyncFormatEnv *conv_env = group->conv_env;
814 
815  if (osync_conv_objtype_is_any(objtypestr)) {
816  GList *element;
817  for (element = conv_env->objtypes; element; element = element->next) {
818  OSyncObjType *objtype = element->data;
819  objtype->needs_slow_sync = FALSE;
820  }
821  } else {
822  OSyncObjType *objtype = osync_conv_find_objtype(conv_env, objtypestr);
823  g_assert(objtype);
824  objtype->needs_slow_sync = FALSE;
825  }
826 
827  osync_trace(TRACE_EXIT, "%s", __func__);
828 }
829 
839 osync_bool osync_group_get_slow_sync(OSyncGroup *group, const char *objtype)
840 {
841  osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, group, objtype);
842 
843  g_assert(group);
844  OSyncFormatEnv *env = group->conv_env;
845  g_assert(env);
846 
847  OSyncObjType *osync_objtype = osync_conv_find_objtype(env, "data");
848  if (osync_objtype && osync_objtype->needs_slow_sync) {
849  osync_trace(TRACE_EXIT, "%s: Data objtype needs slow-sync", __func__);
850  return TRUE;
851  }
852  osync_objtype = osync_conv_find_objtype(env, objtype);
853  g_assert(osync_objtype);
854 
855  osync_trace(TRACE_EXIT, "%s: %i", __func__, osync_objtype->needs_slow_sync);
856  return osync_objtype->needs_slow_sync;
857 }
858 
870 osync_bool osync_group_objtype_enabled(OSyncGroup *group, const char *objtype)
871 {
872  //FIXME We should actually return a 3-state here.
873  //0 if none is enabled
874  //"0.5" if some are enabled, some are not
875  //1 if all are enabled
876  g_assert(group);
877  GList *m;
878  for (m = group->members; m; m = m->next) {
879  OSyncMember *member = m->data;
880  if (osync_member_objtype_enabled(member, objtype))
881  return TRUE;
882  }
883  return FALSE;
884 }
885 
899 void osync_group_set_objtype_enabled(OSyncGroup *group, const char *objtypestr, osync_bool enabled)
900 {
901  g_assert(group);
902  GList *m;
903  for (m = group->members; m; m = m->next) {
904  OSyncMember *member = m->data;
905 
906  /*TODO: What this function should do if we don't have
907  * any objtype sink information?
908  * It can't return error currently. We should either
909  * require that the plugin is instanced, or change the function
910  * interface. As changing the function interface require more
911  * care, currently the function is marked as requiring the plugin to be instanced
912  */
913  if (!osync_member_require_sink_info(member, NULL)) {
914  osync_debug("OSGRP", 0, "%s: No sink information, can't load plugin, and I can't return error");
915  continue;
916  }
917 
918  osync_member_set_objtype_enabled(member, objtypestr, enabled);
919  }
920 }
921 
929 {
930  g_assert(group);
931  return g_list_length(group->filters);
932 }
933 
945 {
946  g_assert(group);
947  return g_list_nth_data(group->filters, nth);
948 }
949 
955 {
956  g_assert(group);
957  while (group->filters) {
958  OSyncFilter *f = g_list_nth_data(group->filters, 0);
960 
961  /* Delete the first item */
962  group->filters = g_list_delete_link(group->filters, group->filters);
963  }
964 }
965 
976 osync_bool osync_group_open_changelog(OSyncGroup *group, char ***uids, char ***objtype, long long int **memberids, int **changetypes, OSyncError **error)
977 {
978  return osync_db_open_changelog(group, uids, objtype, memberids, changetypes, error);
979 }
980 
988 osync_bool osync_group_save_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error)
989 {
990  return osync_db_save_changelog(group, change, error);
991 }
992 
1001 {
1002  return osync_db_remove_changelog(group, change, error);
1003 }
1004 
1012 void osync_group_set_last_synchronization(OSyncGroup *group, time_t last_sync)
1013 {
1014  osync_trace(TRACE_ENTRY, "%s(%p, not shown)", __func__, last_sync);
1015  osync_assert_msg(group, "Group missing");
1016 
1017  group->last_sync = last_sync;
1018 
1019  osync_trace(TRACE_EXIT, "%s", __func__);
1020 }
1021 
1030 {
1031  osync_assert_msg(group, "Group missing");
1032  return group->last_sync;
1033 }
1034 
void osync_env_remove_group(OSyncEnv *env, OSyncGroup *group)
Removes the given group from the enviroment.
Definition: opensync_env.c:598
void osync_filter_register(OSyncGroup *group, OSyncFilter *filter)
Registers a filter with a group.
OSyncGroup * osync_group_new(OSyncEnv *env)
Creates a new group for the given environment.
OSyncGroup * osync_group_load(OSyncEnv *env, const char *path, OSyncError **error)
Loads a group from a directory.
void osync_member_free(OSyncMember *member)
Frees a member.
void osync_group_remove_member(OSyncGroup *group, OSyncMember *member)
Removes a member from the group.
Represent an error.
osync_bool osync_group_open_changelog(OSyncGroup *group, char ***uids, char ***objtype, long long int **memberids, int **changetypes, OSyncError **error)
Can be used to load all items from the changelog. Loaded items will be removed.
void osync_member_set_objtype_enabled(OSyncMember *member, const char *objtypestr, osync_bool enabled)
Enables or disables a object type on a member.
osync_bool _osync_open_xml_file(xmlDocPtr *doc, xmlNodePtr *cur, const char *path, const char *topentry, OSyncError **error)
Opens a xml document.
Definition: opensync_env.c:652
void osync_group_set_configdir(OSyncGroup *group, const char *directory)
Sets the configdir of the group.
OSyncFilter * osync_group_nth_filter(OSyncGroup *group, int nth)
Gets the nth filter of a group.
int osync_group_num_members(OSyncGroup *group)
Counts the members of the group.
osync_bool osync_group_save(OSyncGroup *group, OSyncError **error)
Saves the group to disc.
void osync_group_set_data(OSyncGroup *group, void *data)
Sets the custom data of a group.
OSyncEnv * osync_group_get_env(OSyncGroup *group)
Returns the environment in which a group is registered.
OSyncMember * osync_member_load(OSyncGroup *group, const char *path, OSyncError **error)
Loads a member from a directory where it has been saved.
int osync_group_num_filters(OSyncGroup *group)
Returns the number of filters registered in a group.
void osync_filter_free(OSyncFilter *filter)
Frees a filter.
void osync_env_append_group(OSyncEnv *env, OSyncGroup *group)
Adds the given group to the environment.
Definition: opensync_env.c:585
osync_bool osync_group_objtype_enabled(OSyncGroup *group, const char *objtype)
Returns if the object type is enabled for the group.
osync_bool osync_member_save(OSyncMember *member, OSyncError **error)
Saves a member to it config directory.
Represent a group of members that should be synchronized.
void osync_group_set_objtype_enabled(OSyncGroup *group, const char *objtypestr, osync_bool enabled)
Sets if the object type is accepted for ALL members.
osync_bool osync_group_save_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error)
Saves a change to the changelog.
void osync_group_reset(OSyncGroup *group)
Resets all databases of a group.
long long int osync_group_create_member_id(OSyncGroup *group)
Creates a new unique member if in this group.
A member of a group which represent a single device.
void osync_group_add_member(OSyncGroup *group, OSyncMember *member)
Appends a member to the group.
void osync_group_unlock(OSyncGroup *group, osync_bool remove)
Unlocks a group.
void osync_group_reset_slow_sync(OSyncGroup *group, const char *objtypestr)
Reset slow-sync for this group.
void osync_group_free(OSyncGroup *group)
Frees the given group.
OSyncObjType * osync_conv_find_objtype(OSyncFormatEnv *env, const char *name)
Finds the object type with the given name.
Represents a filter to filter changes.
OSyncLockState
The lock state of a group.
Definition: opensync_group.h:7
time_t osync_group_get_last_synchronization(OSyncGroup *group)
Gets the last synchronization date from this group.
void osync_debug(const char *subpart, int level, const char *message,...)
Used for debugging.
osync_bool osync_group_load_members(OSyncGroup *group, const char *path, OSyncError **error)
Loads all members of a group.
A change object.
const char * osync_group_get_name(OSyncGroup *group)
Returns the name of a group.
long long int _osync_env_create_group_id(OSyncEnv *env)
Returns the next free number for a group in the environments configdir.
Definition: opensync_env.c:139
osync_bool osync_group_delete(OSyncGroup *group, OSyncError **error)
Deletes a group from disc.
OSyncFormatEnv * osync_conv_env_new(OSyncEnv *env)
This will create a new opensync format environment.
void * osync_group_get_data(OSyncGroup *group)
Gets the custom data of a group.
void osync_error_set(OSyncError **error, OSyncErrorType type, const char *format,...)
Sets the error.
const char * osync_error_print(OSyncError **error)
Returns the message of the error.
void osync_conv_env_free(OSyncFormatEnv *env)
Frees a osync format environment.
void osync_trace(OSyncTraceType type, const char *message,...)
Used for tracing the application.
void osync_group_set_last_synchronization(OSyncGroup *group, time_t last_sync)
Sets the last synchronization date of this group.
osync_bool osync_group_get_slow_sync(OSyncGroup *group, const char *objtype)
Returns if the group will perform a slow-sync for the object type.
osync_bool osync_member_objtype_enabled(OSyncMember *member, const char *objtype)
Returns if a certain object type is enabled on this member.
osync_bool osync_group_remove_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error)
Removes a change from the changelog.
Represent a abstract object type (like "contact")
OSyncLockState osync_group_lock(OSyncGroup *group)
Locks a group.
void osync_group_flush_filters(OSyncGroup *group)
Flushes the list of filters for a group.
The environment used for conversions.
OSyncMember * osync_group_nth_member(OSyncGroup *group, int nth)
Returns the nth member of the group.
void osync_group_set_name(OSyncGroup *group, const char *name)
Sets the name for the group.
OSyncFilter * osync_filter_new(void)
Creates a new filter.
void osync_group_set_slow_sync(OSyncGroup *group, const char *objtypestr, osync_bool slow_sync)
Sets if the group requires slow-sync for the given object type.
const char * osync_group_get_configdir(OSyncGroup *group)
Returns the configdir for the group.
OSyncFormatEnv * osync_group_get_format_env(OSyncGroup *group)
Returns the format environment of a group.