1
0
Fork 0
arangodb/js/server/tests/shell/shell-compaction-mmfiles-no...

999 lines
29 KiB
JavaScript

/*jshint globalstrict:false, strict:false, sub: true */
/*global fail, assertEqual, assertTrue, assertFalse */
////////////////////////////////////////////////////////////////////////////////
/// @brief test the compaction
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var internal = require("internal");
var testHelper = require("@arangodb/test-helper").Helper;
var ArangoCollection = require("@arangodb/arango-collection").ArangoCollection;
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: collection
////////////////////////////////////////////////////////////////////////////////
function CompactionSuite () {
'use strict';
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief create movement of shapes
////////////////////////////////////////////////////////////////////////////////
testShapesMovement : function () {
var collectionName = "example";
internal.db._drop(collectionName);
var cn = internal.db._create(collectionName, { "journalSize" : 1048576 });
var x, i, j, doc;
for (i = 0; i < 1000; ++i) {
doc = {
_key: "old" + i,
a: i,
b: "test" + i,
values: [ ],
atts: { } };
x = { };
for (j = 0; j < 10; ++j) {
doc.values.push(j);
doc.atts["test" + i + j] = "test";
x["foo" + i] = [ "1" ];
}
doc.atts.foo = x;
cn.save(doc);
}
// now access the documents once, to build the shape accessors
for (i = 0; i < 1000; ++i) {
doc = cn.document("old" + i);
assertTrue(doc.hasOwnProperty("a"));
assertEqual(i, doc.a);
assertTrue(doc.hasOwnProperty("b"));
assertEqual("test" + i, doc.b);
assertTrue(doc.hasOwnProperty("values"));
assertEqual(10, doc.values.length);
assertTrue(doc.hasOwnProperty("atts"));
assertEqual(11, Object.keys(doc.atts).length);
for (j = 0; j < 10; ++j) {
assertEqual("test", doc.atts["test" + i + j]);
}
for (j = 0; j < 10; ++j) {
assertEqual([ "1" ], doc.atts.foo["foo" + i]);
}
}
// fill the datafile with rubbish
for (i = 0; i < 10000; ++i) {
cn.save({ _key: "test" + i, value: "thequickbrownfox" });
}
for (i = 0; i < 10000; ++i) {
cn.remove("test" + i);
}
internal.wait(7, false);
assertEqual(1000, cn.count());
// now access the "old" documents, which were probably moved
for (i = 0; i < 1000; ++i) {
doc = cn.document("old" + i);
assertTrue(doc.hasOwnProperty("a"));
assertEqual(i, doc.a);
assertTrue(doc.hasOwnProperty("b"));
assertEqual("test" + i, doc.b);
assertTrue(doc.hasOwnProperty("values"));
assertEqual(10, doc.values.length);
assertTrue(doc.hasOwnProperty("atts"));
assertEqual(11, Object.keys(doc.atts).length);
for (j = 0; j < 10; ++j) {
assertEqual("test", doc.atts["test" + i + j]);
}
for (j = 0; j < 10; ++j) {
assertEqual([ "1" ], doc.atts.foo["foo" + i]);
}
}
internal.db._drop(collectionName);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test shapes
////////////////////////////////////////////////////////////////////////////////
testShapes1 : function () {
var cn = "example";
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
var i, doc;
// prefill with "trash"
for (i = 0; i < 1000; ++i) {
c1.save({ _key: "test" + i });
}
// this accesses all documents, and creates shape accessors for all of them
c1.toArray();
c1.truncate();
testHelper.rotate(c1);
// create lots of different shapes
for (i = 0; i < 100; ++i) {
doc = { _key: "test" + i };
doc["number" + i] = i;
doc["string" + i] = "test" + i;
doc["bool" + i] = (i % 2 === 0);
c1.save(doc);
}
// make sure compaction moves the shapes
testHelper.rotate(c1);
c1.truncate();
internal.wait(5, false);
for (i = 0; i < 100; ++i) {
doc = { _key: "test" + i };
doc["number" + i] = i + 1;
doc["string" + i] = "test" + (i + 1);
doc["bool" + i] = (i % 2 !== 0);
c1.save(doc);
}
for (i = 0; i < 100; ++i) {
doc = c1.document("test" + i);
assertTrue(doc.hasOwnProperty("number" + i));
assertTrue(doc.hasOwnProperty("string" + i));
assertTrue(doc.hasOwnProperty("bool" + i));
assertEqual(i + 1, doc["number" + i]);
assertEqual("test" + (i + 1), doc["string" + i]);
assertEqual(i % 2 !== 0, doc["bool" + i]);
}
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test shapes
////////////////////////////////////////////////////////////////////////////////
testShapes2 : function () {
var cn = "example";
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
var i, doc;
// prefill with "trash"
for (i = 0; i < 1000; ++i) {
c1.save({ _key: "test" + i });
}
c1.truncate();
testHelper.rotate(c1);
// create lots of different shapes
for (i = 0; i < 100; ++i) {
doc = { _key: "test" + i };
doc["number" + i] = i;
doc["string" + i] = "test" + i;
doc["bool" + i] = (i % 2 === 0);
c1.save(doc);
}
c1.save({ _key: "foo", name: { first: "foo", last: "bar" } });
c1.save({ _key: "bar", name: { first: "bar", last: "baz", middle: "foo" }, age: 22 });
// remove most of the shapes
for (i = 0; i < 100; ++i) {
c1.remove("test" + i);
}
// make sure compaction moves the shapes
testHelper.rotate(c1);
doc = c1.document("foo");
assertTrue(doc.hasOwnProperty("name"));
assertFalse(doc.hasOwnProperty("age"));
assertEqual({ first: "foo", last: "bar" }, doc.name);
doc = c1.document("bar");
assertTrue(doc.hasOwnProperty("name"));
assertTrue(doc.hasOwnProperty("age"));
assertEqual({ first: "bar", last: "baz", middle: "foo" }, doc.name);
assertEqual(22, doc.age);
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test shapes
////////////////////////////////////////////////////////////////////////////////
testShapesUnloadReload : function () {
var cn = "example";
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
var i, doc;
// create lots of different shapes
for (i = 0; i < 100; ++i) {
doc = { _key: "test" + i };
doc["number" + i] = i;
doc["string" + i] = "test" + i;
doc["bool" + i] = (i % 2 === 0);
c1.save(doc);
}
c1.save({ _key: "foo", name: { first: "foo", last: "bar" } });
c1.save({ _key: "bar", name: { first: "bar", last: "baz", middle: "foo" }, age: 22 });
// this accesses all documents, and creates shape accessors for all of them
c1.toArray();
// remove most of the shapes
for (i = 0; i < 100; ++i) {
c1.remove("test" + i);
}
// make sure compaction moves the shapes
testHelper.rotate(c1);
// unload the collection
testHelper.waitUnload(c1);
c1 = internal.db._collection(cn);
// check if documents are still there
doc = c1.document("foo");
assertTrue(doc.hasOwnProperty("name"));
assertFalse(doc.hasOwnProperty("age"));
assertEqual({ first: "foo", last: "bar" }, doc.name);
doc = c1.document("bar");
assertTrue(doc.hasOwnProperty("name"));
assertTrue(doc.hasOwnProperty("age"));
assertEqual({ first: "bar", last: "baz", middle: "foo" }, doc.name);
assertEqual(22, doc.age);
// create docs with already existing shapes
for (i = 0; i < 100; ++i) {
doc = { _key: "test" + i };
doc["number" + i] = i;
doc["string" + i] = "test" + i;
doc["bool" + i] = (i % 2 === 0);
c1.save(doc);
}
// check if the documents work
for (i = 0; i < 100; ++i) {
doc = c1.document("test" + i);
assertTrue(doc.hasOwnProperty("number" + i));
assertTrue(doc.hasOwnProperty("string" + i));
assertTrue(doc.hasOwnProperty("bool" + i));
assertEqual(i, doc["number" + i]);
assertEqual("test" + i, doc["string" + i]);
assertEqual(i % 2 === 0, doc["bool" + i]);
}
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test journals
////////////////////////////////////////////////////////////////////////////////
testJournals : function () {
var cn = "example";
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
internal.wal.flush(true, true);
// empty collection
var fig = c1.figures();
assertEqual(0, c1.count());
assertEqual(0, fig["alive"]["count"]);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["size"]);
assertEqual(0, fig["dead"]["deletion"]);
assertEqual(0, fig["journals"]["count"]);
assertEqual(0, fig["datafiles"]["count"]);
assertEqual(0, fig["compactors"]["count"]);
c1.save({ "foo": "bar" });
internal.wal.flush(true, true);
var tries = 0;
while (++tries < 20) {
fig = c1.figures();
if (fig["alive"]["count"] === 1) {
break;
}
internal.wait(1, false);
}
fig = c1.figures();
assertEqual(1, c1.count());
assertEqual(1, fig["alive"]["count"]);
assertTrue(0 < fig["alive"]["size"]);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["size"]);
assertEqual(0, fig["dead"]["deletion"]);
assertEqual(1, fig["journals"]["count"]);
assertEqual(0, fig["datafiles"]["count"]);
assertEqual(0, fig["compactors"]["count"]);
testHelper.rotate(c1);
fig = c1.figures();
assertEqual(1, c1.count());
assertEqual(1, fig["alive"]["count"]);
assertTrue(0 < fig["alive"]["size"]);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["size"]);
assertEqual(0, fig["dead"]["deletion"]);
assertEqual(0, fig["journals"]["count"]);
assertEqual(1, fig["datafiles"]["count"]);
assertEqual(0, fig["compactors"]["count"]);
c1.save({ "bar": "baz" });
internal.wal.flush(true, true);
tries = 0;
while (++tries < 20) {
fig = c1.figures();
if (fig["alive"]["count"] === 2) {
break;
}
internal.wait(1, false);
}
var alive = fig["alive"]["size"];
assertEqual(2, c1.count());
assertEqual(2, fig["alive"]["count"]);
assertTrue(0 < alive);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["size"]);
assertEqual(0, fig["dead"]["deletion"]);
assertEqual(1, fig["journals"]["count"]);
assertEqual(1, fig["datafiles"]["count"]);
assertEqual(0, fig["compactors"]["count"]);
c1.properties({ doCompact: false });
internal.wait(1, false);
testHelper.rotate(c1);
fig = c1.figures();
assertEqual(2, c1.count());
assertEqual(2, fig["alive"]["count"]);
assertEqual(alive, fig["alive"]["size"]);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["size"]);
assertEqual(0, fig["dead"]["deletion"]);
assertEqual(0, fig["journals"]["count"]);
assertTrue(1 <= fig["datafiles"]["count"]);
assertEqual(0, fig["compactors"]["count"]);
c1.properties({ doCompact: true });
internal.wait(1, false);
c1.truncate();
testHelper.rotate(c1);
tries = 0;
while (++tries < 20) {
fig = c1.figures();
if (fig["alive"]["count"] === 0) {
break;
}
require("internal").wait(0.1);
}
assertEqual(0, c1.count());
assertEqual(0, fig["alive"]["count"]);
assertEqual(0, fig["alive"]["size"]);
c1.drop();
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test figures after truncate and rotate
////////////////////////////////////////////////////////////////////////////////
testFiguresTruncate : function () {
var i;
var maxWait;
var cn = "example";
var n = 400;
var payload = "the quick brown fox jumped over the lazy dog. a quick dog jumped over the lazy fox. boom bang.";
for (i = 0; i < 5; ++i) {
payload += payload;
}
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 } );
for (i = 0; i < n; ++i) {
c1.save({ _key: "test" + i, value : i, payload : payload });
}
testHelper.waitUnload(c1);
var fig = c1.figures();
c1.properties({ doCompact: false });
assertEqual(n, c1.count());
assertEqual(n, fig["alive"]["count"]);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["size"]);
assertEqual(0, fig["dead"]["deletion"]);
assertEqual(1, fig["journals"]["count"]);
assertTrue(0 < fig["datafiles"]["count"]);
c1.truncate();
fig = c1.figures();
assertEqual(0, c1.count());
assertEqual(0, fig["alive"]["count"]);
assertTrue(0 <= fig["dead"]["count"]);
assertTrue(0 <= fig["dead"]["size"]);
assertTrue(0 <= fig["dead"]["deletion"]);
assertEqual(1, fig["journals"]["count"]);
assertTrue(0 <= fig["datafiles"]["count"]);
internal.wal.flush(true, true);
c1.rotate();
c1.properties({ doCompact: true });
// wait for compactor to run
require("console").log("waiting for compactor to run");
// set max wait time
if (internal.valgrind) {
maxWait = 750;
}
else {
maxWait = 90;
}
var tries = 0;
while (++tries < maxWait) {
fig = c1.figures();
if (fig["dead"]["deletion"] === 0 && fig["dead"]["count"] === 0) {
break;
}
internal.wait(1, false);
}
fig = c1.figures();
assertEqual(0, c1.count());
assertEqual(0, fig["alive"]["count"]);
assertEqual(0, fig["alive"]["size"]);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["size"]);
assertEqual(0, fig["dead"]["deletion"]);
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test figures after truncate and rotate, with compaction disabled
////////////////////////////////////////////////////////////////////////////////
testFiguresNoCompact : function () {
var maxWait;
var cn = "example";
var n = 400;
var i;
var payload = "the quick brown fox jumped over the lazy dog. a quick dog jumped over the lazy fox. boom bang.";
for ( i = 0; i < 5; ++i) {
payload += payload;
}
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576, "doCompact" : false });
for (i = 0; i < n; ++i) {
c1.save({ _key: "test" + i, value : i, payload : payload });
}
testHelper.waitUnload(c1);
var fig = c1.figures();
assertEqual(n, c1.count());
assertEqual(n, fig["alive"]["count"]);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["size"]);
assertEqual(0, fig["dead"]["deletion"]);
assertEqual(1, fig["journals"]["count"]);
assertTrue(0 < fig["datafiles"]["count"]);
c1.truncate();
internal.wal.flush(true, true);
c1.rotate();
var tries = 0;
while (++tries < 20) {
fig = c1.figures();
if (fig["dead"]["deletion"] === n && fig["alive"]["count"] === 0) {
break;
}
internal.wait(1);
}
assertEqual(0, c1.count());
assertEqual(0, fig["alive"]["count"]);
assertEqual(0, fig["alive"]["size"]);
assertEqual(n, fig["dead"]["count"]);
assertTrue(0 < fig["dead"]["size"]);
assertEqual(n, fig["dead"]["deletion"]);
assertEqual(0, fig["journals"]["count"]);
assertTrue(0 < fig["datafiles"]["count"]);
// wait for compactor to run
require("console").log("waiting for compactor to run");
// set max wait time
if (internal.valgrind) {
maxWait = 120;
}
else {
maxWait = 15;
}
tries = 0;
while (++tries < maxWait) {
fig = c1.figures();
if (fig["alive"]["count"] === 0) {
break;
}
internal.wait(1, false);
}
assertEqual(0, c1.count());
assertEqual(0, fig["alive"]["count"]);
assertEqual(0, fig["alive"]["size"]);
assertEqual(n, fig["dead"]["count"]);
assertTrue(0 < fig["dead"]["size"]);
assertEqual(n, fig["dead"]["deletion"]);
assertEqual(0, fig["journals"]["count"]);
assertTrue(0 < fig["datafiles"]["count"]);
c1.save({ "some data": true });
fig = c1.figures();
assertEqual(0, fig["journals"]["count"]);
internal.wal.flush(true, true);
tries = 0;
while (++tries < maxWait) {
fig = c1.figures();
if (fig["journals"]["count"] === 1) {
break;
}
internal.wait(1);
}
assertEqual(1, fig["journals"]["count"]);
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test document presence after compaction
////////////////////////////////////////////////////////////////////////////////
testDocumentPresence : function () {
var maxWait;
var waited;
var cn = "example";
var n = 400;
var i;
var doc;
var payload = "the quick brown fox jumped over the lazy dog. a quick dog jumped over the lazy fox";
for (i = 0; i < 5; ++i) {
payload += payload;
}
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
for (i = 0; i < n; ++i) {
c1.save({ _key: "test" + i, value : i, payload : payload });
}
for (i = 0; i < n; i += 2) {
c1.remove("test" + i);
}
internal.wal.flush(true, true);
// this will create a barrier that will block compaction
doc = c1.document("test1");
c1.rotate();
var tries = 0, fig;
while (++tries < 20) {
fig = c1.figures();
if (fig["alive"]["count"] === n / 2 && fig["dead"]["count"] === 0) {
break;
}
internal.wait(1, false);
}
assertEqual(n / 2, c1.count());
assertEqual(n / 2, fig["alive"]["count"]);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["size"]);
assertTrue(200, fig["dead"]["deletion"]);
assertTrue(0 <= fig["journals"]["count"]);
assertTrue(0 < fig["datafiles"]["count"]);
// trigger GC
doc = null;
internal.wait(0);
// wait for compactor to run
require("console").log("waiting for compactor to run");
// set max wait time
if (internal.valgrind) {
maxWait = 750;
}
else {
maxWait = 90;
}
waited = 0;
var lastValue = fig["dead"]["deletion"];
while (waited < maxWait) {
internal.wait(5);
waited += 5;
fig = c1.figures();
if (fig["dead"]["deletion"] === lastValue) {
break;
}
lastValue = fig["dead"]["deletion"];
}
for (i = 0; i < n; i++) {
// will throw if document does not exist
if (i % 2 === 0) {
try {
doc = c1.document("test" + i);
fail();
}
catch (err) {
}
}
else {
doc = c1.document("test" + i);
}
}
// trigger GC
doc = null;
internal.wait(0);
c1.truncate();
internal.wal.flush(true, true);
c1.rotate();
waited = 0;
while (waited < maxWait) {
internal.wait(2);
waited += 2;
fig = c1.figures();
if (fig["dead"]["deletion"] === 0 && fig["dead"]["count"] === 0) {
break;
}
}
fig = c1.figures();
assertEqual(0, c1.count());
assertEqual(0, fig["alive"]["count"]);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["size"]);
assertEqual(0, fig["dead"]["deletion"]);
assertEqual(0, fig["journals"]["count"]);
assertEqual(0, fig["datafiles"]["count"]);
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief creates documents, rotates the journal and truncates all documents
///
/// this will fully compact the 1st datafile (with the data), but will leave
/// the journal with the delete markers untouched
////////////////////////////////////////////////////////////////////////////////
testCompactAfterTruncate : function () {
var maxWait;
var cn = "example";
var n = 400;
var i;
var payload = "the quick brown fox jumped over the lazy dog. a quick dog jumped over the lazy fox";
for (i = 0; i < 5; ++i) {
payload += payload;
}
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
for (i = 0; i < n; ++i) {
c1.save({ value : i, payload : payload });
}
internal.wal.flush(true, true);
var tries = 0, fig;
while (++tries < 20) {
fig = c1.figures();
if (fig["alive"]["count"] === n) {
break;
}
internal.wait(1, false);
}
assertEqual(n, c1.count());
assertEqual(n, fig["alive"]["count"]);
assertEqual(0, fig["dead"]["count"]);
assertEqual(0, fig["dead"]["deletion"]);
assertEqual(1, fig["journals"]["count"]);
assertTrue(0 < fig["datafiles"]["count"]);
// truncation will go fully into the journal...
internal.wal.flush(true, true);
c1.rotate();
c1.truncate();
internal.wal.flush(true, true);
tries = 0;
while (++tries < 20) {
fig = c1.figures();
if (fig["alive"]["count"] === 0 && fig["dead"]["deletion"] === n) {
break;
}
internal.wait(1, false);
}
assertEqual(0, c1.count());
assertEqual(0, fig["alive"]["count"]);
assertEqual(n, fig["dead"]["deletion"]);
// wait for compactor to run
require("console").log("waiting for compactor to run");
// set max wait time
if (internal.valgrind) {
maxWait = 750;
}
else {
maxWait = 90;
}
tries = 0;
while (++tries < maxWait) {
fig = c1.figures();
if (fig["dead"]["count"] === 0) {
break;
}
internal.wait(1, false);
}
assertEqual(0, c1.count());
// all alive & dead markers should be gone
assertEqual(0, fig["alive"]["count"]);
assertEqual(0, fig["dead"]["count"]);
// we should still have all the deletion markers
assertTrue(n >= fig["dead"]["deletion"]);
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test document presence after compaction
////////////////////////////////////////////////////////////////////////////////
testCompactionAfterUpdateSingleDatafile : function () {
var cn = "example";
var n = 2000;
var i;
var fig;
var payload = "the quick brown fox jumped over the lazy dog.";
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
for (i = 0; i < n; ++i) {
c1.save({ _key: "test" + i, value : i, payload : payload });
}
fig = c1.figures();
assertEqual(0, fig.dead.count);
internal.wal.flush(true, true);
// wait for the above docs to get into the collection journal
internal.wal.waitForCollector(cn);
internal.wait(0.5);
// update all documents so the existing revisions become irrelevant
for (i = 0; i < n; ++i) {
c1.update("test" + i, { payload: payload + ", isn't that nice?", updated: true });
}
fig = c1.figures();
assertTrue(fig.dead.count > 0);
internal.wal.flush(true, true);
internal.wal.waitForCollector(cn);
// wait for the compactor. it shouldn't compact now, but give it a chance to run
internal.wait(5);
// unload collection
c1.unload();
c1 = null;
while (internal.db._collection(cn).status() !== ArangoCollection.STATUS_UNLOADED) {
internal.db._collection(cn).unload();
internal.wait(1, false);
}
// now reload and check documents
c1 = internal.db._collection(cn);
c1.load();
for (i = 0; i < n; ++i) {
var doc = c1.document("test" + i);
assertEqual(payload + ", isn't that nice?", doc.payload);
assertTrue(doc.updated);
}
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test document presence after compaction
////////////////////////////////////////////////////////////////////////////////
testCompactionAfterUpdateMultipleDatafiles : function () {
var cn = "example";
var n = 2000;
var i;
var fig;
var payload = "the quick brown fox jumped over the lazy dog.";
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
for (i = 0; i < n; ++i) {
c1.save({ _key: "test" + i, value : i, payload : payload });
}
fig = c1.figures();
assertEqual(0, fig.dead.count);
internal.wal.flush(true, true);
// wait for the above docs to get into the collection journal
internal.wal.waitForCollector(cn);
internal.wait(0.5);
// update all documents so the existing revisions become irrelevant
for (i = 0; i < n; ++i) {
c1.update("test" + i, { payload: payload + ", isn't that nice?", updated: true });
}
fig = c1.figures();
assertTrue(fig.dead.count > 0);
// create new datafile
c1.rotate();
internal.wal.flush(true, true);
internal.wal.waitForCollector(cn);
// wait for the compactor. it should compact now
var tries = 0;
while (tries++ < 20) {
fig = c1.figures();
if (fig.dead.count === 0) {
break;
}
internal.wait(1);
}
assertEqual(0, fig.dead.count);
// unload collection
c1.unload();
c1 = null;
while (internal.db._collection(cn).status() !== ArangoCollection.STATUS_UNLOADED) {
internal.db._collection(cn).unload();
internal.wait(1, false);
}
// now reload and check documents
c1 = internal.db._collection(cn);
c1.load();
for (i = 0; i < n; ++i) {
var doc = c1.document("test" + i);
assertEqual(payload + ", isn't that nice?", doc.payload);
assertTrue(doc.updated);
}
assertEqual(0, c1.figures().dead.count);
internal.db._drop(cn);
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suites
////////////////////////////////////////////////////////////////////////////////
jsunity.run(CompactionSuite);
return jsunity.done();