Exemplo n.º 1
0
static PyObject *
sophia_cursor_new(SophiaDB *db, PyTypeObject *cursortype,
                     PyObject *args, PyObject *kwargs)
{
    SophiaCursor *pcur;
    int order = SPGTE;
    char *begin = NULL;
    PyObject *pbegin = NULL;
    Py_ssize_t bsize = 0;
    
    static char *keywords[] = {"start_key", "order", NULL};
    
    ensure_is_opened(db, NULL);
    
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi", keywords, &pbegin, &order)
        || (pbegin && pbegin != Py_None && PyBytes_AsStringAndSize(pbegin, &begin, &bsize) == -1))
        return NULL;

    pcur = PyObject_New(SophiaCursor, cursortype);
    if (!pcur)
        return NULL;
    
    void *cursor = sp_cursor(db->db, order, begin, (size_t)bsize);
    if (!cursor) {
        PyObject_Del(pcur);
        PyErr_SetString(SophiaError, sp_error(db->db));
        return NULL;
    }
    
    Py_INCREF(db);
    db->cursors++;
    pcur->db = db;
    pcur->cursor = cursor;
    return (PyObject *)pcur;
}
Exemplo n.º 2
0
static void
meta_cursor(void)
{
	void *env = sp_env();
	t( env != NULL );

	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.index", "key_b", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	t( sp_open(env) == 0 );
	t( sp_setstring(env, "snapshot", "test_snapshot0", 0) == 0 );

	printf("\n");

	void *o;
	void *cur = sp_cursor(env, NULL);
	t( cur != NULL );
	printf("\n");
	while ((o = sp_get(cur, NULL))) {
		char *key = sp_getstring(o, "key", 0);
		char *value = sp_getstring(o, "value", 0);
		printf("%s", key);
		if (value)
			printf(" = %s\n", value);
		else
			printf(" = \n");
		sp_destroy(o);
	}
	t( sp_destroy(cur) == 0 );
	t( sp_destroy(env) == 0 );
}
Exemplo n.º 3
0
static void
object_readonly1(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_open(env) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.index.key", "u32", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );
	t( sp_open(db) == 0 );

	int key = 7;
	void *o = sp_object(db);
	t(o != NULL);
	t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
	t( sp_setstring(o, "value", &key, sizeof(key)) == 0 );
	t( sp_set(db, o) == 0 );
	o = sp_object(db);
	t( o != NULL );
	t( sp_setstring(o, "order", ">", 0) == 0 );
	void *c = sp_cursor(db, o);
	o = sp_get(c, NULL);
	t( o != NULL );
	t( sp_setstring(o, "key", &key, sizeof(key)) == -1 );
	sp_destroy(o);
	sp_destroy(c);

	sp_destroy(env);
}
Exemplo n.º 4
0
static void
compact_delete1(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setint(env, "compaction.0.branch_wm", 1) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "key", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme.key", "u32,key", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "value", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );
	t( sp_open(env) == 0 );

	int key = 0;
	while (key < 20) {
		void *o = sp_document(db);
		t( o != NULL );
		t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
		t( sp_setstring(o, "value", &key, sizeof(key)) == 0 );
		t( sp_set(db, o) == 0 );
		key++;
	}

	t( sp_setint(env, "db.test.branch", 0) == 0 );
	t( sp_setint(env, "db.test.compact", 0) == 0 );

	key = 0;
	while (key < 20) {
		void *o = sp_document(db);
		t( o != NULL );
		t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
		t( sp_delete(db, o) == 0 );
		key++;
	}

	t( sp_setint(env, "db.test.branch", 0) == 0 );
	t( sp_setint(env, "db.test.compact", 0) == 0 );

	void *o = sp_document(db);
	t( o != NULL );
	void *cur = sp_cursor(env);
	t( o != NULL );
	int i = 0;
	while ((o = sp_get(cur, o))) {
		t( *(int*)sp_getstring(o, "key", NULL) == i );
		i++;
	}
	t( i == 0 );

	t( sp_destroy(env) == 0 );
}
Exemplo n.º 5
0
static void
multipart_cursor1(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.index", "key_b", 0) == 0 );
	t( sp_setstring(env, "db.test.index.key_b", "u32", 0) == 0 );
	t( sp_setstring(env, "db.test.index.key", "string", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	t( sp_open(env) == 0 );

	void *db = sp_getobject(env, "db.test");
	t( db != NULL );

	char key_a[] = "hello";
	uint32_t i = 0;
	while (i < 546) {
		void *o = sp_object(db);
		sp_setstring(o, "key", key_a, sizeof(key_a));
		sp_setstring(o, "key_b", &i, sizeof(i));
		sp_setstring(o, "value", &i, sizeof(i));
		t( sp_set(db, o) == 0);
		i++;
	}

	i = 322;
	void *cur = sp_cursor(env);
	t( cur != NULL );
	void *o = sp_object(db);
	sp_setstring(o, "key", key_a, sizeof(key_a));
	sp_setstring(o, "key_b", &i, sizeof(i));
	sp_setstring(o, "value", &i, sizeof(i));
	while ((o = sp_get(cur, o))) {
		int asize;
		t( strcmp(key_a, sp_getstring(o, "key", &asize)) == 0 );
		int bsize;
		t( *(uint32_t*)sp_getstring(o, "key_b", &bsize) == i );
		int vsize;
		t( *(uint32_t*)sp_getstring(o, "value", &vsize) == i );
		t( asize == sizeof(key_a) );
		t( bsize == sizeof(i) );
		t( vsize == sizeof(i) );
		i++;
	}
	sp_destroy(cur);
	t( i == 546 );

	t( sp_destroy(env) == 0 );
}
Exemplo n.º 6
0
static void
mt_upsert2(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 5) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_open(env) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.index.upsert", upsert_op, 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.index.key", "u32", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );
	t( sp_open(db) == 0 );
	uint32_t n = 700000;
	uint32_t i, k = 1234;
	uint32_t value = 1;

	void *tx = sp_begin(env);
	t( tx != NULL );

	for (i = 0; i < n; i++) {
		if (i > 0 && (i % 1000) == 0) {
			void *o = sp_document(db);
			t( o != NULL );
			t( sp_setstring(o, "key", &k, sizeof(k)) == 0 );
			void *c = sp_cursor(env);
			t( c != NULL );
			o = sp_get(c, o);
			t( o != NULL );
			t( *(uint32_t*)sp_getstring(o, "value", NULL) == i);
			sp_destroy(o);
			sp_destroy(c);

			t( sp_commit(tx) == 0 );
			tx = sp_begin(env);
			t( tx != NULL );
		}
		void *o = sp_document(db);
		t( o != NULL );
		t( sp_setstring(o, "key", &k, sizeof(k)) == 0 );
		t( sp_setstring(o, "value", &value, sizeof(value)) == 0 );
		t( sp_upsert(db, o) == 0 );

		print_current(i);
	}

	t( sp_commit(tx) == 0 );

	t( sp_destroy(env) == 0 );
}
Exemplo n.º 7
0
static void
github_104(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "key", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme.key", "string,key(0)", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "value", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	t( sp_open(env) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );

	char key_a[] = "aa";
	char key_b[] = "bb";
	char key_c[] = "cc";
	char key_d[] = "dd";

	void *o = sp_document(db);
	t( sp_setstring(o, "key", key_a, sizeof(key_a)) == 0 );
	t( sp_set(db, o) == 0 );
	o = sp_document(db);
	t( sp_setstring(o, "key", key_b, sizeof(key_b)) == 0 );
	t( sp_set(db, o) == 0 );
	o = sp_document(db);
	t( sp_setstring(o, "key", key_c, sizeof(key_c)) == 0 );
	t( sp_set(db, o) == 0 );
	o = sp_document(db);
	t( sp_setstring(o, "key", key_d, sizeof(key_d)) == 0 );
	t( sp_set(db, o) == 0 );

	void *cur = sp_cursor(env);
	t( cur != NULL );
	o = sp_document(db);
	t( o != NULL );
	t( sp_setstring(o, "key", key_b, sizeof(key_b)) == 0 );
	t( sp_setstring(o, "order", "<=", 0) == 0 );
	int i = 0;
	while ((o = sp_get(cur, o))) {
		printf(" %s", (char*)sp_getstring(o, "key", 0));
		i++;
	}
	fflush(NULL);
	t( i == 2 );
	sp_destroy(cur);

	t( sp_destroy(env) == 0 );
}
Exemplo n.º 8
0
static void
cache_test1(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.index.key", "u32",0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setint(env, "compaction.0.branch_wm", 1) == 0 );
	t( sp_open(env) == 0 );

	void *db = sp_getobject(env, "db.test");
	t( db != NULL );

	int i = 0;
	while (i < 185) {
		void *o = sp_object(db);
		t( o != NULL );
		t( sp_setstring(o, "key", &i, sizeof(i)) == 0 );
		t( sp_setstring(o, "value", &i, sizeof(i)) == 0 );
		t( sp_set(db, o) == 0 );
		i++;
	}
	t( sp_setint(env, "db.test.branch", 0) == 0 );
	i = 185;
	while (i < 370) {
		void *o = sp_object(db);
		t( o != NULL );
		t( sp_setstring(o, "key", &i, sizeof(i)) == 0 );
		t( sp_setstring(o, "value", &i, sizeof(i)) == 0 );
		t( sp_set(db, o) == 0 );
		i++;
	}
	t( i == 370 );
	t( sp_setint(env, "db.test.branch", 0) == 0 );

	void *cur = sp_cursor(env);
	t( cur != NULL );
	void *o = sp_object(db);
	i = 0;
	while ((o = sp_get(cur, o))) {
		t( *(int*)sp_getstring(o, "key", NULL) == i );
		i++;
	}
	t( sp_destroy(cur) == 0 );

	t( sp_getint(env, "db.test.index.read_disk") == 2 );
	t( sp_getint(env, "db.test.index.read_cache") == 553 );
	t( sp_destroy(env) == 0 );
}
Exemplo n.º 9
0
jlong JNICALL Java_eu_unicredit_sophia_SophiaInterface_sp_1cursor
  (JNIEnv * env, jobject obj, jlongArray args)
{
    jlong* array = (*env)->GetLongArrayElements(env, args,JNI_FALSE);
    jint size = (*env)->GetArrayLength(env, args);
    void* ret = NULL;
    switch(size) {
      case 0:
        printf("Not supported\n");
        break;
      case 1:
        ret = sp_cursor((void*)array[0]);
        break;
      case 2:
        ret = sp_cursor((void*)array[0],
                        (void*)array[1]);
        break;
      default:
        printf("Not supported\n");
        break;
    };
    return (jlong)ret;
}
Exemplo n.º 10
0
Arquivo: db.c Projeto: jwerle/todo.c
int
todo_db_foreach (todo_db_t *db, void (*fn)(char *key, char *value, todo_db_t *db)) {
  void *c = sp_cursor(db->dbh, SPGT, NULL, 0);

  if (NULL == c) {
    return -1;
  }

  while (sp_fetch(c)) {
    fn(strdup(sp_key(c)), strdup(sp_value(c)), db);
  }

  sp_destroy(c);
  return 0;
}
Exemplo n.º 11
0
static void
scheme_comparator(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "key", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme.key", "string,key(0)", 0) == 0 );
	t( sp_setstring(env, "db.test.index.comparator", (char*)(intptr_t)comparator, 0) );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );
	t( sp_open(env) == 0 );

	uint32_t key = 0;
	while (key < 10) {
		void *o = sp_document(db);
		t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
		t( sp_set(db, o) == 0 );
		key++;
	}

	key = 4;
	void *o = sp_document(db);
	sp_setstring(o, "key", &key, sizeof(key));
	o = sp_get(db, o);
	t( o != NULL );
	sp_destroy(o);

	key = 0;
	o = sp_document(db);
	sp_setstring(o, "order", ">=", 0);
	sp_setstring(o, "key", &key, sizeof(key));
	void *c = sp_cursor(env);
	while ((o = sp_get(c, o))) {
		t( *(uint32_t*)sp_getstring(o, "key", NULL) == key );
		key++;
	}
	t(key == 10);
	sp_destroy(c);

	t( sp_destroy(env) == 0 );
}
Exemplo n.º 12
0
sphia_iterator_node_t *
sphia_iterator_next (sphia_iterator_t *self) {
  sphia_iterator_node_t *node = NULL;
  size_t keysize = 0;
  size_t valuesize = 0;
  const char *key = NULL;
  const char *value = NULL;

  if (NULL == self->cursor) {
    self->cursor = sp_cursor(self->db
      , self->direction
      , self->last_key
      , self->last_keysize);
    if (NULL == self->cursor) return NULL;
  }

  if (0 == sp_fetch(self->cursor)) return NULL;

  if (!(node = malloc(sizeof(sphia_iterator_node_t))))
    return NULL;

  node->key = NULL;
  node->value = NULL;

  if (!(key = sp_key(self->cursor)) || !(value = sp_value(self->cursor))) {
    free(node);
    return NULL;
  }

  keysize = sp_keysize(self->cursor);
  valuesize = sp_valuesize(self->cursor);

  // record so we can create a
  // cursor at this position
  self->last_key = key;
  self->last_keysize = keysize;

  if (!(node->key = sphia_strdup(key))
    || !(node->value = sphia_strdup(value))) {
    sphia_iterator_node_free(node);
    return NULL;
  }

  return node;
}
Exemplo n.º 13
0
static void
github_97(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setint(env, "db.test.compaction.branch_wm", 1) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "key", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme.key", "u32,key(0)", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "value", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	t( sp_open(env) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );

	/* we must pass sizeof(uint32_t) in sp_setstring() */
	uint32_t i = 0;
	while ( i < 100 ) {
		void *o = sp_document(db);
		t( sp_setstring(o, "key", &i, sizeof(i)) == 0 );   /* < */
		t( sp_setstring(o, "value", &i, sizeof(i)) == 0 ); /* < */
		t( sp_set(db, o) == 0 );
		i++;
	}

	void *cur = sp_cursor(env);
	t( cur != NULL );

	void *o = sp_document(db);
	t( o != NULL );
	uint32_t key = 99;
	t( sp_setstring(o, "key", &key, sizeof(key)) == 0 ); /* <  */

	i = 0;
	while ((o = sp_get(cur, o)))
		i++;
	t( i == 1 );
	sp_destroy(cur);

	t( sp_destroy(env) == 0 );
}
Exemplo n.º 14
0
static int
rangefwd(int n)
{
	void *c = sp_cursor(db, SPGTE, NULL, 0);
	if (c == NULL) {
		printf("cursor failed: %s\n", sp_error(db));
		return 1;
	}
	while (sp_fetch(c)) {
		const char *k = sp_key(c);
		size_t sz = sp_valuesize(c);
		(void)k;
		(void)sz;
		keytraversed++;
	}
	sp_destroy(c);
	return 0;
}
Exemplo n.º 15
0
void
st_scene_truncate(stscene *g, stc *cx)
{
    printf(".truncate");
    fflush(NULL);
    void *o = sp_object(cx->db);
    t( o != NULL );
    void *c = sp_cursor(cx->db, o);
    t( c != NULL );
    while ((o = sp_get(c))) {
        void *k = sp_object(cx->db);
        t( k != NULL );
        int keysize;
        void *key = sp_get(o, "key", &keysize);
        sp_set(k, "key", key, keysize);
        t( sp_delete(cx->db, k) == 0 );
    }
    t( sp_destroy(c) == 0 );
}
Exemplo n.º 16
0
/* Count the number of records in the database. This is O(n) time,
 * and then absolutely inefficient, but keeping an up-to-date counter
 * of the records would require to check the existence of a record before
 * each insert or delete operation, which would be very costly at the end.
 */
static PyObject *
sophia_db_count_records(SophiaDB *db)
{
    size_t count = 0;
    
    ensure_is_opened(db, NULL);
    
    void *cur = sp_cursor(db->db, SPGT, NULL, 0);
    if (!cur) {
        PyErr_SetString(SophiaError, sp_error(db->db));
        return NULL;
    }
    
    while ((sp_fetch(cur)))
        count++;
    sp_destroy(cur);
    
    return PyLong_FromSize_t(count);
}
Exemplo n.º 17
0
static void
scheme_timestamp1(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "key", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme.key", "u32,key(0)", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "ts0", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme.ts0", "u32,timestamp", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "ts1", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme.ts1", "u32,timestamp", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );
	t( sp_open(env) == 0 );

	uint32_t key = 0;
	while (key < 10) {
		void *o = sp_document(db);
		t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
		t( sp_set(db, o) == 0 );
		key++;
	}

	key = 0;
	void *o = sp_document(db);
	sp_setstring(o, "order", ">=", 0);
	void *c = sp_cursor(env);
	while ((o = sp_get(c, o))) {
		t( *(uint32_t*)sp_getstring(o, "key", NULL) == key );
		t( *(uint32_t*)sp_getstring(o, "ts0", NULL) > 0 );
		t( *(uint32_t*)sp_getstring(o, "ts1", NULL) > 0 );
		key++;
	}

	t( sp_destroy(env) == 0 );
}
Exemplo n.º 18
0
int
sphia_iterator_direction (sphia_iterator_t *self, sporder direction) {
  if (NULL == self) return -1;
  if (direction == self->direction) return 0;

  // can't change the direction of an active
  // cursor, so we need to close it first
  if (self->cursor) sphia_iterator_end(self);

  self->cursor = sp_cursor(self->db
    , direction
    , self->last_key
    , self->last_keysize);

  if (self->cursor) {
    self->direction = direction;
    return 0;
  }

  return -1;
}
Exemplo n.º 19
0
Arquivo: db.c Projeto: jwerle/todo.c
int
todo_db_rm_each (todo_db_t *db, int (*fn)(char *key, char *value, todo_db_t *db)) {
  int rc = -1;
  int i = 0, l = 0;
  void *c = sp_cursor(db->dbh, SPGT, NULL, 0);
  const char *ckey;
  const char *cvalue;
  char *keys[512];
  size_t sizes[512] = { };
  size_t size;

  while (sp_fetch(c)) {
    ckey = sp_key(c);
    cvalue = sp_value(c);
    size = sp_keysize(c);
    rc = fn(strdup((char *) ckey), strdup((char *)cvalue), db);
    if (0 == rc) {
      keys[i++] = (char *)ckey;
      sizes[i] = size;
      if (-1 == rc) {
        return rc;
      }
    }
  }


  sp_destroy(c);

  l = i;
  i = 0;
  for (; i < l; ++i) {
    rc = sp_delete(db->dbh, (const char *)keys[i], strlen((const char*) keys[i]));
    if (-1 == rc) {
      return rc;
    }
  }

  return rc;
}
Exemplo n.º 20
0
sphia_iterator_t *
sphia_iterator_new (sphia_t *self) {
  if (NULL == self) return NULL;

  void *cursor = NULL;
  sphia_iterator_t *iterator;
  if (!(iterator = malloc(sizeof(sphia_iterator_t))))
    return NULL;

  if (!(cursor = sp_cursor(self->db, SPGT, NULL, 0))) {
    free(iterator);
    return NULL;
  }

  iterator->cursor = cursor;
  iterator->direction = SPGT;
  iterator->db = self->db;
  iterator->last_key = NULL;
  iterator->last_keysize = 0;

  return iterator;
}
Exemplo n.º 21
0
Arquivo: db.c Projeto: jwerle/todo.c
char *
todo_db_reduce (todo_db_t *db, char *(*fn)(char *curkey, char *curvalue, char *nextkey, char *nextvalue, todo_db_t *db)) {
  void *c = sp_cursor(db->dbh, SPGT, NULL, 0);
  char *reduced = NULL;
  char *tmp = "";
  int i = 0;
  char *ckey, *cvalue;
  char *nkey, *nvalue;

  if (NULL == c) {
    return NULL;
  }

  while (sp_fetch(c)) {
    // next value
    if (i++ % 2) {
      nkey = strndup(sp_key(c), sp_keysize(c));
      nvalue = strndup(sp_value(c), sp_valuesize(c));
      reduced = fn(ckey, cvalue, nkey, nvalue, db);
      free(nkey);
      free(nvalue);
    } else {
      ckey =  strdup(sp_key(c));
      cvalue = strdup(sp_value(c));
    }

    if (NULL != reduced) break;
  }

  if (NULL == reduced) {
    reduced = fn(ckey, cvalue, tmp, tmp, db);
  }


  sp_destroy(c);

  return reduced;
}
Exemplo n.º 22
0
int sn_storageinfo(snstorage *s, snbuf *info)
{
	int rc = 0;
	assert(s->env != NULL );
	char buf[1024];
	void *c = sp_cursor(s->env, NULL);
	void *o;
	while ((o = sp_get(c, NULL)))
	{
		int keysize = 0;
		int valuesize = 0;
		char *key = sp_getstring(o, "key", &keysize);
		char *value = sp_getstring(o, "value", &valuesize);
		int len = snprintf(buf, sizeof(buf), "%s = %s\n",
				key, (value) ? value : "");
		rc = sn_bufadd(info, buf, len);
		if (snunlikely(rc == -1))
			break;
		sp_destroy(o);
	}
	sp_destroy(c);
	return rc;
}
Exemplo n.º 23
0
static void
gc_test1(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setint(env, "db.test.compaction.cache", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "key", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme.key", "u32,key(0)", 0) == 0 );
	t( sp_setstring(env, "db.test.scheme", "value", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	t( sp_open(env) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );

	void *t0 = sp_begin(env);

	int value = 0;
	int i = 0;
	while ( i < 100 ) {
		value = i;
		void *o = sp_document(db);
		t( sp_setstring(o, "key", &i, sizeof(i)) == 0 );
		t( sp_setstring(o, "value", &i, sizeof(i)) == 0 );
		t( sp_set(db, o) == 0 );
		i++;
	}

	i = 0;
	while ( i < 100 ) {
		value = i + 1;
		void *o = sp_document(db);
		t( sp_setstring(o, "key", &i, sizeof(i)) == 0 );
		t( sp_setstring(o, "value", &value, sizeof(value)) == 0 );
		t( sp_set(db, o) == 0 );
		i++;
	}
	t( sp_setint(env, "db.test.compaction.compact", 0) == 0 );

	i = 0;
	void *o = sp_document(db);
	t( o != NULL );
	void *cur = sp_cursor(env);
	while ((o = sp_get(cur, o))) {
		t( *(int*)sp_getstring(o, "key", NULL) == i );
		t( *(int*)sp_getstring(o, "value", NULL) == i + 1);
		i++;
	}
	sp_destroy(cur);

	t( sp_getint(env, "db.test.index.count") == 200 );
	t( sp_getint(env, "db.test.index.count_dup") == 100 );

	t( sp_setint(env, "db.test.compaction.compact", 0) == 0 );

	i = 0;
	o = sp_document(db);
	t( o != NULL );
	cur = sp_cursor(env);
	while ((o = sp_get(cur, o))) {
		t( *(int*)sp_getstring(o, "key", NULL) == i );
		t( *(int*)sp_getstring(o, "value", NULL) == i + 1);
		i++;
	}
	sp_destroy(cur);

	t( sp_getint(env, "db.test.index.count") == 200 );
	t( sp_getint(env, "db.test.index.count_dup") == 100 );

	sp_destroy(t0);
	t( sp_destroy(env) == 0 );
}
Exemplo n.º 24
0
int main(int argc, char *argv[])
{
	(void)argc;
	(void)argv;

	/* open or create environment and database */
	void *env = sp_env();
	sp_setstring(env, "sophia.path", "_test", 0);
	sp_setstring(env, "db", "test", 0);
	sp_setstring(env, "db.test.index", "key", 0);
	sp_setstring(env, "db.test.index", "key_j", 0);
	sp_setstring(env, "db.test.index", "key_k", 0);
	sp_setstring(env, "db.test.index.key",   "u32", 0);
	sp_setstring(env, "db.test.index.key_j", "u32", 0);
	sp_setstring(env, "db.test.index.key_k", "u32", 0);
	void *db = sp_getobject(env, "db.test");
	int rc = sp_open(env);
	if (rc == -1)
		goto error;

	/* set */
	uint32_t i = 0;
	uint32_t j = 0;
	uint32_t k = 0;
	for (i = 0; i <= 2; i++) {
		for (j = 0; j <= 2; j++) {
			for (k = 0; k <= 2; k++) {
				void *o = sp_document(db);
				sp_setstring(o, "key",   &i, sizeof(i));
				sp_setstring(o, "key_j", &j, sizeof(j));
				sp_setstring(o, "key_k", &k, sizeof(k));
				rc = sp_set(db, o);
				if (rc == -1)
					goto error;
			}
		}
	}

	/* get random key */
	i = 1;
	j = 2;
	k = 0;
	void *o = sp_document(db);
	sp_setstring(o, "key",   &i, sizeof(i));
	sp_setstring(o, "key_j", &j, sizeof(j));
	sp_setstring(o, "key_k", &k, sizeof(k));
	o = sp_get(db, o);
	assert(o != NULL);
	sp_destroy(o);

	/* do forward iteration */
	void *cursor = sp_cursor(env);
	o = sp_document(db);
	while ((o = sp_get(cursor, o))) {
		i = *(uint32_t*)sp_getstring(o, "key", NULL);
		j = *(uint32_t*)sp_getstring(o, "key_j", NULL);
		k = *(uint32_t*)sp_getstring(o, "key_k", NULL);
		printf("%"PRIu32".%"PRIu32".%"PRIu32 "\n", i, j, k);
	}
	sp_destroy(cursor);

	/* finish work */
	sp_destroy(env);
	return 0;

error:;
	int size;
	char *error = sp_getstring(env, "sophia.error", &size);
	printf("error: %s\n", error);
	free(error);
	sp_destroy(env);
	return 1;
}
Exemplo n.º 25
0
static void
get_cache_test1(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "compaction.0.branch_wm", 1) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.index.key", "u32", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	t( sp_open(env) == 0 );
	void *db = sp_getobject(env, "db.test");

	uint32_t key = 7;
	void *o = sp_object(db);
	t( o != NULL );
	t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
	t( sp_set(db, o) == 0 );

	key = 8;
	o = sp_object(db);
	t( o != NULL );
	t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
	t( sp_set(db, o) == 0 );

	void *cursor;

	/* default */
	cursor = sp_cursor(env);
	o = sp_object(db);
	t( o != NULL );
	t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
	o = sp_get(cursor, o);
	t( o != NULL );
	sp_destroy(o);
	sp_destroy(cursor);

	/* cache only */
	cursor = sp_cursor(env);
	o = sp_object(db);
	t( o != NULL );
	t( sp_setint(o, "cache_only", 1) == 0 );
	t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
	o = sp_get(cursor, o);
	t( o == NULL );
	sp_destroy(cursor);

	t( sp_setint(env, "db.test.branch", 0) == 0 );

	/* start by filling cache (gte) */
	cursor = sp_cursor(env);
	o = sp_object(db);
	t( o != NULL );
	o = sp_get(cursor, o);
	t( o != NULL );
	t( *(uint32_t*)sp_getstring(o, "key", NULL) == 7 );

	/* continue from cache */
	t( sp_setint(o, "cache_only", 1) == 0 );

	o = sp_get(cursor, o);
	t( o != NULL );
	t( *(uint32_t*)sp_getstring(o, "key", NULL) == 8 );
	sp_destroy(o);
	sp_destroy(cursor);

	t( sp_destroy(env) == 0 );
}
Exemplo n.º 26
0
static inline int
workflow_write_read(void *env, void *db)
{
	/* write */
	void *o = sp_document(db);
	if (o == NULL)
		return -1;
	uint32_t key = 123;
	int rc;
	rc = sp_setstring(o, "key", &key, sizeof(key));
	if (rc == -1) {
		sp_destroy(o);
		return -1;
	}
	rc = sp_setstring(o, "value", &key, sizeof(key));
	if (rc == -1) {
		sp_destroy(o);
		return -1;
	}
	rc = sp_set(db, o);
	if (rc == -1)
		return -1;

	/* transaction */
	void *tx = sp_begin(env);
	if (tx == NULL)
		return -1;
	o = sp_document(db);
	if (o == NULL)
		return -1;
	key = 123;
	rc = sp_setstring(o, "key", &key, sizeof(key));
	if (rc == -1) {
		sp_destroy(o);
		sp_destroy(tx);
		return -1;
	}
	rc = sp_setstring(o, "value", &key, sizeof(key));
	if (rc == -1) {
		sp_destroy(o);
		sp_destroy(tx);
		return -1;
	}
	rc = sp_set(tx, o);
	if (rc == -1) {
		sp_destroy(tx);
		return -1;
	}
	o = sp_document(db);
	if (o == NULL)
		return -1;
	rc = sp_setstring(o, "key", &key, sizeof(key));
	if (rc == -1) {
		sp_destroy(o);
		sp_destroy(tx);
		return -1;
	}
	o = sp_get(tx, o);
	if (o == NULL) {
		sp_destroy(tx);
		return -1;
	}
	sp_destroy(o);
	rc = sp_commit(tx);
	if (rc == -1)
		return -1;

	/* read */
	o = sp_document(db);
	if (o == NULL)
		return -1;
	rc = sp_setstring(o, "key", &key, sizeof(key));
	if (rc == -1) {
		sp_destroy(o);
		return -1;
	}
	o = sp_get(db, o);
	if (o == NULL)
		return -1;
	sp_destroy(o);

	/* cursor */
	void *c = sp_cursor(env);
	if (c == NULL)
		return -1;
	o = sp_document(db);
	if (o == NULL) {
		sp_destroy(c);
		return -1;
	}
	o = sp_get(c, o);
	if (o == NULL) {
		sp_destroy(c);
		return -1;
	}
	sp_destroy(o);
	sp_destroy(c);
	return 0;
}
Exemplo n.º 27
0
static void
cursor_md_test0(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setint(env, "log.sync", 0) == 0 );
	t( sp_setint(env, "log.rotate_sync", 0) == 0 );
	t( sp_setstring(env, "db", "t0", 0) == 0 );
	t( sp_setstring(env, "db", "t1", 0) == 0 );
	t( sp_setstring(env, "db.t0.scheme", "key", 0) == 0 );
	t( sp_setstring(env, "db.t1.scheme", "key", 0) == 0 );
	t( sp_setstring(env, "db.t0.scheme", "value", 0) == 0 );
	t( sp_setstring(env, "db.t1.scheme", "value", 0) == 0 );
	t( sp_setstring(env, "db.t0.scheme.key", "u32,key", 0) == 0 );
	t( sp_setstring(env, "db.t1.scheme.key", "u32,key", 0) == 0 );
	t( sp_setint(env, "db.t0.sync", 0) == 0 );
	t( sp_setint(env, "db.t1.sync", 0) == 0 );

	void *t0 = sp_getobject(env, "db.t0");
	t( t0 != NULL );
	void *t1 = sp_getobject(env, "db.t1");
	t( t1 != NULL );
	t( sp_open(env) == 0 );

	uint32_t key = 7;
	uint32_t value = 7;
	void *o = sp_document(t0);
	t( o != NULL );
	t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
	t( sp_setstring(o, "value", &value, sizeof(value)) == 0 );
	t( sp_set(t0, o) == 0 );
	o = sp_document(t1);
	t( o != NULL );
	t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
	t( sp_setstring(o, "value", &value, sizeof(value)) == 0 );
	t( sp_set(t1, o) == 0 );

	void *c = sp_cursor(env);

	value = 8;
	o = sp_document(t0);
	t( o != NULL );
	t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
	t( sp_setstring(o, "value", &value, sizeof(value)) == 0 );
	t( sp_set(t0, o) == 0 );
	o = sp_document(t1);
	t( o != NULL );
	t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
	t( sp_setstring(o, "value", &value, sizeof(value)) == 0 );
	t( sp_set(t1, o) == 0 );

	o = sp_document(t0);
	o = sp_get(c, o);
	t( o != NULL );
	t( *(uint32_t*)sp_getstring(o, "value", 0) == 7 );
	o = sp_get(c, o);
	t( o == NULL );

	o = sp_document(t1);
	o = sp_get(c, o);
	t( o != NULL );
	t( *(uint32_t*)sp_getstring(o, "value", 0) == 7 );
	o = sp_get(c, o);
	t( o == NULL );

	sp_destroy(c);

	o = sp_document(t0);
	sp_setstring(o, "order", ">", 0);
	o = sp_get(t0, o);
	t( o != NULL );
	t( *(uint32_t*)sp_getstring(o, "value", 0) == 8 );
	o = sp_get(t0, o);
	t( o == NULL );

	o = sp_document(t1);
	sp_setstring(o, "order", ">", 0);
	o = sp_get(t1, o);
	t( o != NULL );
	t( *(uint32_t*)sp_getstring(o, "value", 0) == 8 );
	o = sp_get(t1, o);
	t( o == NULL );

	t( sp_destroy(env) == 0 );
}
Exemplo n.º 28
0
static void
compact_delete_node1(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setint(env, "compaction.0.branch_wm", 1) == 0 );
	t( sp_setint(env, "compaction.node_size", 524288 /* 512K */) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.index.key", "u32", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );
	t( sp_open(env) == 0 );

	int key = 0;
	char value[100];
	memset(value, 0, sizeof(value));
	while (key < 13000) {
		void *o = sp_object(db);
		t( o != NULL );
		t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
		t( sp_setstring(o, "value", value, sizeof(value)) == 0 );
		t( sp_set(db, o) == 0 );
		key++;
	}
	t( sp_setint(env, "db.test.branch", 0) == 0 );
	t( sp_setint(env, "db.test.compact", 0) == 0 );

	t( sp_getint(env, "db.test.index.node_count") == 2 );

	key = 0;
	while (key < 5511 ) {
		void *o = sp_object(db);
		t( o != NULL );
		t( sp_setstring(o, "key", &key, sizeof(key)) == 0 );
		t( sp_delete(db, o) == 0 );
		key++;
	}

	t( sp_setint(env, "db.test.branch", 0) == 0 );
	t( sp_setint(env, "db.test.compact", 0) == 0 );

	t( sp_getint(env, "db.test.index.node_count") == 1 );

	void *o = sp_object(db);
	void *cur = sp_cursor(db, o);
	while ((o = sp_get(cur, NULL))) {
		t( sp_delete(db, o) == 0 );
		key++;
		sp_destroy(o);
	}
	sp_destroy(cur);
	t( key == 13000 );

	t( sp_setint(env, "db.test.branch", 0) == 0 );
	t( sp_setint(env, "db.test.compact", 0) == 0 );

	t( sp_getint(env, "db.test.index.node_count") == 1 );
	t( sp_destroy(env) == 0 );
}
Exemplo n.º 29
0
static void
snapshot_cursor(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 0) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setstring(env, "db.test.index.key", "u32", 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );
	t( sp_open(env) == 0 );

	int i = 0;
	while ( i < 100 ) {
		void *o = sp_object(db);
		t( sp_setstring(o, "key", &i, sizeof(i)) == 0 );
		t( sp_setstring(o, "value", &i, sizeof(i)) == 0 );
		t( sp_set(db, o) == 0 );
		i++;
	}

	t( sp_setstring(env, "snapshot", "test_snapshot", 0) == 0 );
	void *snapshot = sp_getobject(env, "snapshot.test_snapshot");
	t( snapshot != NULL );

	i = 0;
	while ( i < 100 ) {
		void *o = sp_object(db);
		int value = i + 1;
		t( sp_setstring(o, "key", &i, sizeof(i)) == 0 );
		t( sp_setstring(o, "value", &value, sizeof(value)) == 0 );
		t( sp_set(db, o) == 0 );
		i++;
	}

	i = 0;
	void *o = sp_object(db);
	t( o != NULL );
	t( sp_setstring(o, "order", ">=", 0) == 0 );
	void *cur = sp_cursor(env);
	while ((o = sp_get(cur, o))) {
		t( *(int*)sp_getstring(o, "key", NULL) == i );
		t( *(int*)sp_getstring(o, "value", NULL) == i + 1);
		i++;
	}
	sp_destroy(cur);

	i = 0;
	o = sp_object(db);
	t( o != NULL );
	t( sp_setstring(o, "order", ">=", 0) == 0 );
	cur = sp_cursor(snapshot);
	while ((o = sp_get(cur, o))) {
		t( *(int*)sp_getstring(o, "key", NULL) == i );
		t( *(int*)sp_getstring(o, "value", NULL) == i );
		i++;
	}
	sp_destroy(cur);

	t( sp_destroy(env) == 0 );
}
Exemplo n.º 30
0
static void
mt_set_get_document_multipart_cursor(void)
{
	void *env = sp_env();
	t( env != NULL );
	t( sp_setstring(env, "sophia.path", st_r.conf->sophia_dir, 0) == 0 );
	t( sp_setint(env, "scheduler.threads", 5) == 0 );
	t( sp_setstring(env, "log.path", st_r.conf->log_dir, 0) == 0 );
	t( sp_setstring(env, "db", "test", 0) == 0 );
	t( sp_setstring(env, "db.test.path", st_r.conf->db_dir, 0) == 0 );
	t( sp_setint(env, "db.test.sync", 0) == 0 );
	t( sp_setstring(env, "db.test.format", "document", 0) == 0 );
	t( sp_setstring(env, "db.test.index.key", "u32", 0) == 0 );
	t( sp_setstring(env, "db.test.index", "key_b", 0) == 0 );
	t( sp_setstring(env, "db.test.index.key_b", "u32", 0) == 0 );
	void *db = sp_getobject(env, "db.test");
	t( db != NULL );
	t( sp_open(env) == 0 );

	struct document {
		uint32_t value;
		char used0[89];
		uint32_t key_a;
		char used1[15];
		uint32_t key_b;
		char used2[10];
	} sspacked;
	struct document doc;
	memset(&doc, 'x', sizeof(doc));

	uint32_t n = 500000;
	uint32_t i;

	for (i = 0; i < n; i++) {
		doc.key_a = i;
		doc.key_b = i;
		doc.value = doc.key_a ^ doc.key_b;
		void *o = sp_object(db);
		t( o != NULL );
		t( sp_setstring(o, "key", &doc.key_a, sizeof(doc.key_a)) == 0 );
		t( sp_setstring(o, "key_b", &doc.key_b, sizeof(doc.key_b)) == 0 );
		t( sp_setstring(o, "value", &doc, sizeof(doc)) == 0 );
		t( sp_set(db, o) == 0 );
		print_current(i);
	}

	i = 0;
	void *o = sp_object(db);
	t( o != NULL );
	void *cursor = sp_cursor(env);
	t( cursor != NULL );
	while ((o = sp_get(cursor, o))) {
		int valuesize = 0;
		struct document *ret =
			(struct document*)sp_getstring(o, "value", &valuesize);
		t( valuesize == sizeof(doc) );
		t( ret->key_a == i );
		t( ret->key_b == i );
		print_current(i);
		i++;
	}
	sp_destroy(cursor);
	t( i == n );

	t( sp_destroy(env) == 0 );
}