Implement the FB-Assoc API via thrift.

Summary:

Test Plan:

Reviewers:

CC:

Task ID: #

Blame Rev:
This commit is contained in:
Dhruba Borthakur 2012-08-01 16:17:43 -07:00
parent 4abf94eeb4
commit b40ad060e0
47 changed files with 5090 additions and 303 deletions

View File

@ -102,7 +102,7 @@ esac
# prune take effect. # prune take effect.
DIRS="util db table" DIRS="util db table"
if test "$USE_THRIFT"; then if test "$USE_THRIFT"; then
DIRS+=" thrift/gen-cpp thrift/server_utils.cpp thrift/server_options.cpp" DIRS+=" thrift/gen-cpp thrift/server_utils.cpp "
THRIFTSERVER=leveldb_server THRIFTSERVER=leveldb_server
fi fi
set -f # temporarily disable globbing so that our patterns aren't expanded set -f # temporarily disable globbing so that our patterns aren't expanded
@ -192,7 +192,7 @@ fi
# shall we build thrift server # shall we build thrift server
if test "$USE_THRIFT"; then if test "$USE_THRIFT"; then
THRIFT_CCFLAGS=" -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -I/usr/include -std=gnu++0x" THRIFT_CCFLAGS=" -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -I/usr/include -std=gnu++0x"
THRIFT_LDFLAGS=" -lserver -lthrift_base -ltransport -lthrift_exception -lutil -L./thrift/libs " THRIFT_LDFLAGS=" -lexample -lserver -lthrift_base -ltransport -lthrift_exception -lutil -L./thrift/libs "
COMMON_FLAGS+=$THRIFT_CCFLAGS COMMON_FLAGS+=$THRIFT_CCFLAGS
PLATFORM_LDFLAGS+=$THRIFT_LDFLAGS PLATFORM_LDFLAGS+=$THRIFT_LDFLAGS
fi fi

450
thrift/assoc.h Normal file
View File

@ -0,0 +1,450 @@
/**
* Thrift server that supports operations on the
* Facebook TAO Graph database
* @author Dhruba Borthakur (dhruba@gmail.com)
* Copyright 2012 Facebook
*/
#ifndef THRIFT_LEVELDB_ASSOC_SERVER_H_
#define THRIFT_LEVELDB_ASSOC_SERVER_H_
#include <AssocService.h>
#include <leveldb_types.h>
#include "openhandles.h"
#include "server_options.h"
#include "leveldb/db.h"
#include "leveldb/write_batch.h"
#include "util/testharness.h"
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
using boost::shared_ptr;
using namespace ::Tleveldb;
//
// These are the service methods that processes Association Data.
class AssocServiceHandler : virtual public AssocServiceIf {
public:
AssocServiceHandler(OpenHandles* openhandles) {
openhandles_ = openhandles;
}
int64_t taoAssocPut(const Text& tableName, int64_t assocType, int64_t id1,
int64_t id2, int64_t id1Type, int64_t id2Type,
int64_t timestamp, AssocVisibility visibility,
bool update_count, int64_t dataVersion, const Text& data,
const Text& wormhole_comment) {
leveldb::DB* db = openhandles_->get(tableName, NULL);
if (db == NULL) {
return Code::kNotFound;
}
int64_t ret = assocPutInternal(tableName,
db, assocType, id1, id2, id1Type, id2Type,
timestamp, visibility, update_count, dataVersion,
data, wormhole_comment);
return ret;
}
int64_t taoAssocDelete(const Text& tableName, int64_t assocType, int64_t id1,
int64_t id2, AssocVisibility visibility, bool update_count,
const Text& wormhole_comment) {
printf("taoAssocDelete\n");
}
void taoAssocRangeGet(std::vector<TaoAssocGetResult> & _return,
const Text& tableName, int64_t assocType, int64_t id1,
int64_t start_time, int64_t end_time, int64_t offset,
int64_t limit) {
printf("taoAssocRangeGet\n");
}
void taoAssocGet(std::vector<TaoAssocGetResult> & _return,
const Text& tableName, int64_t assocType, int64_t id1,
const std::vector<int64_t> & id2s) {
leveldb::DB* db = openhandles_->get(tableName, NULL);
if (db == NULL) {
throw generate_exception(tableName, Code::kNotFound,
"Unable to database " ,
assocType, id1, 0, 0, 0, 0, Tleveldb::UNUSED1);
}
taoAssocGetInternal(_return, tableName, db, assocType, id1, id2s);
}
int64_t taoAssocCount(const Text& tableName, int64_t assocType, int64_t id1) {
leveldb::DB* db = openhandles_->get(tableName, NULL);
if (db == NULL) {
return Code::kNotFound;
}
return taoAssocCountInternal(tableName, db, assocType, id1);
}
private:
OpenHandles* openhandles_;
//
// inserts an assoc
// Returns true if the iinsertion is successful, otherwise return false.
//
bool assocPutInternal(const Text& tableName, leveldb::DB* db,
int64_t assocType, int64_t id1,
int64_t id2, int64_t id1Type, int64_t id2Type,
int64_t ts, AssocVisibility vis,
bool update_count, int64_t dataVersion, const Text& data,
const Text& wormhole_comment) {
leveldb::WriteOptions woptions;
woptions.sync = true;
// create the payload for this assoc
int payloadsize = sizeof(id1Type) + sizeof(id2Type) +
sizeof(dataVersion) + data.size() + wormhole_comment.size();
std::string payload;
payload.reserve(payloadsize);
payload.resize(payloadsize);
makePayload(&payload[0], id1Type, id2Type, dataVersion, data,
wormhole_comment);
leveldb::Slice payload_slice(payload);
// create RowKey with plenty of space at the end to query
// all columns 'c', 'm', 'p, etc.
int maxkeysize = sizeof(id1) + sizeof(assocType) +
1 + // 'c', 'p' or 'm'
sizeof(ts) +
sizeof(id2);
std::string dummy;
dummy.reserve(maxkeysize);
dummy.resize(maxkeysize);
char* keybuf = &dummy[0];
int rowkeysize = makeRowKey(keybuf, id1, assocType);
leveldb::ReadOptions roptions;
leveldb::Status status;
std::string value;
int keysize;
int64_t count = 0;
int64_t oldts;
int8_t oldvis;
bool newassoc = false; // is this assoc new or an overwrite
// make a key for count
keysize = appendRowKeyForCount(rowkeysize, keybuf);
leveldb::Slice ckey(keybuf, keysize);
// Scan 'c' to get $count if $update_count == true
if (update_count) {
status = db->Get(roptions, ckey, &value);
if (status.IsNotFound()) {
// nothing to do
} else if (!status.ok() || (value.size() != sizeof(int64_t))) {
throw generate_exception(tableName, Code::kNotFound,
"Unable to find count ",
assocType, id1, id2, id1Type, id2Type, ts, vis);
} else {
extract_int64(&count, (char *)value.c_str());
}
}
// Scan 'm'$id2 to get $ts and $vis
keysize = appendRowKeyForMeta(rowkeysize, keybuf, id2);
leveldb::Slice mkey(keybuf, keysize);
status = db->Get(roptions, mkey, &value);
if (status.IsNotFound()) {
newassoc = true;
} else if (!status.ok() ||
(value.size() != sizeof(int64_t) + sizeof(int8_t))) {
throw generate_exception(tableName, Code::kNotFound,
"Unable to find m$id2 ",
assocType, id1, id2, id1Type, id2Type, ts, vis);
}
// make the key 'p'$old_ts$id2
keysize = appendRowKeyForPayload(rowkeysize, keybuf, oldts, id2);
leveldb::Slice pkey(keybuf, keysize);
// if ts != oldts, then delete 'p'$old_ts$id2
if (!newassoc) {
char* val = (char *)value.c_str();
extract_int64(&oldts, val);
extract_int8(&oldvis, val + sizeof(int64_t));
if (ts != oldts) {
if (!db->Delete(woptions, pkey).ok()) {
throw generate_exception(tableName, Code::kNotFound,
"Unable to delete from p$oldts$id2 ",
assocType, id1, id2, id1Type, id2Type, ts, vis);
}
}
}
// store in m$id2 the value of $ts$vis
std::string myvalue;
appendRowKeyForMeta(rowkeysize, keybuf, id2);
myvalue.reserve(sizeof(int64_t) + sizeof(int8_t));
myvalue.resize(sizeof(int64_t) + sizeof(int8_t));
makeTsVisString(&myvalue[0], ts, vis);
leveldb::Slice sl(myvalue);
if (!db->Put(woptions, mkey, sl).ok()) {
// throw exception;
throw generate_exception(tableName, Code::kNotFound,
"Unable to put into m$id2",
assocType, id1, id2, id1Type, id2Type, ts, vis);
}
// store in p$ts$id2 the payload
appendRowKeyForPayload(rowkeysize, keybuf, ts, id2);
if (!db->Put(woptions, pkey, payload_slice).ok()) {
throw generate_exception(tableName, Code::kNotFound,
"Unable to put into p$ts$id2",
assocType, id1, id2, id1Type, id2Type, ts, vis);
}
// increment count
if (update_count && (newassoc || oldvis != VISIBLE)) {
assert(count >= 0);
count++;
appendRowKeyForCount(rowkeysize, keybuf);
myvalue.reserve(sizeof(int64_t));
myvalue.resize(sizeof(int64_t));
makeCountString(&myvalue[0], count);
leveldb::Slice count_slice(myvalue);
if (!db->Put(woptions, ckey, count_slice).ok()) {
throw generate_exception(tableName, Code::kNotFound,
"Unable to insert into count",
assocType, id1, id2, id1Type, id2Type, ts, vis);
}
}
if (update_count) {
assert(count > 0);
return count;
}
return 0;
}
int64_t taoAssocCountInternal(const Text& tableName, leveldb::DB* db,
int64_t assocType, int64_t id1) {
// create key to query
int maxkeysize = sizeof(id1) + sizeof(assocType) + 1;
std::string dummy;
dummy.reserve(maxkeysize);
dummy.resize(maxkeysize);
char* keybuf = &dummy[0];
int rowkeysize = makeRowKey(keybuf, id1, assocType);
int keysize = appendRowKeyForCount(rowkeysize, keybuf); // column 'c'
leveldb::Slice ckey(keybuf, keysize);
// query database to find value
leveldb::ReadOptions roptions;
leveldb::Status status;
std::string value;
int64_t count;
status = db->Get(roptions, ckey, &value);
// parse results retrieved from database
if (status.IsNotFound()) {
return 0; // non existant assoc
} else if (!status.ok()) {
throw generate_exception(tableName, Code::kNotFound,
"Unable to find count ",
assocType, id1, 0, 0, 0, 0, Tleveldb::UNUSED1);
}
if (value.size() != sizeof(int64_t)) {
printf("expected %lld got %lld\n", sizeof(int64_t), value.size());
throw generate_exception(tableName, Code::kNotFound,
"Bad sizes for count ",
assocType, id1, 0, 0, 0, 0, Tleveldb::UNUSED1);
}
extract_int64(&count, (char *)value.c_str());
return count;
}
void taoAssocGetInternal(std::vector<TaoAssocGetResult> & _return,
const Text& tableName,
leveldb::DB* db,
int64_t assocType, int64_t id1,
const std::vector<int64_t> & id2s) {
int64_t ts, id2;
int8_t oldvis;
leveldb::ReadOptions roptions;
leveldb::Status status;
std::string value;
int numout = 0;
// create max key to query
int maxkeysize = sizeof(id1) + sizeof(assocType) + 1 + sizeof(ts) +
sizeof(id2);
std::string dummy;
dummy.reserve(maxkeysize);
dummy.resize(maxkeysize);
// create rowkey
char* keybuf = &dummy[0];
int rowkeysize = makeRowKey(keybuf, id1, assocType);
for (int index = 0; index < id2s.size(); index++) {
int64_t id2 = id2s[index];
// query column 'm'$id2
int keysize = appendRowKeyForMeta(rowkeysize, keybuf, id2);
leveldb::Slice ckey(keybuf, keysize);
status = db->Get(roptions, ckey, &value);
// parse results retrieved from database
if (status.IsNotFound()) {
continue; // non existant assoc
} else if (!status.ok() ||
value.size() != sizeof(int64_t) + sizeof(int8_t)) {
throw generate_exception(tableName, Code::kNotFound,
"Unable to find m$id2 ",
assocType, id1, id2, 0, 0, 0, Tleveldb::UNUSED1);
}
extractTsVisString(&ts, &oldvis, &value[0]);
if(oldvis != AssocVisibility::VISIBLE) {
continue;
}
ASSERT_NE(ts, 0);
printf("XXX ts = %lld\n", ts);
// this assoc is visible, scan 'p'$ts$id2 to retrieve payload.
keysize = appendRowKeyForPayload(rowkeysize, keybuf, ts, id2);
leveldb::Slice pkey(keybuf, keysize);
status = db->Get(roptions, pkey, &value);
// parse results retrieved from database
if (status.IsNotFound()) {
printf("XXX2");
continue; // non existant assoc
} else if (!status.ok()) {
throw generate_exception(tableName, Code::kNotFound,
"Unable to find m$id2 ",
assocType, id1, id2, 0, 0, 0, Tleveldb::UNUSED1);
}
// update return values
_return[numout].id2 = id2;
_return[numout].data = value;
// un-encoded from the payload XXX
_return[numout].id1Type = 0;
_return[numout].id2Type = 0;
_return[numout].dataVersion = 0;
numout++;
}
}
// fill the row key and returns the size of the key
inline int makeRowKey(char* dest, int64_t id1, int64_t assocType) {
dest = copy_int64_switch_endian(dest, id1);
dest = copy_int64_switch_endian(dest, assocType);
return sizeof(id1) + sizeof(assocType);
}
// fill the row key +'c' and returns the size of the key
inline int appendRowKeyForCount(int rowkeysize, char* dest) {
dest += rowkeysize;
*dest = 'c';
return rowkeysize + 1;
}
// fill the row key +'p' + $ts$id2 and returns the size of the key
inline int appendRowKeyForPayload(int rowkeysize, char* dest,
int64_t ts, int64_t id2) {
dest += rowkeysize;
*dest++ = 'p';
dest = copy_int64_switch_endian(dest, ts);
dest = copy_int64_switch_endian(dest, id2);
return rowkeysize + sizeof(ts) + sizeof(id2) + 1;
}
// fill the row key +'m' + id2 and returns the size of the key
inline int appendRowKeyForMeta(int rowkeysize, char* dest,
int64_t id2) {
dest += rowkeysize;
*dest++ = 'm';
dest = copy_int64_switch_endian(dest, id2);
return rowkeysize + sizeof(id2) + 1;
}
//
// encode id1Type, id2Type, dataversion, etc into the payload
inline void makePayload(char* dest, int64_t id1Type, int64_t id2Type,
int64_t dataVersion, const Text& data,
const Text& wormhole_comment) {
dest = copy_int64_switch_endian(dest, id1Type);
dest = copy_int64_switch_endian(dest, id2Type);
dest = copy_int64_switch_endian(dest, dataVersion);
memcpy(dest, data.data(), data.size());
dest += data.size();
memcpy(dest, wormhole_comment.data(), wormhole_comment.size());
dest += wormhole_comment.size();
}
// fill the timestamp and visibility
inline void makeTsVisString(char* dest, int64_t ts, int8_t vis) {
dest = copy_int64_switch_endian(dest, ts);
*dest = vis;
}
// extracts the timestamp and visibility from a byte stream
inline void extractTsVisString(int64_t* ts, int8_t* vis, char* src) {
extract_int64(ts, src);
extract_int8(vis, src + sizeof(*ts));
}
// fill the count value
inline void makeCountString(char* dest, int64_t count) {
dest = copy_int64_switch_endian(dest, count);
}
//
// Switch endianess of the id and copy it to dest.
// Returns the updated destination address
//
inline char* copy_int64_switch_endian(char* dest, int64_t id) {
char* src = (char *)&id + sizeof(id) - 1;
for (int i = 0; i < sizeof(id); i++) {
*dest++ = *src--;
}
return dest;
}
// extracts a int64 type from the char stream. Swaps endianness.
inline void extract_int64(int64_t* dest, char* src) {
src += sizeof(int64_t) - 1;
for (int i = 0; i < sizeof(uint64_t); i++) {
*dest++ = *src--;
}
}
// extracts a 1 byte integer from the char stream.
inline void extract_int8(int8_t* dest, char* src) {
*dest = *(int8_t *)src;
}
// generate an exception message
LeveldbException generate_exception(const Text& tableName,
Code errorCode, const char* message,
int64_t assocType, int64_t id1,
int64_t id2, int64_t id1Type, int64_t id2Type,
int64_t ts, AssocVisibility vis) {
char result[1024];
sprintf(result,
"id1=%d assocType=%d id2=%d id1Type=%d id2Type=%d ts=%d vis=%d ",
id1, assocType, id2, id1Type, id2Type, ts, vis);
fprintf(stderr, "assoc_server error table %s: %s errorCode=%d %s",
tableName.c_str(), message, errorCode, result);
LeveldbException e;
e.errorCode = errorCode;
e.message = message;
throw e;
}
};
#endif // THRIFT_LEVELDB_ASSOC_SERVER_H_

View File

@ -0,0 +1,70 @@
/*
* Copyright 2012 Facebook, Inc.
*
* 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.
*/
// @author: Andrei Alexandrescu
#ifndef FOLLY_PREPROCESSOR_
#define FOLLY_PREPROCESSOR_
/**
* Necessarily evil preprocessor-related amenities.
*/
/**
* FB_ONE_OR_NONE(hello, world) expands to hello and
* FB_ONE_OR_NONE(hello) expands to nothing. This macro is used to
* insert or eliminate text based on the presence of another argument.
*/
#define FB_ONE_OR_NONE(a, ...) FB_THIRD(a, ## __VA_ARGS__, a)
#define FB_THIRD(a, b, ...) __VA_ARGS__
/**
* Helper macro that extracts the first argument out of a list of any
* number of arguments.
*/
#define FB_ARG_1(a, ...) a
/**
* Helper macro that extracts the second argument out of a list of any
* number of arguments. If only one argument is given, it returns
* that.
*/
#define FB_ARG_2_OR_1(...) FB_ARG_2_OR_1_IMPL(__VA_ARGS__, __VA_ARGS__)
// Support macro for the above
#define FB_ARG_2_OR_1_IMPL(a, b, ...) b
/**
* FB_ANONYMOUS_VARIABLE(str) introduces an identifier starting with
* str and ending with a number that varies with the line.
*/
#ifndef FB_ANONYMOUS_VARIABLE
#define FB_CONCATENATE_IMPL(s1, s2) s1##s2
#define FB_CONCATENATE(s1, s2) FB_CONCATENATE_IMPL(s1, s2)
#ifdef __COUNTER__
#define FB_ANONYMOUS_VARIABLE(str) FB_CONCATENATE(str, __COUNTER__)
#else
#define FB_ANONYMOUS_VARIABLE(str) FB_CONCATENATE(str, __LINE__)
#endif
#endif
/**
* Use FB_STRINGIZE(name) when you'd want to do what #name does inside
* another macro expansion.
*/
#define FB_STRINGIZE(name) #name
#endif // FOLLY_PREPROCESSOR_

158
thrift/folly/ScopeGuard.h Normal file
View File

@ -0,0 +1,158 @@
/*
* Copyright 2012 Facebook, Inc.
*
* 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.
*/
#ifndef FOLLY_SCOPEGUARD_H_
#define FOLLY_SCOPEGUARD_H_
#include <cstddef>
#include <iostream>
#include <functional>
#include <new>
//#include <glog/logging.h>
#include "folly/Preprocessor.h"
namespace folly {
/**
* ScopeGuard is a general implementation of the "Initilization is
* Resource Acquisition" idiom. Basically, it guarantees that a function
* is executed upon leaving the currrent scope unless otherwise told.
*
* The makeGuard() function is used to create a new ScopeGuard object.
* It can be instantiated with a lambda function, a std::function<void()>,
* a functor, or a void(*)() function pointer.
*
*
* Usage example: Add a friend to memory iff it is also added to the db.
*
* void User::addFriend(User& newFriend) {
* // add the friend to memory
* friends_.push_back(&newFriend);
*
* // If the db insertion that follows fails, we should
* // remove it from memory.
* // (You could also declare this as "auto guard = makeGuard(...)")
* ScopeGuard guard = makeGuard([&] { friends_.pop_back(); });
*
* // this will throw an exception upon error, which
* // makes the ScopeGuard execute UserCont::pop_back()
* // once the Guard's destructor is called.
* db_->addFriend(GetName(), newFriend.GetName());
*
* // an exception was not thrown, so don't execute
* // the Guard.
* guard.dismiss();
* }
*
* Examine ScopeGuardTest.cpp for some more sample usage.
*
* Stolen from:
* Andrei's and Petru Marginean's CUJ article:
* http://drdobbs.com/184403758
* and the loki library:
* http://loki-lib.sourceforge.net/index.php?n=Idioms.ScopeGuardPointer
* and triendl.kj article:
* http://www.codeproject.com/KB/cpp/scope_guard.aspx
*/
class ScopeGuardImplBase {
public:
void dismiss() noexcept {
dismissed_ = true;
}
protected:
ScopeGuardImplBase()
: dismissed_(false) {}
ScopeGuardImplBase(ScopeGuardImplBase&& other)
: dismissed_(other.dismissed_) {
other.dismissed_ = true;
}
bool dismissed_;
};
template<typename FunctionType>
class ScopeGuardImpl : public ScopeGuardImplBase {
public:
explicit ScopeGuardImpl(const FunctionType& fn)
: function_(fn) {}
explicit ScopeGuardImpl(FunctionType&& fn)
: function_(std::move(fn)) {}
ScopeGuardImpl(ScopeGuardImpl&& other)
: ScopeGuardImplBase(std::move(other)),
function_(std::move(other.function_)) {
}
~ScopeGuardImpl() noexcept {
if (!dismissed_) {
execute();
}
}
private:
void* operator new(size_t) = delete;
void execute() noexcept {
try {
function_();
} catch (const std::exception& ex) {
std::cout << "ScopeGuard cleanup function threw a " <<
typeid(ex).name() << "exception: " << ex.what();
} catch (...) {
std::cout << "ScopeGuard cleanup function threw a non-exception object";
}
}
FunctionType function_;
};
template<typename FunctionType>
ScopeGuardImpl<typename std::decay<FunctionType>::type>
makeGuard(FunctionType&& fn) {
return ScopeGuardImpl<typename std::decay<FunctionType>::type>(
std::forward<FunctionType>(fn));
}
/**
* This is largely unneeded if you just use auto for your guards.
*/
typedef ScopeGuardImplBase&& ScopeGuard;
namespace detail {
/**
* Internal use for the macro SCOPE_EXIT below
*/
enum class ScopeGuardOnExit {};
template <typename FunctionType>
ScopeGuardImpl<typename std::decay<FunctionType>::type>
operator+(detail::ScopeGuardOnExit, FunctionType&& fn) {
return ScopeGuardImpl<typename std::decay<FunctionType>::type>(
std::forward<FunctionType>(fn));
}
} // namespace detail
} // folly
#define SCOPE_EXIT \
auto FB_ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
= ::folly::detail::ScopeGuardOnExit() + [&]
#endif // FOLLY_SCOPEGUARD_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@
* @generated * @generated
*/ */
#include "DB.h" #include "DB.h"
#include "folly/ScopeGuard.h"
namespace Tleveldb { namespace Tleveldb {
@ -2246,16 +2247,16 @@ uint32_t DB_CompactRange_args::read(apache::thrift::protocol::TProtocol* iprot)
break; break;
case 2: case 2:
if (ftype == apache::thrift::protocol::T_STRUCT) { if (ftype == apache::thrift::protocol::T_STRUCT) {
xfer += this->begin.read(iprot); xfer += this->start.read(iprot);
this->__isset.begin = true; this->__isset.start = true;
} else { } else {
xfer += iprot->skip(ftype); xfer += iprot->skip(ftype);
} }
break; break;
case 3: case 3:
if (ftype == apache::thrift::protocol::T_STRUCT) { if (ftype == apache::thrift::protocol::T_STRUCT) {
xfer += this->end.read(iprot); xfer += this->endhere.read(iprot);
this->__isset.end = true; this->__isset.endhere = true;
} else { } else {
xfer += iprot->skip(ftype); xfer += iprot->skip(ftype);
} }
@ -2278,11 +2279,11 @@ uint32_t DB_CompactRange_args::write(apache::thrift::protocol::TProtocol* oprot)
xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1);
xfer += this->dbhandle.write(oprot); xfer += this->dbhandle.write(oprot);
xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("begin", apache::thrift::protocol::T_STRUCT, 2); xfer += oprot->writeFieldBegin("start", apache::thrift::protocol::T_STRUCT, 2);
xfer += this->begin.write(oprot); xfer += this->start.write(oprot);
xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("end", apache::thrift::protocol::T_STRUCT, 3); xfer += oprot->writeFieldBegin("endhere", apache::thrift::protocol::T_STRUCT, 3);
xfer += this->end.write(oprot); xfer += this->endhere.write(oprot);
xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop(); xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd(); xfer += oprot->writeStructEnd();
@ -2295,11 +2296,11 @@ uint32_t DB_CompactRange_pargs::write(apache::thrift::protocol::TProtocol* oprot
xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1);
xfer += (*(this->dbhandle)).write(oprot); xfer += (*(this->dbhandle)).write(oprot);
xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("begin", apache::thrift::protocol::T_STRUCT, 2); xfer += oprot->writeFieldBegin("start", apache::thrift::protocol::T_STRUCT, 2);
xfer += (*(this->begin)).write(oprot); xfer += (*(this->start)).write(oprot);
xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("end", apache::thrift::protocol::T_STRUCT, 3); xfer += oprot->writeFieldBegin("endhere", apache::thrift::protocol::T_STRUCT, 3);
xfer += (*(this->end)).write(oprot); xfer += (*(this->endhere)).write(oprot);
xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop(); xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd(); xfer += oprot->writeStructEnd();
@ -2418,20 +2419,20 @@ int32_t DBClient::getNextRecvSequenceId()
void DBClient::Open(DBHandle& _return, const Text& dbname, const DBOptions& dboptions) void DBClient::Open(DBHandle& _return, const Text& dbname, const DBOptions& dboptions)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.Open", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.Open", NULL);
try { try {
this->setContextStack(ctx.get());
send_Open(dbname, dboptions); send_Open(dbname, dboptions);
recv_Open(_return); recv_Open(_return);
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.Open"); this->handlerError(this->getClientContextStack(), "DB.Open");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.Open"); this->handlerError(this->getClientContextStack(), "DB.Open");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -2441,7 +2442,7 @@ void DBClient::Open(DBHandle& _return, const Text& dbname, const DBOptions& dbop
void DBClient::send_Open(const Text& dbname, const DBOptions& dboptions) void DBClient::send_Open(const Text& dbname, const DBOptions& dboptions)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.Open"); this->preWrite(ctx, "DB.Open");
oprot_->writeMessageBegin("Open", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("Open", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -2459,7 +2460,7 @@ void DBClient::send_Open(const Text& dbname, const DBOptions& dboptions)
void DBClient::recv_Open(DBHandle& _return) void DBClient::recv_Open(DBHandle& _return)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -2512,20 +2513,20 @@ void DBClient::recv_Open(DBHandle& _return)
Code DBClient::Close(const DBHandle& dbhandle, const Text& dbname) Code DBClient::Close(const DBHandle& dbhandle, const Text& dbname)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.Close", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.Close", NULL);
try { try {
this->setContextStack(ctx.get());
send_Close(dbhandle, dbname); send_Close(dbhandle, dbname);
return recv_Close(); return recv_Close();
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.Close"); this->handlerError(this->getClientContextStack(), "DB.Close");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.Close"); this->handlerError(this->getClientContextStack(), "DB.Close");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -2535,7 +2536,7 @@ Code DBClient::Close(const DBHandle& dbhandle, const Text& dbname)
void DBClient::send_Close(const DBHandle& dbhandle, const Text& dbname) void DBClient::send_Close(const DBHandle& dbhandle, const Text& dbname)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.Close"); this->preWrite(ctx, "DB.Close");
oprot_->writeMessageBegin("Close", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("Close", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -2553,7 +2554,7 @@ void DBClient::send_Close(const DBHandle& dbhandle, const Text& dbname)
Code DBClient::recv_Close() Code DBClient::recv_Close()
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -2603,20 +2604,20 @@ Code DBClient::recv_Close()
Code DBClient::Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOptions& options) Code DBClient::Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOptions& options)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.Put", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.Put", NULL);
try { try {
this->setContextStack(ctx.get());
send_Put(dbhandle, keyvalue, options); send_Put(dbhandle, keyvalue, options);
return recv_Put(); return recv_Put();
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.Put"); this->handlerError(this->getClientContextStack(), "DB.Put");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.Put"); this->handlerError(this->getClientContextStack(), "DB.Put");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -2626,7 +2627,7 @@ Code DBClient::Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOpti
void DBClient::send_Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOptions& options) void DBClient::send_Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOptions& options)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.Put"); this->preWrite(ctx, "DB.Put");
oprot_->writeMessageBegin("Put", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("Put", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -2645,7 +2646,7 @@ void DBClient::send_Put(const DBHandle& dbhandle, const kv& keyvalue, const Writ
Code DBClient::recv_Put() Code DBClient::recv_Put()
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -2695,20 +2696,20 @@ Code DBClient::recv_Put()
Code DBClient::Delete(const DBHandle& dbhandle, const Slice& key, const WriteOptions& options) Code DBClient::Delete(const DBHandle& dbhandle, const Slice& key, const WriteOptions& options)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.Delete", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.Delete", NULL);
try { try {
this->setContextStack(ctx.get());
send_Delete(dbhandle, key, options); send_Delete(dbhandle, key, options);
return recv_Delete(); return recv_Delete();
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.Delete"); this->handlerError(this->getClientContextStack(), "DB.Delete");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.Delete"); this->handlerError(this->getClientContextStack(), "DB.Delete");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -2718,7 +2719,7 @@ Code DBClient::Delete(const DBHandle& dbhandle, const Slice& key, const WriteOpt
void DBClient::send_Delete(const DBHandle& dbhandle, const Slice& key, const WriteOptions& options) void DBClient::send_Delete(const DBHandle& dbhandle, const Slice& key, const WriteOptions& options)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.Delete"); this->preWrite(ctx, "DB.Delete");
oprot_->writeMessageBegin("Delete", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("Delete", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -2737,7 +2738,7 @@ void DBClient::send_Delete(const DBHandle& dbhandle, const Slice& key, const Wri
Code DBClient::recv_Delete() Code DBClient::recv_Delete()
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -2787,20 +2788,20 @@ Code DBClient::recv_Delete()
Code DBClient::Write(const DBHandle& dbhandle, const std::vector<kv> & batch, const WriteOptions& options) Code DBClient::Write(const DBHandle& dbhandle, const std::vector<kv> & batch, const WriteOptions& options)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.Write", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.Write", NULL);
try { try {
this->setContextStack(ctx.get());
send_Write(dbhandle, batch, options); send_Write(dbhandle, batch, options);
return recv_Write(); return recv_Write();
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.Write"); this->handlerError(this->getClientContextStack(), "DB.Write");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.Write"); this->handlerError(this->getClientContextStack(), "DB.Write");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -2810,7 +2811,7 @@ Code DBClient::Write(const DBHandle& dbhandle, const std::vector<kv> & batch, co
void DBClient::send_Write(const DBHandle& dbhandle, const std::vector<kv> & batch, const WriteOptions& options) void DBClient::send_Write(const DBHandle& dbhandle, const std::vector<kv> & batch, const WriteOptions& options)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.Write"); this->preWrite(ctx, "DB.Write");
oprot_->writeMessageBegin("Write", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("Write", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -2829,7 +2830,7 @@ void DBClient::send_Write(const DBHandle& dbhandle, const std::vector<kv> & batc
Code DBClient::recv_Write() Code DBClient::recv_Write()
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -2879,20 +2880,20 @@ Code DBClient::recv_Write()
void DBClient::Get(ResultItem& _return, const DBHandle& dbhandle, const Slice& inputkey, const ReadOptions& options) void DBClient::Get(ResultItem& _return, const DBHandle& dbhandle, const Slice& inputkey, const ReadOptions& options)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.Get", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.Get", NULL);
try { try {
this->setContextStack(ctx.get());
send_Get(dbhandle, inputkey, options); send_Get(dbhandle, inputkey, options);
recv_Get(_return); recv_Get(_return);
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.Get"); this->handlerError(this->getClientContextStack(), "DB.Get");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.Get"); this->handlerError(this->getClientContextStack(), "DB.Get");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -2902,7 +2903,7 @@ void DBClient::Get(ResultItem& _return, const DBHandle& dbhandle, const Slice& i
void DBClient::send_Get(const DBHandle& dbhandle, const Slice& inputkey, const ReadOptions& options) void DBClient::send_Get(const DBHandle& dbhandle, const Slice& inputkey, const ReadOptions& options)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.Get"); this->preWrite(ctx, "DB.Get");
oprot_->writeMessageBegin("Get", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("Get", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -2921,7 +2922,7 @@ void DBClient::send_Get(const DBHandle& dbhandle, const Slice& inputkey, const R
void DBClient::recv_Get(ResultItem& _return) void DBClient::recv_Get(ResultItem& _return)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -2971,20 +2972,20 @@ void DBClient::recv_Get(ResultItem& _return)
void DBClient::NewIterator(ResultIterator& _return, const DBHandle& dbhandle, const ReadOptions& options, IteratorType iteratorType, const Slice& target) void DBClient::NewIterator(ResultIterator& _return, const DBHandle& dbhandle, const ReadOptions& options, IteratorType iteratorType, const Slice& target)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.NewIterator", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.NewIterator", NULL);
try { try {
this->setContextStack(ctx.get());
send_NewIterator(dbhandle, options, iteratorType, target); send_NewIterator(dbhandle, options, iteratorType, target);
recv_NewIterator(_return); recv_NewIterator(_return);
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.NewIterator"); this->handlerError(this->getClientContextStack(), "DB.NewIterator");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.NewIterator"); this->handlerError(this->getClientContextStack(), "DB.NewIterator");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -2994,7 +2995,7 @@ void DBClient::NewIterator(ResultIterator& _return, const DBHandle& dbhandle, co
void DBClient::send_NewIterator(const DBHandle& dbhandle, const ReadOptions& options, IteratorType iteratorType, const Slice& target) void DBClient::send_NewIterator(const DBHandle& dbhandle, const ReadOptions& options, IteratorType iteratorType, const Slice& target)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.NewIterator"); this->preWrite(ctx, "DB.NewIterator");
oprot_->writeMessageBegin("NewIterator", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("NewIterator", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -3014,7 +3015,7 @@ void DBClient::send_NewIterator(const DBHandle& dbhandle, const ReadOptions& opt
void DBClient::recv_NewIterator(ResultIterator& _return) void DBClient::recv_NewIterator(ResultIterator& _return)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -3064,20 +3065,20 @@ void DBClient::recv_NewIterator(ResultIterator& _return)
Code DBClient::DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator) Code DBClient::DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.DeleteIterator", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.DeleteIterator", NULL);
try { try {
this->setContextStack(ctx.get());
send_DeleteIterator(dbhandle, iterator); send_DeleteIterator(dbhandle, iterator);
return recv_DeleteIterator(); return recv_DeleteIterator();
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.DeleteIterator"); this->handlerError(this->getClientContextStack(), "DB.DeleteIterator");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.DeleteIterator"); this->handlerError(this->getClientContextStack(), "DB.DeleteIterator");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -3087,7 +3088,7 @@ Code DBClient::DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator
void DBClient::send_DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator) void DBClient::send_DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.DeleteIterator"); this->preWrite(ctx, "DB.DeleteIterator");
oprot_->writeMessageBegin("DeleteIterator", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("DeleteIterator", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -3105,7 +3106,7 @@ void DBClient::send_DeleteIterator(const DBHandle& dbhandle, const Iterator& ite
Code DBClient::recv_DeleteIterator() Code DBClient::recv_DeleteIterator()
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -3155,20 +3156,20 @@ Code DBClient::recv_DeleteIterator()
void DBClient::GetNext(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator) void DBClient::GetNext(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.GetNext", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.GetNext", NULL);
try { try {
this->setContextStack(ctx.get());
send_GetNext(dbhandle, iterator); send_GetNext(dbhandle, iterator);
recv_GetNext(_return); recv_GetNext(_return);
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.GetNext"); this->handlerError(this->getClientContextStack(), "DB.GetNext");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.GetNext"); this->handlerError(this->getClientContextStack(), "DB.GetNext");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -3178,7 +3179,7 @@ void DBClient::GetNext(ResultPair& _return, const DBHandle& dbhandle, const Iter
void DBClient::send_GetNext(const DBHandle& dbhandle, const Iterator& iterator) void DBClient::send_GetNext(const DBHandle& dbhandle, const Iterator& iterator)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.GetNext"); this->preWrite(ctx, "DB.GetNext");
oprot_->writeMessageBegin("GetNext", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("GetNext", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -3196,7 +3197,7 @@ void DBClient::send_GetNext(const DBHandle& dbhandle, const Iterator& iterator)
void DBClient::recv_GetNext(ResultPair& _return) void DBClient::recv_GetNext(ResultPair& _return)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -3246,20 +3247,20 @@ void DBClient::recv_GetNext(ResultPair& _return)
void DBClient::GetPrev(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator) void DBClient::GetPrev(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.GetPrev", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.GetPrev", NULL);
try { try {
this->setContextStack(ctx.get());
send_GetPrev(dbhandle, iterator); send_GetPrev(dbhandle, iterator);
recv_GetPrev(_return); recv_GetPrev(_return);
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.GetPrev"); this->handlerError(this->getClientContextStack(), "DB.GetPrev");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.GetPrev"); this->handlerError(this->getClientContextStack(), "DB.GetPrev");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -3269,7 +3270,7 @@ void DBClient::GetPrev(ResultPair& _return, const DBHandle& dbhandle, const Iter
void DBClient::send_GetPrev(const DBHandle& dbhandle, const Iterator& iterator) void DBClient::send_GetPrev(const DBHandle& dbhandle, const Iterator& iterator)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.GetPrev"); this->preWrite(ctx, "DB.GetPrev");
oprot_->writeMessageBegin("GetPrev", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("GetPrev", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -3287,7 +3288,7 @@ void DBClient::send_GetPrev(const DBHandle& dbhandle, const Iterator& iterator)
void DBClient::recv_GetPrev(ResultPair& _return) void DBClient::recv_GetPrev(ResultPair& _return)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -3337,20 +3338,20 @@ void DBClient::recv_GetPrev(ResultPair& _return)
void DBClient::GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle) void DBClient::GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.GetSnapshot", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.GetSnapshot", NULL);
try { try {
this->setContextStack(ctx.get());
send_GetSnapshot(dbhandle); send_GetSnapshot(dbhandle);
recv_GetSnapshot(_return); recv_GetSnapshot(_return);
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.GetSnapshot"); this->handlerError(this->getClientContextStack(), "DB.GetSnapshot");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.GetSnapshot"); this->handlerError(this->getClientContextStack(), "DB.GetSnapshot");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -3360,7 +3361,7 @@ void DBClient::GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle)
void DBClient::send_GetSnapshot(const DBHandle& dbhandle) void DBClient::send_GetSnapshot(const DBHandle& dbhandle)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.GetSnapshot"); this->preWrite(ctx, "DB.GetSnapshot");
oprot_->writeMessageBegin("GetSnapshot", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("GetSnapshot", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -3377,7 +3378,7 @@ void DBClient::send_GetSnapshot(const DBHandle& dbhandle)
void DBClient::recv_GetSnapshot(ResultSnapshot& _return) void DBClient::recv_GetSnapshot(ResultSnapshot& _return)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -3427,20 +3428,20 @@ void DBClient::recv_GetSnapshot(ResultSnapshot& _return)
Code DBClient::ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) Code DBClient::ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.ReleaseSnapshot", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.ReleaseSnapshot", NULL);
try { try {
this->setContextStack(ctx.get());
send_ReleaseSnapshot(dbhandle, snapshot); send_ReleaseSnapshot(dbhandle, snapshot);
return recv_ReleaseSnapshot(); return recv_ReleaseSnapshot();
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.ReleaseSnapshot"); this->handlerError(this->getClientContextStack(), "DB.ReleaseSnapshot");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.ReleaseSnapshot"); this->handlerError(this->getClientContextStack(), "DB.ReleaseSnapshot");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -3450,7 +3451,7 @@ Code DBClient::ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapsho
void DBClient::send_ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) void DBClient::send_ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.ReleaseSnapshot"); this->preWrite(ctx, "DB.ReleaseSnapshot");
oprot_->writeMessageBegin("ReleaseSnapshot", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("ReleaseSnapshot", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
@ -3468,7 +3469,7 @@ void DBClient::send_ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& sn
Code DBClient::recv_ReleaseSnapshot() Code DBClient::recv_ReleaseSnapshot()
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -3516,22 +3517,22 @@ Code DBClient::recv_ReleaseSnapshot()
throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "ReleaseSnapshot failed: unknown result"); throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "ReleaseSnapshot failed: unknown result");
} }
Code DBClient::CompactRange(const DBHandle& dbhandle, const Slice& begin, const Slice& end) Code DBClient::CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere)
{ {
std::unique_ptr<apache::thrift::ContextStack> ctx(this->getContextStack("DB.CompactRange", NULL)); folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); });
this->generateClientContextStack("DB.CompactRange", NULL);
try { try {
this->setContextStack(ctx.get()); send_CompactRange(dbhandle, start, endhere);
send_CompactRange(dbhandle, begin, end);
return recv_CompactRange(); return recv_CompactRange();
} catch(apache::thrift::transport::TTransportException& ex) { } catch(apache::thrift::transport::TTransportException& ex) {
this->handlerError(ctx.get(), "DB.CompactRange"); this->handlerError(this->getClientContextStack(), "DB.CompactRange");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
throw; throw;
} catch(apache::thrift::TApplicationException& ex) { } catch(apache::thrift::TApplicationException& ex) {
if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) {
this->handlerError(ctx.get(), "DB.CompactRange"); this->handlerError(this->getClientContextStack(), "DB.CompactRange");
iprot_->getTransport()->close(); iprot_->getTransport()->close();
oprot_->getTransport()->close(); oprot_->getTransport()->close();
} }
@ -3539,16 +3540,16 @@ Code DBClient::CompactRange(const DBHandle& dbhandle, const Slice& begin, const
} }
} }
void DBClient::send_CompactRange(const DBHandle& dbhandle, const Slice& begin, const Slice& end) void DBClient::send_CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere)
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
this->preWrite(ctx, "DB.CompactRange"); this->preWrite(ctx, "DB.CompactRange");
oprot_->writeMessageBegin("CompactRange", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); oprot_->writeMessageBegin("CompactRange", apache::thrift::protocol::T_CALL, getNextSendSequenceId());
DB_CompactRange_pargs args; DB_CompactRange_pargs args;
args.dbhandle = &dbhandle; args.dbhandle = &dbhandle;
args.begin = &begin; args.start = &start;
args.end = &end; args.endhere = &endhere;
args.write(oprot_); args.write(oprot_);
oprot_->writeMessageEnd(); oprot_->writeMessageEnd();
@ -3560,7 +3561,7 @@ void DBClient::send_CompactRange(const DBHandle& dbhandle, const Slice& begin, c
Code DBClient::recv_CompactRange() Code DBClient::recv_CompactRange()
{ {
apache::thrift::ContextStack* ctx = this->getContextStack(); apache::thrift::ContextStack* ctx = this->getClientContextStack();
uint32_t bytes; uint32_t bytes;
int32_t rseqid = 0; int32_t rseqid = 0;
int32_t eseqid = getNextRecvSequenceId(); int32_t eseqid = getNextRecvSequenceId();
@ -4125,7 +4126,7 @@ void DBProcessor::process_CompactRange(int32_t seqid, apache::thrift::protocol::
DB_CompactRange_result result; DB_CompactRange_result result;
try { try {
result.success = iface_->CompactRange(args.dbhandle, args.begin, args.end); result.success = iface_->CompactRange(args.dbhandle, args.start, args.endhere);
result.__isset.success = true; result.__isset.success = true;
} catch (const std::exception& e) { } catch (const std::exception& e) {
this->handlerError(ctx.get(), "DB.CompactRange"); this->handlerError(ctx.get(), "DB.CompactRange");

View File

@ -27,7 +27,7 @@ class DBIf {
virtual void GetPrev(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator) = 0; virtual void GetPrev(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator) = 0;
virtual void GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle) = 0; virtual void GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle) = 0;
virtual Code ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) = 0; virtual Code ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) = 0;
virtual Code CompactRange(const DBHandle& dbhandle, const Slice& begin, const Slice& end) = 0; virtual Code CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere) = 0;
}; };
class DBIfFactory { class DBIfFactory {
@ -99,7 +99,7 @@ class DBNull : virtual public DBIf {
Code _return = (Code)0; Code _return = (Code)0;
return _return; return _return;
} }
Code CompactRange(const DBHandle& /* dbhandle */, const Slice& /* begin */, const Slice& /* end */) { Code CompactRange(const DBHandle& /* dbhandle */, const Slice& /* start */, const Slice& /* endhere */) {
Code _return = (Code)0; Code _return = (Code)0;
return _return; return _return;
} }
@ -1808,36 +1808,36 @@ class DB_CompactRange_args {
void __clear() { void __clear() {
dbhandle.__clear(); dbhandle.__clear();
begin.__clear(); start.__clear();
end.__clear(); endhere.__clear();
__isset.__clear(); __isset.__clear();
} }
virtual ~DB_CompactRange_args() throw() {} virtual ~DB_CompactRange_args() throw() {}
DBHandle dbhandle; DBHandle dbhandle;
Slice begin; Slice start;
Slice end; Slice endhere;
struct __isset { struct __isset {
__isset() { __clear(); } __isset() { __clear(); }
void __clear() { void __clear() {
dbhandle = false; dbhandle = false;
begin = false; start = false;
end = false; endhere = false;
} }
bool dbhandle; bool dbhandle;
bool begin; bool start;
bool end; bool endhere;
} __isset; } __isset;
bool operator == (const DB_CompactRange_args & rhs) const bool operator == (const DB_CompactRange_args & rhs) const
{ {
if (!(this->dbhandle == rhs.dbhandle)) if (!(this->dbhandle == rhs.dbhandle))
return false; return false;
if (!(this->begin == rhs.begin)) if (!(this->start == rhs.start))
return false; return false;
if (!(this->end == rhs.end)) if (!(this->endhere == rhs.endhere))
return false; return false;
return true; return true;
} }
@ -1861,8 +1861,8 @@ class DB_CompactRange_pargs {
virtual ~DB_CompactRange_pargs() throw() {} virtual ~DB_CompactRange_pargs() throw() {}
const DBHandle* dbhandle; const DBHandle* dbhandle;
const Slice* begin; const Slice* start;
const Slice* end; const Slice* endhere;
uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; uint32_t write(apache::thrift::protocol::TProtocol* oprot) const;
@ -1999,8 +1999,8 @@ class DBClient : virtual public DBIf, virtual public apache::thrift::TClientBase
Code ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot); Code ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot);
void send_ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot); void send_ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot);
Code recv_ReleaseSnapshot(); Code recv_ReleaseSnapshot();
Code CompactRange(const DBHandle& dbhandle, const Slice& begin, const Slice& end); Code CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere);
void send_CompactRange(const DBHandle& dbhandle, const Slice& begin, const Slice& end); void send_CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere);
Code recv_CompactRange(); Code recv_CompactRange();
/** /**
@ -2209,13 +2209,13 @@ class DBMultiface : virtual public DBIf {
return ifaces_[i]->ReleaseSnapshot(dbhandle, snapshot); return ifaces_[i]->ReleaseSnapshot(dbhandle, snapshot);
} }
Code CompactRange(const DBHandle& dbhandle, const Slice& begin, const Slice& end) { Code CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere) {
uint32_t i; uint32_t i;
uint32_t sz = ifaces_.size(); uint32_t sz = ifaces_.size();
for (i = 0; i < sz - 1; ++i) { for (i = 0; i < sz - 1; ++i) {
ifaces_[i]->CompactRange(dbhandle, begin, end); ifaces_[i]->CompactRange(dbhandle, start, endhere);
} }
return ifaces_[i]->CompactRange(dbhandle, begin, end); return ifaces_[i]->CompactRange(dbhandle, start, endhere);
} }
}; };

View File

@ -107,6 +107,42 @@ return findValue( ::Tleveldb::_IteratorType_NAMES_TO_VALUES, name, out);
} }
}} // apache::thrift }} // apache::thrift
namespace Tleveldb {
int _kAssocVisibilityValues[] = {
VISIBLE,
DELETED,
UNUSED1,
HIDDEN,
UNUSED2,
HARD_DELETE
};
const char* _kAssocVisibilityNames[] = {
"VISIBLE",
"DELETED",
"UNUSED1",
"HIDDEN",
"UNUSED2",
"HARD_DELETE"
};
const std::map<int, const char*> _AssocVisibility_VALUES_TO_NAMES(apache::thrift::TEnumIterator<int>(6, _kAssocVisibilityValues, _kAssocVisibilityNames), apache::thrift::TEnumIterator<int>(-1, NULL, NULL));
const std::map<const char*, int, apache::thrift::ltstr> _AssocVisibility_NAMES_TO_VALUES(apache::thrift::TEnumInverseIterator<int>(6, _kAssocVisibilityValues, _kAssocVisibilityNames), apache::thrift::TEnumInverseIterator<int>(-1, NULL, NULL));
} // namespace
namespace apache { namespace thrift {
template<>
const char* TEnumTraits< ::Tleveldb::AssocVisibility>::findName( ::Tleveldb::AssocVisibility value) {
return findName( ::Tleveldb::_AssocVisibility_VALUES_TO_NAMES, value);
}
template<>
bool TEnumTraits< ::Tleveldb::AssocVisibility>::findValue(const char* name, ::Tleveldb::AssocVisibility* out) {
return findValue( ::Tleveldb::_AssocVisibility_NAMES_TO_VALUES, name, out);
}
}} // apache::thrift
namespace Tleveldb { namespace Tleveldb {
// Reflection initializer for struct leveldb.Slice // Reflection initializer for struct leveldb.Slice
namespace { namespace {
@ -831,13 +867,6 @@ void reflectionInitializer_8973827971994157004(::apache::thrift::reflection::Sch
f.name = "dbname"; f.name = "dbname";
dt.fields[1] = f; dt.fields[1] = f;
} }
{
::apache::thrift::reflection::StructField f;
f.isRequired = true;
f.type = 6U;
f.name = "handleid";
dt.fields[2] = f;
}
schema.dataTypes[id] = dt; schema.dataTypes[id] = dt;
schema.names[dt.name] = id; schema.names[dt.name] = id;
} }
@ -875,14 +904,6 @@ uint32_t DBHandle::read(apache::thrift::protocol::TProtocol* iprot) {
xfer += iprot->skip(ftype); xfer += iprot->skip(ftype);
} }
break; break;
case 2:
if (ftype == apache::thrift::protocol::T_I64) {
xfer += iprot->readI64(this->handleid);
this->__isset.handleid = true;
} else {
xfer += iprot->skip(ftype);
}
break;
default: default:
xfer += iprot->skip(ftype); xfer += iprot->skip(ftype);
break; break;
@ -901,9 +922,6 @@ uint32_t DBHandle::write(apache::thrift::protocol::TProtocol* oprot) const {
xfer += oprot->writeFieldBegin("dbname", apache::thrift::protocol::T_STRING, 1); xfer += oprot->writeFieldBegin("dbname", apache::thrift::protocol::T_STRING, 1);
xfer += oprot->writeBinary(this->dbname); xfer += oprot->writeBinary(this->dbname);
xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("handleid", apache::thrift::protocol::T_I64, 2);
xfer += oprot->writeI64(this->handleid);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop(); xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd(); xfer += oprot->writeStructEnd();
return xfer; return xfer;
@ -914,7 +932,6 @@ void swap(DBHandle &a, DBHandle &b) {
(void)a; (void)a;
(void)b; (void)b;
swap(a.dbname, b.dbname); swap(a.dbname, b.dbname);
swap(a.handleid, b.handleid);
swap(a.__isset, b.__isset); swap(a.__isset, b.__isset);
} }
@ -1653,4 +1670,265 @@ void swap(LeveldbException &a, LeveldbException &b) {
swap(a.__isset, b.__isset); swap(a.__isset, b.__isset);
} }
// Reflection initializer for struct leveldb.IOError
namespace {
void reflectionInitializer_8460881927871070060(::apache::thrift::reflection::Schema& schema) {
const uint64_t id = 8460881927871070060U;
if (schema.dataTypes.count(id)) return;
::apache::thrift::reflection::DataType dt;
dt.name = "struct leveldb.IOError";
dt.__isset.fields = true;
{
::apache::thrift::reflection::StructField f;
f.isRequired = true;
f.type = 1U;
f.name = "message";
dt.fields[1] = f;
}
schema.dataTypes[id] = dt;
schema.names[dt.name] = id;
}
} // namespace
const uint64_t IOError::_reflection_id;
void IOError::_reflection_register(::apache::thrift::reflection::Schema& schema) {
reflectionInitializer_8460881927871070060(schema);
}
uint32_t IOError::read(apache::thrift::protocol::TProtocol* iprot) {
uint32_t xfer = 0;
std::string fname;
apache::thrift::protocol::TType ftype;
int16_t fid;
xfer += iprot->readStructBegin(fname);
using apache::thrift::protocol::TProtocolException;
while (true)
{
xfer += iprot->readFieldBegin(fname, ftype, fid);
if (ftype == apache::thrift::protocol::T_STOP) {
break;
}
switch (fid)
{
case 1:
if (ftype == apache::thrift::protocol::T_STRING) {
xfer += iprot->readString(this->message);
this->__isset.message = true;
} else {
xfer += iprot->skip(ftype);
}
break;
default:
xfer += iprot->skip(ftype);
break;
}
xfer += iprot->readFieldEnd();
}
xfer += iprot->readStructEnd();
return xfer;
}
uint32_t IOError::write(apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
xfer += oprot->writeStructBegin("IOError");
xfer += oprot->writeFieldBegin("message", apache::thrift::protocol::T_STRING, 1);
xfer += oprot->writeString(this->message);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd();
return xfer;
}
void swap(IOError &a, IOError &b) {
using ::std::swap;
(void)a;
(void)b;
swap(a.message, b.message);
swap(a.__isset, b.__isset);
}
// Reflection initializer for struct leveldb.TaoAssocGetResult
namespace {
void reflectionInitializer_6301164048086986412(::apache::thrift::reflection::Schema& schema) {
const uint64_t id = 6301164048086986412U;
if (schema.dataTypes.count(id)) return;
::apache::thrift::reflection::DataType dt;
dt.name = "struct leveldb.TaoAssocGetResult";
dt.__isset.fields = true;
{
::apache::thrift::reflection::StructField f;
f.isRequired = true;
f.type = 6U;
f.name = "id2";
dt.fields[1] = f;
}
{
::apache::thrift::reflection::StructField f;
f.isRequired = true;
f.type = 6U;
f.name = "id1Type";
dt.fields[2] = f;
}
{
::apache::thrift::reflection::StructField f;
f.isRequired = true;
f.type = 6U;
f.name = "id2Type";
dt.fields[3] = f;
}
{
::apache::thrift::reflection::StructField f;
f.isRequired = true;
f.type = 6U;
f.name = "time";
dt.fields[4] = f;
}
{
::apache::thrift::reflection::StructField f;
f.isRequired = true;
f.type = 6U;
f.name = "dataVersion";
dt.fields[5] = f;
}
{
::apache::thrift::reflection::StructField f;
f.isRequired = true;
f.type = 1U;
f.name = "data";
dt.fields[6] = f;
}
schema.dataTypes[id] = dt;
schema.names[dt.name] = id;
}
} // namespace
const uint64_t TaoAssocGetResult::_reflection_id;
void TaoAssocGetResult::_reflection_register(::apache::thrift::reflection::Schema& schema) {
reflectionInitializer_6301164048086986412(schema);
}
uint32_t TaoAssocGetResult::read(apache::thrift::protocol::TProtocol* iprot) {
uint32_t xfer = 0;
std::string fname;
apache::thrift::protocol::TType ftype;
int16_t fid;
xfer += iprot->readStructBegin(fname);
using apache::thrift::protocol::TProtocolException;
while (true)
{
xfer += iprot->readFieldBegin(fname, ftype, fid);
if (ftype == apache::thrift::protocol::T_STOP) {
break;
}
switch (fid)
{
case 1:
if (ftype == apache::thrift::protocol::T_I64) {
xfer += iprot->readI64(this->id2);
this->__isset.id2 = true;
} else {
xfer += iprot->skip(ftype);
}
break;
case 2:
if (ftype == apache::thrift::protocol::T_I64) {
xfer += iprot->readI64(this->id1Type);
this->__isset.id1Type = true;
} else {
xfer += iprot->skip(ftype);
}
break;
case 3:
if (ftype == apache::thrift::protocol::T_I64) {
xfer += iprot->readI64(this->id2Type);
this->__isset.id2Type = true;
} else {
xfer += iprot->skip(ftype);
}
break;
case 4:
if (ftype == apache::thrift::protocol::T_I64) {
xfer += iprot->readI64(this->time);
this->__isset.time = true;
} else {
xfer += iprot->skip(ftype);
}
break;
case 5:
if (ftype == apache::thrift::protocol::T_I64) {
xfer += iprot->readI64(this->dataVersion);
this->__isset.dataVersion = true;
} else {
xfer += iprot->skip(ftype);
}
break;
case 6:
if (ftype == apache::thrift::protocol::T_STRING) {
xfer += iprot->readBinary(this->data);
this->__isset.data = true;
} else {
xfer += iprot->skip(ftype);
}
break;
default:
xfer += iprot->skip(ftype);
break;
}
xfer += iprot->readFieldEnd();
}
xfer += iprot->readStructEnd();
return xfer;
}
uint32_t TaoAssocGetResult::write(apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
xfer += oprot->writeStructBegin("TaoAssocGetResult");
xfer += oprot->writeFieldBegin("id2", apache::thrift::protocol::T_I64, 1);
xfer += oprot->writeI64(this->id2);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("id1Type", apache::thrift::protocol::T_I64, 2);
xfer += oprot->writeI64(this->id1Type);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("id2Type", apache::thrift::protocol::T_I64, 3);
xfer += oprot->writeI64(this->id2Type);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("time", apache::thrift::protocol::T_I64, 4);
xfer += oprot->writeI64(this->time);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("dataVersion", apache::thrift::protocol::T_I64, 5);
xfer += oprot->writeI64(this->dataVersion);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("data", apache::thrift::protocol::T_STRING, 6);
xfer += oprot->writeBinary(this->data);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd();
return xfer;
}
void swap(TaoAssocGetResult &a, TaoAssocGetResult &b) {
using ::std::swap;
(void)a;
(void)b;
swap(a.id2, b.id2);
swap(a.id1Type, b.id1Type);
swap(a.id2Type, b.id2Type);
swap(a.time, b.time);
swap(a.dataVersion, b.dataVersion);
swap(a.data, b.data);
swap(a.__isset, b.__isset);
}
} // namespace } // namespace

View File

@ -90,6 +90,32 @@ return ::Tleveldb::IteratorType::seekToKey;
} }
}} // apache:thrift }} // apache:thrift
namespace Tleveldb {
enum AssocVisibility {
VISIBLE = 0,
DELETED = 1,
UNUSED1 = 2,
HIDDEN = 3,
UNUSED2 = 4,
HARD_DELETE = 4
};
extern const std::map<int, const char*> _AssocVisibility_VALUES_TO_NAMES;
extern const std::map<const char*, int, apache::thrift::ltstr> _AssocVisibility_NAMES_TO_VALUES;
} // namespace
namespace apache { namespace thrift {
template<>
inline constexpr ::Tleveldb::AssocVisibility TEnumTraits< ::Tleveldb::AssocVisibility>::min() {
return ::Tleveldb::AssocVisibility::VISIBLE;
}
template<>
inline constexpr ::Tleveldb::AssocVisibility TEnumTraits< ::Tleveldb::AssocVisibility>::max() {
return ::Tleveldb::AssocVisibility::HARD_DELETE;
}
}} // apache:thrift
namespace Tleveldb { namespace Tleveldb {
typedef std::string Text; typedef std::string Text;
@ -460,7 +486,7 @@ class DBHandle {
static const uint64_t _reflection_id = 8973827971994157004U; static const uint64_t _reflection_id = 8973827971994157004U;
static void _reflection_register(::apache::thrift::reflection::Schema&); static void _reflection_register(::apache::thrift::reflection::Schema&);
DBHandle() : dbname(""), handleid(0) { DBHandle() : dbname("") {
} }
DBHandle(const DBHandle&) = default; DBHandle(const DBHandle&) = default;
@ -470,31 +496,25 @@ class DBHandle {
void __clear() { void __clear() {
dbname = ""; dbname = "";
handleid = 0;
__isset.__clear(); __isset.__clear();
} }
virtual ~DBHandle() throw() {} virtual ~DBHandle() throw() {}
Text dbname; Text dbname;
int64_t handleid;
struct __isset { struct __isset {
__isset() { __clear(); } __isset() { __clear(); }
void __clear() { void __clear() {
dbname = false; dbname = false;
handleid = false;
} }
bool dbname; bool dbname;
bool handleid;
} __isset; } __isset;
bool operator == (const DBHandle & rhs) const bool operator == (const DBHandle & rhs) const
{ {
if (!(this->dbname == rhs.dbname)) if (!(this->dbname == rhs.dbname))
return false; return false;
if (!(this->handleid == rhs.handleid))
return false;
return true; return true;
} }
bool operator != (const DBHandle &rhs) const { bool operator != (const DBHandle &rhs) const {
@ -901,6 +921,140 @@ class LeveldbException : public apache::thrift::TException {
class LeveldbException; class LeveldbException;
void swap(LeveldbException &a, LeveldbException &b); void swap(LeveldbException &a, LeveldbException &b);
class IOError : public apache::thrift::TException {
public:
static const uint64_t _reflection_id = 8460881927871070060U;
static void _reflection_register(::apache::thrift::reflection::Schema&);
IOError() : message("") {
}
IOError(const IOError&) = default;
IOError& operator=(const IOError&) = default;
IOError(IOError&&) = default;
IOError& operator=(IOError&&) = default;
void __clear() {
message = "";
__isset.__clear();
}
virtual ~IOError() throw() {}
std::string message;
struct __isset {
__isset() { __clear(); }
void __clear() {
message = false;
}
bool message;
} __isset;
bool operator == (const IOError & rhs) const
{
if (!(this->message == rhs.message))
return false;
return true;
}
bool operator != (const IOError &rhs) const {
return !(*this == rhs);
}
bool operator < (const IOError & ) const;
uint32_t read(apache::thrift::protocol::TProtocol* iprot);
uint32_t write(apache::thrift::protocol::TProtocol* oprot) const;
virtual const char* what() const throw() {
return "IOError";
}
};
class IOError;
void swap(IOError &a, IOError &b);
class TaoAssocGetResult {
public:
static const uint64_t _reflection_id = 6301164048086986412U;
static void _reflection_register(::apache::thrift::reflection::Schema&);
TaoAssocGetResult() : id2(0), id1Type(0), id2Type(0), time(0), dataVersion(0), data("") {
}
TaoAssocGetResult(const TaoAssocGetResult&) = default;
TaoAssocGetResult& operator=(const TaoAssocGetResult&) = default;
TaoAssocGetResult(TaoAssocGetResult&&) = default;
TaoAssocGetResult& operator=(TaoAssocGetResult&&) = default;
void __clear() {
id2 = 0;
id1Type = 0;
id2Type = 0;
time = 0;
dataVersion = 0;
data = "";
__isset.__clear();
}
virtual ~TaoAssocGetResult() throw() {}
int64_t id2;
int64_t id1Type;
int64_t id2Type;
int64_t time;
int64_t dataVersion;
Text data;
struct __isset {
__isset() { __clear(); }
void __clear() {
id2 = false;
id1Type = false;
id2Type = false;
time = false;
dataVersion = false;
data = false;
}
bool id2;
bool id1Type;
bool id2Type;
bool time;
bool dataVersion;
bool data;
} __isset;
bool operator == (const TaoAssocGetResult & rhs) const
{
if (!(this->id2 == rhs.id2))
return false;
if (!(this->id1Type == rhs.id1Type))
return false;
if (!(this->id2Type == rhs.id2Type))
return false;
if (!(this->time == rhs.time))
return false;
if (!(this->dataVersion == rhs.dataVersion))
return false;
if (!(this->data == rhs.data))
return false;
return true;
}
bool operator != (const TaoAssocGetResult &rhs) const {
return !(*this == rhs);
}
bool operator < (const TaoAssocGetResult & ) const;
uint32_t read(apache::thrift::protocol::TProtocol* iprot);
uint32_t write(apache::thrift::protocol::TProtocol* oprot) const;
};
class TaoAssocGetResult;
void swap(TaoAssocGetResult &a, TaoAssocGetResult &b);
} // namespace } // namespace
#endif #endif

View File

@ -67,10 +67,9 @@ struct ReadOptions {
3:Snapshot snapshot 3:Snapshot snapshot
} }
// Represents a open database object // Represents a database object
struct DBHandle { struct DBHandle {
1:Text dbname; //name of the database 1:Text dbname //name of the database
2:i64 handleid // server generated
} }
struct Iterator { struct Iterator {
@ -177,5 +176,196 @@ service DB {
// compact a range of keys // compact a range of keys
// begin.size == 0 to start at a range earlier than the first existing key // begin.size == 0 to start at a range earlier than the first existing key
// end.size == 0 to end at a range later than the last existing key // end.size == 0 to end at a range later than the last existing key
Code CompactRange(1:DBHandle dbhandle, 2:Slice begin, 3:Slice end), Code CompactRange(1:DBHandle dbhandle, 2:Slice start, 3:Slice endhere),
} }
// ****************** FACEBOOK specific stuff ********************
//
// An IOError exception from an assoc operation
//
exception IOError {
1:string message
}
//
// Visibility state for assoc
//
enum AssocVisibility
{
VISIBLE = 0, // live object, include in lookups and count
DELETED = 1, // exclude from lookup queries and count, ok to
// delete permanently from persistent store
UNUSED1 = 2, // not used
HIDDEN = 3, // exclude from lookup queries and count
UNUSED2 = 4, // not used
HARD_DELETE = 4 // deleted by calling expunge, will be swept
// as soon as possible
}
/**
* Holds the assoc get result of a id2
*/
struct TaoAssocGetResult {
/** id2 of assoc */
1:i64 id2,
/** id1 type of assoc */
2:i64 id1Type,
/** id2 type of assoc */
3:i64 id2Type,
/** time stamp of the assoc */
4:i64 time,
/** version of the data blob */
5:i64 dataVersion,
/** serialized data of the asoc */
6:Text data,
}
//
// Service
//
service AssocService {
/**
* TAO Assoc Put operation.
* Note that currently the argument visibility has no effect.
*
* @if update_count is true, then return the updated count for this assoc
* @if update_count is false, then return 0
* @return negative number if failure
*/
i64 taoAssocPut(
/** name of table */
1:Text tableName,
/** type assoc */
2:i64 assocType,
/** id1 of assoc */
3:i64 id1,
/** id2 of assoc */
4:i64 id2,
/** id1Type of assoc */
5:i64 id1Type,
/** id2Type of assoc */
6:i64 id2Type,
/** timestamp of assoc */
7:i64 timestamp,
/** visibility */
8:AssocVisibility visibility,
/** whether to keep the count or not */
9:bool update_count,
/** version of the data blob */
10:i64 dataVersion,
/** serialized data of assoc */
11:Text data,
/** wormhole comment */
12:Text wormhole_comment
) throws (1:IOError io)
/**
* TAO Assoc Delete operation.
*
* @return the updated count for this assoc
*/
i64 taoAssocDelete(
/** name of table */
1:Text tableName,
/** type assoc */
2:i64 assocType,
/** id1 of assoc */
3:i64 id1,
/** id2 of assoc */
4:i64 id2,
/** visibility flag for this delete */
5:AssocVisibility visibility,
/** whether to keep the count or not */
6:bool update_count,
/** wormhole comment */
7:Text wormhole_comment
) throws (1:IOError io)
/**
* TAO Assoc RangeGet operation.
* Obtain assocs in bewteen start_time and end_time in reverse time order.
* The range check is inclusive: start_time >= time && time >= end_time.
* And yes, start_time >= end_time.
*/
list<TaoAssocGetResult> taoAssocRangeGet(
/** name of table */
1:Text tableName,
/** type of assoc */
2:i64 assocType,
/** id1 of assoc */
3:i64 id1,
/** maximum timestamp of assocs to retrieve */
4:i64 start_time,
/** minimum timestamp of assocs to retrieve */
5:i64 end_time,
/** number of assocs to skip from start */
6:i64 offset,
/** max number of assocs (columns) returned */
7:i64 limit
) throws (1:IOError io)
/**
* TAO Assoc Get operation.
*/
list<TaoAssocGetResult> taoAssocGet(
/** name of table */
1:Text tableName,
/** type of assoc */
2:i64 assocType,
/** id1 of assoc */
3:i64 id1,
/** list of id2 need to be fetch */
4:list<i64> id2s
) throws (1:IOError io)
/**
* TAO Assoc Count Get operation.
* Returns the number of assocs for given id1 and assoc type
*/
i64 taoAssocCount(
/** name of table */
1:Text tableName,
/** type of assoc */
2:i64 assocType,
/** id1 of assoc */
3:i64 id1,
) throws (1:IOError io)
}

View File

@ -142,15 +142,15 @@ class ContextStack {
}; };
class EventHandlerBase { class EventHandlerBase {
private:
int setEventHandlerPos_;
ContextStack* s_;
public: public:
EventHandlerBase() EventHandlerBase()
: setEventHandlerPos_(-1) : setEventHandlerPos_(-1) {}
, s_(NULL)
{} EventHandlerBase(const EventHandlerBase& original)
: handlers_(original.handlers_),
eventHandler_(original.eventHandler_),
setEventHandlerPos_(original.setEventHandlerPos_),
s_() {}
void addEventHandler( void addEventHandler(
const boost::shared_ptr<TProcessorEventHandler>& handler) { const boost::shared_ptr<TProcessorEventHandler>& handler) {
@ -191,13 +191,18 @@ class EventHandlerBase {
* The generated code should be the ONLY user of s_. All other functions * The generated code should be the ONLY user of s_. All other functions
* should just use the ContextStack parameter. * should just use the ContextStack parameter.
*/ */
ContextStack* getContextStack() { void generateClientContextStack(const char* fn_name,
return s_; TConnectionContext* connectionContext) {
auto s = getContextStack(fn_name, connectionContext);
s_ = std::move(s);
} }
// Context only freed by freer, this is only used across function calls. void clearClientContextStack() {
void setContextStack(ContextStack* s) { s_.reset();
s_ = s; }
ContextStack* getClientContextStack() {
return s_.get();
} }
protected: protected:
@ -259,8 +264,14 @@ class EventHandlerBase {
} }
} }
public:
std::vector<boost::shared_ptr<TProcessorEventHandler>> handlers_; std::vector<boost::shared_ptr<TProcessorEventHandler>> handlers_;
boost::shared_ptr<TProcessorEventHandler> eventHandler_; boost::shared_ptr<TProcessorEventHandler> eventHandler_;
private:
int setEventHandlerPos_;
std::unique_ptr<ContextStack> s_;
}; };
class TProcessorEventHandlerFactory { class TProcessorEventHandlerFactory {

View File

@ -272,6 +272,12 @@ void profile_print_info();
void profile_write_pprof(FILE* gen_calls_f, FILE* virtual_calls_f); void profile_write_pprof(FILE* gen_calls_f, FILE* virtual_calls_f);
#endif #endif
template <class ThriftContainer>
inline void reallyClear(ThriftContainer& container) {
ThriftContainer emptyContainer;
swap(container, emptyContainer);
}
}} // apache::thrift }} // apache::thrift
#endif // #ifndef THRIFT_THRIFT_H_ #endif // #ifndef THRIFT_THRIFT_H_

View File

@ -372,6 +372,7 @@ class TAsyncSSLSocket : public TAsyncSocket {
void invalidState(HandshakeCallback* callback); void invalidState(HandshakeCallback* callback);
bool willBlock(int ret, int *errorOut) THRIFT_NOEXCEPT; bool willBlock(int ret, int *errorOut) THRIFT_NOEXCEPT;
virtual void checkForImmediateRead() THRIFT_NOEXCEPT;
// TAsyncSocket calls this at the wrong time for SSL // TAsyncSocket calls this at the wrong time for SSL
void handleInitialReadWrite() THRIFT_NOEXCEPT {} void handleInitialReadWrite() THRIFT_NOEXCEPT {}

View File

@ -435,7 +435,7 @@ class TAsyncServerSocket : public TDelayedDestruction,
/** /**
* Get the number of connections dropped by the TAsyncServerSocket * Get the number of connections dropped by the TAsyncServerSocket
*/ */
double getNumDroppedConnections() const { uint64_t getNumDroppedConnections() const {
return numDroppedConnections_; return numDroppedConnections_;
} }
@ -502,7 +502,7 @@ class TAsyncServerSocket : public TDelayedDestruction,
double acceptRateAdjustSpeed_; //0 to disable auto adjust double acceptRateAdjustSpeed_; //0 to disable auto adjust
double acceptRate_; double acceptRate_;
int64_t lastAccepTimestamp_; // milliseconds int64_t lastAccepTimestamp_; // milliseconds
int64_t numDroppedConnections_; uint64_t numDroppedConnections_;
uint32_t callbackIndex_; uint32_t callbackIndex_;
BackoffTimeout *backoffTimeout_; BackoffTimeout *backoffTimeout_;
std::vector<CallbackInfo> callbacks_; std::vector<CallbackInfo> callbacks_;

View File

@ -360,6 +360,14 @@ class TAsyncSocket : public TAsyncTransport,
*/ */
int setNoDelay(bool noDelay); int setNoDelay(bool noDelay);
/*
* Set the Flavor of Congestion Control to be used for this Socket
* Please check '/lib/modules/<kernel>/kernel/net/ipv4' for tcp_*.ko
* first to make sure the module is available for plugging in
* Alternatively you can choose from net.ipv4.tcp_allowed_congestion_control
*/
int setCongestionFlavor(const std::string &cname);
/* /*
* Forces ACKs to be sent immediately * Forces ACKs to be sent immediately
* *
@ -486,6 +494,7 @@ class TAsyncSocket : public TAsyncTransport,
// event notification methods // event notification methods
void ioReady(uint16_t events) THRIFT_NOEXCEPT; void ioReady(uint16_t events) THRIFT_NOEXCEPT;
virtual void checkForImmediateRead() THRIFT_NOEXCEPT;
virtual void handleInitialReadWrite() THRIFT_NOEXCEPT; virtual void handleInitialReadWrite() THRIFT_NOEXCEPT;
virtual void handleRead() THRIFT_NOEXCEPT; virtual void handleRead() THRIFT_NOEXCEPT;
virtual void handleWrite() THRIFT_NOEXCEPT; virtual void handleWrite() THRIFT_NOEXCEPT;

View File

@ -137,6 +137,15 @@ class TAsyncTimeout : private boost::noncopyable {
static void libeventCallback(int fd, short events, void* arg); static void libeventCallback(int fd, short events, void* arg);
struct event event_; struct event event_;
/*
* In debug builds, store a pointer to the TEventBase. We only use this
* for some assert() statements, to make sure that TAsyncTimeout is always
* used from the correct thread.
*/
#ifndef NDEBUG
TEventBase* eventBase_;
#endif
}; };
}}} // apache::thrift::async }}} // apache::thrift::async

View File

@ -180,6 +180,9 @@ class TAsyncTransport {
* If a ReadCallback is already installed, it is replaced with the new * If a ReadCallback is already installed, it is replaced with the new
* callback. * callback.
* *
* Note that setReadCallback() may invoke the ReadCallback immediately,
* before returning.
*
* @param callback The callback to invoke when data is available. * @param callback The callback to invoke when data is available.
* This parameter may be NULL to uninstall the current * This parameter may be NULL to uninstall the current
* read callback. * read callback.

View File

@ -340,7 +340,7 @@ class TEventServer : public apache::thrift::server::TServer {
*/ */
template<typename AsyncProcessor> template<typename AsyncProcessor>
TEventServer(boost::shared_ptr<AsyncProcessor> processor, TEventServer(boost::shared_ptr<AsyncProcessor> processor,
boost::shared_ptr<apache::thrift::server::TProtocolFactory> boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>
protocolFactory, protocolFactory,
int port, int port,
int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS, int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS,
@ -386,9 +386,9 @@ class TEventServer : public apache::thrift::server::TServer {
*/ */
template<typename AsyncProcessor> template<typename AsyncProcessor>
TEventServer(boost::shared_ptr<AsyncProcessor> processor, TEventServer(boost::shared_ptr<AsyncProcessor> processor,
boost::shared_ptr<apache::thrift::server::TProtocolFactory> boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>
inputProtocolFactory, inputProtocolFactory,
boost::shared_ptr<apache::thrift::server::TProtocolFactory> boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>
outputProtocolFactory, outputProtocolFactory,
int port, int port,
int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS, int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS,
@ -433,8 +433,9 @@ class TEventServer : public apache::thrift::server::TServer {
@param nWorkers the number of worker threads @param nWorkers the number of worker threads
*/ */
template<typename AsyncProcessor> template<typename AsyncProcessor>
TEventServer(boost::shared_ptr<AsyncProcessor> processor, TEventServer(
boost::shared_ptr<apache::thrift::server::TDuplexProtocolFactory> boost::shared_ptr<AsyncProcessor> processor,
boost::shared_ptr<apache::thrift::protocol::TDuplexProtocolFactory>
duplexProtocolFactory, duplexProtocolFactory,
int port, int port,
int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS, int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS,
@ -479,8 +480,8 @@ class TEventServer : public apache::thrift::server::TServer {
*/ */
template<typename Processor> template<typename Processor>
TEventServer( TEventServer(
boost::shared_ptr<Processor>& processor, boost::shared_ptr<Processor> processor,
boost::shared_ptr<apache::thrift::server::TProtocolFactory>& boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>
protocolFactory, protocolFactory,
int port, int port,
boost::shared_ptr<concurrency::ThreadManager> const& threadManager = boost::shared_ptr<concurrency::ThreadManager> const& threadManager =
@ -524,8 +525,8 @@ class TEventServer : public apache::thrift::server::TServer {
*/ */
template<typename Processor> template<typename Processor>
TEventServer( TEventServer(
boost::shared_ptr<Processor>& processor, boost::shared_ptr<Processor> processor,
boost::shared_ptr<apache::thrift::server::TDuplexProtocolFactory>& boost::shared_ptr<apache::thrift::protocol::TDuplexProtocolFactory>
duplexProtocolFactory, duplexProtocolFactory,
int port, int port,
boost::shared_ptr<concurrency::ThreadManager> const& threadManager = boost::shared_ptr<concurrency::ThreadManager> const& threadManager =
@ -714,7 +715,7 @@ class TEventServer : public apache::thrift::server::TServer {
/** /**
* Get the number of connections dropped by the TAsyncServerSocket * Get the number of connections dropped by the TAsyncServerSocket
*/ */
void getNumDroppedConnections() const; uint64_t getNumDroppedConnections() const;
/** Reset the maximum number of inactive connection objects to the default. /** Reset the maximum number of inactive connection objects to the default.
*/ */

View File

@ -202,7 +202,10 @@ class THeaderProtocol
uint32_t writeDouble(const double dub); uint32_t writeDouble(const double dub);
uint32_t writeString(const std::string& str); template<typename StrType>
uint32_t writeString(const StrType& str) {
return proto_->writeString(str);
}
uint32_t writeBinary(const std::string& str); uint32_t writeBinary(const std::string& str);
@ -255,7 +258,10 @@ class THeaderProtocol
uint32_t readDouble(double& dub); uint32_t readDouble(double& dub);
uint32_t readString(std::string& str); template<typename StrType>
uint32_t readString(StrType& str) {
return proto_->readString(str);
}
uint32_t readBinary(std::string& binary); uint32_t readBinary(std::string& binary);

View File

@ -199,6 +199,9 @@ class TBufferedTransport
: transport_(transport) : transport_(transport)
, rBufSize_(DEFAULT_BUFFER_SIZE) , rBufSize_(DEFAULT_BUFFER_SIZE)
, wBufSize_(DEFAULT_BUFFER_SIZE) , wBufSize_(DEFAULT_BUFFER_SIZE)
, wBufResetSize_(0)
, wBufResetEveryN_(0)
, wBufResetCount_(0)
, rBuf_(new uint8_t[rBufSize_]) , rBuf_(new uint8_t[rBufSize_])
, wBuf_(new uint8_t[wBufSize_]) , wBuf_(new uint8_t[wBufSize_])
{ {
@ -210,17 +213,34 @@ class TBufferedTransport
: transport_(transport) : transport_(transport)
, rBufSize_(sz) , rBufSize_(sz)
, wBufSize_(sz) , wBufSize_(sz)
, wBufResetSize_(0)
, wBufResetEveryN_(0)
, wBufResetCount_(0)
, rBuf_(new uint8_t[rBufSize_]) , rBuf_(new uint8_t[rBufSize_])
, wBuf_(new uint8_t[wBufSize_]) , wBuf_(new uint8_t[wBufSize_])
{ {
initPointers(); initPointers();
} }
/// Use specified read and write buffer sizes. /**
TBufferedTransport(boost::shared_ptr<TTransport> transport, uint32_t rsz, uint32_t wsz) * Ctor with initial read and write buffer sizes and write buffer reset
* behaviour settings.
*
* @param transport Underlying transport.
* @param sz Initial buffer size.
* @param reset_sz Buffer size after a reset. See also reset_every_n.
* @param reset_every_n Reset the buffer after every N calls to flush().
* If set to zero (default), no reset is done.
*/
TBufferedTransport(boost::shared_ptr<TTransport> transport, uint32_t rsz,
uint32_t wsz, uint32_t reset_sz = 0,
uint32_t reset_every_n = 0)
: transport_(transport) : transport_(transport)
, rBufSize_(rsz) , rBufSize_(rsz)
, wBufSize_(wsz) , wBufSize_(wsz)
, wBufResetSize_(reset_sz)
, wBufResetEveryN_(reset_every_n)
, wBufResetCount_(0)
, rBuf_(new uint8_t[rBufSize_]) , rBuf_(new uint8_t[rBufSize_])
, wBuf_(new uint8_t[wBufSize_]) , wBuf_(new uint8_t[wBufSize_])
{ {
@ -291,6 +311,9 @@ class TBufferedTransport
uint32_t rBufSize_; uint32_t rBufSize_;
uint32_t wBufSize_; uint32_t wBufSize_;
uint32_t wBufResetSize_;
uint32_t wBufResetEveryN_;
uint32_t wBufResetCount_;
boost::scoped_array<uint8_t> rBuf_; boost::scoped_array<uint8_t> rBuf_;
boost::scoped_array<uint8_t> wBuf_; boost::scoped_array<uint8_t> wBuf_;
}; };
@ -336,19 +359,36 @@ class TFramedTransport
: transport_(transport) : transport_(transport)
, rBufSize_(0) , rBufSize_(0)
, wBufSize_(DEFAULT_BUFFER_SIZE) , wBufSize_(DEFAULT_BUFFER_SIZE)
, wBufResetSize_(0)
, wBufResetEveryN_(0)
, wBufResetCount_(0)
, rBuf_() , rBuf_()
, wBuf_(new uint8_t[wBufSize_]) , wBuf_(new uint8_t[wBufSize_])
{ {
initPointers(); initPointers();
} }
TFramedTransport(boost::shared_ptr<TTransport> transport, uint32_t sz) /**
* Ctor with initial buffer size and write buffer reset behaviour settings.
*
* @param transport Underlying transport.
* @param sz Initial buffer size.
* @param reset_sz Buffer size after a reset. See also reset_every_n.
* @param reset_every_n Reset the buffer after every N calls to flush().
* If set to zero (default), no reset is done.
*/
TFramedTransport(boost::shared_ptr<TTransport> transport, uint32_t sz,
uint32_t reset_sz = 0, uint32_t reset_every_n = 0)
: transport_(transport) : transport_(transport)
, rBufSize_(0) , rBufSize_(0)
, wBufSize_(sz) , wBufSize_(sz)
, wBufResetSize_(reset_sz)
, wBufResetEveryN_(reset_every_n)
, wBufResetCount_(0)
, rBuf_() , rBuf_()
, wBuf_(new uint8_t[wBufSize_]) , wBuf_(new uint8_t[wBufSize_])
{ {
assert(wBufResetSize_ == 0 || wBufSize_ <= wBufResetSize_);
initPointers(); initPointers();
} }
@ -396,6 +436,9 @@ class TFramedTransport
TFramedTransport() TFramedTransport()
: rBufSize_(0) : rBufSize_(0)
, wBufSize_(DEFAULT_BUFFER_SIZE) , wBufSize_(DEFAULT_BUFFER_SIZE)
, wBufResetSize_(0)
, wBufResetEveryN_(0)
, wBufResetCount_(0)
, rBuf_() , rBuf_()
, wBuf_(new uint8_t[wBufSize_]) , wBuf_(new uint8_t[wBufSize_])
{ {
@ -426,6 +469,9 @@ class TFramedTransport
uint32_t rBufSize_; uint32_t rBufSize_;
uint32_t wBufSize_; uint32_t wBufSize_;
uint32_t wBufResetSize_;
uint32_t wBufResetEveryN_;
uint32_t wBufResetCount_;
boost::scoped_array<uint8_t> rBuf_; boost::scoped_array<uint8_t> rBuf_;
boost::scoped_array<uint8_t> wBuf_; boost::scoped_array<uint8_t> wBuf_;
}; };

View File

@ -34,7 +34,7 @@ namespace apache { namespace thrift { namespace transport {
*/ */
class THttpTransport : public TVirtualTransport<THttpTransport> { class THttpTransport : public TVirtualTransport<THttpTransport> {
public: public:
THttpTransport(boost::shared_ptr<TTransport> transport); explicit THttpTransport(boost::shared_ptr<TTransport> transport);
virtual ~THttpTransport(); virtual ~THttpTransport();
@ -62,6 +62,10 @@ class THttpTransport : public TVirtualTransport<THttpTransport> {
virtual void flush() = 0; virtual void flush() = 0;
boost::shared_ptr<TTransport> getUnderlyingTransport() {
return transport_;
}
protected: protected:
boost::shared_ptr<TTransport> transport_; boost::shared_ptr<TTransport> transport_;

View File

@ -167,6 +167,9 @@ class ServerCreatorBase : public ServerCreator {
*/ */
virtual boost::shared_ptr<protocol::TProtocolFactory> getProtocolFactory(); virtual boost::shared_ptr<protocol::TProtocolFactory> getProtocolFactory();
virtual boost::shared_ptr<protocol::TDuplexProtocolFactory>
getDuplexProtocolFactory();
bool strictRead_; bool strictRead_;
bool strictWrite_; bool strictWrite_;
int32_t stringLimit_; int32_t stringLimit_;

View File

@ -25,6 +25,12 @@
namespace apache { namespace thrift { namespace apache { namespace thrift {
class TProcessor;
namespace concurrency {
class ThreadManager;
}
namespace async { namespace async {
class TAsyncProcessor; class TAsyncProcessor;
class TEventServer; class TEventServer;
@ -36,8 +42,11 @@ class TEventServerCreator : public ServerCreatorBase {
public: public:
typedef async::TEventServer ServerType; typedef async::TEventServer ServerType;
/// Use 8 worker threads by default. /// Use 8 IO worker threads by default.
static const size_t DEFAULT_NUM_THREADS = 8; static const size_t DEFAULT_NUM_IO_THREADS = 8;
/// Use 8 task worker threads by default.
static const size_t DEFAULT_NUM_TASK_THREADS = 8;
/// Default limit on the size of each worker's idle connection pool /// Default limit on the size of each worker's idle connection pool
static const uint32_t DEFAULT_CONN_POOL_SIZE = 64; static const uint32_t DEFAULT_CONN_POOL_SIZE = 64;
@ -78,17 +87,44 @@ class TEventServerCreator : public ServerCreatorBase {
static const int DEFAULT_RESIZE_EVERY_N = 64; static const int DEFAULT_RESIZE_EVERY_N = 64;
/** /**
* Create a new TEventServerCreator. * Create a new TEventServerCreator to be used for building a native-mode
* TEventServer.
*/ */
TEventServerCreator(const boost::shared_ptr<async::TAsyncProcessor>& proc, TEventServerCreator(
const boost::shared_ptr<async::TAsyncProcessor>& asyncProcessor,
uint16_t port, uint16_t port,
size_t numThreads = DEFAULT_NUM_THREADS); size_t numIoThreads = DEFAULT_NUM_IO_THREADS);
/** /**
* Set the number of threads to use. * Create a new TEventServerCreator to be used for building a queuing-mode
* TEventServer.
*/ */
void setNumThreads(size_t numThreads) { TEventServerCreator(
numThreads_ = numThreads; const boost::shared_ptr<TProcessor>& syncProcessor,
uint16_t port,
size_t numIoThreads = DEFAULT_NUM_IO_THREADS,
size_t numTaskThreads = DEFAULT_NUM_TASK_THREADS);
/**
* Set the number of IO threads to use.
*/
void setNumIoThreads(size_t numIoThreads) {
numIoThreads_ = numIoThreads;
}
/**
* Set the number of task threads to use.
*/
void setNumTaskThreads(size_t numTaskThreads) {
numTaskThreads_ = numTaskThreads;
}
/**
* Set the thread manager to use for task queue threads.
*/
void setTaskQueueThreadManager(
const boost::shared_ptr<concurrency::ThreadManager>& threadManager) {
taskQueueThreadManager_ = threadManager;
} }
/** /**
@ -176,9 +212,12 @@ class TEventServerCreator : public ServerCreatorBase {
boost::shared_ptr<async::TEventServer> createEventServer(); boost::shared_ptr<async::TEventServer> createEventServer();
private: private:
boost::shared_ptr<async::TAsyncProcessor> processor_; boost::shared_ptr<TProcessor> syncProcessor_;
boost::shared_ptr<async::TAsyncProcessor> asyncProcessor_;
boost::shared_ptr<concurrency::ThreadManager> taskQueueThreadManager_;
uint16_t port_; uint16_t port_;
size_t numThreads_; size_t numIoThreads_;
size_t numTaskThreads_;
uint32_t maxConnPoolSize_; uint32_t maxConnPoolSize_;
int recvTimeout_; int recvTimeout_;
uint32_t maxFrameSize_; uint32_t maxFrameSize_;

BIN
thrift/libs/libasync.a Normal file

Binary file not shown.

BIN
thrift/libs/libasync_base.a Normal file

Binary file not shown.

BIN
thrift/libs/libasync_ssl.a Normal file

Binary file not shown.

Binary file not shown.

BIN
thrift/libs/libexample.a Normal file

Binary file not shown.

BIN
thrift/libs/libheader.a Normal file

Binary file not shown.

BIN
thrift/libs/libhttpparser.a Normal file

Binary file not shown.

Binary file not shown.

BIN
thrift/libs/libprocessor.a Normal file

Binary file not shown.

BIN
thrift/libs/libprotocol.a Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
!<arch>

BIN
thrift/libs/libserver.a Normal file

Binary file not shown.

BIN
thrift/libs/libthrift.a Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
thrift/libs/libtransport.a Normal file

Binary file not shown.

Binary file not shown.

BIN
thrift/libs/libutil.a Normal file

Binary file not shown.

View File

@ -60,7 +60,6 @@ struct onehandle {
Text name; Text name;
leveldb::DB* onedb; // locate the localleveldb instance leveldb::DB* onedb; // locate the localleveldb instance
int refcount; // currently not used int refcount; // currently not used
int64_t uniqueid; // unique identifier
std::atomic<uint64_t> currentSnapshotId; // valid snapshotids > 0 std::atomic<uint64_t> currentSnapshotId; // valid snapshotids > 0
std::atomic<uint64_t> currentIteratorId; // valid iterators > 0 std::atomic<uint64_t> currentIteratorId; // valid iterators > 0
unordered_map<uint64_t, struct snapshotEntry*> snaplist; unordered_map<uint64_t, struct snapshotEntry*> snaplist;
@ -139,7 +138,7 @@ struct onehandle {
class OpenHandles { class OpenHandles {
public: public:
OpenHandles() : dbnum_(1) { OpenHandles() {
} }
// Inserts a new database into the list. // Inserts a new database into the list.
@ -150,7 +149,6 @@ class OpenHandles {
if (found == NULL) { if (found == NULL) {
found = new onehandle; found = new onehandle;
found->name = dbname; found->name = dbname;
found->uniqueid = dbnum_++;
fprintf(stderr, "openhandle.add: Opening leveldb DB %s\n", fprintf(stderr, "openhandle.add: Opening leveldb DB %s\n",
dbname.c_str()); dbname.c_str());
leveldb::Status status = leveldb::DB::Open(options, dbdir, &found->onedb); leveldb::Status status = leveldb::DB::Open(options, dbdir, &found->onedb);
@ -166,20 +164,15 @@ class OpenHandles {
head_[dbname] = found; head_[dbname] = found;
} }
found->refcount++; found->refcount++;
return found->uniqueid;
} }
leveldb::DB* get(Text dbname, int64_t uniqueid, struct onehandle** f) { leveldb::DB* get(Text dbname, struct onehandle** f) {
auto p = head_.find(dbname); auto p = head_.find(dbname);
if (p == head_.end()) { if (p == head_.end()) {
fprintf(stderr, "get:No db with name\n"); fprintf(stderr, "get:No db with name\n");
return NULL; return NULL;
} }
struct onehandle* found = p->second; struct onehandle* found = p->second;
if (found->uniqueid != uniqueid) {
fprintf(stderr, "get:Uniqueid does not match\n.");
return NULL;
}
if (found->refcount <= 0) { if (found->refcount <= 0) {
fprintf(stderr, "get:bad refcount\n."); fprintf(stderr, "get:bad refcount\n.");
return NULL; return NULL;
@ -191,17 +184,13 @@ class OpenHandles {
return found->onedb; return found->onedb;
} }
bool remove(Text dbname, int64_t uniqueid) { bool remove(Text dbname) {
auto p = head_.find(dbname); auto p = head_.find(dbname);
if (p == head_.end()) { if (p == head_.end()) {
fprintf(stderr, "get:No db with name\n"); fprintf(stderr, "get:No db with name\n");
return false; return false;
} }
struct onehandle* found = p->second; struct onehandle* found = p->second;
if (found->uniqueid != uniqueid) {
fprintf(stderr, "remove:Uniqueid does not match\n.");
return false;
}
if (found->refcount == 1) { if (found->refcount == 1) {
delete found->onedb; // close database delete found->onedb; // close database
int numRemoved = head_.erase(dbname); int numRemoved = head_.erase(dbname);
@ -214,7 +203,6 @@ class OpenHandles {
private: private:
unordered_map<std::string, struct onehandle*> head_; // all open databases unordered_map<std::string, struct onehandle*> head_; // all open databases
std::atomic<uint64_t> dbnum_;
struct onehandle* lookup(Text dbname) { struct onehandle* lookup(Text dbname) {
auto p = head_.find(dbname); auto p = head_.find(dbname);

View File

@ -1,11 +0,0 @@
/**
* Options for the Thrift leveldb server.
* @author Dhruba Borthakur (dhruba@gmail.com)
* Copyright 2012 Facebook
**/
#include <DB.h>
#include "server_options.h"
const std::string ServerOptions::DEFAULT_HOST = "hostname";
const std::string ServerOptions::DEFAULT_ROOTDIR = "/tmp/ldb/";

View File

@ -41,24 +41,20 @@ class ServerOptions {
// default port // default port
const static int DEFAULT_PORT = 6666; const static int DEFAULT_PORT = 6666;
// default machine name
const static std::string DEFAULT_HOST;
// default directory where the server stores all its data
const static std::string DEFAULT_ROOTDIR;
public: public:
ServerOptions() : num_threads_(DEFAULT_threads), ServerOptions() : num_threads_(DEFAULT_threads),
cache_numshardbits_(DEFAULT_cache_numshardbits), cache_numshardbits_(DEFAULT_cache_numshardbits),
cache_size_(DEFAULT_cache_size), cache_size_(DEFAULT_cache_size),
port_(DEFAULT_PORT), port_(DEFAULT_PORT),
hostname_(DEFAULT_HOST),
rootdir_(DEFAULT_ROOTDIR + DEFAULT_HOST),
cache_(NULL) { cache_(NULL) {
char buf[100]; char* buf = new char[HOST_NAME_MAX];
if (gethostname(buf, sizeof(buf)) == 0) { if (gethostname(buf, HOST_NAME_MAX) == 0) {
hostname_ = buf; hostname_ = buf;
} else {
hostname_ = "unknownhost";
delete buf;
} }
rootdir_ = "/tmp"; // default rootdir
} }
// //
@ -121,11 +117,18 @@ public:
} }
} }
// Returns the server port // Returns the base server port
int getPort() { int getPort() {
return port_; return port_;
} }
// Returns the assoc server port. Currently, it is one more than the base
// server port. In fiture, the assoc service would be supported on multiple
// ports, each port serving a distinct range of keys.
int getAssocPort() {
return port_ + 1;
}
// Returns the cache // Returns the cache
leveldb::Cache* getCache() { leveldb::Cache* getCache() {
return cache_; return cache_;

View File

@ -18,6 +18,7 @@
#include <leveldb_types.h> #include <leveldb_types.h>
#include "openhandles.h" #include "openhandles.h"
#include "server_options.h" #include "server_options.h"
#include "assoc.h"
#include "leveldb/db.h" #include "leveldb/db.h"
#include "leveldb/write_batch.h" #include "leveldb/write_batch.h"
@ -34,15 +35,16 @@ using boost::shared_ptr;
extern "C" void startServer(int argc, char** argv); extern "C" void startServer(int argc, char** argv);
extern "C" void stopServer(int port); extern "C" void stopServer(int port);
static boost::shared_ptr<TServer> tServer; static boost::shared_ptr<TServer> baseServer;
static boost::shared_ptr<TServer> assocServer;
// The global object that stores the default configuration of the server // The global object that stores the default configuration of the server
ServerOptions server_options; ServerOptions server_options;
class DBHandler : virtual public DBIf { class DBHandler : virtual public DBIf {
public: public:
DBHandler() { DBHandler(OpenHandles* oh) {
openHandles = new OpenHandles(); openHandles = oh;
} }
void Open(DBHandle& _return, const Text& dbname, void Open(DBHandle& _return, const Text& dbname,
@ -73,19 +75,15 @@ class DBHandler : virtual public DBIf {
} else if (dboptions.compression == kSnappyCompression) { } else if (dboptions.compression == kSnappyCompression) {
options.compression = leveldb::kSnappyCompression; options.compression = leveldb::kSnappyCompression;
} }
int64_t session = openHandles->add(options, dbname, dbdir); openHandles->add(options, dbname, dbdir);
_return.dbname = dbname; _return.dbname = dbname;
_return.handleid = session;
} }
Code Close(const DBHandle& dbhandle, const Text& dbname) { Code Close(const DBHandle& dbhandle, const Text& dbname) {
/** //
* We do not close any handles for now, otherwise we have to do // We do not close any handles for now, otherwise we have to do
* some locking that will degrade performance in the normal case. // some locking that will degrade performance in the normal case.
if (openHandles->remove(dbname, dbhandle.handleid) == false) { //
return Code::kIOError;
}
*/
return Code::kNotSupported; return Code::kNotSupported;
} }
@ -98,7 +96,7 @@ class DBHandler : virtual public DBIf {
key.size_ = kv.key.size; key.size_ = kv.key.size;
value.data_ = kv.value.data.data(); value.data_ = kv.value.data.data();
value.size_ = kv.value.size; value.size_ = kv.value.size;
leveldb::DB* db = openHandles->get(dbhandle.dbname, dbhandle.handleid, NULL); leveldb::DB* db = openHandles->get(dbhandle.dbname, NULL);
if (db == NULL) { if (db == NULL) {
return Code::kNotFound; return Code::kNotFound;
} }
@ -116,7 +114,7 @@ class DBHandler : virtual public DBIf {
leveldb::Slice key; leveldb::Slice key;
key.data_ = kv.data.data(); key.data_ = kv.data.data();
key.size_ = kv.size; key.size_ = kv.size;
leveldb::DB* db = openHandles->get(dbhandle.dbname, dbhandle.handleid, NULL); leveldb::DB* db = openHandles->get(dbhandle.dbname, NULL);
if (db == NULL) { if (db == NULL) {
return Code::kNotFound; return Code::kNotFound;
} }
@ -141,7 +139,7 @@ class DBHandler : virtual public DBIf {
value.size_ = one.value.size; value.size_ = one.value.size;
lbatch.Put(key, value); lbatch.Put(key, value);
} }
leveldb::DB* db = openHandles->get(dbhandle.dbname, dbhandle.handleid, NULL); leveldb::DB* db = openHandles->get(dbhandle.dbname, NULL);
if (db == NULL) { if (db == NULL) {
return Code::kNotFound; return Code::kNotFound;
} }
@ -160,8 +158,7 @@ class DBHandler : virtual public DBIf {
leveldb::Slice ikey; leveldb::Slice ikey;
ikey.data_ = inputkey.data.data(); ikey.data_ = inputkey.data.data();
ikey.size_ = inputkey.size; ikey.size_ = inputkey.size;
leveldb::DB* db = openHandles->get(dbhandle.dbname, dbhandle.handleid, leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle);
&thishandle);
if (db == NULL) { if (db == NULL) {
return; return;
} }
@ -192,8 +189,7 @@ class DBHandler : virtual public DBIf {
const Slice& target) { const Slice& target) {
struct onehandle* thishandle; struct onehandle* thishandle;
_return.status = Code::kNotFound; _return.status = Code::kNotFound;
leveldb::DB* db = openHandles->get(dbhandle.dbname, dbhandle.handleid, leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle);
&thishandle);
if (db == NULL) { if (db == NULL) {
return; return;
} }
@ -245,8 +241,7 @@ class DBHandler : virtual public DBIf {
Code DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator) { Code DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator) {
// find the db // find the db
struct onehandle* thishandle; struct onehandle* thishandle;
leveldb::DB* db = openHandles->get(dbhandle.dbname, dbhandle.handleid, leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle);
&thishandle);
if (db == NULL) { if (db == NULL) {
return kNotFound; return kNotFound;
} }
@ -271,8 +266,7 @@ class DBHandler : virtual public DBIf {
// find the db // find the db
struct onehandle* thishandle; struct onehandle* thishandle;
_return.status = Code::kNotFound; _return.status = Code::kNotFound;
leveldb::DB* db = openHandles->get(dbhandle.dbname, dbhandle.handleid, leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle);
&thishandle);
if (db == NULL) { if (db == NULL) {
return; return;
} }
@ -338,8 +332,7 @@ class DBHandler : virtual public DBIf {
void GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle) { void GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle) {
_return.status = kIOError; _return.status = kIOError;
struct onehandle* thishandle; struct onehandle* thishandle;
leveldb::DB* db = openHandles->get(dbhandle.dbname, dbhandle.handleid, leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle);
&thishandle);
if (db == NULL) { if (db == NULL) {
return; return;
} }
@ -354,8 +347,7 @@ class DBHandler : virtual public DBIf {
Code ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) { Code ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) {
struct onehandle* thishandle; struct onehandle* thishandle;
leveldb::DB* db = openHandles->get(dbhandle.dbname, dbhandle.handleid, leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle);
&thishandle);
if (db == NULL) { if (db == NULL) {
return kNotFound; return kNotFound;
} }
@ -369,7 +361,7 @@ class DBHandler : virtual public DBIf {
Code CompactRange(const DBHandle& dbhandle, const Slice& begin, Code CompactRange(const DBHandle& dbhandle, const Slice& begin,
const Slice& end) { const Slice& end) {
leveldb::DB* db = openHandles->get(dbhandle.dbname, dbhandle.handleid, NULL); leveldb::DB* db = openHandles->get(dbhandle.dbname, NULL);
if (db == NULL) { if (db == NULL) {
return Code::kNotFound; return Code::kNotFound;
} }
@ -395,6 +387,14 @@ class DBHandler : virtual public DBIf {
OpenHandles* openHandles; OpenHandles* openHandles;
}; };
//
// starts a service
static void* startOneService(void *arg) {
TSimpleServer* t = (TSimpleServer *)arg;
t->serve();
}
// Starts a very simple thrift server // Starts a very simple thrift server
void startServer(int argc, char** argv) { void startServer(int argc, char** argv) {
@ -410,17 +410,43 @@ void startServer(int argc, char** argv) {
// create the server's block cache // create the server's block cache
server_options.createCache(); server_options.createCache();
int port = server_options.getPort(); // data structure to record ope databases
shared_ptr<DBHandler> handler(new DBHandler()); OpenHandles* openHandles = new OpenHandles();
shared_ptr<TProcessor> processor(new DBProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer tServer(processor, serverTransport, transportFactory, protocolFactory); // create the service to process the normal get/put to leveldb.
fprintf(stderr, "Server started on port %d\n", port); int port = server_options.getPort();
fprintf(stderr, "Server starting on port %d\n", port);
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<DBHandler> handler(new DBHandler(openHandles));
shared_ptr<TProcessor> processor(new DBProcessor(handler));
TSimpleServer* baseServer = new TSimpleServer(processor, serverTransport,
transportFactory, protocolFactory);
pthread_t dbServerThread;
int rc = pthread_create(&dbServerThread, NULL, startOneService,
(void *)baseServer);
if (rc != 0) {
fprintf(stderr, "Unable to start DB server on port %d\n.", port);
exit(1);
}
tServer.serve(); // create the service to process the assoc get/put to leveldb.
int assocport = server_options.getAssocPort();
fprintf(stderr, "Server starting on port %d\n", assocport);
shared_ptr<TServerTransport> assocTransport(new TServerSocket(assocport));
shared_ptr<AssocServiceHandler> assocHandler(new AssocServiceHandler(openHandles));
shared_ptr<TProcessor> assocProcessor(new AssocServiceProcessor(assocHandler));
TSimpleServer* assocServer = new TSimpleServer(assocProcessor,
assocTransport, transportFactory, protocolFactory);
pthread_t assocServerThread;
rc = pthread_create(&assocServerThread, NULL, startOneService,
(void *)assocServer);
if (rc != 0) {
fprintf(stderr, "Unable to start assoc server on port %d\n.", port);
exit(1);
}
} }
/** /**
@ -436,5 +462,6 @@ void startEventServer(int port) {
// Stops the thrift server // Stops the thrift server
void stopServer(int port) { void stopServer(int port) {
tServer->stop(); baseServer->stop();
assocServer->stop();
} }

View File

@ -6,7 +6,9 @@
#include <protocol/TBinaryProtocol.h> #include <protocol/TBinaryProtocol.h>
#include <transport/TSocket.h> #include <transport/TSocket.h>
#include <transport/TBufferTransports.h> #include <transport/TBufferTransports.h>
#include <util/testharness.h>
#include <DB.h> #include <DB.h>
#include <AssocService.h>
#include <leveldb_types.h> #include <leveldb_types.h>
#include "server_options.h" #include "server_options.h"
@ -22,7 +24,8 @@ extern ServerOptions server_options;
static DBHandle dbhandle; static DBHandle dbhandle;
static DBClient* dbclient; static DBClient* dbclient;
static const Text dbname = "test"; static AssocServiceClient* aclient;
static const Text dbname = "test-dhruba";
static pthread_t serverThread; static pthread_t serverThread;
static int ARGC; static int ARGC;
static char** ARGV; static char** ARGV;
@ -51,17 +54,31 @@ static void createDatabase() {
dbclient->Open(dbhandle, dbname, options); dbclient->Open(dbhandle, dbname, options);
} }
static void testClient(int port) { static void initialize(int port) {
boost::shared_ptr<TSocket> socket(new TSocket("localhost", port)); boost::shared_ptr<TSocket> socket1(new TSocket("localhost", port));
boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket)); boost::shared_ptr<TTransport> transport1(new TBufferedTransport(socket1));
boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); boost::shared_ptr<TProtocol> protocol1(new TBinaryProtocol(transport1));
WriteOptions writeOptions;
// open database // open database
dbclient = new DBClient(protocol); dbclient = new DBClient(protocol1);
transport->open(); transport1->open();
boost::shared_ptr<TSocket> socket2(new TSocket("localhost", port+1));
boost::shared_ptr<TTransport> transport2(new TBufferedTransport(socket2));
boost::shared_ptr<TProtocol> protocol2(new TBinaryProtocol(transport2));
aclient = new AssocServiceClient(protocol2);
transport2->open();
createDatabase(); createDatabase();
printf("Database created.\n"); printf("Database created.\n");
}
//
// Run base leveldb thrift server get/put/iter/scan tests
//
static void testClient() {
WriteOptions writeOptions;
printf("Running base leveldb operations .................\n");
// insert record into leveldb // insert record into leveldb
Slice key; Slice key;
@ -74,23 +91,23 @@ static void testClient(int port) {
keyvalue.key = key; keyvalue.key = key;
keyvalue.value = value; keyvalue.value = value;
int ret = dbclient->Put(dbhandle, keyvalue, writeOptions); int ret = dbclient->Put(dbhandle, keyvalue, writeOptions);
assert(ret == Code::kOk); ASSERT_TRUE(ret == Code::kOk);
printf("Put Key1 suceeded.\n"); printf("Put Key1 suceeded.\n");
//read it back //read it back
ReadOptions readOptions; ReadOptions readOptions;
ResultItem rValue; ResultItem rValue;
dbclient->Get(rValue, dbhandle, key, readOptions); dbclient->Get(rValue, dbhandle, key, readOptions);
assert(rValue.status == Code::kOk); ASSERT_TRUE(rValue.status == Code::kOk);
assert(value.data.compare(rValue.value.data) == 0); ASSERT_TRUE(value.data.compare(rValue.value.data) == 0);
assert(value.size == rValue.value.size); ASSERT_TRUE(value.size == rValue.value.size);
printf("Get suceeded.\n"); printf("Get suceeded.\n");
// get a snapshot // get a snapshot
ResultSnapshot rsnap; ResultSnapshot rsnap;
dbclient->GetSnapshot(rsnap, dbhandle); dbclient->GetSnapshot(rsnap, dbhandle);
assert(rsnap.status == Code::kOk); ASSERT_TRUE(rsnap.status == Code::kOk);
assert(rsnap.snapshot.snapshotid > 0); ASSERT_TRUE(rsnap.snapshot.snapshotid > 0);
printf("Snapshot suceeded.\n"); printf("Snapshot suceeded.\n");
// insert a new record into leveldb // insert a new record into leveldb
@ -103,29 +120,29 @@ static void testClient(int port) {
keyvalue.key = key2; keyvalue.key = key2;
keyvalue.value = value2; keyvalue.value = value2;
ret = dbclient->Put(dbhandle, keyvalue, writeOptions); ret = dbclient->Put(dbhandle, keyvalue, writeOptions);
assert(ret == Code::kOk); ASSERT_TRUE(ret == Code::kOk);
printf("Put Key2 suceeded.\n"); printf("Put Key2 suceeded.\n");
// verify that a get done with a previous snapshot does not find Key2 // verify that a get done with a previous snapshot does not find Key2
readOptions.snapshot = rsnap.snapshot; readOptions.snapshot = rsnap.snapshot;
dbclient->Get(rValue, dbhandle, key2, readOptions); dbclient->Get(rValue, dbhandle, key2, readOptions);
assert(rValue.status == Code::kNotFound); ASSERT_TRUE(rValue.status == Code::kNotFound);
printf("Get with snapshot succeeded.\n"); printf("Get with snapshot succeeded.\n");
// release snapshot // release snapshot
ret = dbclient->ReleaseSnapshot(dbhandle, rsnap.snapshot); ret = dbclient->ReleaseSnapshot(dbhandle, rsnap.snapshot);
assert(ret == Code::kOk); ASSERT_TRUE(ret == Code::kOk);
printf("Snapshot released.\n"); printf("Snapshot released.\n");
// if we try to re-release the same snapshot, it should fail // if we try to re-release the same snapshot, it should fail
ret = dbclient->ReleaseSnapshot(dbhandle, rsnap.snapshot); ret = dbclient->ReleaseSnapshot(dbhandle, rsnap.snapshot);
assert(ret == Code::kNotFound); ASSERT_TRUE(ret == Code::kNotFound);
// compact whole database // compact whole database
Slice range; Slice range;
range.size = 0; range.size = 0;
ret = dbclient->CompactRange(dbhandle, range, range); ret = dbclient->CompactRange(dbhandle, range, range);
assert(ret == Code::kOk); ASSERT_TRUE(ret == Code::kOk);
printf("Compaction trigger suceeded.\n"); printf("Compaction trigger suceeded.\n");
// create a new iterator to scan all keys from the start // create a new iterator to scan all keys from the start
@ -134,7 +151,7 @@ static void testClient(int port) {
readOptions.snapshot.snapshotid = 0; readOptions.snapshot.snapshotid = 0;
dbclient->NewIterator(ri, dbhandle, readOptions, dbclient->NewIterator(ri, dbhandle, readOptions,
IteratorType::seekToFirst, target); IteratorType::seekToFirst, target);
assert(ri.status == Code::kOk); ASSERT_TRUE(ri.status == Code::kOk);
int foundPairs = 0; int foundPairs = 0;
while (true) { while (true) {
ResultPair pair; ResultPair pair;
@ -145,16 +162,16 @@ static void testClient(int port) {
break; break;
} }
} }
assert(foundPairs == 2); ASSERT_TRUE(foundPairs == 2);
ret = dbclient->DeleteIterator(dbhandle, ri.iterator); ret = dbclient->DeleteIterator(dbhandle, ri.iterator);
assert(ret == Code::kOk); ASSERT_TRUE(ret == Code::kOk);
printf("Iterator scan-all forward passes.\n"); printf("Iterator scan-all forward passes.\n");
// create a new iterator, position at end and scan backwards // create a new iterator, position at end and scan backwards
readOptions.snapshot.snapshotid = 0; readOptions.snapshot.snapshotid = 0;
dbclient->NewIterator(ri, dbhandle, readOptions, dbclient->NewIterator(ri, dbhandle, readOptions,
IteratorType::seekToLast, target); IteratorType::seekToLast, target);
assert(ri.status == Code::kOk); ASSERT_TRUE(ri.status == Code::kOk);
foundPairs = 0; foundPairs = 0;
while (true) { while (true) {
ResultPair pair; ResultPair pair;
@ -165,9 +182,9 @@ static void testClient(int port) {
break; break;
} }
} }
assert(foundPairs == 2); ASSERT_TRUE(foundPairs == 2);
ret = dbclient->DeleteIterator(dbhandle, ri.iterator); ret = dbclient->DeleteIterator(dbhandle, ri.iterator);
assert(ret == Code::kOk); ASSERT_TRUE(ret == Code::kOk);
printf("Iterator scan-all backward passes.\n"); printf("Iterator scan-all backward passes.\n");
// create a new iterator, position at middle // create a new iterator, position at middle
@ -175,7 +192,7 @@ static void testClient(int port) {
target = key; target = key;
dbclient->NewIterator(ri, dbhandle, readOptions, dbclient->NewIterator(ri, dbhandle, readOptions,
IteratorType::seekToKey, target); IteratorType::seekToKey, target);
assert(ri.status == Code::kOk); ASSERT_TRUE(ri.status == Code::kOk);
foundPairs = 0; foundPairs = 0;
while (true) { while (true) {
ResultPair pair; ResultPair pair;
@ -186,29 +203,78 @@ static void testClient(int port) {
break; break;
} }
} }
assert(foundPairs == 1); ASSERT_TRUE(foundPairs == 1);
ret = dbclient->DeleteIterator(dbhandle, ri.iterator); ret = dbclient->DeleteIterator(dbhandle, ri.iterator);
assert(ret == Code::kOk); ASSERT_TRUE(ret == Code::kOk);
printf("Iterator scan-selective backward passes.\n"); printf("Iterator scan-selective backward passes.\n");
}
//
// Run assoc tests
//
static void testAssocs() {
WriteOptions writeOptions;
printf("Running assoc leveldb operations ................\n");
// insert record into leveldb
int64_t assocType = 100;
int64_t id1 = 1;
int64_t id2 = 2;
int64_t id1Type = 101;
int64_t id2Type = 102;
int64_t ts =3333;
AssocVisibility vis = AssocVisibility::VISIBLE;
bool update_count = true;
int64_t dataVersion = 5;
const Text data = "data......";
const Text wormhole_comments = "wormhole...";
int64_t count = aclient->taoAssocPut(dbname, assocType,
id1, id2, id1Type, id2Type,
ts, vis, update_count,
dataVersion, data, wormhole_comments);
ASSERT_GE(count, 0);
printf("Put AssocPut suceeded.\n");
// verify assoc counts.
int64_t cnt = aclient->taoAssocCount(dbname, assocType, id1);
ASSERT_EQ(cnt, 1);
printf("AssocCount suceeded.\n");
// verify that we can read back what we inserted earlier
std::vector<int64_t> id2list(1);
id2list[0] = id2;
std::vector<TaoAssocGetResult> readback(1);
aclient->taoAssocGet(readback, dbname,
assocType, id1, id2list);
printf("AssocGet suceeded.\n");
printf("size = %lld\n", readback.size());
ASSERT_EQ(1, readback.size());
ASSERT_EQ(id1Type, readback[0].id1Type);
printf("XXX %lld %lld\n", id1Type, readback[0].id1Type);
ASSERT_EQ(id2Type, readback[0].id2Type);
ASSERT_EQ(ts, readback[0].time);
ASSERT_EQ(dataVersion, readback[0].dataVersion);
ASSERT_EQ(readback[0].data.compare(wormhole_comments), 0);
}
//
// close all resources
//
static void close() {
// close database // close database
dbclient->Close(dbhandle, dbname); dbclient->Close(dbhandle, dbname);
transport->close(); // transport->close();
} }
static void* startTestServer(void *arg) {
printf("Server test server\n");
startServer(ARGC, ARGV);
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
ARGC = argc; ARGC = argc;
ARGV = argv; ARGV = argv;
// create a server // create a server
int rc = pthread_create(&serverThread, NULL, startTestServer, NULL); startServer(argc, argv);
printf("Server thread created.\n"); printf("Server thread created.\n");
// give some time to the server to initialize itself // give some time to the server to initialize itself
@ -217,7 +283,14 @@ int main(int argc, char **argv) {
} }
// test client // test client
testClient(server_options.getPort()); initialize(server_options.getPort());
// run all tests
testClient();
testAssocs();
// done all tests
close();
return 0; return 0;
} }