diff options
author | JP Rosevear <jpr@helixcode.com> | 2000-09-20 06:48:47 +0800 |
---|---|---|
committer | JP Rosevear <jpr@src.gnome.org> | 2000-09-20 06:48:47 +0800 |
commit | 58b5fd92fc9f5419beabe82d38622aba064cc56e (patch) | |
tree | a8219b9cc9b1311466f9854b0fa673045250edb1 /calendar/conduits | |
parent | 6820bb50e53b479997ae5a9616186301c333fad8 (diff) | |
download | gsoc2013-evolution-58b5fd92fc9f5419beabe82d38622aba064cc56e.tar gsoc2013-evolution-58b5fd92fc9f5419beabe82d38622aba064cc56e.tar.gz gsoc2013-evolution-58b5fd92fc9f5419beabe82d38622aba064cc56e.tar.bz2 gsoc2013-evolution-58b5fd92fc9f5419beabe82d38622aba064cc56e.tar.lz gsoc2013-evolution-58b5fd92fc9f5419beabe82d38622aba064cc56e.tar.xz gsoc2013-evolution-58b5fd92fc9f5419beabe82d38622aba064cc56e.tar.zst gsoc2013-evolution-58b5fd92fc9f5419beabe82d38622aba064cc56e.zip |
Add some other cases where a slow sync is in order (pre_sync): Pre load
2000-09-19 JP Rosevear <jpr@helixcode.com>
* conduits/todo/todo-conduit.c (check_for_slow_setting): Add some
other cases where a slow sync is in order
(pre_sync): Pre load the uids, the map and the add/mod/del lists
(match_record): Use the map hash to match records
(iterate): Iterate using the pre-loaded uid list
(iterate_specific): Iterate using the add/mod/del lists
(purge): Delete all entries in the del list
(set_status): Set status by adding to an appropriate list
(set_pilot_id): Set pilot_id by updating map hash
* conduits/todo/todo-conduit.h: Add lists for added, modified and
deleted objects
* conduits/todo/todo-conduit.c (map_name): Get the pilot_id->uid
map
file name
(map_sax_start_element): SAX handler to extract a pilot_id->uid
mapping
(map_sax_parse): Parse the given file and build a pilot_id->uid
hash
(map_write_foreach): Write out individual mapping elements
(map_write): Write out the pilot_id->uid mapping
(start_calendar_server_cb): Rename from gnome_calendar_load_cb
* conduits/todo/todo-conduit-config.h: Rename pilotID to pilot_id
* conduits/todo/e-todo.conduit.in: A little renaming
* conduits/todo/Makefile.am: Fix build slightly
* pcs/cal.c (build_change_seq): Build a corba sequence out of a
list
of CalObjChanges
(Cal_get_objects_in_range): Implement new corba function
* pcs/cal-backend.c (cal_backend_init): Intiliaze to NULL
(cal_backend_load): Track the uri so we can write the log file
to the same place
(cal_backend_log_name): Figure out the log filename/path based on
the calendar uri
(cal_backend_set_node_timet): Set an xml node property value from
a time_t
(cal_backend_log_entry): Adds a log entry to list waiting to be
written
out
(cal_backend_log_sync): Syncs the log entries to disk
(cal_backend_log_sax_start_element): SAX callback for reading in
log entries
(cal_backend_log_sax_end_element): ditto
(cal_backend_log_sax_parse): Main SAX parser call to parse the log
file looking for particular log entries and creating a
CalObjChange
hash with the last change for each object
(cal_backend_get_log_entries): Returns a hash of objects of a
given
type changed since the given time
(cal_backend_update_object): Add appropriate log entries
(cal_backend_remove_object): ditto
(cal_backend_get_changed_uids): Implement new idl interface call
(cal_backend_foreach_changed): Convert CalObjChange hash into a
list
* pcs/cal-backend-imc.[hc]: Remove crufty files
* pcs/cal-backend-file.c (cal_backend_file_get_type_by_uid): New
function that returns the CalObjType for a uid.
* cal-client/cal-client.h: Update prototypes.
* cal-client/cal-client.c (build_change_list): Build a list
of CalObjChange items from a corba sequence.
(cal_client_get_changed_uids): New accessor method for the
similarly named addition to the idl file.
* cal-util/cal-util.h: Update prototypes and add CalObjChangeType
enum.
* cal-util/cal-util.c (cal_obj_change_list_free): New utility
method to free a list of CalObjChange objects.
* idl/evolution-calendar.idl: Add get_changed_uids method
and associated types.
svn path=/trunk/; revision=5512
Diffstat (limited to 'calendar/conduits')
-rw-r--r-- | calendar/conduits/todo/Makefile.am | 6 | ||||
-rw-r--r-- | calendar/conduits/todo/e-todo.conduit.in | 4 | ||||
-rw-r--r-- | calendar/conduits/todo/todo-conduit-config.h | 12 | ||||
-rw-r--r-- | calendar/conduits/todo/todo-conduit.c | 964 | ||||
-rw-r--r-- | calendar/conduits/todo/todo-conduit.h | 18 |
5 files changed, 495 insertions, 509 deletions
diff --git a/calendar/conduits/todo/Makefile.am b/calendar/conduits/todo/Makefile.am index 3bbfc3f418..94eb5251b5 100644 --- a/calendar/conduits/todo/Makefile.am +++ b/calendar/conduits/todo/Makefile.am @@ -3,7 +3,7 @@ INCLUDES = \ -I$(top_srcdir)/calendar \ -I$(top_srcdir)/libical/src/libical \ -I$(top_builddir)/libical/src/libical \ - $(BONOBO_GNOME_CFLAGS) \ + $(BONOBO_VFS_GNOME_CFLAGS) \ $(GNOME_PILOT_CFLAGS) # ToDo Capplet @@ -30,9 +30,6 @@ e_todo_conduits_LTLIBRARIES = libetodo_conduit.la libetodo_conduit_la_SOURCES = todo-conduit.c -libetodo_conduit_la_LDFLAGS = \ - -rpath $(libdir) - libetodo_conduit_la_LIBADD = \ $(top_builddir)/calendar/cal-client/libcal-client-static.la \ $(top_builddir)/calendar/cal-util/libcal-util-static.la \ @@ -40,6 +37,7 @@ libetodo_conduit_la_LIBADD = \ $(top_builddir)/libical/src/libical/libical-static.la \ $(BONOBO_VFS_GNOME_LIBS) \ $(PISOCK_LIBDIR) $(PISOCK_LIBS) \ + $(UNICODE_LIBS) \ $(GNOME_LIBDIR) \ $(GNOME_LIBS) diff --git a/calendar/conduits/todo/e-todo.conduit.in b/calendar/conduits/todo/e-todo.conduit.in index 42691745a6..40e6fd620c 100644 --- a/calendar/conduits/todo/e-todo.conduit.in +++ b/calendar/conduits/todo/e-todo.conduit.in @@ -1,6 +1,6 @@ <gnome-pilot-conduit version="1.0"> -<conduit id="todo_conduit" type="shlib" location="@prefix@/lib/gnome-pilot/conduits/libetodo_conduit.so"/> -<name value="e-todo"/> +<conduit id="e_todo_conduit" type="shlib" location="@prefix@/lib/gnome-pilot/conduits/libetodo_conduit.so"/> +<name value="EToDo"/> <conduit-attribute name="description" value="Synchronizes ToDo List with Evolution"/> <conduit-attribute name="default-synctype" value="synchronize"/> <conduit-attribute name="icon" value="@prefix@/share/pixmaps/gnome-calendar-conduit.png"/> diff --git a/calendar/conduits/todo/todo-conduit-config.h b/calendar/conduits/todo/todo-conduit-config.h index 18bb353b08..38f3cf8e39 100644 --- a/calendar/conduits/todo/todo-conduit-config.h +++ b/calendar/conduits/todo/todo-conduit-config.h @@ -33,16 +33,16 @@ typedef struct _EToDoConduitCfg EToDoConduitCfg; struct _EToDoConduitCfg { gboolean open_secret; - guint32 pilotId; + guint32 pilot_id; GnomePilotConduitSyncType sync_type; /* only used by capplet */ }; static void -todoconduit_load_configuration (EToDoConduitCfg **c, guint32 pilotId) +todoconduit_load_configuration (EToDoConduitCfg **c, guint32 pilot_id) { gchar prefix[256]; g_snprintf (prefix, 255, "/gnome-pilot.d/e-todo-conduit/Pilot_%u/", - pilotId); + pilot_id); *c = g_new0 (EToDoConduitCfg,1); g_assert (*c != NULL); @@ -54,7 +54,7 @@ todoconduit_load_configuration (EToDoConduitCfg **c, guint32 pilotId) (*c)->sync_type = GnomePilotConduitSyncTypeCustom; gnome_config_pop_prefix (); - (*c)->pilotId = pilotId; + (*c)->pilot_id = pilot_id; } /* Saves the configuration data. */ @@ -64,7 +64,7 @@ todoconduit_save_configuration (EToDoConduitCfg *c) gchar prefix[256]; g_snprintf (prefix, 255, "/gnome-pilot.d/e-todo-conduit/Pilot_%u/", - c->pilotId); + c->pilot_id); gnome_config_push_prefix (prefix); gnome_config_set_bool ("open_secret", c->open_secret); @@ -85,7 +85,7 @@ todoconduit_dupe_configuration (EToDoConduitCfg *c) retval = g_new0 (EToDoConduitCfg, 1); retval->sync_type = c->sync_type; retval->open_secret = c->open_secret; - retval->pilotId = c->pilotId; + retval->pilot_id = c->pilot_id; return retval; } diff --git a/calendar/conduits/todo/todo-conduit.c b/calendar/conduits/todo/todo-conduit.c index f1f0e11e28..6b9659f70f 100644 --- a/calendar/conduits/todo/todo-conduit.c +++ b/calendar/conduits/todo/todo-conduit.c @@ -48,7 +48,6 @@ GnomePilotConduit * conduit_get_gpilot_conduit (guint32); void conduit_destroy_gpilot_conduit (GnomePilotConduit*); -void local_record_from_compobject (EToDoLocalRecord *local, CalComponent *comp); #define CONDUIT_VERSION "0.8.11" #ifdef G_LOG_DOMAIN @@ -60,15 +59,13 @@ void local_record_from_compobject (EToDoLocalRecord *local, CalComponent *comp); /* #undef DEBUG_CALCONDUIT */ #ifdef DEBUG_CALCONDUIT -#define show_exception(e) g_warning ("Exception: %s\n", CORBA_exception_id (e)) -#define LOG(e...) g_log(G_LOG_DOMAIN,G_LOG_LEVEL_MESSAGE, e) +#define LOG(e...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, e) #else -#define show_exception(e) #define LOG(e...) #endif -#define WARN(e...) g_log(G_LOG_DOMAIN,G_LOG_LEVEL_WARNING, e) -#define INFO(e...) g_log(G_LOG_DOMAIN,G_LOG_LEVEL_MESSAGE, e) +#define WARN(e...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, e) +#define INFO(e...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, e) /* debug spew DELETE ME */ static char *print_local (EToDoLocalRecord *local) @@ -120,19 +117,16 @@ static char *print_remote (PilotRecord *remote) return buff; } -/* Given a GCalConduitContxt*, allocates the structure */ +/* Context Routines */ static void -e_todo_context_new (EToDoConduitContext **ctxt, guint32 pilotId) +e_todo_context_new (EToDoConduitContext **ctxt, guint32 pilot_id) { *ctxt = g_new0 (EToDoConduitContext,1); g_assert (ctxt!=NULL); - todoconduit_load_configuration (&(*ctxt)->cfg, pilotId); + todoconduit_load_configuration (&(*ctxt)->cfg, pilot_id); } - -/* Destroys any data allocated by gcalconduit_new_context - and deallocates its data. */ static void e_todo_context_destroy (EToDoConduitContext **ctxt) { @@ -149,15 +143,135 @@ e_todo_context_destroy (EToDoConduitContext **ctxt) *ctxt = NULL; } +/* Map routines */ +static char * +map_name (EToDoConduitContext *ctxt) +{ + char *filename; + + filename = g_strdup_printf ("%s/evolution/local/Calendar/pilot-map-%d.xml", g_get_home_dir (), ctxt->cfg->pilot_id); + + return filename; +} + +static void +map_sax_start_element (void *data, const xmlChar *name, + const xmlChar **attrs) +{ + EToDoConduitContext *ctxt = (EToDoConduitContext *)data; + + if (!strcmp (name, "map")) { + char *uid = NULL; + guint32 *pid = g_new (guint32, 1); + + *pid = 0; + + while (*attrs != NULL) { + const xmlChar **val = attrs; + + val++; + if (!strcmp (*attrs, "uid")) + uid = g_strdup (*val); + + if (!strcmp (*attrs, "pilotid")) + *pid = strtoul (*val, NULL, 0); + + attrs = ++val; + } + + if (uid && *pid != 0) + g_hash_table_insert (ctxt->map, pid, uid); + else + g_free (pid); + } +} + +static int +map_sax_parse (xmlSAXHandler *handler, EToDoConduitContext *ctxt, const char *filename) +{ + int ret = 0; + xmlParserCtxtPtr xc; + + if (!g_file_exists (filename)) + return 0; + + xc = xmlCreateFileParserCtxt (filename); + if (xc == NULL) + return -1; + + xc->sax = handler; + xc->userData = (void *)ctxt; + + xmlParseDocument (xc); + + if (xc->wellFormed) + ret = 0; + else + ret = -1; + + if (handler != NULL) + xc->sax = NULL; + xmlFreeParserCtxt(xc); + + return ret; +} static void -gnome_calendar_load_cb (GtkWidget *cal_client, - CalClientLoadStatus status, - EToDoConduitContext *ctxt) +map_write_foreach (gpointer key, gpointer value, gpointer data) +{ + xmlNodePtr root = data; + xmlNodePtr mnode; + unsigned long *pid = key; + const char *uid = value; + char *pidstr; + + mnode = xmlNewChild (root, NULL, "map", NULL); + xmlSetProp (mnode, "uid", uid); + pidstr = g_strdup_printf ("%lu", *pid); + xmlSetProp (mnode, "pilot_id", pidstr); + g_free (pidstr); +} + +static int +map_write (EToDoConduitContext *ctxt, char *filename) +{ + xmlDocPtr doc; + int ret; + + if (ctxt->map == NULL) + return 0; + + doc = xmlNewDoc ("1.0"); + if (doc == NULL) { + WARN ("Pilot map file could not be created\n"); + return -1; + } + doc->root = xmlNewDocNode(doc, NULL, "PilotMap", NULL); + + g_hash_table_foreach (ctxt->map, map_write_foreach, doc->root); + + /* Write the file */ + xmlSetDocCompressMode (doc, 0); + ret = xmlSaveFile (filename, doc); + if (ret < 0) { + g_warning ("Pilot map file '%s' could not be saved\n", filename); + return -1; + } + + xmlFreeDoc (doc); + + return 0; +} + +/* Calendar Server routines */ +static void +start_calendar_server_cb (GtkWidget *cal_client, + CalClientLoadStatus status, + EToDoConduitContext *ctxt) { CalClient *client = CAL_CLIENT (cal_client); - LOG (" todo-conduit entering gnome_calendar_load_cb, tried=%d\n", + LOG (" entering start_calendar_server_load_cb, tried=%d\n", ctxt->calendar_load_tried); if (status == CAL_CLIENT_LOAD_SUCCESS) { @@ -172,21 +286,15 @@ gnome_calendar_load_cb (GtkWidget *cal_client, } cal_client_create_calendar (client, ctxt->calendar_file); - ctxt->calendar_load_tried = 1; + ctxt->calendar_load_tried = TRUE; } } - - - - static int -start_calendar_server (GnomePilotConduitStandardAbs *conduit, - EToDoConduitContext *ctxt) +start_calendar_server (EToDoConduitContext *ctxt) { - g_return_val_if_fail(conduit!=NULL,-2); - g_return_val_if_fail(ctxt!=NULL,-2); + g_return_val_if_fail (ctxt != NULL, -2); ctxt->client = cal_client_new (); @@ -195,7 +303,7 @@ start_calendar_server (GnomePilotConduitStandardAbs *conduit, "evolution/local/Calendar/calendar.ics"); gtk_signal_connect (GTK_OBJECT (ctxt->client), "cal_loaded", - gnome_calendar_load_cb, ctxt); + start_calendar_server_cb, ctxt); LOG (" calling cal_client_load_calendar\n"); cal_client_load_calendar (ctxt->client, ctxt->calendar_file); @@ -210,59 +318,9 @@ start_calendar_server (GnomePilotConduitStandardAbs *conduit, return -1; } - -static GSList * -get_calendar_objects(GnomePilotConduitStandardAbs *conduit, - gboolean *status, - EToDoConduitContext *ctxt) -{ - GList *uids; - GSList *result = NULL; - - g_return_val_if_fail (conduit != NULL, NULL); - g_return_val_if_fail (ctxt != NULL, NULL); - - uids = cal_client_get_uids (ctxt->client, CALOBJ_TYPE_TODO); - - LOG ("got %d todo entries from cal server\n", g_list_length (uids)); - - if (status != NULL) - (*status) = TRUE; - - if (! uids) - INFO ("No entries found"); - else { - GList *c; - for (c=uids; c; c=c->next) - result = g_slist_prepend (result, (gchar *) c->data); - /* FIX ME free uids */ - } - - return result; -} - - -static void -local_record_from_comp_uid (EToDoLocalRecord *local, - char *uid, - EToDoConduitContext *ctxt) -{ - CalComponent *comp; - CalClientGetStatus status; - - g_assert(local!=NULL); - - status = cal_client_get_object (ctxt->client, uid, &comp); - - if (status == CAL_CLIENT_GET_SUCCESS) - local_record_from_compobject (local, comp); - else - INFO ("Object did not exist"); -} - - - -static const char *gnome_pilot_status_to_string (gint status) +/* Utility routines */ +static const char * +status_to_string (gint status) { switch(status) { case GnomePilotRecordPending: return "GnomePilotRecordPending"; @@ -275,14 +333,37 @@ static const char *gnome_pilot_status_to_string (gint status) return "Unknown"; } +static PilotRecord * +local_record_to_pilot_record (EToDoLocalRecord *local, + EToDoConduitContext *ctxt) +{ + PilotRecord *p = NULL; + + g_return_val_if_fail (local != NULL, NULL); + g_assert (local->comp != NULL); + g_assert (local->todo != NULL ); + + LOG ("local_record_to_remote_record\n"); + + p = g_new0 (PilotRecord, 1); + p->ID = local->local.ID; + p->attr = local->local.attr; + p->archived = local->local.archived; + p->secret = local->local.secret; + + /* Generate pilot record structure */ + p->record = g_new0 (char,0xffff); + p->length = pack_ToDo (local->todo, p->record, 0xffff); + + return p; +} /* * converts a CalComponent object to a EToDoLocalRecord */ -void -local_record_from_compobject(EToDoLocalRecord *local, - CalComponent *comp) +static void +local_record_from_comp (EToDoLocalRecord *local, CalComponent *comp) { int *priority; struct icaltimetype *completed; @@ -295,7 +376,7 @@ local_record_from_compobject(EToDoLocalRecord *local, unsigned long *pilot_id; unsigned long *pilot_status; - LOG ("local_record_from_compobject\n"); + LOG ("local_record_from_comp\n"); g_return_if_fail (local != NULL); g_return_if_fail (comp != NULL); @@ -364,68 +445,23 @@ local_record_from_compobject(EToDoLocalRecord *local, local->local.archived = 0; } - -/* - * Given a PilotRecord, find the matching record in - * the calendar repository. If no match, return NULL - */ -static EToDoLocalRecord * -find_record_in_repository(GnomePilotConduitStandardAbs *conduit, - PilotRecord *remote, - EToDoConduitContext *ctxt) +static void +local_record_from_uid (EToDoLocalRecord *local, + char *uid, + EToDoConduitContext *ctxt) { - char *uid = NULL; - EToDoLocalRecord *loc; - CalClientGetStatus status; CalComponent *comp; - - g_return_val_if_fail(conduit!=NULL,NULL); - g_return_val_if_fail(remote!=NULL,NULL); - - LOG ("find_record_in_repository: remote=%s... ", - print_remote (remote)); + CalClientGetStatus status; - LOG ("requesting %ld", remote->ID); + g_assert(local!=NULL); - status = cal_client_get_uid_by_pilot_id (ctxt->client, remote->ID, &uid); + status = cal_client_get_object (ctxt->client, uid, &comp); if (status == CAL_CLIENT_GET_SUCCESS) { - status = cal_client_get_object (ctxt->client, uid, &comp); - if (status == CAL_CLIENT_GET_SUCCESS) { - LOG ("found %s\n", cal_component_get_as_string (comp)); - loc = g_new0(EToDoLocalRecord,1); - /* memory allocated in new_from_string is freed in free_match */ - local_record_from_compobject (loc, comp); - return loc; - } - LOG ("Pilot ID found, but comp for uid %s was not\n", uid); - } - - INFO ("Object did not exist"); - return NULL; -} - - -/* - * updates an given CalComponent in the repository - */ -static void -update_calendar_entry_in_repository(GnomePilotConduitStandardAbs *conduit, - CalComponent *comp, - EToDoConduitContext *ctxt) -{ - gboolean success; - - g_return_if_fail (conduit != NULL); - g_return_if_fail (comp != NULL); - - LOG (" update_calendar_entry_in_repository " - "saving to desktop\n%s", cal_component_get_as_string (comp)); - - success = cal_client_update_object (ctxt->client, comp); - - if (!success) - WARN (_("Error while communicating with calendar server")); + local_record_from_comp (local, comp); + } else { + INFO ("Object did not exist"); + } } @@ -505,90 +541,34 @@ comp_from_remote_record (GnomePilotConduitStandardAbs *conduit, return comp; } - -/* Code blatantly stolen from - * calendar-pilot-sync.c: - * - * (C) 1999 International GNOME Support - * - * Author: - * Miguel de Icaza (miguel@gnome-support.com) - * - * store a copy of a pilot record in the desktop database - * - */ -static gint -update_record (GnomePilotConduitStandardAbs *conduit, - PilotRecord *remote, - EToDoConduitContext *ctxt) +static void +update_comp (GnomePilotConduitStandardAbs *conduit, CalComponent *comp, + EToDoConduitContext *ctxt) { - CalComponent *comp; - CalClientGetStatus status; - struct ToDo todo; - unsigned long pilot_status = GnomePilotRecordNothing; - char *uid; - - g_return_val_if_fail (remote!=NULL,-1); - - memset (&todo, 0, sizeof (struct ToDo)); - unpack_ToDo (&todo, remote->record, remote->length); - - LOG (" cal_client_get_uid_by_pilot_id... "); - - status = cal_client_get_uid_by_pilot_id (ctxt->client, - remote->ID, &uid); - if (status == CAL_CLIENT_GET_SUCCESS) { - LOG (" succeeded with '%s'\n", uid); - LOG (" cal_client_get_object... "); - status = cal_client_get_object (ctxt->client, uid, &comp); - } - - if (status != CAL_CLIENT_GET_SUCCESS) { - comp = comp_from_remote_record (conduit, remote, NULL); - } else { - CalComponent *new_comp; - - LOG ("succeeded %s\n", cal_component_get_as_string (comp)); - - new_comp = comp_from_remote_record (conduit, remote, comp); - gtk_object_unref (GTK_OBJECT (comp)); - comp = new_comp; - } + gboolean success; - /* update record on server */ - { - const char *uid; - unsigned long *pilot_id; + g_return_if_fail (conduit != NULL); + g_return_if_fail (comp != NULL); - cal_component_get_uid (comp, &uid); - cal_component_get_pilot_id (comp, &pilot_id); - - update_calendar_entry_in_repository (conduit, comp, ctxt); - cal_client_update_pilot_id (ctxt->client, (char *) uid, - *pilot_id, pilot_status); - } + LOG ("update_comp: saving to desktop\n%s\n", + cal_component_get_as_string (comp)); - /* - * Shutdown - */ - gtk_object_unref (GTK_OBJECT (comp)); - free_ToDo(&todo); + success = cal_client_update_object (ctxt->client, comp); - return 0; + if (!success) + WARN (_("Error while communicating with calendar server")); } static void check_for_slow_setting (GnomePilotConduit *c, EToDoConduitContext *ctxt) { - GList *uids; - unsigned long int entry_number; - - uids = cal_client_get_uids (ctxt->client, CALOBJ_TYPE_TODO); - - entry_number = g_list_length (uids); + int count, map_count; - /* If the local base is empty, do a slow sync */ - if (entry_number == 0) { + count = g_list_length (ctxt->uids); + map_count = g_hash_table_size (ctxt->map); + + /* If there are no objects or objects but no log */ + if ((count == 0) || (count > 0 && map_count == 0)) { GnomePilotConduitStandard *conduit; LOG (" doing slow sync\n"); conduit = GNOME_PILOT_CONDUIT_STANDARD (c); @@ -598,24 +578,21 @@ check_for_slow_setting (GnomePilotConduit *c, EToDoConduitContext *ctxt) } } +/* Pilot syncing callbacks */ static gint -pre_sync (GnomePilotConduit *c, +pre_sync (GnomePilotConduit *conduit, GnomePilotDBInfo *dbi, EToDoConduitContext *ctxt) { - int l; + GnomePilotConduitStandardAbs *abs_conduit; + int len, ret; unsigned char *buf; - GnomePilotConduitStandardAbs *conduit; + char *filename; + xmlSAXHandler handler; + GList *changes, *l; gint num_records; - /* - g_log_set_always_fatal (G_LOG_LEVEL_ERROR | - G_LOG_LEVEL_CRITICAL | - G_LOG_LEVEL_WARNING); - */ - - - conduit = GNOME_PILOT_CONDUIT_STANDARD_ABS(c); + abs_conduit = GNOME_PILOT_CONDUIT_STANDARD_ABS (conduit); LOG ("---------------------------------------------------------\n"); LOG ("pre_sync: ToDo Conduit v.%s", CONDUIT_VERSION); @@ -623,102 +600,174 @@ pre_sync (GnomePilotConduit *c, ctxt->client = NULL; - if (start_calendar_server (GNOME_PILOT_CONDUIT_STANDARD_ABS(c), ctxt) != 0) { - WARN(_("Could not start gnomecal server")); - gnome_pilot_conduit_error(GNOME_PILOT_CONDUIT(c), - _("Could not start gnomecal server")); + if (start_calendar_server (ctxt) != 0) { + WARN(_("Could not start wombat server")); + gnome_pilot_conduit_error (conduit, _("Could not start wombat")); return -1; } - + /* Get the local database */ + ctxt->uids = cal_client_get_uids (ctxt->client, CALOBJ_TYPE_TODO); + + /* Load the uid <--> pilot id mapping */ + ctxt->map = g_hash_table_new (g_int_hash, g_int_equal); + memset (&handler, 0, sizeof (xmlSAXHandler)); + handler.startElement = map_sax_start_element; + + filename = map_name (ctxt); + ret = map_sax_parse (&handler, ctxt, filename); + if (ret < 0) + return ret; + + g_free (filename); + + /* Find the added, modified and deleted items */ + changes = cal_client_get_changed_uids (ctxt->client, CALOBJ_TYPE_TODO, 0); + for (l = changes; l != NULL; l = l->next) { + CalObjChange *coc = l->data; + + switch (coc->type) { + case CALOBJ_UPDATED: + if (g_hash_table_lookup (ctxt->map, coc->uid)) + ctxt->modified = g_list_prepend (ctxt->modified, coc); + else + ctxt->added = g_list_prepend (ctxt->added, coc); + break; + case CALOBJ_REMOVED: + ctxt->deleted = g_list_prepend (ctxt->deleted, coc); + break; + } + } + g_list_free (changes); + + /* Set the count information */ num_records = cal_client_get_n_objects (ctxt->client, CALOBJ_TYPE_TODO); - gnome_pilot_conduit_standard_abs_set_num_local_records(GNOME_PILOT_CONDUIT_STANDARD_ABS(c), num_records); + gnome_pilot_conduit_standard_abs_set_num_local_records(abs_conduit, num_records); + num_records = g_list_length (ctxt->added); + gnome_pilot_conduit_standard_abs_set_num_new_local_records (abs_conduit, num_records); + num_records = g_list_length (ctxt->modified); + gnome_pilot_conduit_standard_abs_set_num_updated_local_records (abs_conduit, num_records); + num_records = g_list_length (ctxt->deleted); + gnome_pilot_conduit_standard_abs_set_num_deleted_local_records(abs_conduit, num_records); - /* FIX ME How are we going to fill in these fields? */ - num_records = 0; - gnome_pilot_conduit_standard_abs_set_num_updated_local_records(GNOME_PILOT_CONDUIT_STANDARD_ABS(c), num_records); - gnome_pilot_conduit_standard_abs_set_num_new_local_records(GNOME_PILOT_CONDUIT_STANDARD_ABS(c), num_records); - gnome_pilot_conduit_standard_abs_set_num_deleted_local_records(GNOME_PILOT_CONDUIT_STANDARD_ABS(c), num_records); + gtk_object_set_data (GTK_OBJECT (conduit), "dbinfo", dbi); - gtk_object_set_data (GTK_OBJECT(c), "dbinfo", dbi); - buf = (unsigned char*)g_malloc (0xffff); - l = dlp_ReadAppBlock (dbi->pilot_socket, dbi->db_handle, 0, + len = dlp_ReadAppBlock (dbi->pilot_socket, dbi->db_handle, 0, (unsigned char *)buf, 0xffff); - if (l < 0) { - WARN(_("Could not read pilot's ToDo application block")); - WARN("dlp_ReadAppBlock(...) = %d",l); - gnome_pilot_conduit_error(GNOME_PILOT_CONDUIT(c), - _("Could not read pilot's ToDo application block")); + if (len < 0) { + WARN (_("Could not read pilot's ToDo application block")); + WARN ("dlp_ReadAppBlock(...) = %d", len); + gnome_pilot_conduit_error (conduit, + _("Could not read pilot's ToDo application block")); return -1; } - unpack_ToDoAppInfo (&(ctxt->ai), buf, l); + unpack_ToDoAppInfo (&(ctxt->ai), buf, len); g_free (buf); - check_for_slow_setting (c, ctxt); + check_for_slow_setting (conduit, ctxt); return 0; } -/** - * Find (if possible) the local record which matches - * the given PilotRecord. - * if successfull, return non-zero and set *local to - * a non-null value (the located local record), - * otherwise return 0 and set *local = NULL; - */ +static gint +update_record (GnomePilotConduitStandardAbs *conduit, + PilotRecord *remote, + EToDoConduitContext *ctxt) +{ + CalComponent *comp; + CalClientGetStatus status; + struct ToDo todo; + const char *uid; + + LOG ("update_record\n"); + + g_return_val_if_fail (remote != NULL, -1); + + memset (&todo, 0, sizeof (struct ToDo)); + unpack_ToDo (&todo, remote->record, remote->length); + + uid = g_hash_table_lookup (ctxt->map, &remote->ID); + + if (uid) + status = cal_client_get_object (ctxt->client, uid, &comp); + else + status = CAL_CLIENT_LOAD_ERROR; + + if (status != CAL_CLIENT_GET_SUCCESS) { + comp = comp_from_remote_record (conduit, remote, NULL); + } else { + CalComponent *new_comp; + + LOG ("succeeded %s\n", cal_component_get_as_string (comp)); + + new_comp = comp_from_remote_record (conduit, remote, comp); + gtk_object_unref (GTK_OBJECT (comp)); + comp = new_comp; + } + + update_comp (conduit, comp, ctxt); + + if (!uid) { + guint32 *pid = g_new (guint32, 1); + + *pid = remote->ID; + cal_component_get_uid (comp, &uid); + g_hash_table_insert (ctxt->map, pid, g_strdup (uid)); + } + + gtk_object_unref (GTK_OBJECT (comp)); + free_ToDo(&todo); + + return 0; +} static gint -match_record (GnomePilotConduitStandardAbs *conduit, - EToDoLocalRecord **local, - PilotRecord *remote, - EToDoConduitContext *ctxt) +match_record (GnomePilotConduitStandardAbs *conduit, + EToDoLocalRecord **local, + PilotRecord *remote, + EToDoConduitContext *ctxt) { + char *uid; + LOG ("match_record: looking for local copy of %s\n", - print_remote (remote)); - + print_remote (remote)); + g_return_val_if_fail (local != NULL, -1); g_return_val_if_fail (remote != NULL, -1); - *local = find_record_in_repository (conduit, remote, ctxt); + uid = g_hash_table_lookup (ctxt->map, &remote->ID); + + if (!uid) + return -1; + *local = g_new0 (EToDoLocalRecord, 1); + local_record_from_uid (*local, uid, ctxt); + if (*local == NULL) - LOG (" match_record: not found.\n"); - else - LOG (" match_record: found, %s\n", - print_local (*local)); - - if (*local == NULL) return -1; - + return 0; } -/** - * Free the data allocated by a previous match_record call. - * If successfull, return non-zero and ser *local=NULL, otherwise - * return 0. - */ static gint -free_match (GnomePilotConduitStandardAbs *conduit, - EToDoLocalRecord **local, - EToDoConduitContext *ctxt) +free_match (GnomePilotConduitStandardAbs *conduit, + EToDoLocalRecord **local, + EToDoConduitContext *ctxt) { LOG ("free_match: %s\n", print_local (*local)); g_return_val_if_fail (local != NULL, -1); g_return_val_if_fail (*local != NULL, -1); + gtk_object_unref (GTK_OBJECT ((*local)->comp)); g_free (*local); *local = NULL; return 0; } -/* - Move to archive and set status to Nothing - */ static gint archive_local (GnomePilotConduitStandardAbs *conduit, EToDoLocalRecord *local, @@ -731,9 +780,6 @@ archive_local (GnomePilotConduitStandardAbs *conduit, return -1; } -/* - Store in archive and set status to Nothing - */ static gint archive_remote (GnomePilotConduitStandardAbs *conduit, EToDoLocalRecord *local, @@ -741,30 +787,29 @@ archive_remote (GnomePilotConduitStandardAbs *conduit, EToDoConduitContext *ctxt) { LOG ("archive_remote: doing nothing with %s\n", - print_local (local)); - -/* g_return_val_if_fail(remote!=NULL,-1); */ -/* g_return_val_if_fail(local!=NULL,-1); */ - + print_local (local)); + + g_return_val_if_fail (remote != NULL, -1); + g_return_val_if_fail (local != NULL, -1); + return -1; } -/* - Store and set status to Nothing - */ static gint store_remote (GnomePilotConduitStandardAbs *conduit, PilotRecord *remote, EToDoConduitContext *ctxt) { + int ret; + g_return_val_if_fail (remote != NULL, -1); LOG ("store_remote: copying pilot record %s to desktop\n", print_remote (remote)); - remote->attr = GnomePilotRecordNothing; + ret = update_record (conduit, remote, ctxt); - return update_record (conduit, remote, ctxt); + return ret; } static gint @@ -784,59 +829,48 @@ iterate (GnomePilotConduitStandardAbs *conduit, EToDoLocalRecord **local, EToDoConduitContext *ctxt) { - static GSList *events,*iterator; - static int hest; + static GList *uids, *iterator; + static int count; g_return_val_if_fail (local != NULL, -1); if (*local == NULL) { LOG ("beginning iteration"); - events = get_calendar_objects (conduit, NULL, ctxt); - hest = 0; + uids = ctxt->uids; + count = 0; - if (events != NULL) { - LOG ("iterating over %d records", g_slist_length (events)); + if (uids != NULL) { + LOG ("iterating over %d records", g_list_length (uids)); + *local = g_new0 (EToDoLocalRecord, 1); + local_record_from_uid (*local, uids->data, ctxt); - local_record_from_comp_uid (*local, - (gchar*)events->data, - ctxt); - iterator = events; + iterator = uids; } else { LOG ("no events"); (*local) = NULL; + return -1; } } else { - LOG ("continuing iteration\n"); - hest++; - if (g_slist_next (iterator) == NULL) { - GSList *l; + count++; + if (g_list_next (iterator)) { + iterator = g_list_next (iterator); - LOG ("ending"); - /** free stuff allocated for iteration */ - g_free((*local)); - - LOG ("iterated over %d records", hest); - for (l=events; l; l = l->next) - g_free (l->data); + *local = g_new0 (EToDoLocalRecord, 1); + local_record_from_uid (*local, iterator->data, ctxt); + } else { + LOG ("iteration ending"); - g_slist_free (events); + /* Tell the pilot the iteration is over */ + *local = NULL; - /* ends iteration */ - (*local) = NULL; return 0; - } else { - iterator = g_slist_next (iterator); - local_record_from_comp_uid(*local, - (gchar*)(iterator->data), - ctxt); } } return 1; } - static gint iterate_specific (GnomePilotConduitStandardAbs *conduit, EToDoLocalRecord **local, @@ -844,44 +878,88 @@ iterate_specific (GnomePilotConduitStandardAbs *conduit, gint archived, EToDoConduitContext *ctxt) { - (*local) = NULL; /* ??? */ + static GList *changes, *iterator; + static int count; - /* debugging */ - { - const char *tmp = gnome_pilot_status_to_string (flag); - LOG ("\niterate_specific: (flag = %s)... ", tmp); - } + g_return_val_if_fail (local != NULL, 0); - g_return_val_if_fail (local != NULL, -1); + /* FIX ME Hack - gnome-pilot does not recognize iterate_specific err values */ + if (*local == NULL) { + LOG ("beginning iteration for %s\n", status_to_string (flag)); - /* iterate until a record meets the criteria */ - while (gnome_pilot_conduit_standard_abs_iterate (conduit, - (LocalRecord**)local)) { - if ((*local) == NULL) + switch (flag) { + case GnomePilotRecordNew: + changes = ctxt->added; break; - if (archived && ((*local)->local.archived == archived)) + case GnomePilotRecordModified: + changes = ctxt->modified; break; - if (((*local)->local.attr == flag)) + case GnomePilotRecordDeleted: + changes = ctxt->deleted; break; - } + } + + count = 0; + + if (changes != NULL) { + CalObjChange *coc = changes->data; + + LOG ("iterating over %d records", g_list_length (changes)); + + *local = g_new0 (EToDoLocalRecord, 1); + local_record_from_uid (*local, coc->uid, ctxt); - if ((*local)) - LOG (" found %s\n", print_local (*local)); - else - LOG (" no more found.\n"); + iterator = changes; + } else { + LOG ("no events"); + (*local) = NULL; + return 0; + } + } else { + count++; + if (g_list_next (iterator)) { + CalObjChange *coc; + + iterator = g_list_next (iterator); + coc = iterator->data; + + *local = g_new0 (EToDoLocalRecord, 1); + local_record_from_uid (*local, coc->uid, ctxt); + } else { + LOG ("iteration ending"); - return (*local) == NULL ? 0 : 1; + /* Tell the pilot the iteration is over */ + (*local) = NULL; + + return 0; + } + } + + return 1; } static gint purge (GnomePilotConduitStandardAbs *conduit, EToDoConduitContext *ctxt) { - LOG ("purge: doing nothing\n"); + GList *l; + char *filename; + int ret = 0; + + LOG ("purge\n"); + + /* FIX ME report an error */ + for (l = ctxt->deleted; l != NULL; l = l->next) { + CalObjChange *coc = l->data; + + cal_client_remove_object (ctxt->client, coc->uid); + } - /* HEST, gem posterne her */ + filename = map_name (ctxt); + ret = map_write (ctxt, filename); + g_free (filename); - return -1; + return ret; } @@ -891,37 +969,28 @@ set_status (GnomePilotConduitStandardAbs *conduit, gint status, EToDoConduitContext *ctxt) { - gboolean success; - - LOG ("set_status: %s status is now '%s' for %s\n", - print_local (local), - gnome_pilot_status_to_string (status), - cal_component_get_as_string (local->comp)); + CalObjChange *coc; g_return_val_if_fail (local != NULL, -1); g_assert (local->comp != NULL); - - local->local.attr = status; - if (status == GnomePilotRecordDeleted) { - const char *uid; - cal_component_get_uid (local->comp, &uid); - success = cal_client_remove_object (ctxt->client, uid); - } else { - const char *uid; - unsigned long *pilot_id; - cal_component_get_uid (local->comp, &uid); - cal_component_get_pilot_id (local->comp, &pilot_id); + LOG ("set_status: %s status is now '%s' for %s\n", + print_local (local), + status_to_string (status), + cal_component_get_as_string (local->comp)); - success = cal_client_update_object (ctxt->client, local->comp); - cal_client_update_pilot_id (ctxt->client, (char *) uid, - *pilot_id, status); + /* FIX ME New and modified? */ + switch (status) { + case GnomePilotRecordNew: + break; + case GnomePilotRecordModified: + break; + case GnomePilotRecordDeleted: + coc = g_new0 (CalObjChange, 1); + ctxt->deleted = g_list_prepend (ctxt->deleted, coc); + break; } - if (!success) { - WARN (_("Error while communicating with calendar server")); - } - return 0; } @@ -938,10 +1007,12 @@ set_archived (GnomePilotConduitStandardAbs *conduit, g_assert(local->comp!=NULL); local->local.archived = archived; - update_calendar_entry_in_repository(conduit,local->comp,ctxt); + update_comp (conduit, local->comp, ctxt); + /* FIXME: This should move the entry into a speciel calendar file, eg. Archive, or (by config option), simply delete it */ + return 0; } @@ -952,24 +1023,11 @@ set_pilot_id (GnomePilotConduitStandardAbs *conduit, EToDoConduitContext *ctxt) { const char *uid; - unsigned long *pilot_status; - - LOG ("set_pilot_id: %s pilot ID is now '%d'\n", - print_local (local), ID); - - g_return_val_if_fail(local!=NULL,-1); - g_assert(local->comp!=NULL); - - local->local.ID = ID; - cal_component_set_pilot_id (local->comp, (unsigned long *)&ID); - + guint32 *pid = g_new (guint32, 1); + cal_component_get_uid (local->comp, &uid); - cal_component_get_pilot_status (local->comp, &pilot_status); - - cal_client_update_pilot_id (ctxt->client, - (char *) uid, - local->local.ID, - *pilot_status); + *pid = ID; + g_hash_table_insert (ctxt->map, pid, g_strdup (uid)); return 0; } @@ -980,80 +1038,13 @@ transmit (GnomePilotConduitStandardAbs *conduit, PilotRecord **remote, EToDoConduitContext *ctxt) { - PilotRecord *p; - int *priority; - struct icaltimetype *completed; - CalComponentText summary; - GSList *d_list = NULL; - CalComponentText *description; - CalComponentDateTime due; - time_t due_time; - CalComponentClassification classif; - LOG ("transmit: encoding local %s\n", print_local (local)); - g_return_val_if_fail (local != NULL,-1); - g_return_val_if_fail (remote != NULL,-1); - g_assert (local->comp != NULL); - - p = g_new0 (PilotRecord,1); - - p->ID = local->local.ID; - p->attr = local->local.attr; - p->archived = local->local.archived; - p->secret = local->local.secret; - - local->todo = g_new0 (struct ToDo,1); - - /* STOP: don't replace these with g_strdup, since free_ToDo - uses free to deallocate */ - cal_component_get_summary (local->comp, &summary); - if (summary.value) - local->todo->description = strdup ((char *) summary.value); - - cal_component_get_description_list (local->comp, &d_list); - if (d_list) { - description = (CalComponentText *) d_list->data; - if (description && description->value) - local->todo->note = strdup (description->value); - else - local->todo->note = NULL; - } else { - local->todo->note = NULL; - } - - cal_component_get_due (local->comp, &due); - if (due.value) { - due_time = icaltime_as_timet (*due.value); - - local->todo->due = *localtime (&due_time); - local->todo->indefinite = 0; - } else { - local->todo->indefinite = 1; - } - - cal_component_get_completed (local->comp, &completed); - if (completed) { - local->todo->complete = 1; - cal_component_free_icaltimetype (completed); - } - - cal_component_get_priority (local->comp, &priority); - if (priority) { - local->todo->priority = *priority; - cal_component_free_priority (priority); - } - - cal_component_get_classification (local->comp, &classif); - if (classif == CAL_COMPONENT_CLASS_PRIVATE) - p->attr = p->attr & dlpRecAttrSecret; - - /* Generate pilot record structure */ - p->record = g_new0 (char,0xffff); - p->length = pack_ToDo (local->todo, p->record, 0xffff); - - *remote = p; + *remote = local_record_to_pilot_record (local, ctxt); + if (!*remote) + return -1; + return 0; } @@ -1063,14 +1054,12 @@ free_transmit (GnomePilotConduitStandardAbs *conduit, PilotRecord **remote, EToDoConduitContext *ctxt) { - LOG ("free_transmit: freeing %s\n", - print_local (local)); + LOG ("free_transmit: freeing %s\n", print_local (local)); g_return_val_if_fail (local != NULL, -1); g_return_val_if_fail (remote != NULL, -1); - /* free_ToDo(local->todo); */ /* FIX ME is this needed? */ - g_free ((*remote)->record); + g_free (*remote); *remote = NULL; return 0; @@ -1084,9 +1073,8 @@ compare (GnomePilotConduitStandardAbs *conduit, EToDoConduitContext *ctxt) { /* used by the quick compare */ - PilotRecord *remoteOfLocal; - int err; - int retval; + PilotRecord *local_pilot; + int retval = 0; LOG ("compare: local=%s remote=%s...\n", print_local (local), print_remote (remote)); @@ -1094,31 +1082,21 @@ compare (GnomePilotConduitStandardAbs *conduit, g_return_val_if_fail (local!=NULL,-1); g_return_val_if_fail (remote!=NULL,-1); - err = transmit(conduit,local,&remoteOfLocal,ctxt); - if (err != 0) return err; + local_pilot = local_record_to_pilot_record (local, ctxt); + if (!local_pilot) + return -1; - retval = 0; - if (remote->length == remoteOfLocal->length) { - if (memcmp (remoteOfLocal->record, - remote->record, remote->length)!=0) { - LOG (" compare failed on contents\n"); - retval = 1; - } - } else { - LOG(" compare failed on length\n"); + if (remote->length != local_pilot->length + || memcmp (local_pilot->record, remote->record, remote->length)) retval = 1; - } - - if (retval == 0) { + if (retval == 0) LOG (" match.\n"); - } else { - /* debug spew */ - LOG (" local:%s\n", print_remote (remoteOfLocal)); - LOG (" remote:%s\n", print_remote (remote)); - } - - free_transmit(conduit,local,&remoteOfLocal,ctxt); + else + LOG (" did not match"); + + g_free (local_pilot); + return retval; } @@ -1134,6 +1112,8 @@ compare_backup (GnomePilotConduitStandardAbs *conduit, g_return_val_if_fail(local!=NULL,-1); g_return_val_if_fail(remote!=NULL,-1); + /* FIX ME - What the hell? */ + return -1; } @@ -1142,25 +1122,21 @@ static gint delete_all (GnomePilotConduitStandardAbs *conduit, EToDoConduitContext *ctxt) { - GSList *events,*it; - gboolean error; + GList *uids, *it; gboolean success; - events = get_calendar_objects(conduit,&error,ctxt); - LOG ("delete_all: deleting all objects from desktop\n"); - if (error == FALSE) return -1; - for (it=events; it; it = g_slist_next (it)) { + uids = cal_client_get_uids (ctxt->client, CALOBJ_TYPE_TODO); + + for (it = uids; it != NULL; it = g_list_next (it)) { success = cal_client_remove_object (ctxt->client, it->data); if (!success) INFO ("Object did not exist"); - - g_free (it->data); } + cal_obj_uid_list_free (uids); - g_slist_free (events); return 0; } @@ -1176,7 +1152,7 @@ accept_all_cookies (CORBA_unsigned_long request_id, GnomePilotConduit * -conduit_get_gpilot_conduit (guint32 pilotId) +conduit_get_gpilot_conduit (guint32 pilot_id) { GtkObject *retval; EToDoConduitContext *ctxt; @@ -1202,9 +1178,9 @@ conduit_get_gpilot_conduit (guint32 pilotId) g_assert (retval != NULL); gnome_pilot_conduit_construct (GNOME_PILOT_CONDUIT (retval), - "ToDoConduit"); + "e_todo_conduit"); - e_todo_context_new (&ctxt, pilotId); + e_todo_context_new (&ctxt, pilot_id); gtk_object_set_data (GTK_OBJECT (retval), "todoconduit_context", ctxt); gtk_signal_connect (retval, "match_record", (GtkSignalFunc) match_record, ctxt); diff --git a/calendar/conduits/todo/todo-conduit.h b/calendar/conduits/todo/todo-conduit.h index ee2576ddb7..9e9a02e6db 100644 --- a/calendar/conduits/todo/todo-conduit.h +++ b/calendar/conduits/todo/todo-conduit.h @@ -54,16 +54,28 @@ struct _EToDoLocalRecord { /* This is the context for all the GnomeCal conduit methods. */ typedef struct _EToDoConduitContext EToDoConduitContext; struct _EToDoConduitContext { - struct ToDoAppInfo ai; EToDoConduitCfg *cfg; - CalClient *client; + struct ToDoAppInfo ai; + + CalClient *client; + char *calendar_file; gboolean calendar_load_tried; gboolean calendar_load_success; - char *calendar_file; + GList *uids; + + GList *added; + GList *modified; + GList *deleted; + + GHashTable *map; }; #endif __TODO_CONDUIT_H__ + + + + |