2
* Copyright 2011 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 3, as published
6
* by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranties of
10
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11
* PURPOSE. See the GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License along
14
* with this program. If not, see <http://www.gnu.org/licenses/>.
31
static const char *table_definitions[] = {
32
"CREATE TABLE transaction_log ("
33
" db_rev INTEGER PRIMARY KEY AUTOINCREMENT,"
35
"CREATE TABLE document ("
36
" doc_id TEXT PRIMARY KEY,"
39
"CREATE TABLE document_fields ("
43
" CONSTRAINT document_fields_pkey"
44
" PRIMARY KEY (doc_id, field_name))",
45
"CREATE TABLE sync_log ("
46
" machine_id TEXT PRIMARY KEY,"
47
" known_db_rev INTEGER)",
48
"CREATE TABLE conflicts ("
52
" CONSTRAINT conflicts_pkey PRIMARY KEY (doc_id, doc_rev))",
53
"CREATE TABLE index_definitions ("
57
" CONSTRAINT index_definitions_pkey"
58
" PRIMARY KEY (name, offset))",
59
"CREATE TABLE u1db_config (name TEXT, value TEXT)",
60
"INSERT INTO u1db_config VALUES ('sql_schema', '0')",
64
initialize(u1database *db)
66
sqlite3_stmt *statement;
67
int i, status, final_status;
69
for(i = 0; i < sizeof(table_definitions)/sizeof(char*); i++) {
70
status = sqlite3_prepare_v2(db->sql_handle,
71
table_definitions[i], -1, &statement, NULL);
72
if(status != SQLITE_OK) {
75
status = sqlite3_step(statement);
76
final_status = sqlite3_finalize(statement);
77
if(status != SQLITE_DONE) {
80
if(final_status != SQLITE_OK) {
88
u1db_open(const char *fname)
90
u1database *db = (u1database *)(calloc(1, sizeof(u1database)));
92
status = sqlite3_open(fname, &db->sql_handle);
93
if(status != SQLITE_OK) {
94
// What do we do here?
102
// Windows doesn't have strndup, so we fake one
103
char *_win32_strndup(const char *s, size_t n)
106
out = (char*)malloc(n+1);
116
u1db__sql_close(u1database *db)
118
if (db->sql_handle != NULL) {
119
// sqlite says closing a NULL handle is ok, but we don't want to trust that
121
status = sqlite3_close(db->sql_handle);
122
db->sql_handle = NULL;
129
u1db__sql_is_open(u1database *db)
131
if (db != NULL && db->sql_handle != NULL) {
132
// The handle is still open
139
u1db_free(u1database **db)
141
if (db == NULL || *db == NULL) {
144
free((*db)->machine_id);
145
u1db__sql_close(*db);
151
u1db_set_machine_id(u1database *db, const char *machine_id)
153
sqlite3_stmt *statement;
154
int status, final_status, num_bytes;
155
status = sqlite3_prepare_v2(db->sql_handle,
156
"INSERT INTO u1db_config VALUES (?, ?)", -1,
158
if (status != SQLITE_OK) {
161
status = sqlite3_bind_text(statement, 1, "machine_id", -1, SQLITE_STATIC);
162
if (status != SQLITE_OK) {
163
sqlite3_finalize(statement);
166
status = sqlite3_bind_text(statement, 2, machine_id, -1, SQLITE_TRANSIENT);
167
if (status != SQLITE_OK) {
168
sqlite3_finalize(statement);
171
status = sqlite3_step(statement);
172
final_status = sqlite3_finalize(statement);
173
if (status != SQLITE_DONE) {
176
if (final_status != SQLITE_OK) {
179
// If we got this far, then machine_id has been properly set. Copy it
180
if (db->machine_id != NULL) {
181
free(db->machine_id);
183
num_bytes = strlen(machine_id);
184
db->machine_id = (char *)calloc(1, num_bytes + 1);
185
memcpy(db->machine_id, machine_id, num_bytes + 1);
190
u1db_get_machine_id(u1database *db, char **machine_id)
192
sqlite3_stmt *statement;
193
int status, num_bytes;
194
const unsigned char *text;
195
if (db->machine_id != NULL) {
196
*machine_id = db->machine_id;
199
status = sqlite3_prepare_v2(db->sql_handle,
200
"SELECT value FROM u1db_config WHERE name = 'machine_id'", -1,
202
if(status != SQLITE_OK) {
203
*machine_id = "Failed to prepare statement";
206
status = sqlite3_step(statement);
207
if(status != SQLITE_ROW) {
208
// TODO: Check return for failures
209
sqlite3_finalize(statement);
210
if (status == SQLITE_DONE) {
211
// No machine_id set yet
215
*machine_id = "Failed to step prepared statement";
218
if(sqlite3_column_count(statement) != 1) {
219
sqlite3_finalize(statement);
220
*machine_id = "incorrect column count";
223
text = sqlite3_column_text(statement, 0);
224
num_bytes = sqlite3_column_bytes(statement, 0);
225
db->machine_id = (char *)calloc(1, num_bytes + 1);
226
memcpy(db->machine_id, text, num_bytes+1);
227
*machine_id = db->machine_id;
232
handle_row(sqlite3_stmt *statement, u1db_row **row)
234
// Note: If this was a performance critical function, we could do a
235
// first-pass over the data and determine total size, and fit all that into
236
// a single calloc call.
238
const unsigned char *text;
241
new_row = (u1db_row *)calloc(1, sizeof(u1db_row));
242
if (new_row == NULL) {
246
(*row)->next = new_row;
249
new_row->next = NULL;
250
new_row->num_columns = sqlite3_column_count(statement);
252
new_row->column_sizes = (int*)calloc(new_row->num_columns, sizeof(int));
253
if (new_row->column_sizes == NULL) {
256
new_row->columns = (unsigned char**)calloc(new_row->num_columns,
257
sizeof(unsigned char *));
258
if (new_row->columns == NULL) {
261
for (i = 0; i < new_row->num_columns; i++) {
262
text = sqlite3_column_text(statement, i);
263
// This size does not include the NULL terminator.
264
num_bytes = sqlite3_column_bytes(statement, i);
265
new_row->column_sizes[i] = num_bytes;
266
new_row->columns[i] = (unsigned char*)calloc(num_bytes+1, 1);
267
if (new_row->columns[i] == NULL) {
270
memcpy(new_row->columns[i], text, num_bytes+1);
276
u1db_create_doc(u1database *db, const char *doc, int n, char **doc_id,
279
if (db == NULL || doc == NULL || doc_id == NULL || doc_rev == NULL) {
283
if (*doc_id == NULL) {
284
*doc_id = u1db__allocate_doc_id(db);
286
return u1db_put_doc(db, *doc_id, doc_rev, doc, n);
290
// Lookup the contents for doc_id. We return the statement object, since it
291
// defines the lifetimes of doc and doc_rev. Callers should then finalize
292
// statement when they are done with them.
294
lookup_doc(u1database *db, const char *doc_id,
295
const unsigned char **doc_rev, const unsigned char **doc, int *n,
296
sqlite3_stmt **statement)
300
status = sqlite3_prepare_v2(db->sql_handle,
301
"SELECT doc_rev, doc FROM document WHERE doc_id = ?", -1,
303
if (status != SQLITE_OK) {
306
status = sqlite3_bind_text(*statement, 1, doc_id, -1, SQLITE_TRANSIENT);
307
if (status != SQLITE_OK) {
310
status = sqlite3_step(*statement);
311
if (status == SQLITE_DONE) {
316
} else if (status == SQLITE_ROW) {
317
*doc_rev = sqlite3_column_text(*statement, 0);
318
// fprintf(stderr, "column_type: %d\n", sqlite3_column_type(*statement, 1));
319
if (sqlite3_column_type(*statement, 1) == SQLITE_NULL) {
320
// fprintf(stderr, "column_type: NULL\n");
324
*doc = sqlite3_column_text(*statement, 1);
325
*n = sqlite3_column_bytes(*statement, 1);
333
// Insert the document into the table, we've already done the safety checks
335
write_doc(u1database *db, const char *doc_id, const char *doc_rev,
336
const char *doc, int n, int is_update)
338
sqlite3_stmt *statement;
342
status = sqlite3_prepare_v2(db->sql_handle,
343
"UPDATE document SET doc_rev = ?, doc = ? WHERE doc_id = ?", -1,
346
status = sqlite3_prepare_v2(db->sql_handle,
347
"INSERT INTO document (doc_rev, doc, doc_id) VALUES (?, ?, ?)", -1,
350
if (status != SQLITE_OK) {
353
status = sqlite3_bind_text(statement, 1, doc_rev, -1, SQLITE_TRANSIENT);
354
if (status != SQLITE_OK) {
355
sqlite3_finalize(statement);
359
status = sqlite3_bind_null(statement, 2);
361
status = sqlite3_bind_text(statement, 2, doc, n, SQLITE_TRANSIENT);
363
if (status != SQLITE_OK) {
364
sqlite3_finalize(statement);
367
status = sqlite3_bind_text(statement, 3, doc_id, -1, SQLITE_TRANSIENT);
368
if (status != SQLITE_OK) {
369
sqlite3_finalize(statement);
372
status = sqlite3_step(statement);
373
if (status == SQLITE_DONE) {
376
sqlite3_finalize(statement);
377
if (status != SQLITE_OK) {
380
status = sqlite3_prepare_v2(db->sql_handle,
381
"INSERT INTO transaction_log(doc_id) VALUES (?)", -1,
383
if (status != SQLITE_OK) {
386
status = sqlite3_bind_text(statement, 1, doc_id, -1, SQLITE_TRANSIENT);
387
if (status != SQLITE_OK) {
388
sqlite3_finalize(statement);
391
status = sqlite3_step(statement);
392
if (status == SQLITE_DONE) {
395
sqlite3_finalize(statement);
400
u1db_put_doc(u1database *db, const char *doc_id, char **doc_rev,
401
const char *doc, int n)
403
const unsigned char *old_doc, *old_doc_rev;
406
sqlite3_stmt *statement;
408
if (db == NULL || doc == NULL || doc_rev == NULL) {
412
if (doc_id == NULL) {
413
return U1DB_INVALID_DOC_ID;
415
status = sqlite3_exec(db->sql_handle, "BEGIN", NULL, NULL, NULL);
416
if (status != SQLITE_OK) {
420
status = lookup_doc(db, doc_id, &old_doc_rev, &old_doc, &old_doc_n, &statement);
421
if (status != SQLITE_OK) {
422
sqlite3_finalize(statement);
423
sqlite3_exec(db->sql_handle, "ROLLBACK", NULL, NULL, NULL);
426
if (*doc_rev == NULL) {
427
if (old_doc_rev == NULL) {
428
// We are creating a new document from scratch. No problem.
431
// We were supplied a NULL doc rev, but the doc already exists
432
status = U1DB_INVALID_DOC_REV;
435
if (old_doc_rev == NULL) {
436
// TODO: Handle this case, it is probably just
437
// U1DB_INVALID_DOC_REV, but we want a test case first.
438
// User supplied an old_doc_rev, but there is no entry in the db.
441
if (strcmp(*doc_rev, (const char *)old_doc_rev) == 0) {
442
// The supplied doc_rev exactly matches old_doc_rev, good enough
445
// Invalid old rev, mark it as such
446
status = U1DB_INVALID_DOC_REV;
450
if (status == SQLITE_OK) {
451
// We are ok to proceed, allocating a new document revision, and
452
// storing the document
453
u1db_vectorclock *vc;
454
char *machine_id, *new_rev;
456
vc = u1db__vectorclock_from_str((char*)old_doc_rev);
457
if (vc == NULL) { goto finish; }
458
status = u1db_get_machine_id(db, &machine_id);
459
if (status != U1DB_OK) { goto finish; }
460
status = u1db__vectorclock_increment(vc, machine_id);
461
if (status != U1DB_OK) { goto finish; }
462
status = u1db__vectorclock_as_str(vc, &new_rev);
463
if (status != U1DB_OK) { goto finish; }
465
status = write_doc(db, doc_id, new_rev, doc, n, (old_doc != NULL));
466
if (status == SQLITE_OK) {
467
status = sqlite3_exec(db->sql_handle, "COMMIT", NULL, NULL, NULL);
471
sqlite3_finalize(statement);
472
if (status != SQLITE_OK) {
473
sqlite3_exec(db->sql_handle, "ROLLBACK", NULL, NULL, NULL);
479
u1db_get_doc(u1database *db, const char *doc_id, char **doc_rev,
480
char **doc, int *n, int *has_conflicts)
482
int status = 0, local_n = 0;
483
sqlite3_stmt *statement;
484
const unsigned char *local_doc_rev, *local_doc;
485
if (db == NULL || doc_id == NULL || doc_rev == NULL || doc == NULL || n == NULL
486
|| has_conflicts == NULL) {
488
// TODO: we could handle has_conflicts == NULL meaning that the caller
489
// is ignoring conflicts, but we don't want to make it *too* easy
494
status = lookup_doc(db, doc_id, &local_doc_rev, &local_doc, &local_n,
496
if (status == SQLITE_OK) {
497
if (local_doc_rev == NULL) {
503
if (local_doc == NULL) {
507
*doc = (char *)calloc(1, local_n + 1);
509
status = SQLITE_NOMEM;
512
memcpy(*doc, local_doc, local_n);
515
local_n = strlen((const char*)local_doc_rev);
516
*doc_rev = (char *)calloc(1, local_n+1);
517
if (*doc_rev == NULL) {
518
status = SQLITE_NOMEM;
521
memcpy(*doc_rev, local_doc_rev, local_n);
530
sqlite3_finalize(statement);
535
u1db_delete_doc(u1database *db, const char *doc_id, char **doc_rev)
538
sqlite3_stmt *statement;
539
const unsigned char *cur_doc_rev, *doc;
541
if (db == NULL || doc_id == NULL || doc_rev == NULL || *doc_rev == NULL) {
542
return U1DB_INVALID_PARAMETER;
544
status = sqlite3_exec(db->sql_handle, "BEGIN", NULL, NULL, NULL);
545
if (status != SQLITE_OK) {
548
status = lookup_doc(db, doc_id, &cur_doc_rev, &doc, &n, &statement);
549
if (status != SQLITE_OK) {
550
sqlite3_finalize(statement);
551
sqlite3_exec(db->sql_handle, "ROLLBACK", NULL, NULL, NULL);
554
if (cur_doc_rev == NULL || doc == NULL) {
555
// Can't delete a doc that doesn't exist
556
sqlite3_exec(db->sql_handle, "ROLLBACK", NULL, NULL, NULL);
557
sqlite3_finalize(statement);
558
return U1DB_INVALID_DOC_ID;
560
if (strcmp((const char *)cur_doc_rev, *doc_rev) != 0) {
561
// The saved document revision doesn't match
562
sqlite3_exec(db->sql_handle, "ROLLBACK", NULL, NULL, NULL);
563
sqlite3_finalize(statement);
564
return U1DB_INVALID_DOC_REV;
566
// TODO: Handle conflicts
567
sqlite3_finalize(statement);
569
// TODO: Implement VectorClockRev
570
*doc_rev = (char *)calloc(1, 128);
571
memcpy(*doc_rev, "test:2", 6);
572
status = write_doc(db, doc_id, *doc_rev, NULL, 0, 1);
573
if (status != SQLITE_OK) {
574
sqlite3_exec(db->sql_handle, "ROLLBACK", NULL, NULL, NULL);
576
status = sqlite3_exec(db->sql_handle, "COMMIT", NULL, NULL, NULL);
582
u1db_whats_changed(u1database *db, int *db_rev,
583
int (*cb)(void *, char *doc_id), void *context)
586
sqlite3_stmt *statement;
587
if (db == NULL || db_rev == NULL || cb == NULL) {
588
return -1; // Bad parameters
590
status = sqlite3_prepare_v2(db->sql_handle,
591
"SELECT db_rev, doc_id FROM transaction_log WHERE db_rev > ?", -1,
593
if (status != SQLITE_OK) {
596
status = sqlite3_bind_int(statement, 1, *db_rev);
597
if (status != SQLITE_OK) {
598
sqlite3_finalize(statement);
601
status = sqlite3_step(statement);
602
while (status == SQLITE_ROW) {
605
local_db_rev = sqlite3_column_int(statement, 0);
606
if (local_db_rev > *db_rev) {
607
*db_rev = local_db_rev;
609
doc_id = (char *)sqlite3_column_text(statement, 1);
611
status = sqlite3_step(statement);
613
if (status == SQLITE_DONE) {
616
sqlite3_finalize(statement);
622
u1db__get_db_rev(u1database *db, int *db_rev)
625
sqlite3_stmt *statement;
626
if (db == NULL || db_rev == NULL) {
627
return U1DB_INVALID_PARAMETER;
629
status = sqlite3_prepare_v2(db->sql_handle,
630
"SELECT max(db_rev) FROM transaction_log", -1,
632
if (status != SQLITE_OK) {
635
status = sqlite3_step(statement);
636
if (status == SQLITE_DONE) {
637
// No records, we are at rev 0
640
} else if (status == SQLITE_ROW) {
642
*db_rev = sqlite3_column_int(statement, 0);
644
sqlite3_finalize(statement);
649
u1db__allocate_doc_id(u1database *db)
653
status = u1db__get_db_rev(db, &db_rev);
654
if(status != U1DB_OK) {
655
// There was an error.
658
buf = (char *)calloc(1, 128);
659
snprintf(buf, 128, "doc-%d", db_rev);
664
u1db__sql_run(u1database *db, const char *sql, size_t n)
666
// TODO: This could be simplified *a lot* by using sqlite3_exec
667
int status, do_continue;
668
u1db_table *result = NULL;
669
u1db_row *cur_row = NULL;
670
sqlite3_stmt *statement;
671
result = (u1db_table *)calloc(1, sizeof(u1db_table));
672
if (result == NULL) {
675
status = sqlite3_prepare_v2(db->sql_handle, sql, n, &statement, NULL);
676
if (status != SQLITE_OK) {
677
result->status = status;
683
status = sqlite3_step(statement);
686
result->status = SQLITE_OK;
690
status = handle_row(statement, &cur_row);
691
if (result->first_row == NULL) {
692
result->first_row = cur_row;
694
if (status == SQLITE_OK) {
699
default: // Assume it is an error
700
result->status = status;
704
sqlite3_finalize(statement);
709
u1db__free_table(u1db_table **table)
711
u1db_row *cur_row, *old_row;
713
if (table == NULL || (*table) == NULL) {
716
cur_row = (*table)->first_row;
717
while (cur_row != NULL) {
719
cur_row = cur_row->next;
720
free(old_row->column_sizes);
721
old_row->column_sizes = NULL;
722
for (i = 0; i < old_row->num_columns; i++) {
723
free(old_row->columns[i]);
724
old_row->columns[i] = NULL;
726
free(old_row->columns);
727
old_row->columns = NULL;
730
(*table)->first_row = NULL;
736
u1db__sync_get_machine_info(u1database *db, const char *other_machine_id,
737
int *other_db_rev, char **my_machine_id,
741
sqlite3_stmt *statement;
743
if (db == NULL || other_machine_id == NULL || other_db_rev == NULL) {
744
return U1DB_INVALID_PARAMETER;
746
status = u1db_get_machine_id(db, my_machine_id);
747
if (status != U1DB_OK) {
750
status = u1db__get_db_rev(db, my_db_rev);
751
if (status != U1DB_OK) {
754
status = sqlite3_prepare_v2(db->sql_handle,
755
"SELECT known_db_rev FROM sync_log WHERE machine_id = ?", -1,
757
if (status != SQLITE_OK) {
760
status = sqlite3_bind_text(statement, 1, other_machine_id, -1,
762
if (status != SQLITE_OK) {
763
sqlite3_finalize(statement);
766
status = sqlite3_step(statement);
767
if (status == SQLITE_DONE) {
770
} else if (status == SQLITE_ROW) {
771
*other_db_rev = sqlite3_column_int(statement, 0);
774
sqlite3_finalize(statement);
779
u1db__sync_record_machine_info(u1database *db, const char *machine_id,
783
sqlite3_stmt *statement;
784
if (db == NULL || machine_id == NULL) {
785
return U1DB_INVALID_PARAMETER;
787
status = sqlite3_exec(db->sql_handle, "BEGIN", NULL, NULL, NULL);
788
if (status != SQLITE_OK) {
791
status = sqlite3_prepare_v2(db->sql_handle,
792
"INSERT OR REPLACE INTO sync_log VALUES (?, ?)", -1,
794
if (status != SQLITE_OK) {
797
status = sqlite3_bind_text(statement, 1, machine_id, -1, SQLITE_TRANSIENT);
798
if (status != SQLITE_OK) {
799
sqlite3_finalize(statement);
800
sqlite3_exec(db->sql_handle, "ROLLBACK", NULL, NULL, NULL);
803
status = sqlite3_bind_int(statement, 2, db_rev);
804
if (status != SQLITE_OK) {
805
sqlite3_finalize(statement);
806
sqlite3_exec(db->sql_handle, "ROLLBACK", NULL, NULL, NULL);
809
status = sqlite3_step(statement);
810
if (status == SQLITE_DONE) {
813
sqlite3_finalize(statement);
818
compare_and_insert_doc(u1database *db, const char *doc_rev, const char *doc)
820
return U1DB_INVALID_PARAMETER;
824
insert_records(u1database *db, u1db_record *records)
826
if (db == NULL || records == NULL) {
827
return U1DB_INVALID_PARAMETER;
829
return U1DB_INVALID_PARAMETER;
833
u1db__sync_exchange(u1database *db, const char *from_machine_id,
834
int from_db_rev, int last_known_rev,
835
u1db_record *from_records, u1db_record **new_records,
836
u1db_record **conflict_records)
838
if (db == NULL || from_machine_id == NULL || new_records == NULL
839
|| conflict_records == NULL) {
840
return U1DB_INVALID_PARAMETER;
842
return U1DB_INVALID_PARAMETER;
846
u1db__create_record(const char *doc_id, const char *doc_rev, const char *doc)
848
// TODO: If we wanted, we could allocate one large block, and then point
849
// the arrays to the right locations therein.
851
record = (u1db_record *)calloc(1, sizeof(u1db_record));
852
if (record == NULL) {
855
record->doc_id = strdup(doc_id);
856
record->doc_rev = strdup(doc_rev);
860
record->doc = strdup(doc);
866
u1db__copy_record(u1db_record *src)
871
return u1db__create_record(src->doc_id, src->doc_rev, src->doc);
874
void u1db__free_records(u1db_record **record)
876
u1db_record *cur, *last;
877
if (record == NULL || *record == NULL) {
881
while (cur != NULL) {
886
if (last->doc != NULL) {
894
void u1db__free_vectorclock(u1db_vectorclock **clock)
898
if (clock == NULL || *clock == NULL) {
901
if ((*clock)->items != NULL) {
902
for (i = 0; i < (*clock)->num_items; i++) {
903
machine_id = (*clock)->items[i].machine_id;
904
if (machine_id != NULL) {
909
free((*clock)->items);
914
u1db_vectorclock *u1db__vectorclock_from_str(const char *s)
916
u1db_vectorclock *res = NULL;
918
const char *cur, *colon, *pipe, *end;
924
res = (u1db_vectorclock *)calloc(1, sizeof(u1db_vectorclock));
928
if ((end - s) == 0) {
929
// Empty string, no items
934
// Count the number of '|' symbols, and allocate buffers for it
936
for (cur = s; cur < end; cur++) {
941
res->items = (u1db_vectorclock_item*)calloc(res->num_items,
942
sizeof(u1db_vectorclock_item));
943
// Now walk through it again, looking for the machine:count pairs
945
for (i = 0; i < res->num_items; i++) {
947
// Ran off the end. Most likely indicates a trailing | that isn't
948
// followed by content.
949
u1db__free_vectorclock(&res);
952
pipe = memchr(cur, '|', end-cur);
954
// We assume the rest of the string is what we want
957
colon = memchr(cur, ':', pipe-cur);
958
if (colon == NULL || (colon - cur) == 0 || (pipe - colon) == 1) {
959
// Either, no colon, no machine_id, or no digits
960
u1db__free_vectorclock(&res);
963
res->items[i].machine_id = strndup(cur, colon-cur);
964
res->items[i].db_rev = strtol(colon+1, &last_digit, 10);
965
if (last_digit != pipe) {
966
u1db__free_vectorclock(&res);
975
u1db__vectorclock_increment(u1db_vectorclock *clock, const char *machine_id)
978
u1db_vectorclock_item *new_buf;
979
if (clock == NULL || machine_id == NULL) {
980
return U1DB_INVALID_PARAMETER;
982
for (i = 0; i < clock->num_items; ++i) {
983
cmp = strcmp(machine_id, clock->items[i].machine_id);
985
// We found the entry
986
clock->items[i].db_rev++;
988
} else if (cmp < 0) {
989
// machine_id would come right before items[i] if it was present.
990
// So we break, and insert it here
994
// If we got here, then 'i' points at the location where we want to insert
996
new_buf = (u1db_vectorclock_item*)realloc(clock->items,
997
sizeof(u1db_vectorclock_item) * (clock->num_items + 1));
998
if (new_buf == NULL) {
1001
clock->items = new_buf;
1003
memmove(&clock->items[i + 1], &clock->items[i],
1004
sizeof(u1db_vectorclock_item) * (clock->num_items - i - 1));
1005
clock->items[i].machine_id = strdup(machine_id);
1006
clock->items[i].db_rev = 1;
1010
struct inserts_needed {
1011
struct inserts_needed *next;
1017
free_inserts(struct inserts_needed **chain)
1019
struct inserts_needed *cur, *next;
1020
if (chain == NULL || *chain == NULL) {
1024
while (cur != NULL) {
1033
u1db__vectorclock_maximize(u1db_vectorclock *clock, u1db_vectorclock *other)
1036
int num_inserts, move_to_end, num_to_move, item_size;
1037
struct inserts_needed *needed = NULL, *next = NULL;
1038
u1db_vectorclock_item *new_buf;
1040
if (clock == NULL || other == NULL) {
1041
return U1DB_INVALID_PARAMETER;
1043
num_inserts = ci = oi = 0;
1044
// First pass, walk both lists, determining what items need to be inserted
1045
while (oi < other->num_items) {
1046
if (ci >= clock->num_items) {
1047
// We have already walked all of clock, so everything in other
1049
next = (struct inserts_needed *)calloc(1, sizeof(struct inserts_needed));
1050
next->next = needed;
1052
// We need the final offset, after everything has been moved.
1053
next->clock_offset = ci + num_inserts;
1054
next->other_offset = oi;
1059
cmp = strcmp(clock->items[ci].machine_id, other->items[oi].machine_id);
1061
// These machines are the same, take the 'max' value:
1062
if (clock->items[ci].db_rev < other->items[oi].db_rev) {
1063
clock->items[ci].db_rev = other->items[oi].db_rev;
1068
} else if (cmp < 0) {
1069
// clock[ci] comes before other[oi], so step clock
1072
// oi comes before ci, so it needs to be inserted
1073
next = (struct inserts_needed *)calloc(1, sizeof(struct inserts_needed));
1074
next->next = needed;
1076
next->clock_offset = ci + num_inserts;
1077
next->other_offset = oi;
1082
if (num_inserts == 0) {
1083
// Nothing more to do
1086
// Now we need to expand the clock array, and start shuffling the data
1088
item_size = sizeof(u1db_vectorclock_item);
1089
new_buf = (u1db_vectorclock_item *)realloc(clock->items,
1090
item_size * (clock->num_items + num_inserts));
1091
if (new_buf == NULL) {
1092
free_inserts(&needed);
1093
return SQLITE_NOMEM;
1095
clock->items = new_buf;
1096
clock->num_items += num_inserts;
1098
move_to_end = clock->num_items - 1;
1099
// Imagine we have 3 inserts, into an initial list 5-wide.
1100
// a c e g h, inserting b f i
1101
// Final length is 8,
1102
// i should have ci=7, num_inserts = 3
1103
// f should have ci=4, num_inserts = 2
1104
// b should have ci=1, num_inserts = 1
1105
// First step, we want to move 0 items, and just insert i at the end (7)
1106
// Second step, we want to move g & h from 3 4, to be at 5 6, and then
1108
// Third step, we move c & e from 1 2 to 2 3 and insert b at 1
1109
while (next != NULL) {
1110
num_to_move = move_to_end - next->clock_offset;
1111
if (num_to_move > 0) {
1112
memmove(&clock->items[next->clock_offset + 1],
1113
&clock->items[next->clock_offset - num_inserts + 1],
1114
item_size * num_to_move);
1116
clock->items[next->clock_offset].machine_id = strdup(
1117
other->items[next->other_offset].machine_id);
1118
clock->items[next->clock_offset].db_rev =
1119
other->items[next->other_offset].db_rev;
1121
move_to_end = next->clock_offset - 1;
1124
free_inserts(&needed);
1129
u1db__vectorclock_as_str(u1db_vectorclock *clock, char **result)
1131
int buf_size, i, val, count;
1133
// Quick pass, to determine the buffer size:
1135
if (result == NULL) {
1136
return U1DB_INVALID_PARAMETER;
1138
if (clock == NULL) {
1139
// Allocate space for the empty string
1140
cur = (char *)calloc(1, 1);
1144
for (i = 0; i < clock->num_items; i++) {
1145
buf_size += strlen(clock->items[i].machine_id);
1146
buf_size += 2; // ':' and possible '|'
1147
val = clock->items[i].db_rev;
1149
// divide by 8 is close to divide by 10, to get the number of
1150
// binary digits we will need to represent the decimal form
1155
cur = (char *)calloc(1, buf_size);
1157
for (i = 0; i < clock->num_items; i++) {
1163
count = snprintf(cur, buf_size, fmt, clock->items[i].machine_id,
1164
clock->items[i].db_rev);
1172
u1db__vectorclock_is_newer(u1db_vectorclock *maybe_newer,
1173
u1db_vectorclock *older)
1175
int ci, oi, cmp, is_newer, n_db_rev, o_db_rev;
1176
if (maybe_newer == NULL || maybe_newer->num_items == 0) {
1177
// NULL is never newer
1180
if (older == NULL || older->num_items == 0) {
1181
// This is not NULL, so it should be newer, we may need to check if
1182
// self is the empty string, though.
1187
// First pass, walk both lists, determining what items need to be inserted
1188
while (oi < older->num_items && ci < maybe_newer->num_items) {
1189
cmp = strcmp(maybe_newer->items[ci].machine_id,
1190
older->items[oi].machine_id);
1192
// Both clocks have the same machine, see if one is newer
1193
n_db_rev = maybe_newer->items[ci].db_rev;
1194
o_db_rev = older->items[ci].db_rev;
1195
if (n_db_rev < o_db_rev) {
1196
// At least one entry in older is newer than this
1198
} else if (n_db_rev > o_db_rev) {
1199
// If we have no conflicts, this is strictly newer
1205
} else if (cmp < 0) {
1206
// maybe_newer has an entry that older doesn't have, which would
1211
// older has an entry that maybe_newer doesn't have, so we must
1212
// not be strictly newer
1216
if (oi == older->num_items && ci < maybe_newer->num_items) {
1217
// ci has an entry that older doesn't have, it is newer
1220
if (oi < older->num_items) {
1221
// We didn't walk all of older, which means it has an entry which ci
1222
// doesn't have, and thus maybe_newer is not strictly newer