2013-10-16 21:59:46 +00:00
|
|
|
// Copyright (c) 2013, Facebook, Inc. All rights reserved.
|
|
|
|
// This source code is licensed under the BSD-style license found in the
|
|
|
|
// LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
// of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
//
|
2012-12-11 19:57:35 +00:00
|
|
|
#include <cstdio>
|
|
|
|
|
|
|
|
#include "db/write_batch_internal.h"
|
2013-08-23 15:38:13 +00:00
|
|
|
#include "rocksdb/db.h"
|
|
|
|
#include "rocksdb/types.h"
|
2012-12-11 19:57:35 +00:00
|
|
|
#include "port/atomic_pointer.h"
|
|
|
|
#include "util/testutil.h"
|
|
|
|
|
|
|
|
|
|
|
|
// Run a thread to perform Put's.
|
|
|
|
// Another thread uses GetUpdatesSince API to keep getting the updates.
|
|
|
|
// options :
|
|
|
|
// --num_inserts = the num of inserts the first thread should perform.
|
|
|
|
// --wal_ttl = the wal ttl for the run.
|
|
|
|
|
2013-10-04 04:49:15 +00:00
|
|
|
using namespace rocksdb;
|
2012-12-11 19:57:35 +00:00
|
|
|
|
|
|
|
struct DataPumpThread {
|
|
|
|
size_t no_records;
|
|
|
|
DB* db; // Assumption DB is Open'ed already.
|
|
|
|
};
|
|
|
|
|
|
|
|
static std::string RandomString(Random* rnd, int len) {
|
|
|
|
std::string r;
|
|
|
|
test::RandomString(rnd, len, &r);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DataPumpThreadBody(void* arg) {
|
|
|
|
DataPumpThread* t = reinterpret_cast<DataPumpThread*>(arg);
|
|
|
|
DB* db = t->db;
|
|
|
|
Random rnd(301);
|
|
|
|
size_t i = 0;
|
2013-08-06 19:54:37 +00:00
|
|
|
while(i++ < t->no_records) {
|
|
|
|
if(!db->Put(WriteOptions(), Slice(RandomString(&rnd, 500)),
|
|
|
|
Slice(RandomString(&rnd, 500))).ok()) {
|
|
|
|
fprintf(stderr, "Error in put\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
2012-12-11 19:57:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ReplicationThread {
|
|
|
|
port::AtomicPointer stop;
|
|
|
|
DB* db;
|
|
|
|
volatile size_t no_read;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void ReplicationThreadBody(void* arg) {
|
|
|
|
ReplicationThread* t = reinterpret_cast<ReplicationThread*>(arg);
|
|
|
|
DB* db = t->db;
|
2013-01-24 18:54:26 +00:00
|
|
|
unique_ptr<TransactionLogIterator> iter;
|
2013-08-06 19:54:37 +00:00
|
|
|
SequenceNumber currentSeqNum = 1;
|
2013-03-04 18:44:04 +00:00
|
|
|
while (t->stop.Acquire_Load() != nullptr) {
|
2013-08-06 19:54:37 +00:00
|
|
|
iter.reset();
|
|
|
|
Status s;
|
|
|
|
while(!db->GetUpdatesSince(currentSeqNum, &iter).ok()) {
|
|
|
|
if (t->stop.Acquire_Load() == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf(stderr, "Refreshing iterator\n");
|
|
|
|
for(;iter->Valid(); iter->Next(), t->no_read++, currentSeqNum++) {
|
|
|
|
BatchResult res = iter->GetBatch();
|
|
|
|
if (res.sequence != currentSeqNum) {
|
|
|
|
fprintf(stderr, "Missed a seq no. b/w %ld and %ld\n", currentSeqNum,
|
|
|
|
res.sequence);
|
|
|
|
exit(1);
|
2012-12-11 19:57:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, const char** argv) {
|
|
|
|
|
2013-08-06 19:54:37 +00:00
|
|
|
uint64_t FLAGS_num_inserts = 1000;
|
|
|
|
uint64_t FLAGS_WAL_ttl_seconds = 1000;
|
2012-12-11 19:57:35 +00:00
|
|
|
char junk;
|
|
|
|
long l;
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
|
|
if (sscanf(argv[i], "--num_inserts=%ld%c", &l, &junk) == 1) {
|
|
|
|
FLAGS_num_inserts = l;
|
|
|
|
} else if (sscanf(argv[i], "--wal_ttl=%ld%c", &l, &junk) == 1) {
|
|
|
|
FLAGS_WAL_ttl_seconds = l;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Invalid Flag '%s'\n", argv[i]);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Env* env = Env::Default();
|
|
|
|
std::string default_db_path;
|
|
|
|
env->GetTestDirectory(&default_db_path);
|
|
|
|
default_db_path += "db_repl_stress";
|
|
|
|
Options options;
|
|
|
|
options.create_if_missing = true;
|
|
|
|
options.WAL_ttl_seconds = FLAGS_WAL_ttl_seconds;
|
|
|
|
DB* db;
|
2013-08-06 19:54:37 +00:00
|
|
|
DestroyDB(default_db_path, options);
|
2012-12-11 19:57:35 +00:00
|
|
|
|
|
|
|
Status s = DB::Open(options, default_db_path, &db);
|
|
|
|
|
|
|
|
if (!s.ok()) {
|
|
|
|
fprintf(stderr, "Could not open DB due to %s\n", s.ToString().c_str());
|
2013-08-06 19:54:37 +00:00
|
|
|
exit(1);
|
2012-12-11 19:57:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DataPumpThread dataPump;
|
|
|
|
dataPump.no_records = FLAGS_num_inserts;
|
|
|
|
dataPump.db = db;
|
|
|
|
env->StartThread(DataPumpThreadBody, &dataPump);
|
|
|
|
|
|
|
|
ReplicationThread replThread;
|
|
|
|
replThread.db = db;
|
|
|
|
replThread.no_read = 0;
|
|
|
|
replThread.stop.Release_Store(env); // store something to make it non-null.
|
|
|
|
|
|
|
|
env->StartThread(ReplicationThreadBody, &replThread);
|
2013-08-06 19:54:37 +00:00
|
|
|
while(replThread.no_read < FLAGS_num_inserts);
|
2013-03-04 18:44:04 +00:00
|
|
|
replThread.stop.Release_Store(nullptr);
|
2013-08-06 19:54:37 +00:00
|
|
|
if (replThread.no_read < dataPump.no_records) {
|
2012-12-11 19:57:35 +00:00
|
|
|
// no. read should be => than inserted.
|
|
|
|
fprintf(stderr, "No. of Record's written and read not same\nRead : %ld"
|
2013-08-06 19:54:37 +00:00
|
|
|
" Written : %ld\n", replThread.no_read, dataPump.no_records);
|
2012-12-11 19:57:35 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2013-08-06 19:54:37 +00:00
|
|
|
fprintf(stderr, "Successful!\n");
|
2012-12-11 19:57:35 +00:00
|
|
|
exit(0);
|
|
|
|
}
|