Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix local documents

  • Loading branch information...
commit 54ca3501f25d633e406a92a49a9b38c9a8932bdb 1 parent 47eeb38
@trondn trondn authored
Showing with 190 additions and 4 deletions.
  1. +5 −1 Makefile.am
  2. +0 −1  src/document.c
  3. +81 −2 src/instance.c
  4. +104 −0 tests/testapp.c
View
6 Makefile.am
@@ -34,7 +34,8 @@ check_PROGRAMS = tests/test_open_empty_filename \
tests/test_delete_nonexistent_document \
tests/test_get_deleted_document \
tests/test_bulk_store_documents \
- tests/test_changes_since
+ tests/test_changes_since \
+ tests/test_local_documents
TESTS=${check_PROGRAMS}
@@ -78,6 +79,9 @@ tests_test_changes_since_SOURCES = tests/testapp.c
tests_test_changes_since_DEPENDENCIES = libcbio.la
tests_test_changes_since_LDFLAGS = libcbio.la
+tests_test_local_documents_SOURCES = tests/testapp.c
+tests_test_local_documents_DEPENDENCIES = libcbio.la
+tests_test_local_documents_LDFLAGS = libcbio.la
LINTFLAGS=-Iinclude -b -c -errchk=%all \
-erroff=E_INCL_NUSD,E_CAST_INT_TO_SMALL_INT,E_PTRDIFF_OVERFLOW \
View
1  src/document.c
@@ -101,7 +101,6 @@ cbio_error_t cbio_document_set_id(libcbio_document_t doc,
return CBIO_SUCCESS;
}
-
LIBCBIO_API
cbio_error_t cbio_document_set_meta(libcbio_document_t doc,
const void *meta,
View
83 src/instance.c
@@ -17,6 +17,17 @@
#include "internal.h"
#include <stdlib.h>
+#include <string.h>
+
+static int cbio_is_local_id(const void *data, size_t nb)
+{
+ return (nb > 6 && memcmp(data, "_local/", 7) == 0) ? 1 : 0;
+}
+
+static int cbio_is_local_document(DocInfo *info)
+{
+ return cbio_is_local_id(info->id.buf, info->id.size);
+}
LIBCBIO_API
cbio_error_t cbio_open_handle(const char *name,
@@ -68,12 +79,54 @@ off_t cbio_get_header_position(libcbio_t handle)
return (off_t)couchstore_get_header_position(handle->couchstore_handle);
}
+static cbio_error_t cbio_ldoc2doc(libcbio_t handle, const LocalDoc *ldoc, libcbio_document_t *doc)
+{
+ cbio_error_t e;
+
+ if ((e = cbio_create_empty_document(handle, doc)) == CBIO_SUCCESS &&
+ (e = cbio_document_set_id(*doc, ldoc->id.buf, ldoc->id.size, 1)) == CBIO_SUCCESS &&
+ (e = cbio_document_set_value(*doc, ldoc->json.buf, ldoc->json.size, 1)) == CBIO_SUCCESS &&
+ (e = cbio_document_set_deleted(*doc, ldoc->deleted)) == CBIO_SUCCESS) {
+ return CBIO_SUCCESS;
+ }
+
+ return e;
+}
+
+static cbio_error_t cbio_get_local_document(libcbio_t handle,
+ const void *id,
+ size_t nid,
+ libcbio_document_t *doc)
+{
+ couchstore_error_t err;
+ LocalDoc *ldoc;
+
+ err = couchstore_open_local_document(handle->couchstore_handle, id,
+ nid, &ldoc);
+ if (err == COUCHSTORE_SUCCESS) {
+ cbio_error_t ret;
+ if (ldoc->deleted) {
+ ret = CBIO_ERROR_ENOENT;
+ } else {
+ ret = cbio_ldoc2doc(handle, ldoc, doc);
+ }
+ couchstore_free_local_document(ldoc);
+ return ret;
+ }
+
+ return cbio_remap_error(err);
+}
+
LIBCBIO_API
cbio_error_t cbio_get_document(libcbio_t handle,
const void *id,
size_t nid,
libcbio_document_t *doc)
{
+ if (cbio_is_local_id(id, nid)) {
+ return cbio_get_local_document(handle, id, nid, doc);
+ }
+
libcbio_document_t ret = calloc(1, sizeof(*ret));
couchstore_error_t err;
@@ -81,7 +134,9 @@ cbio_error_t cbio_get_document(libcbio_t handle,
return CBIO_ERROR_ENOMEM;
}
- err = couchstore_docinfo_by_id(handle->couchstore_handle, id, nid, &ret->info);
+
+ err = couchstore_docinfo_by_id(handle->couchstore_handle, id,
+ nid, &ret->info);
if (err != COUCHSTORE_SUCCESS) {
cbio_document_release(ret);
return cbio_remap_error(err);
@@ -109,6 +164,26 @@ cbio_error_t cbio_store_document(libcbio_t handle,
return cbio_store_documents(handle, &doc, 1);
}
+static cbio_error_t cbio_store_local_documents(libcbio_t handle,
+ libcbio_document_t *doc,
+ size_t ndocs)
+{
+ for (size_t ii = 0; ii < ndocs; ++ii) {
+ couchstore_error_t err;
+ LocalDoc mydoc;
+ mydoc.id = doc[ii]->info->id;
+ mydoc.json = doc[ii]->doc->data;
+ mydoc.deleted = doc[ii]->info->deleted;
+
+ err = couchstore_save_local_document(handle->couchstore_handle,
+ &mydoc);
+ if (err != COUCHSTORE_SUCCESS) {
+ return cbio_remap_error(err);
+ }
+ }
+ return CBIO_SUCCESS;
+}
+
LIBCBIO_API
cbio_error_t cbio_store_documents(libcbio_t handle,
libcbio_document_t *doc,
@@ -119,10 +194,14 @@ cbio_error_t cbio_store_documents(libcbio_t handle,
size_t ii;
couchstore_error_t err;
- if (handle->mode == CBIO_OPEN_RDONLY) {
+ if (handle->mode == CBIO_OPEN_RDONLY || ndocs == 0) {
return CBIO_ERROR_EINVAL;
}
+ if (cbio_is_local_document(doc[0]->info)) {
+ return cbio_store_local_documents(handle, doc, ndocs);
+ }
+
docs = calloc(ndocs, sizeof(Doc *));
info = calloc(ndocs, sizeof(DocInfo *));
if (docs == NULL || info == NULL) {
View
104 tests/testapp.c
@@ -501,6 +501,109 @@ static int test_changes_since(void)
return 0;
}
+static int test_local_documents(void)
+{
+ libcbio_t handle;
+ libcbio_document_t doc;
+ cbio_error_t err;
+ const char *key = "_local/hi-there";
+ size_t nkey = strlen(key);
+ const char *json = "{ foo:true }";
+ size_t njson = strlen(json);
+
+
+ err = cbio_open_handle(dbfile, CBIO_OPEN_CREATE, &handle);
+ if (err != CBIO_SUCCESS) {
+ report("Expected open of \"%s\" to succeed, but it \"%s\"",
+ cbio_strerror(err));
+ return 1;
+ }
+
+ err = cbio_get_document(handle, key, nkey, &doc);
+ if (err != CBIO_ERROR_ENOENT) {
+ report("I did not expect to find \"%s\" in the database"
+ ", but I got \"%s\"", key, cbio_strerror(err));
+ return 1;
+ }
+
+ err = cbio_create_empty_document(handle, &doc);
+ if (err != CBIO_SUCCESS) {
+ report("Failed to create an empty document: \"%s\"",
+ cbio_strerror(err));
+ return 1;
+ }
+
+ err = cbio_document_set_id(doc, key, nkey, 0);
+ if (err != CBIO_SUCCESS) {
+ report("Failed to set document id \"%s\"",
+ cbio_strerror(err));
+ return 1;
+ }
+
+ err = cbio_document_set_value(doc, json, njson, 0);
+ if (err != CBIO_SUCCESS) {
+ report("Failed ot set value \"%s\"",
+ cbio_strerror(err));
+ return 1;
+ }
+
+ err = cbio_store_document(handle, doc);
+ if (err != CBIO_SUCCESS) {
+ report("Failed to store document \"%s\"",
+ cbio_strerror(err));
+ return 1;
+ }
+
+ cbio_commit(handle);
+ cbio_document_release(doc);
+
+ err = cbio_get_document(handle, key, nkey, &doc);
+ if (err != CBIO_SUCCESS) {
+ report("The document should have been here now"
+ ", but I got \"%s\"", cbio_strerror(err));
+ return 1;
+ }
+
+ const void *res;
+ size_t nres;
+
+ err = cbio_document_get_value(doc, &res, &nres);
+ if (err != CBIO_SUCCESS) {
+ report("Failed to get the value: %s",
+ cbio_strerror(err));
+ return 1;
+ }
+
+ if (njson != nres) {
+ report("Received a different amount of data than I stored");
+ return 1;
+ }
+
+ if (memcmp(res, json, njson) != 0) {
+ report("Received incorrect data");
+ return 1;
+ }
+
+ cbio_document_set_deleted(doc, 1);
+ err = cbio_store_document(handle, doc);
+ if (err != CBIO_SUCCESS) {
+ report("Failed to store document \"%s\"",
+ cbio_strerror(err));
+ return 1;
+ }
+
+ cbio_document_release(doc);
+ err = cbio_get_document(handle, key, nkey, &doc);
+ if (err != CBIO_ERROR_ENOENT) {
+ report("I did not expect to find \"%s\" in the database"
+ ", but I got \"%s\"", key, cbio_strerror(err));
+ return 1;
+ }
+ cbio_close_handle(handle);
+
+ return 0;
+}
+
static void remove_dbfiles(void)
{
if (remove(dbfile) == -1 && errno != ENOENT) {
@@ -529,6 +632,7 @@ static struct test tests[] = {
{ .name = "test_get_deleted_document", .func = get_deleted_document },
{ .name = "test_bulk_store_documents", .func = bulk_store_documents },
{ .name = "test_changes_since", .func = test_changes_since },
+ { .name = "test_local_documents", .func = test_local_documents },
{ .name = NULL, .func = NULL }
};
Please sign in to comment.
Something went wrong with that request. Please try again.