Skip to content

Commit

Permalink
Merge branch 'watson' into 'master'
Browse files Browse the repository at this point in the history
* watson:
  Destroy lua state before exiting couchscript
  Return a non-zero exit code if a Lua test fails
  Free db handle in couchscript when object is GC'd

Change-Id: I6995194d9faab7b1921c80076ce9958aa6da387a
  • Loading branch information
Chippiewill committed Mar 31, 2016
2 parents 35f7c2c + 9e90a38 commit 1d86ff3
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 4 deletions.
52 changes: 49 additions & 3 deletions src/couchscript.cc
Expand Up @@ -32,6 +32,13 @@ extern "C" {
#include <lauxlib.h>
}

#define CHECK_NULL(db) \
if(db == nullptr) { \
lua_pushstring(ls, "The db instance is closed"); \
lua_error(ls); \
return 1; \
}

typedef union {
struct {
uint64_t cas;
Expand Down Expand Up @@ -119,26 +126,35 @@ extern "C" {
{
Db **d = static_cast<Db **>(luaL_checkudata(ls, 1, "couch"));
assert(d);
assert(*d);
return *d;
}

static void nullDb(lua_State *ls)
{
Db **d = static_cast<Db **>(luaL_checkudata(ls, 1, "couch"));
*d = nullptr;
}

static int couch_close(lua_State *ls)
{
Db *db = getDb(ls);
CHECK_NULL(db)

couchstore_error_t err = couchstore_close_file(db);
couchstore_free_db(db);
if (err != COUCHSTORE_SUCCESS) {
lua_pushstring(ls, "error closing database");
lua_error(ls);
return 1;
}
nullDb(ls);
return 0;
}

static int couch_commit(lua_State *ls)
{
Db *db = getDb(ls);
CHECK_NULL(db)

if (couchstore_commit(db) != COUCHSTORE_SUCCESS) {
lua_pushstring(ls, "error committing");
Expand All @@ -157,7 +173,8 @@ extern "C" {
}

Db *db = getDb(ls);
assert(db);
CHECK_NULL(db)

Doc *doc(NULL);
lua_remove(ls, 1);
DocInfo *docinfo = getDocInfo(ls);
Expand Down Expand Up @@ -192,6 +209,7 @@ extern "C" {
Doc *doc;
DocInfo *docinfo;
Db *db = getDb(ls);
CHECK_NULL(db)

size_t klen;
const char *key = luaL_checklstring(ls, 2, &klen);
Expand Down Expand Up @@ -237,6 +255,7 @@ extern "C" {
}

Db *db = getDb(ls);
CHECK_NULL(db)

int64_t arg = static_cast<int64_t>(luaL_checknumber(ls, 2));
cs_off_t location(0);
Expand Down Expand Up @@ -286,6 +305,7 @@ extern "C" {
}

Db *db = getDb(ls);
CHECK_NULL(db)

int rc = couchstore_save_document(db, &doc, &docinfo, 0);
if (rc < 0) {
Expand Down Expand Up @@ -407,6 +427,7 @@ extern "C" {
}

Db *db = getDb(ls);
CHECK_NULL(db)

int rc = couchstore_save_documents(db, bs.docs, bs.infos,
bs.size, COMPRESS_DOC_BODIES);
Expand Down Expand Up @@ -468,6 +489,7 @@ extern "C" {
docinfo.rev_meta.buf = revbuf.bytes;

Db *db = getDb(ls);
CHECK_NULL(db)

int rc = couchstore_save_document(db, &doc, &docinfo,
COMPRESS_DOC_BODIES);
Expand Down Expand Up @@ -497,6 +519,7 @@ extern "C" {
doc.deleted = 0;

Db *db = getDb(ls);
CHECK_NULL(db)

int rc = couchstore_save_local_document(db, &doc);
if (rc < 0) {
Expand Down Expand Up @@ -524,6 +547,7 @@ extern "C" {
doc.deleted = 1;

Db *db = getDb(ls);
CHECK_NULL(db)

int rc = couchstore_save_local_document(db, &doc);
if (rc < 0) {
Expand All @@ -548,6 +572,7 @@ extern "C" {

LocalDoc *doc;
Db *db = getDb(ls);
CHECK_NULL(db)

size_t klen;
// Should be const :/
Expand Down Expand Up @@ -618,6 +643,7 @@ extern "C" {
}

Db *db = getDb(ls);
CHECK_NULL(db)

uint64_t since((uint64_t)luaL_checknumber(ls, 2));
couchstore_docinfos_options options((uint64_t)luaL_checknumber(ls, 3));
Expand Down Expand Up @@ -645,6 +671,17 @@ extern "C" {
return 0;
}

static int couch_gc(lua_State *ls) {
Db *db = getDb(ls);
if(db != nullptr) {
// Not allowed to error during garbage collection.
couchstore_close_file(db);
couchstore_free_db(db);
nullDb(ls);
}
return 1;
}

static const luaL_Reg couch_funcs[] = {
{"open", couch_open},
{NULL, NULL}
Expand All @@ -663,6 +700,7 @@ extern "C" {
{"commit", couch_commit},
{"close", couch_close},
{"truncate", couch_truncate},
{"__gc", couch_gc},
{NULL, NULL}
};

Expand Down Expand Up @@ -821,6 +859,14 @@ int main(int argc, char **argv)
int rv(luaL_dofile(ls, argv[1]));
if (rv != 0) {
std::cerr << "Error running stuff: " << lua_tostring(ls, -1) << std::endl;
return rv;
}

int top = lua_gettop(ls);
int rc = 1;
if (top && lua_isnumber(ls, top)) {
rc = static_cast<int>(lua_tonumber(ls, top));
}
return rv;
lua_close(ls);
return rc;
}
1 change: 1 addition & 0 deletions tests/bulk.lua
Expand Up @@ -54,3 +54,4 @@ end

testlib.run_test("Explicit bulk test", test_explicit)
testlib.run_test("Big bulk test", large_txn_bulk_test)
return testlib.fail_count()
1 change: 1 addition & 0 deletions tests/changessincefilter.lua
Expand Up @@ -67,3 +67,4 @@ end

testlib.run_test("Filter deletes", test_filter_deletes)
testlib.run_test("Filter mutations", test_filter_mutations)
return testlib.fail_count()
1 change: 1 addition & 0 deletions tests/compact.lua
Expand Up @@ -57,3 +57,4 @@ end

testlib.run_test("Compaction test", compaction_test)
os.remove(outfile)
return testlib.fail_count()
1 change: 1 addition & 0 deletions tests/corrupt.lua
Expand Up @@ -77,3 +77,4 @@ end

testlib.run_test("Simple truncation test", simpletrunc)
testlib.run_test("Various mangling of headers", header_mangling)
return testlib.fail_count()
1 change: 1 addition & 0 deletions tests/dropdel.lua
Expand Up @@ -64,3 +64,4 @@ end

testlib.run_test("Deletion dropping test", compaction_test)
os.remove(outfile)
return testlib.fail_count()
1 change: 1 addition & 0 deletions tests/large.lua
Expand Up @@ -81,3 +81,4 @@ end

testlib.run_test("Big item test bulk", test_big_bulk)
testlib.run_test("Big item test sequential", test_big_sequential)
return testlib.fail_count()
1 change: 1 addition & 0 deletions tests/largefile.lua
Expand Up @@ -18,3 +18,4 @@ function bigdb(dbname)
end

testlib.run_test("A Big Database", bigdb)
return testlib.fail_count()
1 change: 1 addition & 0 deletions tests/localdoc.lua
Expand Up @@ -47,3 +47,4 @@ function localtest(dbname)
end

testlib.run_test("Local doc test", localtest)
return testlib.fail_count()
7 changes: 6 additions & 1 deletion tests/testlib.lua
@@ -1,5 +1,5 @@
local M = {}

local failures = 0

-- Verify a doc with the given key exists with the given value in the
-- given database.
Expand Down Expand Up @@ -54,7 +54,12 @@ function M.run_test(name, fun)
print(name .. ": PASS")
else
print(name .. ": FAIL (" .. result .. ")")
failures = failures + 1
end
end

function M.fail_count()
return failures
end

return M

0 comments on commit 1d86ff3

Please sign in to comment.