OpenSync  0.22
opensync_db.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 
24 void osync_db_trace(void *data, const char *query)
25 {
26  osync_trace(TRACE_INTERNAL, "query executed: %s", query);
27 }
28 
29 OSyncDB *osync_db_open(char *filename, OSyncError **error)
30 {
31  osync_trace(TRACE_ENTRY, "%s(%s, %p)", __func__, filename, error);
32 
33  OSyncDB *db = osync_try_malloc0(sizeof(OSyncDB), error);
34  if (!db)
35  goto error;
36 
37  int rc = sqlite3_open(filename, &(db->db));
38  if (rc) {
39  osync_error_set(error, OSYNC_ERROR_GENERIC, "Cannot open database: %s", sqlite3_errmsg(db->db));
40  goto error_close;
41  }
42  sqlite3_trace(db->db, osync_db_trace, NULL);
43 
44  osync_trace(TRACE_EXIT, "%s: %p", __func__, db);
45  return db;
46 
47 error_close:
48  osync_db_close(db);
49 //error_free:
50  g_free(db);
51 error:
52  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
53  return NULL;
54 }
55 
56 void osync_db_close(OSyncDB *db)
57 {
58  osync_trace(TRACE_ENTRY, "%s(%p)", __func__, db);
59 
60  int ret = sqlite3_close(db->db);
61  if (ret != SQLITE_OK)
62  osync_trace(TRACE_INTERNAL, "Can't close database: %s", sqlite3_errmsg(db->db));
63 
64  osync_trace(TRACE_EXIT, "%s", __func__);
65 }
66 
67 int osync_db_count(OSyncDB *db, char *query)
68 {
69  int ret = 0;
70 
71  sqlite3_stmt *ppStmt = NULL;
72  if (sqlite3_prepare(db->db, query, -1, &ppStmt, NULL) != SQLITE_OK)
73  osync_debug("OSDB", 3, "Unable prepare count! %s", sqlite3_errmsg(db->db));
74  ret = sqlite3_step(ppStmt);
75  if (ret != SQLITE_DONE && ret != SQLITE_ROW)
76  osync_debug("OSDB", 3, "Unable step count! %s", sqlite3_errmsg(db->db));
77  if (ret == SQLITE_DONE)
78  osync_debug("OSDB", 3, "No row found!");
79  ret = sqlite3_column_int64(ppStmt, 0);
80  sqlite3_finalize(ppStmt);
81  return ret;
82 }
83 
84 OSyncDB *_open_changelog(OSyncGroup *group, OSyncError **error)
85 {
86  g_assert(group);
87  OSyncDB *log_db;
88 
89  char *filename = g_strdup_printf("%s/changelog.db", group->configdir);
90  if (!(log_db = osync_db_open(filename, error))) {
91  osync_error_update(error, "Unable to load changelog: %s", osync_error_print(error));
92  g_free(filename);
93  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
94  return NULL;
95  }
96  osync_debug("OSDB", 3, "Preparing to changelog from file %s", filename);
97  g_free(filename);
98 
99  sqlite3 *sdb = log_db->db;
100 
101  if (sqlite3_exec(sdb, "CREATE TABLE tbl_log (uid VARCHAR, objtype VARCHAR, memberid INTEGER, changetype INTEGER)", NULL, NULL, NULL) != SQLITE_OK)
102  osync_debug("OSDB", 2, "Unable create log table! %s", sqlite3_errmsg(sdb));
103  return log_db;
104 }
105 
106 osync_bool osync_db_open_changelog(OSyncGroup *group, char ***uids, char ***objtype, long long int **memberids, int **changetypes, OSyncError **error)
107 {
108  osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, group, uids, changetypes, error);
109 
110  OSyncDB *log_db = _open_changelog(group, error);
111  if (!log_db) {
112  goto error;
113  }
114  sqlite3 *sdb = log_db->db;
115 
116  int count = osync_db_count(log_db, "SELECT count(*) FROM tbl_log");
117 
118  *uids = g_malloc0(sizeof(char *) * (count + 1));
119  *objtype = g_malloc0(sizeof(char *) * (count + 1));
120  *memberids = g_malloc0(sizeof(long long int) * (count + 1));
121  *changetypes = g_malloc0(sizeof(int) * (count + 1));
122 
123  sqlite3_stmt *ppStmt = NULL;
124  sqlite3_prepare(sdb, "SELECT uid, objtype, memberid, changetype FROM tbl_log", -1, &ppStmt, NULL);
125  int i = 0;
126  while (sqlite3_step(ppStmt) == SQLITE_ROW) {
127  (*uids)[i] = g_strdup((gchar*)sqlite3_column_text(ppStmt, 0));
128  (*objtype)[i] = g_strdup((gchar*)sqlite3_column_text(ppStmt, 1));
129  (*memberids)[i] = sqlite3_column_int64(ppStmt, 2);
130  (*changetypes)[i] = sqlite3_column_int(ppStmt, 3);
131  i++;
132  }
133  (*uids)[i] = NULL;
134  (*objtype)[i] = NULL;
135  (*memberids)[i] = 0;
136  (*changetypes)[i] = 0;
137  sqlite3_finalize(ppStmt);
138 
139  char *query = g_strdup_printf("DELETE FROM tbl_log");
140  if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
141  osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to remove all logs! %s", sqlite3_errmsg(sdb));
142  g_free(query);
143  goto error_db_close;
144  }
145  g_free(query);
146 
147  osync_db_close(log_db);
148  osync_trace(TRACE_EXIT, "%s", __func__);
149  return TRUE;
150 
151 error_db_close:
152  osync_db_close(log_db);
153 
154 error:
155  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
156  return FALSE;
157 }
158 
159 osync_bool osync_db_save_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error)
160 {
161  osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, group, change, error);
162 
163  OSyncDB *log_db = _open_changelog(group, error);
164  if (!log_db) {
165  goto error;
166  }
167  sqlite3 *sdb = log_db->db;
168 
169  char *escaped_uid = osync_db_sql_escape(change->uid);
170  char *query = g_strdup_printf("INSERT INTO tbl_log (uid, objtype, memberid, changetype) VALUES('%s', '%s', '%lli', '%i')", escaped_uid, osync_change_get_objtype(change)->name, change->member->id, change->changetype);
171  g_free(escaped_uid);
172 
173  if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
174  osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to insert log! %s", sqlite3_errmsg(sdb));
175  g_free(query);
176  goto error_db_close;
177  }
178  g_free(query);
179 
180  osync_db_close(log_db);
181  osync_trace(TRACE_EXIT, "%s", __func__);
182  return TRUE;
183 
184 error_db_close:
185  osync_db_close(log_db);
186 
187 error:
188  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
189  return FALSE;
190 
191 }
192 
193 osync_bool osync_db_remove_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error)
194 {
195  osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, group, change, error);
196 
197  OSyncDB *log_db = _open_changelog(group, error);
198  if (!log_db) {
199  goto error;
200  }
201  sqlite3 *sdb = log_db->db;
202 
203  char *escaped_uid = osync_db_sql_escape(change->uid);
204  char *query = g_strdup_printf("DELETE FROM tbl_log WHERE uid='%s' AND memberid='%lli' AND objtype='%s'",
205  escaped_uid, change->member->id, osync_change_get_objtype(change)->name);
206  g_free(escaped_uid);
207 
208  if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
209  osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to remove log! %s", sqlite3_errmsg(sdb));
210  g_free(query);
211  goto error_db_close;
212  }
213  g_free(query);
214 
215  osync_db_close(log_db);
216  osync_trace(TRACE_EXIT, "%s", __func__);
217  return TRUE;
218 
219 error_db_close:
220  osync_db_close(log_db);
221 
222 error:
223  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
224  return FALSE;
225 }
226 
227 osync_bool osync_db_open_changes(OSyncGroup *group, OSyncChange ***changes, OSyncError **error)
228 {
229  osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, group, changes, error);
230  g_assert(group);
231 
232  group->changes_path = g_strdup(group->configdir);
233  char *filename = g_strdup_printf("%s/change.db", group->changes_path);
234  if (!(group->changes_db = osync_db_open(filename, error))) {
235  osync_error_update(error, "Unable to load changes: %s", osync_error_print(error));
236  goto error;
237  }
238  osync_debug("OSDB", 3, "Preparing to load changes from file %s", filename);
239  g_free(filename);
240 
241  sqlite3 *sdb = group->changes_db->db;
242 
243  if (sqlite3_exec(sdb, "CREATE TABLE tbl_changes (id INTEGER PRIMARY KEY, uid VARCHAR, objtype VARCHAR, format VARCHAR, memberid INTEGER, mappingid INTEGER)", NULL, NULL, NULL) != SQLITE_OK)
244  osync_debug("OSDB", 2, "Unable create changes table! %s", sqlite3_errmsg(sdb));
245 
246  int count = osync_db_count(group->changes_db, "SELECT count(*) FROM tbl_changes");
247  *changes = g_malloc0(sizeof(OSyncChange *) * (count + 1));
248 
249  sqlite3_stmt *ppStmt = NULL;
250  sqlite3_prepare(sdb, "SELECT id, uid, objtype, format, memberid, mappingid FROM tbl_changes ORDER BY mappingid", -1, &ppStmt, NULL);
251  int i = 0;
252  while (sqlite3_step(ppStmt) == SQLITE_ROW) {
253  OSyncChange *change = osync_change_new();
254  change->id = sqlite3_column_int64(ppStmt, 0);
255  change->uid = g_strdup((gchar*)sqlite3_column_text(ppStmt, 1));
256  change->objtype_name = g_strdup((gchar*)sqlite3_column_text(ppStmt, 2));
257  change->format_name = g_strdup((gchar*)sqlite3_column_text(ppStmt, 3));
258  change->initial_format_name = g_strdup(change->format_name);
259  change->mappingid = sqlite3_column_int64(ppStmt, 5);
260  long long int memberid = sqlite3_column_int64(ppStmt, 4);
261  change->changes_db = group->changes_db;
262  osync_change_set_member(change, osync_member_from_id(group, memberid));
263  osync_trace(TRACE_INTERNAL, "Loaded change with uid %s, changetype %i, data %p, size %i, objtype %s and format %s from member %lli", osync_change_get_uid(change), osync_change_get_changetype(change), osync_change_get_data(change), osync_change_get_datasize(change), osync_change_get_objtype(change) ? osync_objtype_get_name(osync_change_get_objtype(change)) : "None", osync_change_get_objformat(change) ? osync_objformat_get_name(osync_change_get_objformat(change)) : "None", memberid);
264  (*changes)[i] = change;
265  i++;
266  }
267  (*changes)[i] = NULL;
268  sqlite3_finalize(ppStmt);
269 
270  osync_trace(TRACE_EXIT, "%s", __func__);
271  return TRUE;
272 
273 error:
274  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
275  return FALSE;
276 }
277 
278 osync_bool osync_db_save_change(OSyncChange *change, osync_bool save_format, OSyncError **error)
279 {
280  osync_trace(TRACE_ENTRY, "%s(%p, %i, %p) (Table: %p)", __func__, change, save_format, error, change->changes_db);
281  osync_assert_msg(change, "Need to set change");
282  osync_assert_msg(osync_change_get_objtype(change), "change->objtype was NULL while saving");
283  osync_assert_msg(osync_change_get_objformat(change), "change->objformat was NULL while saving");
284 
285  if (!change || !change->changes_db) {
286  osync_error_set(error, OSYNC_ERROR_PARAMETER, "osync_db_save_change was called with wrong parameters");
287  goto error;
288  }
289  sqlite3 *sdb = change->changes_db->db;
290 
291  char *query = NULL;
292  if (!change->id) {
293  char *escaped_uid = osync_db_sql_escape(change->uid);
294  query = g_strdup_printf("INSERT INTO tbl_changes (uid, objtype, format, memberid, mappingid) VALUES('%s', '%s', '%s', '%lli', '%lli')", escaped_uid, osync_change_get_objtype(change)->name, osync_change_get_objformat(change)->name, change->member->id, change->mappingid);
295  g_free(escaped_uid);
296 
297  if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
298  osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to insert change! %s", sqlite3_errmsg(sdb));
299  g_free(query);
300  goto error;
301  }
302  change->id = sqlite3_last_insert_rowid(sdb);
303  } else {
304  char *escaped_uid = osync_db_sql_escape(change->uid);
305  if (save_format)
306  query = g_strdup_printf("UPDATE tbl_changes SET uid='%s', objtype='%s', format='%s', memberid='%lli', mappingid='%lli' WHERE id=%lli", escaped_uid, osync_change_get_objtype(change)->name, osync_change_get_objformat(change)->name, change->member->id, change->mappingid, change->id);
307  else
308  query = g_strdup_printf("UPDATE tbl_changes SET uid='%s', memberid='%lli', mappingid='%lli' WHERE id=%lli", escaped_uid, change->member->id, change->mappingid, change->id);
309  g_free(escaped_uid);
310 
311  if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
312  osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to update change! %s", sqlite3_errmsg(sdb));
313  g_free(query);
314  goto error;
315  }
316  }
317  g_free(query);
318  osync_trace(TRACE_EXIT, "%s", __func__);
319  return TRUE;
320 
321 error:
322  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
323  return FALSE;
324 
325 }
326 
327 osync_bool osync_db_delete_change(OSyncChange *change, OSyncError **error)
328 {
329  osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, change, error);
330 
331  if (!change || !change->changes_db) {
332  osync_error_set(error, OSYNC_ERROR_PARAMETER, "osync_db_delete_change was called with wrong parameters");
333  goto error;
334  }
335  sqlite3 *sdb = change->changes_db->db;
336 
337  char *query = g_strdup_printf("DELETE FROM tbl_changes WHERE id=%lli", change->id);
338  if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
339  osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to delete change! %s", sqlite3_errmsg(sdb));
340  g_free(query);
341  goto error;
342  }
343  g_free(query);
344  osync_trace(TRACE_EXIT, "%s", __func__);
345  return TRUE;
346 
347 error:
348  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
349  return FALSE;
350 }
351 
352 osync_bool osync_db_reset_changes(OSyncGroup *group, const char *objtype, OSyncError **error)
353 {
354  osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, group, objtype, error);
355 
356  if (!group || !objtype) {
357  osync_error_set(error, OSYNC_ERROR_PARAMETER, "osync_db_reset_changes was called with wrong parameters");
358  goto error;
359  }
360  sqlite3 *sdb = group->changes_db->db;
361 
362  char *query = NULL;
363  if (osync_conv_objtype_is_any(objtype)) {
364  query = g_strdup_printf("DELETE FROM tbl_changes");
365  } else {
366  query = g_strdup_printf("DELETE FROM tbl_changes WHERE objtype='%s'", objtype);
367  }
368 
369  if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
370  osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to reset changes! %s", sqlite3_errmsg(sdb));
371  g_free(query);
372  goto error;
373  }
374 
375  g_free(query);
376  osync_trace(TRACE_EXIT, "%s", __func__);
377  return TRUE;
378 
379 error:
380  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
381  return FALSE;
382 
383 }
384 
385 osync_bool osync_db_reset_group(OSyncGroup *group, OSyncError **error)
386 {
387  osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, group, error);
388  OSyncDB *db = NULL;
389 
390  if (!group) {
391  osync_error_set(error, OSYNC_ERROR_PARAMETER, "osync_db_reset_group was called with wrong parameters");
392  goto error;
393  }
394 
395  char *changesdb = g_strdup_printf("%s/change.db", group->configdir);
396  if (!(db = osync_db_open(changesdb, error))) {
397  g_free(changesdb);
398  goto error;
399  }
400 
401  if (sqlite3_exec(db->db, "DELETE FROM tbl_changes", NULL, NULL, NULL) != SQLITE_OK) {
402  osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to reset changes! %s", sqlite3_errmsg(db->db));
403  g_free(changesdb);
404  goto error_db_close;
405  }
406 
407  osync_db_close(db);
408  g_free(changesdb);
409 
410  osync_trace(TRACE_EXIT, "%s", __func__);
411  return TRUE;
412 
413 error_db_close:
414  osync_db_close(db);
415 
416 error:
417  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
418  return FALSE;
419 }
420 
421 osync_bool osync_db_reset_member(OSyncMember *member, OSyncError **error)
422 {
423  osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, member, error);
424  OSyncDB *db = NULL;
425 
426  if (!member) {
427  osync_error_set(error, OSYNC_ERROR_PARAMETER, "osync_db_reset_member was called with wrong parameters");
428  goto error;
429  }
430 
431  char *hashtable = g_strdup_printf("%s/hash.db", member->configdir);
432  if (g_file_test(hashtable, G_FILE_TEST_EXISTS)) {
433  if (!(db = osync_db_open(hashtable, error))) {
434  g_free(hashtable);
435  goto error;
436  }
437 
438  if (sqlite3_exec(db->db, "DELETE FROM tbl_hash", NULL, NULL, NULL) != SQLITE_OK) {
439  osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to reset hashtable! %s", sqlite3_errmsg(db->db));
440  g_free(hashtable);
441  goto error_db_close;
442  }
443 
444  osync_db_close(db);
445  }
446  g_free(hashtable);
447 
448  char *anchordb = g_strdup_printf("%s/anchor.db", member->configdir);
449  if (g_file_test(anchordb, G_FILE_TEST_EXISTS)) {
450  if (!(db = osync_db_open(anchordb, error))) {
451  g_free(anchordb);
452  goto error;
453  }
454 
455  if (sqlite3_exec(db->db, "DELETE FROM tbl_anchor", NULL, NULL, NULL) != SQLITE_OK) {
456  osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to reset anchors! %s", sqlite3_errmsg(db->db));
457  g_free(anchordb);
458  goto error_db_close;
459  }
460 
461  osync_db_close(db);
462  }
463  g_free(anchordb);
464 
465  osync_trace(TRACE_EXIT, "%s", __func__);
466  return TRUE;
467 
468 error_db_close:
469  osync_db_close(db);
470 
471 error:
472  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
473  return FALSE;
474 
475 }
476 
477 void osync_db_close_changes(OSyncGroup *group)
478 {
479  if (group->changes_db)
480  osync_db_close(group->changes_db);
481 }
482 
483 OSyncDB *osync_db_open_anchor(OSyncMember *member, OSyncError **error)
484 {
485  g_assert(member);
486  OSyncDB *sdb = NULL;
487  char *filename = g_strdup_printf ("%s/anchor.db", member->configdir);
488  if (!(sdb = osync_db_open(filename, error))) {
489  g_free(filename);
490  osync_error_update(error, "Unable to open anchor table: %s", (*error)->message);
491  return NULL;
492  }
493  g_free(filename);
494 
495  if (sqlite3_exec(sdb->db, "CREATE TABLE tbl_anchor (id INTEGER PRIMARY KEY, anchor VARCHAR, objtype VARCHAR UNIQUE)", NULL, NULL, NULL) != SQLITE_OK)
496  osync_debug("OSDB", 3, "Unable create anchor table! %s", sqlite3_errmsg(sdb->db));
497 
498  return sdb;
499 }
500 
501 void osync_db_close_anchor(OSyncDB *db)
502 {
503  osync_db_close(db);
504 }
505 
506 void osync_db_get_anchor(OSyncDB *sdb, const char *objtype, char **retanchor)
507 {
508  sqlite3_stmt *ppStmt = NULL;
509  char *query = g_strdup_printf("SELECT anchor FROM tbl_anchor WHERE objtype='%s'", objtype);
510  if (sqlite3_prepare(sdb->db, query, -1, &ppStmt, NULL) != SQLITE_OK)
511  osync_debug("OSDB", 3, "Unable prepare anchor! %s", sqlite3_errmsg(sdb->db));
512  int ret = sqlite3_step(ppStmt);
513  if (ret != SQLITE_DONE && ret != SQLITE_ROW)
514  osync_debug("OSDB", 3, "Unable step count! %s", sqlite3_errmsg(sdb->db));
515  if (ret == SQLITE_DONE)
516  osync_debug("OSDB", 3, "No row found!");
517  *retanchor = g_strdup((gchar*)sqlite3_column_text(ppStmt, 0));
518  sqlite3_finalize(ppStmt);
519  g_free(query);
520 }
521 
522 void osync_db_put_anchor(OSyncDB *sdb, const char *objtype, const char *anchor)
523 {
524  char *escaped_anchor = osync_db_sql_escape(anchor);
525  char *query = g_strdup_printf("REPLACE INTO tbl_anchor (objtype, anchor) VALUES('%s', '%s')", objtype, escaped_anchor);
526  g_free(escaped_anchor);
527 
528  if (sqlite3_exec(sdb->db, query, NULL, NULL, NULL) != SQLITE_OK)
529  osync_debug("OSDB", 1, "Unable put anchor! %s", sqlite3_errmsg(sdb->db));
530 
531  g_free(query);
532 }
533 
534 
535 osync_bool osync_db_open_hashtable(OSyncHashTable *table, OSyncMember *member, OSyncError **error)
536 {
537  g_assert(member);
538  char *filename = g_strdup_printf ("%s/hash.db", member->configdir);
539  if (!(table->dbhandle = osync_db_open(filename, error))) {
540  g_free(filename);
541  osync_error_update(error, "Unable to open hashtable: %s", (*error)->message);
542  return FALSE;
543  }
544  g_free(filename);
545 
546  sqlite3 *db = table->dbhandle->db;
547 
548  if (sqlite3_exec(db, "CREATE TABLE tbl_hash (id INTEGER PRIMARY KEY, uid VARCHAR, hash VARCHAR, objtype VARCHAR)", NULL, NULL, NULL) != SQLITE_OK)
549  osync_debug("OSDB", 3, "Unable create hash table! %s", sqlite3_errmsg(db));
550 
551  return TRUE; //FIXME
552 }
553 
554 void osync_db_close_hashtable(OSyncHashTable *table)
555 {
556  osync_db_close(table->dbhandle);
557 }
558 
559 int exists_hashtable_id(OSyncHashTable *table, const char *uid, const char *objtype)
560 {
561  g_assert(table->dbhandle);
562  sqlite3 *sdb = table->dbhandle->db;
563 
564  int id = -1;
565 
566  char *exist = g_strdup_printf("SELECT id FROM tbl_hash WHERE uid='%s' AND objtype='%s'",uid, objtype);
567 
568  sqlite3_stmt *ppStmt = NULL;
569  if (sqlite3_prepare(sdb, exist, -1, &ppStmt, NULL) != SQLITE_OK)
570  {
571  osync_debug("OSDB", 3, "Unable prepare get id! %s", sqlite3_errmsg(sdb));
572  return (id);
573  }
574  int ret = sqlite3_step(ppStmt);
575  if (ret != SQLITE_DONE && ret != SQLITE_ROW)
576  return (id);
577  if (ret == SQLITE_DONE)
578  return (id);
579 
580  id = sqlite3_column_int64(ppStmt, 0);
581  sqlite3_finalize(ppStmt);
582  g_free(exist);
583 
584  return(id);
585 }
586 
587 void osync_db_save_hash(OSyncHashTable *table, const char *uid, const char *hash, const char *objtype)
588 {
589  g_assert(table->dbhandle);
590  sqlite3 *sdb = table->dbhandle->db;
591 
592  char *escaped_uid = osync_db_sql_escape(uid);
593  char *escaped_hash = osync_db_sql_escape(hash);
594  char *escaped_objtype = osync_db_sql_escape(objtype);
595  int id = exists_hashtable_id(table, escaped_uid, escaped_objtype);
596  char *query = NULL;
597  if(id < 0){
598  query = g_strdup_printf(
599  "REPLACE INTO tbl_hash ('uid', 'hash', 'objtype') VALUES('%s', '%s', '%s')",
600  escaped_uid, escaped_hash, escaped_objtype);
601  }else{
602  query = g_strdup_printf(
603  "REPLACE INTO tbl_hash ('id', 'uid', 'hash', 'objtype') VALUES('%i', '%s', '%s', '%s')",
604  id, escaped_uid, escaped_hash, escaped_objtype);
605  }
606 
607  if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK)
608  osync_debug("OSDB", 1, "Unable to insert hash! uid = %s, hash = %s, error = %s", escaped_uid, escaped_hash, sqlite3_errmsg(sdb));
609 
610  g_free(escaped_uid);
611  g_free(escaped_hash);
612  g_free(escaped_objtype);
613  g_free(query);
614 }
615 
616 
617 void osync_db_delete_hash(OSyncHashTable *table, const char *uid)
618 {
619  g_assert(table->dbhandle);
620  sqlite3 *sdb = table->dbhandle->db;
621 
622  char *escaped_uid = osync_db_sql_escape(uid);
623  char *query = g_strdup_printf("DELETE FROM tbl_hash WHERE uid='%s'", escaped_uid);
624  g_free(escaped_uid);
625 
626  if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK)
627  osync_debug("OSDB", 1, "Unable to delete hash! %s", sqlite3_errmsg(sdb));
628  g_free(query);
629 }
630 
631 char **osync_db_get_deleted_hash(OSyncHashTable *table, const char *objtype)
632 {
633  g_assert(table->dbhandle);
634  sqlite3 *sdb = table->dbhandle->db;
635 
636  char **azResult = NULL;
637  int numrows = 0;
638  char *query = NULL;
639 
640  if (osync_conv_objtype_is_any(objtype)) {
641  query = g_strdup_printf("SELECT uid, hash FROM tbl_hash");
642  } else {
643  query = g_strdup_printf("SELECT uid, hash FROM tbl_hash WHERE objtype='%s'", objtype);
644  }
645  sqlite3_get_table(sdb, query, &azResult, &numrows, NULL, NULL);
646  g_free(query);
647 
648  char **ret = g_malloc0((numrows + 1) * sizeof(char *));
649 
650  int i;
651  int ccell = 2;
652  int num = 0;
653  for (i = 0; i < numrows; i++) {
654  char *uid = azResult[ccell];
655  ccell += 2;
656 
657  if (!g_hash_table_lookup(table->used_entries, uid)) {
658  ret[num] = g_strdup(uid);
659  num++;
660  }
661  }
662  sqlite3_free_table(azResult);
663  return ret;
664 }
665 
666 void osync_db_get_hash(OSyncHashTable *table, const char *uid, const char *objtype, char **rethash)
667 {
668  sqlite3 *sdb = table->dbhandle->db;
669  sqlite3_stmt *ppStmt = NULL;
670  char *escaped_uid = osync_db_sql_escape(uid);
671  char *escaped_objtype = osync_db_sql_escape(objtype);
672  char *query = g_strdup_printf("SELECT hash FROM tbl_hash WHERE uid='%s' AND objtype='%s'", escaped_uid, escaped_objtype);
673  g_free(escaped_uid);
674  g_free(escaped_objtype);
675 
676  if (sqlite3_prepare(sdb, query, -1, &ppStmt, NULL) != SQLITE_OK)
677  osync_debug("OSDB", 3, "Unable prepare get hash! %s", sqlite3_errmsg(sdb));
678  int ret = sqlite3_step(ppStmt);
679  if (ret != SQLITE_DONE && ret != SQLITE_ROW)
680  osync_debug("OSDB", 3, "Unable step get hash! %s", sqlite3_errmsg(sdb));
681  if (ret == SQLITE_DONE)
682  osync_debug("OSDB", 3, "No row found!");
683  *rethash = g_strdup((gchar*)sqlite3_column_text(ppStmt, 0));
684  sqlite3_finalize(ppStmt);
685  g_free(query);
686 }
687 
688 void osync_db_reset_hash(OSyncHashTable *table, const char *objtype)
689 {
690  sqlite3 *sdb = table->dbhandle->db;
691  char *query = NULL;
692  if (osync_conv_objtype_is_any(objtype)) {
693  query = g_strdup_printf("DELETE FROM tbl_hash");
694  } else {
695  query = g_strdup_printf("DELETE FROM tbl_hash WHERE objtype='%s'", objtype);
696  }
697  if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK)
698  osync_debug("OSDB", 1, "Unable to reset hash! %s", sqlite3_errmsg(sdb));
699  g_free(query);
700 }
701 
702 char *osync_db_sql_escape(const char *s)
703 {
704  return osync_strreplace(s, "'", "''");
705 }
706 
OSyncChangeType osync_change_get_changetype(OSyncChange *change)
Gets the changetype of a change.
int osync_change_get_datasize(OSyncChange *change)
Gets the size of the data of a change.
Represent an error.
Represent a group of members that should be synchronized.
OSyncChange * osync_change_new(void)
Spawns a new change object.
const char * osync_change_get_uid(OSyncChange *change)
Gets the uid of a change.
A member of a group which represent a single device.
OSyncObjFormat * osync_change_get_objformat(OSyncChange *change)
Gets the object format of a change.
void * osync_try_malloc0(unsigned int size, OSyncError **error)
Safely tries to malloc memory.
Definition: opensync_env.c:796
void osync_debug(const char *subpart, int level, const char *message,...)
Used for debugging.
void osync_error_update(OSyncError **error, const char *format,...)
Updates the error message.
long long int mappingid
const char * osync_objformat_get_name(OSyncObjFormat *format)
Returns the name of a object format.
A change object.
void osync_change_set_member(OSyncChange *change, OSyncMember *member)
Sets the member of a change.
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_trace(OSyncTraceType type, const char *message,...)
Used for tracing the application.
const char * osync_objtype_get_name(OSyncObjType *type)
Returns the name of a object type.
OSyncObjType * osync_change_get_objtype(OSyncChange *change)
Gets the object type of a change.
OSyncMember * osync_member_from_id(OSyncGroup *group, int id)
Searches for a member by its id.
Represent a hashtable which can be used to check if changes have been modifed or deleted.
OSyncChangeType changetype
char * osync_change_get_data(OSyncChange *change)
Gets the data of a change.