OpenSync  0.22
opensync_hashtable.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 
33 
34 static void osync_hashtable_assert_loaded(OSyncHashTable *table)
35 {
36  osync_assert_msg(table, "You have to pass a valid hashtable to the call!");
37  osync_assert_msg(table->dbhandle, "Hashtable not loaded yet. You have to load the hashtable first using osync_hashtable_load!");
38 }
39 
84 
94 {
95  OSyncHashTable *table = g_malloc0(sizeof(OSyncHashTable));
96  g_assert(table);
97  table->used_entries = g_hash_table_new(g_str_hash, g_str_equal);
98  return table;
99 }
100 
108 {
109  g_hash_table_destroy(table->used_entries);
110  g_free(table);
111 }
112 
125 {
126  g_hash_table_destroy(table->used_entries);
127  table->used_entries = g_hash_table_new(g_str_hash, g_str_equal);
128 }
129 
138 osync_bool osync_hashtable_load(OSyncHashTable *table, OSyncMember *member, OSyncError **error)
139 {
140  return osync_db_open_hashtable(table, member, error);
141 }
142 
151 {
152  osync_hashtable_assert_loaded(table);
153 
154  osync_hashtable_forget(table);
155  osync_db_close(table->dbhandle);
156 }
157 
165 {
166  osync_hashtable_assert_loaded(table);
167 
168  return osync_db_count(table->dbhandle, "SELECT count(*) FROM tbl_hash");
169 }
170 
182 osync_bool osync_hashtable_nth_entry(OSyncHashTable *table, int i, char **uid, char **hash)
183 {
184  osync_hashtable_assert_loaded(table);
185 
186  sqlite3 *sdb = table->dbhandle->db;
187 
188  sqlite3_stmt *ppStmt = NULL;
189  char *query = g_strdup_printf("SELECT uid, hash FROM tbl_hash LIMIT 1 OFFSET %i", i);
190  sqlite3_prepare(sdb, query, -1, &ppStmt, NULL);
191  sqlite3_step(ppStmt);
192  *uid = g_strdup((gchar*)sqlite3_column_text(ppStmt, 0));
193  *hash = g_strdup((gchar*)sqlite3_column_text(ppStmt, 1));
194  sqlite3_finalize(ppStmt);
195  g_free(query);
196  return TRUE;
197 }
198 
209 {
210  osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, table, change);
211  osync_hashtable_assert_loaded(table);
212  osync_assert_msg(change, "Change was NULL. Bug in a plugin");
213  osync_assert_msg(change->uid, "No uid was set on change. Bug in a plugin");
214 
215  osync_trace(TRACE_INTERNAL, "Updating hashtable with hash \"%s\" and changetype %i",
216  change->hash, osync_change_get_changetype(change));
217 
218  switch (osync_change_get_changetype(change)) {
219  case CHANGE_MODIFIED:
220  case CHANGE_ADDED:
221  osync_db_save_hash(table, change->uid, change->hash,
222  osync_change_get_objtype(change) ? osync_change_get_objtype(change)->name : NULL);
223  break;
224  case CHANGE_DELETED:
225  osync_db_delete_hash(table, change->uid);
226  break;
227  default:
228  g_assert_not_reached();
229  }
230 
231  osync_trace(TRACE_EXIT, "%s", __func__);
232 }
233 
244 void osync_hashtable_report(OSyncHashTable *table, const char *uid)
245 {
246  osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, table, uid);
247  osync_hashtable_assert_loaded(table);
248 
249  g_hash_table_insert(table->used_entries, g_strdup(uid), GINT_TO_POINTER(1));
250 
251  osync_trace(TRACE_EXIT, "%s", __func__);
252 }
253 
261 void osync_hashtable_report_deleted(OSyncHashTable *table, OSyncContext *context, const char *objtype)
262 {
263  osync_trace(TRACE_ENTRY, "%s(%p, %p, %s)", __func__, table, context, objtype);
264  osync_hashtable_assert_loaded(table);
265 
266  char **uidarr = osync_db_get_deleted_hash(table, objtype);
267  int i = 0;
268  for (i = 0; uidarr[i]; i++) {
269  char *uid = uidarr[i];
270  OSyncChange *change = osync_change_new();
271  change->changetype = CHANGE_DELETED;
272  osync_change_set_objtype_string(change, objtype);
273  osync_change_set_uid(change, uid);
274  osync_context_report_change(context, change);
275  osync_hashtable_update_hash(table, change);
276  g_free(uid);
277  }
278  g_free(uidarr);
279 
280  osync_trace(TRACE_EXIT, "%s", __func__);
281 }
282 
290 char **osync_hashtable_get_deleted(OSyncHashTable *table, const char *objtype)
291 {
292  osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, table, objtype);
293  osync_hashtable_assert_loaded(table);
294 
295  char **retarr = osync_db_get_deleted_hash(table, objtype);
296  osync_trace(TRACE_EXIT, "%s: %p", __func__, retarr);
297  return retarr;
298 }
299 
304 {
305  char *orighash = NULL;
306  osync_db_get_hash(table, chg->uid, osync_change_get_objtype(chg)->name, &orighash);
307  osync_change_set_hash(chg, orighash);
308  g_free(orighash);
309 }
310 
323 OSyncChangeType osync_hashtable_get_changetype(OSyncHashTable *table, const char *uid, const char *objtype, const char *hash)
324 {
325  osync_trace(TRACE_ENTRY, "%s(%p, %s, %s, %s)", __func__, table, uid, objtype, hash);
326  osync_hashtable_assert_loaded(table);
328 
329  char *orighash = NULL;
330  osync_db_get_hash(table, uid, objtype, &orighash);
331  osync_trace(TRACE_INTERNAL, "Comparing %s with %s", hash, orighash);
332 
333  if (orighash) {
334  if (strcmp(hash, orighash) == 0)
335  retval = CHANGE_UNMODIFIED;
336  else
337  retval = CHANGE_MODIFIED;
338  } else
339  retval = CHANGE_ADDED;
340 
341  osync_trace(TRACE_EXIT, "%s: %s", __func__, retval ? "TRUE" : "FALSE");
342  return retval;
343 }
344 
355 {
356  osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, table, change);
357  osync_bool retval = FALSE;
358 
360  if (change->changetype != CHANGE_UNMODIFIED)
361  retval = TRUE;
362 
363  g_hash_table_insert(table->used_entries, g_strdup(change->uid), GINT_TO_POINTER(1));
364  osync_trace(TRACE_EXIT, "%s: %s", __func__, retval ? "TRUE" : "FALSE");
365  return retval;
366 }
367 
373 void osync_hashtable_set_slow_sync(OSyncHashTable *table, const char *objtype)
374 {
375  osync_hashtable_assert_loaded(table);
376 
377  osync_db_reset_hash(table, objtype);
378 }
379