removed dead files, switch to CMake
git-svn-id: svn+ssh://svn.corp.yahoo.com/yahoo/yrl/labs/pnuts/code/logstore@523 8dad8b1f-cf64-0410-95b6-bcf113ffbcfe
This commit is contained in:
parent
648a725920
commit
78f9ad12c1
11 changed files with 0 additions and 2083 deletions
77
LogUtils.cc
77
LogUtils.cc
|
@ -1,77 +0,0 @@
|
||||||
/*! \file log4_util.cc
|
|
||||||
* \brief This file has the helper functions for log4cpp;
|
|
||||||
*
|
|
||||||
* Copyright (c) 2008 Yahoo, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
|
||||||
#include <iostream>
|
|
||||||
#include <log4cpp/PropertyConfigurator.hh>
|
|
||||||
|
|
||||||
#include "LogUtils.h"
|
|
||||||
|
|
||||||
using namespace log4cpp;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
// hacked link to actioncontext
|
|
||||||
std::string s_trackPathLog;
|
|
||||||
|
|
||||||
LogMethod::
|
|
||||||
LogMethod(log4cpp::Category& log, log4cpp::Priority::Value priority,
|
|
||||||
const char *function) :
|
|
||||||
log_(log), priority_(priority), function_(function)
|
|
||||||
{
|
|
||||||
if(log_.isPriorityEnabled(priority_)) {
|
|
||||||
log_.getStream(priority_) << "Entering: " << function_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LogMethod::
|
|
||||||
~LogMethod()
|
|
||||||
{
|
|
||||||
if(log_.isPriorityEnabled(priority_)) {
|
|
||||||
log_.getStream(priority_) << "Exiting: " << function_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protects against multiple calls (won't try to re-init) and gives
|
|
||||||
// back the same answer the original call got.
|
|
||||||
static int log4cppInitResult = -1;
|
|
||||||
|
|
||||||
bool
|
|
||||||
initLog4cpp(const string &confFile)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (log4cppInitResult != -1) {
|
|
||||||
return (log4cppInitResult == 0 ? true : false);
|
|
||||||
}
|
|
||||||
|
|
||||||
log4cppInitResult = 0; // Assume success.
|
|
||||||
try {
|
|
||||||
PropertyConfigurator::configure(confFile);
|
|
||||||
} catch (log4cpp::ConfigureFailure &e) {
|
|
||||||
cerr << "log4cpp configuration failure while loading '" <<
|
|
||||||
confFile << "' : " << e.what() << endl;
|
|
||||||
log4cppInitResult = 1;
|
|
||||||
} catch (std::exception &e) {
|
|
||||||
cerr << "exception caught while configuring log4cpp via '" <<
|
|
||||||
confFile << "': " << e.what() << endl;
|
|
||||||
log4cppInitResult = 1;
|
|
||||||
} catch (...) {
|
|
||||||
cerr << "unknown exception while configuring log4cpp via '" <<
|
|
||||||
confFile << "'." << endl;
|
|
||||||
log4cppInitResult = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (log4cppInitResult == 0 ? true : false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For customized vim control
|
|
||||||
* Local variables:
|
|
||||||
* tab-width: 4
|
|
||||||
* c-basic-offset: 4
|
|
||||||
* End:
|
|
||||||
* vim600: sw=4:ts=4:et
|
|
||||||
* vim<600: sw=4:ts=4:et
|
|
||||||
*/
|
|
130
LogUtils.h
130
LogUtils.h
|
@ -1,130 +0,0 @@
|
||||||
/* Copyright (C) 2007 Yahoo! Inc. All Rights Reserved. */
|
|
||||||
|
|
||||||
#ifndef LOG_UTIL_H
|
|
||||||
#define LOG_UTIL_H
|
|
||||||
|
|
||||||
#include <log4cpp/Category.hh>
|
|
||||||
#include "StringUtils.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Quick and dirty link between LogUtils and ActionContext without having to
|
|
||||||
* resolve cross-inclusion issues, or force all components to start including
|
|
||||||
* ActionContext if they don't already.
|
|
||||||
*/
|
|
||||||
extern std::string s_trackPathLog;
|
|
||||||
|
|
||||||
// These macros cannot be protected by braces because of the trailing stream
|
|
||||||
// arguments that get appended. Care must taken not to use them inside if/else
|
|
||||||
// blocks that do not use curly braces.
|
|
||||||
// I.e., the following will give unexpected results:
|
|
||||||
// if(foo)
|
|
||||||
// DHT_DEBUG_STREAM() << "heyheyhey";
|
|
||||||
// else
|
|
||||||
// blah();
|
|
||||||
// The 'else' will end up applying to the 'if' within the debug macro.
|
|
||||||
// Regardless of this, our standards say to always use curly brackets
|
|
||||||
// on every block anyway, no matter what.
|
|
||||||
|
|
||||||
#define DHT_DEBUG_STREAM() if(log.isDebugEnabled()) log.debugStream() << __FUNCTION__ << "():" << __LINE__ << ":"
|
|
||||||
#define DHT_INFO_STREAM() if(log.isInfoEnabled()) log.infoStream() << __FUNCTION__ << "():" << __LINE__ << ":"
|
|
||||||
#define DHT_INFO_WITH_STACK_STREAM() if(log.isInfoEnabled()) log.infoStream() << __FUNCTION__ << "():" << __LINE__ << ":" << s_trackPathLog
|
|
||||||
#define DHT_WARN_STREAM() if(log.isWarnEnabled()) log.warnStream() << __FUNCTION__ << "():" << __LINE__ << ":" << s_trackPathLog
|
|
||||||
#define DHT_ERROR_STREAM() if(log.isErrorEnabled()) log.errorStream() << __FUNCTION__ << "():" << __LINE__ << ":" << s_trackPathLog
|
|
||||||
#define DHT_CRIT_STREAM() if(log.isCritEnabled()) log.critStream() << __FUNCTION__ << "():" << __LINE__ << ":" << s_trackPathLog
|
|
||||||
#define DHT_TRACE_PRIORITY log4cpp::Priority::DEBUG + 50
|
|
||||||
#define DHT_TRACE_STREAM() if (log.isPriorityEnabled(DHT_TRACE_PRIORITY)) log.getStream(DHT_TRACE_PRIORITY) << __FUNCTION__ << "():" << __LINE__ << ":"
|
|
||||||
|
|
||||||
// Sadly, sometimes 'log' is reserved by someone else so the code needs to
|
|
||||||
// use a different name for log. In that case, it can be passed in to these.
|
|
||||||
#define DHT_DEBUG_STREAML(x_log_hdl_x) if((x_log_hdl_x).isDebugEnabled()) (x_log_hdl_x).debugStream() << __FUNCTION__ << "():" << __LINE__ << ":"
|
|
||||||
#define DHT_INFO_STREAML(x_log_hdl_x) if((x_log_hdl_x).isInfoEnabled()) (x_log_hdl_x).infoStream() << __FUNCTION__ << "():" << __LINE__ << ":"
|
|
||||||
#define DHT_INFO_WITH_STACK_STREAML(x_log_hdl_x) if((x_log_hdl_x).isInfoEnabled()) (x_log_hdl_x).infoStream() << __FUNCTION__ << "():" << __LINE__ << ":" << s_trackPathLog
|
|
||||||
#define DHT_WARN_STREAML(x_log_hdl_x) if((x_log_hdl_x).isWarnEnabled()) (x_log_hdl_x).warnStream() << __FUNCTION__ << "():" << __LINE__ << ":" << s_trackPathLog
|
|
||||||
#define DHT_ERROR_STREAML(x_log_hdl_x) if((x_log_hdl_x).isErrorEnabled()) (x_log_hdl_x).errorStream() << __FUNCTION__ << "():" << __LINE__ << ":" << s_trackPathLog
|
|
||||||
#define DHT_CRIT_STREAML(x_log_hdl_x) if((x_log_hdl_x).isCritEnabled()) (x_log_hdl_x).critStream() << __FUNCTION__ << "():" << __LINE__ << ":" << s_trackPathLog
|
|
||||||
#define DHT_TRACE_STREAML(x_log_hdl_x) if ((x_log_hdl_x).isPriorityEnabled(DHT_TRACE_PRIORITY)) (x_log_hdl_x).getStream(DHT_TRACE_PRIORITY) << __FUNCTION__ << "():" << __LINE__ << ":"
|
|
||||||
|
|
||||||
//Macros to use when a function returns on error without writing any log message
|
|
||||||
// or error translation
|
|
||||||
#define RETURN_IF_NOT_OK(x_call_x) \
|
|
||||||
{ \
|
|
||||||
FwCode::ResponseCode rcx___ = (x_call_x); \
|
|
||||||
if(rcx___ != FwCode::FwOk) { \
|
|
||||||
return rcx___; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RETURN_THIS_IF_NOT_OK(x_othercode_x, x_call_x) \
|
|
||||||
{ \
|
|
||||||
FwCode::ResponseCode rcx___ = (x_call_x); \
|
|
||||||
if(rcx___ != FwCode::FwOk) { \
|
|
||||||
return (x_othercode_x); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Caution! Only use in checks for 'impossible' code conditions. Regular errors
|
|
||||||
/// should be handled regularly
|
|
||||||
#define BAD_CODE_ABORT() \
|
|
||||||
{ \
|
|
||||||
std::string x_msg_x("Bad code at " __FILE__ ":"); \
|
|
||||||
x_msg_x.append(StringUtils::toString(__LINE__)); \
|
|
||||||
throw std::runtime_error(x_msg_x); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BAD_CODE_IF_NOT_OK(x_call_x) \
|
|
||||||
do {\
|
|
||||||
if((x_call_x) != FwCode::FwOk) { \
|
|
||||||
BAD_CODE_ABORT(); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Above macros are meant to be used by all components.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that allows for method entry/exit logging with a single declaration.
|
|
||||||
* Always uses debug.
|
|
||||||
*/
|
|
||||||
class LogMethod
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LogMethod(log4cpp::Category& log, log4cpp::Priority::Value priority,
|
|
||||||
const char *function);
|
|
||||||
virtual ~LogMethod();
|
|
||||||
|
|
||||||
private:
|
|
||||||
log4cpp::Category& log_;
|
|
||||||
log4cpp::Priority::Value priority_;
|
|
||||||
const char *function_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// convenience macros to use the above class
|
|
||||||
#define LOG_METHOD() LogMethod log_method_entry_exit(log, log4cpp::Priority::DEBUG, __FUNCTION__)
|
|
||||||
#define TRACE_METHOD() LogMethod log_method_entry_exit(log, DHT_TRACE_PRIORITY, __FUNCTION__)
|
|
||||||
|
|
||||||
/** Initialize log4cpp config file.
|
|
||||||
* This function needs to be called once for each executable. Multiple
|
|
||||||
* initializations will return the result of the first initialization (IOW,
|
|
||||||
* an executable can be initialized with exactly one config file). Errors
|
|
||||||
* encountered by this function are printed onto cerr. See log4cpp
|
|
||||||
* documentation for what happens when PropertyConfigurator::configure()
|
|
||||||
* fails.
|
|
||||||
* \param confFile is the path name of the log4cpp config file.
|
|
||||||
* Depending on the machine that the executable is running in, the path
|
|
||||||
* will be different.
|
|
||||||
* \return true if the initialization succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool initLog4cpp(const std::string & confFile);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For customized vim control
|
|
||||||
* Local variables:
|
|
||||||
* tab-width: 4
|
|
||||||
* c-basic-offset: 4
|
|
||||||
* End:
|
|
||||||
* vim600: sw=4:ts=4:et
|
|
||||||
* vim<600: sw=4:ts=4:et
|
|
||||||
*/
|
|
74
Makefile
74
Makefile
|
@ -1,74 +0,0 @@
|
||||||
STASIS_DIR=../stasis
|
|
||||||
|
|
||||||
LIB=$(STASIS_DIR)/build/src/stasis \
|
|
||||||
-L/home/y/lib
|
|
||||||
INCLUDE=-I$(STASIS_DIR)/src/ -I$(STASIS_DIR) -I./ \
|
|
||||||
-I/home/y/include
|
|
||||||
|
|
||||||
LIBLIST=-lpthread \
|
|
||||||
-lstasis \
|
|
||||||
-lm
|
|
||||||
# -licui18n \
|
|
||||||
# -licuuc \
|
|
||||||
# -licudata \
|
|
||||||
# -licuio \
|
|
||||||
# -llog4cpp_y \
|
|
||||||
# -lthoth
|
|
||||||
|
|
||||||
FLAGS=-pg -g -O1
|
|
||||||
#FLAGS=-O3
|
|
||||||
|
|
||||||
HFILES=logserver.h logstore.h logiterators.h datapage.h merger.h tuplemerger.h datatuple.h
|
|
||||||
CFILES=logserver.cpp logstore.cpp logiterators.cpp datapage.cpp merger.cpp tuplemerger.cpp
|
|
||||||
|
|
||||||
|
|
||||||
# STASIS_DIR=../stasis
|
|
||||||
# LD_LIBRARY_PATH=$STASIS_DIR/build/src/stasis
|
|
||||||
# LD_LIBRARY_PATH=$STASIS_DIR/build/src/stasis ./hello
|
|
||||||
|
|
||||||
|
|
||||||
logstore: check_gen.cpp $(HFILES) $(CFILES)
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
test: dp_check lt_check ltable_check merger_check rb_check \
|
|
||||||
lmerger_check tmerger_check server_check tcpclient_check
|
|
||||||
|
|
||||||
lt_check: check_logtree.cpp $(HFILES) $(CFILES)
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
dp_check: check_datapage.cpp $(HFILES) $(CFILES)
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
ltable_check: check_logtable.cpp $(HFILES) $(CFILES)
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
merger_check: check_merge.cpp $(HFILES) $(CFILES)
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
lmerger_check: check_mergelarge.cpp $(HFILES) $(CFILES)
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
tmerger_check: check_mergetuple.cpp $(HFILES) $(CFILES)
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
rb_check: check_rbtree.cpp $(HFILES) $(CFILES)
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
server_check: check_server.cpp $(HFILES) $(CFILES)
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
tcpclient_check: check_tcpclient.cpp $(HFILES) $(CFILES)
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
|
|
||||||
hello : hello.cpp UCharUtils.cc LogUtils.cc
|
|
||||||
g++ -o $@ $^ -L$(LIB) $(INCLUDE) $(LIBLIST) $(FLAGS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f logstore server_check hello lt_check merger_check lmerger_check rb_check \
|
|
||||||
dp_check ltable_check tmerger_check rose tcpclient_check
|
|
||||||
veryclean: clean
|
|
||||||
rm -f *~ gmon.out prof.res
|
|
||||||
|
|
||||||
|
|
||||||
|
|
326
UCharUtils.cc
326
UCharUtils.cc
|
@ -1,326 +0,0 @@
|
||||||
/* $Id: UCharUtils.cc,v 1.16 2009/03/03 20:19:18 dlomax Exp $ */
|
|
||||||
/* Copyright (C) 2008 Yahoo! Inc. All Rights Reserved. */
|
|
||||||
|
|
||||||
//#include <dht/UCharUtils.h>
|
|
||||||
#include "UCharUtils.h"
|
|
||||||
#include <log4cpp/Category.hh>
|
|
||||||
#include "LogUtils.h"
|
|
||||||
//#include "ActionContext.h"
|
|
||||||
#include <unicode/ucnv.h>
|
|
||||||
#include <unicode/unorm.h>
|
|
||||||
#include <thoth/validate.h> // To make sure we have UTF-8
|
|
||||||
|
|
||||||
static log4cpp::Category &log =
|
|
||||||
log4cpp::Category::getInstance("dht.framework." __FILE__);
|
|
||||||
|
|
||||||
|
|
||||||
UCharUtilsImpl *UCharUtils::instance_ = NULL;
|
|
||||||
|
|
||||||
UCharUtilsImpl::
|
|
||||||
UCharUtilsImpl() : uconv_(NULL) {
|
|
||||||
LOG_METHOD();
|
|
||||||
|
|
||||||
ucBuffLen = 0;
|
|
||||||
ucBuff = NULL;
|
|
||||||
|
|
||||||
ucNormBuffLen = 0;
|
|
||||||
ucNormBuff = NULL;
|
|
||||||
|
|
||||||
charBuffLen = 0;
|
|
||||||
charBuff = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FwCode::ResponseCode UCharUtilsImpl::
|
|
||||||
init()
|
|
||||||
{
|
|
||||||
UErrorCode erc = U_ZERO_ERROR;
|
|
||||||
|
|
||||||
uconv_ = ucnv_open("utf-8", &erc);
|
|
||||||
if (uconv_ == NULL) {
|
|
||||||
DHT_ERROR_STREAM() << "EC:UNICODE:Problem geting utf-8 converter, erc:" << erc
|
|
||||||
<< ", " << u_errorName(erc);
|
|
||||||
return FwCode::UcnvOpenFailed;
|
|
||||||
}
|
|
||||||
return FwCode::FwOk;
|
|
||||||
}
|
|
||||||
|
|
||||||
UCharUtilsImpl::
|
|
||||||
~UCharUtilsImpl() {
|
|
||||||
reset();
|
|
||||||
if (uconv_ != NULL) {
|
|
||||||
ucnv_close(uconv_);
|
|
||||||
uconv_ = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UCharUtilsImpl::
|
|
||||||
reset() {
|
|
||||||
LOG_METHOD();
|
|
||||||
|
|
||||||
if (ucBuff != NULL) {
|
|
||||||
delete[] ucBuff;
|
|
||||||
ucBuffLen = 0;
|
|
||||||
ucBuff = NULL;
|
|
||||||
}
|
|
||||||
if (ucNormBuff != NULL) {
|
|
||||||
delete[] ucNormBuff;
|
|
||||||
ucNormBuffLen = 0;
|
|
||||||
ucNormBuff = NULL;
|
|
||||||
}
|
|
||||||
if (charBuff != NULL) {
|
|
||||||
delete[] charBuff;
|
|
||||||
charBuffLen = 0;
|
|
||||||
charBuff = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Small wrapper to hide multi-line thoth api inside single-line call.
|
|
||||||
*/
|
|
||||||
bool UCharUtils::
|
|
||||||
isUTF8(const std::string& value)
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
thoth_result result = thoth_validate_utf8(value.c_str(), value.length(),
|
|
||||||
&pos);
|
|
||||||
|
|
||||||
if(result != UTF8_VALID) {
|
|
||||||
std::cerr
|
|
||||||
//RESPONSE_DEBUG_STREAM(FwCode::DataNotUtf8)
|
|
||||||
<< "value (" << value << ") is not UTF-8. thoth_result:" << result
|
|
||||||
<< ", position=" << pos;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Small wrapper to hide multi-line thoth api inside single-line call.
|
|
||||||
*/
|
|
||||||
bool UCharUtils::
|
|
||||||
isUTF8(const char * value, size_t value_len)
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
thoth_result result = thoth_validate_utf8(value, value_len, &pos);
|
|
||||||
|
|
||||||
if(result != UTF8_VALID) {
|
|
||||||
//RESPONSE_DEBUG_STREAM(FwCode::DataNotUtf8)
|
|
||||||
std::cerr
|
|
||||||
<< "value (" << std::string(value, value_len)
|
|
||||||
<< ") is not UTF-8. thoth_result:" << result
|
|
||||||
<< ", position=" << pos;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert an input string (expected to be UTF-8) into unicode UChars
|
|
||||||
// The result of the conversion will be sitting in our ucBuff area.
|
|
||||||
FwCode::ResponseCode UCharUtilsImpl::
|
|
||||||
convert(const std::string &input, int32_t &len)
|
|
||||||
{
|
|
||||||
LOG_METHOD();
|
|
||||||
|
|
||||||
//UTF-8 validation
|
|
||||||
if(!UCharUtils::isUTF8(input)) {
|
|
||||||
return FwCode::DataNotUtf8;
|
|
||||||
}
|
|
||||||
|
|
||||||
int size = input.length() * 2;
|
|
||||||
|
|
||||||
// Check if we already have a big enough buffer
|
|
||||||
if (ucBuffLen < size) {
|
|
||||||
// Nope, first check if we need to release what we've been using
|
|
||||||
if (ucBuff) {
|
|
||||||
delete[] ucBuff;
|
|
||||||
}
|
|
||||||
ucBuffLen = size;
|
|
||||||
ucBuff = new UChar[ucBuffLen];
|
|
||||||
}
|
|
||||||
|
|
||||||
UErrorCode erc = U_ZERO_ERROR;
|
|
||||||
len = ucnv_toUChars(uconv_,
|
|
||||||
ucBuff,
|
|
||||||
ucBuffLen,
|
|
||||||
input.data(),
|
|
||||||
input.length(), &erc);
|
|
||||||
|
|
||||||
if (U_FAILURE(erc)) {
|
|
||||||
//RESPONSE_ERROR_STREAM(FwCode::ConvertToUCharFailed)
|
|
||||||
std::cerr
|
|
||||||
<< "EC:UNICODE:error:" << erc
|
|
||||||
<< ", " << u_errorName(erc)
|
|
||||||
<< " from converting input:'" << input << "'";
|
|
||||||
len = 0;
|
|
||||||
return FwCode::ConvertToUCharFailed;
|
|
||||||
}
|
|
||||||
return FwCode::FwOk;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize an input string. Note that all three internal buffers will
|
|
||||||
// be used by this operation, but by the time we finish, we'll be done
|
|
||||||
// with them.
|
|
||||||
FwCode::ResponseCode UCharUtilsImpl::
|
|
||||||
normalize(const std::string &input, std::string &result /* out */)
|
|
||||||
{
|
|
||||||
LOG_METHOD();
|
|
||||||
|
|
||||||
// convert our UTF-8 into UChar
|
|
||||||
int32_t inLen = 0;
|
|
||||||
FwCode::ResponseCode rc = convert(input, inLen);
|
|
||||||
|
|
||||||
if (rc != FwCode::FwOk) {
|
|
||||||
result.erase();
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do a quick check if the input is already normalized so that
|
|
||||||
// we can duck out early
|
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
|
||||||
if (unorm_quickCheck(ucBuff, inLen,
|
|
||||||
UNORM_NFC, &status) == UNORM_YES) {
|
|
||||||
DHT_DEBUG_STREAM() << "already normalized input:" << input;
|
|
||||||
result = input;
|
|
||||||
return FwCode::FwOk;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we have enough space for the normalized result.
|
|
||||||
// We'll make the output space twice as big as the input (although
|
|
||||||
// it's more likely that the normalized result will be shorter
|
|
||||||
// as it combines characters. E.g. 'A' 'put an accent on the previous'
|
|
||||||
int32_t newSize = inLen * 2;
|
|
||||||
if (newSize > ucNormBuffLen) {
|
|
||||||
DHT_DEBUG_STREAM() << "newSize:" << newSize
|
|
||||||
<< " ucNormBuffLen:" << ucNormBuffLen;
|
|
||||||
if (ucNormBuff) {
|
|
||||||
delete[] ucNormBuff;
|
|
||||||
}
|
|
||||||
ucNormBuffLen = newSize;
|
|
||||||
ucNormBuff = new UChar[ucNormBuffLen];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the actual normalization
|
|
||||||
status = U_ZERO_ERROR;
|
|
||||||
int32_t normLen = unorm_normalize(ucBuff, inLen,
|
|
||||||
UNORM_NFC, 0,
|
|
||||||
ucNormBuff,
|
|
||||||
ucNormBuffLen,
|
|
||||||
&status);
|
|
||||||
if(U_FAILURE(status)) {
|
|
||||||
//RESPONSE_ERROR_STREAM(FwCode::FwError)
|
|
||||||
std::cerr
|
|
||||||
<< "EC:UNICODE:error:" << status << ", " << u_errorName(status)
|
|
||||||
<<" in unorm_normalize, inLen:" << inLen
|
|
||||||
<< " ucNormBuffLen:" << ucNormBuffLen;
|
|
||||||
return FwCode::FwError;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we have some space to convert back to UTF-8
|
|
||||||
int32_t resultLen = normLen * 4;
|
|
||||||
if (resultLen > charBuffLen) {
|
|
||||||
DHT_DEBUG_STREAM() << "resultLen:" << resultLen
|
|
||||||
<< " charBuffLen:" << charBuffLen;
|
|
||||||
if (charBuff) {
|
|
||||||
delete[] charBuff;
|
|
||||||
charBuff= NULL;
|
|
||||||
}
|
|
||||||
charBuffLen = resultLen;
|
|
||||||
charBuff = new char[charBuffLen];
|
|
||||||
}
|
|
||||||
|
|
||||||
DHT_DEBUG_STREAM() <<"calling ucnv_fromUChars, normLen:" << normLen;
|
|
||||||
|
|
||||||
// Go from UChar array to UTF-8
|
|
||||||
int32_t actualLen = ucnv_fromUChars(uconv_,
|
|
||||||
charBuff, charBuffLen,
|
|
||||||
ucNormBuff, normLen,
|
|
||||||
&status);
|
|
||||||
if(U_FAILURE(status)) {
|
|
||||||
//RESPONSE_ERROR_STREAM(FwCode::FwError)
|
|
||||||
std::cerr
|
|
||||||
<< "EC:UNICODE:error:" << status << ", " << u_errorName(status)
|
|
||||||
<< " in ucnv_fromUChars charBuffLen:" << charBuffLen
|
|
||||||
<< " normLen:" << normLen;
|
|
||||||
return FwCode::FwError;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smack our UTF-8 characters into the result string
|
|
||||||
result.assign(charBuff, actualLen);
|
|
||||||
DHT_DEBUG_STREAM() << "leaving actualLen:" << actualLen
|
|
||||||
<< " result:" << result;
|
|
||||||
return FwCode::FwOk;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FwCode::ResponseCode UCharUtils::
|
|
||||||
init()
|
|
||||||
{
|
|
||||||
if (instance_ == NULL) {
|
|
||||||
instance_ = new UCharUtilsImpl();
|
|
||||||
return instance_->init();
|
|
||||||
}
|
|
||||||
return FwCode::FwOk; // already initialized
|
|
||||||
}
|
|
||||||
|
|
||||||
void UCharUtils::
|
|
||||||
close()
|
|
||||||
{
|
|
||||||
if(instance_ != NULL) {
|
|
||||||
delete instance_;
|
|
||||||
instance_ = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given an input string, return a unicode UChar array. Note that the
|
|
||||||
// return value is a pointer to our internal buffer.
|
|
||||||
UChar * UCharUtils::
|
|
||||||
getUChar(const std::string &input, int32_t& len) {
|
|
||||||
LOG_METHOD();
|
|
||||||
|
|
||||||
// do the conversion...somehow need 2x input len for utf8 to utf16
|
|
||||||
if(instance_->convert(input, len) != FwCode::FwOk) {
|
|
||||||
len = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance_->ucBuff;
|
|
||||||
}
|
|
||||||
|
|
||||||
FwCode::ResponseCode UCharUtils::
|
|
||||||
normalize(const std::string &input, std::string &result) {
|
|
||||||
LOG_METHOD();
|
|
||||||
return(instance_->normalize(input, result));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FwCode::ResponseCode UCharUtils::
|
|
||||||
parseRegExpPattern(const std::string &pattern,
|
|
||||||
URegularExpression * & result /* out */)
|
|
||||||
{
|
|
||||||
UParseError perr;
|
|
||||||
UErrorCode erc = U_ZERO_ERROR;
|
|
||||||
int32_t ureglen = 0;
|
|
||||||
|
|
||||||
// Do not delete uregexp, it's a static reusable buffer inside UCharUtils
|
|
||||||
UChar *uregexp = UCharUtils::getUChar(pattern, ureglen);
|
|
||||||
if (uregexp == NULL) {
|
|
||||||
//RESPONSE_ERROR_STREAM(FwCode::ConvertToUCharFailed)
|
|
||||||
std::cerr
|
|
||||||
<< "EC:UNICODE|IMPOSSIBLE:Unable to convert pattern to unicode: " << pattern;
|
|
||||||
return FwCode::ConvertToUCharFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
URegularExpression *regexp= uregex_open(uregexp, ureglen, 0,
|
|
||||||
&perr,
|
|
||||||
&erc);
|
|
||||||
if(erc != U_ZERO_ERROR) {
|
|
||||||
//RESPONSE_DEBUG_STREAM(FwCode::CompileRegExFailed)
|
|
||||||
std::cerr
|
|
||||||
<< "Compiling regex failed at: " << perr.offset
|
|
||||||
<< "; re=" << pattern;
|
|
||||||
return FwCode::CompileRegExFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = regexp;
|
|
||||||
return FwCode::FwOk;
|
|
||||||
}
|
|
139
UCharUtils.h
139
UCharUtils.h
|
@ -1,139 +0,0 @@
|
||||||
/* Copyright (C) 2008 Yahoo! Inc. All Rights Reserved. */
|
|
||||||
|
|
||||||
#ifndef UCHAR_UTILS_H
|
|
||||||
#define UCHAR_UTILS_H
|
|
||||||
|
|
||||||
#include <unicode/ucnv.h>
|
|
||||||
#include <string>
|
|
||||||
#include "FwCode.h"
|
|
||||||
#include <unicode/uregex.h>
|
|
||||||
|
|
||||||
// Forward declaration
|
|
||||||
class UCharUtilsImpl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Some handy utilities for working with unicode characters. Yes, these
|
|
||||||
* could have just been some regular routines instead of static methods
|
|
||||||
* in a class, but doing it this way gives us some containment of what
|
|
||||||
* other static tidbits might be necessary (like reusable buffer space).
|
|
||||||
* which are all hidden within the UCharUtilsImpl class.
|
|
||||||
*
|
|
||||||
* This is a singleton - do not use in a threaded program.
|
|
||||||
*/
|
|
||||||
class UCharUtils {
|
|
||||||
private:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Our pointer to all sorts of goodness.
|
|
||||||
*/
|
|
||||||
static UCharUtilsImpl *instance_;
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the utilities. Primarily opens the utf-8 converter.
|
|
||||||
* Calling this is required prior to using the converter.
|
|
||||||
*
|
|
||||||
* @return FwCode::FwOk on success, FwCode::UcnvOpenFailed on
|
|
||||||
* failure.
|
|
||||||
*/
|
|
||||||
static FwCode::ResponseCode init();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release all resources. <code>init()</code> must be called again
|
|
||||||
* in order to use again.
|
|
||||||
*/
|
|
||||||
static void close();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Small wrapper to hide multi-line thoth api inside single-line call.
|
|
||||||
*
|
|
||||||
* @param value string to be tested for utf-8-ness
|
|
||||||
* @return true if it is utf-8, false if not
|
|
||||||
*/
|
|
||||||
static bool isUTF8(const std::string& value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Small wrapper to hide multi-line thoth api inside single-line call.
|
|
||||||
*
|
|
||||||
* @param value char string to be tested for utf-8-ness
|
|
||||||
* @param value_len length of <code>value</code>
|
|
||||||
* @return true if it is utf-8, false if not
|
|
||||||
*/
|
|
||||||
static bool isUTF8(const char * value, size_t value_len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert utf-8 strings into UChar strings. Note that the
|
|
||||||
* result is an internal reusable buffer so the caller should
|
|
||||||
* *not* release it.
|
|
||||||
* @param input utf-8 string to convert
|
|
||||||
* @param len set to length of output string
|
|
||||||
* @return NULL if anything bad happens, otherwise an allocated UChar *
|
|
||||||
* the caller must *NEVER* free this pointer.
|
|
||||||
*/
|
|
||||||
static UChar * getUChar(const std::string &input, int32_t& len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do a NFC normalization so that different yet equivalent strings
|
|
||||||
* will have a single representation. See
|
|
||||||
* http://www.unicode.org/unicode/reports/tr15/
|
|
||||||
* for more information.
|
|
||||||
* @param input A UTF-8 string that we want to normalize
|
|
||||||
* @param result (output) the normalized UTF-8 string
|
|
||||||
* @return FwCode::FwOk on success,
|
|
||||||
* FwCode::FwError on conversion failure,
|
|
||||||
* FwCode::InvalidData if input was not utf-8
|
|
||||||
*/
|
|
||||||
static FwCode::ResponseCode normalize(const std::string &input,
|
|
||||||
std::string &result);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compile a regular expression in a unicode-friendly way.
|
|
||||||
*
|
|
||||||
* @param pattern the regexp pattern to compile. Assumed to
|
|
||||||
* be utf-8.
|
|
||||||
* @param result (output) Set to point to the compiled regexp.
|
|
||||||
* Must be released by the caller via uregex_close() when
|
|
||||||
* finished with it.
|
|
||||||
* @return FwCode::FwOk if compilation succeeded,
|
|
||||||
* FwCode::CompileRegExFailed or FwCode::ConvertToUCharFailed
|
|
||||||
* on failure.
|
|
||||||
*/
|
|
||||||
static FwCode::ResponseCode parseRegExpPattern
|
|
||||||
(const std::string &pattern,
|
|
||||||
URegularExpression * & result /* out */);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bug 2574599 - Impl exposed for use by multiple threads; singleton not
|
|
||||||
* appropriate for multi-threaded program.
|
|
||||||
*/
|
|
||||||
class UCharUtilsImpl
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
UConverter *uconv_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
UCharUtilsImpl();
|
|
||||||
~UCharUtilsImpl();
|
|
||||||
|
|
||||||
FwCode::ResponseCode init();
|
|
||||||
void reset();
|
|
||||||
FwCode::ResponseCode convert(const std::string &input, int32_t &len);
|
|
||||||
|
|
||||||
FwCode::ResponseCode normalize(const std::string &nput, std::string &result);
|
|
||||||
|
|
||||||
// Buffer used to convert from UTF-* into UChar
|
|
||||||
int32_t ucBuffLen;
|
|
||||||
UChar *ucBuff;
|
|
||||||
|
|
||||||
// Buffer used for UChar normalization output
|
|
||||||
int32_t ucNormBuffLen;
|
|
||||||
UChar *ucNormBuff;
|
|
||||||
|
|
||||||
// Buffer used to convert UChars back to UTF-8
|
|
||||||
int32_t charBuffLen;
|
|
||||||
char *charBuff;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _DHT_UCHAR_UTILS_
|
|
48
hello.cpp
48
hello.cpp
|
@ -1,48 +0,0 @@
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <string.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include<stasis/transactional.h>
|
|
||||||
|
|
||||||
typedef unsigned char uchar;
|
|
||||||
typedef struct datatuple
|
|
||||||
{
|
|
||||||
|
|
||||||
typedef byte* key_t;
|
|
||||||
typedef byte* data_t;
|
|
||||||
uint32_t keylen;
|
|
||||||
uint32_t datalen;
|
|
||||||
key_t key;
|
|
||||||
data_t data;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
|
|
||||||
bool * m1 = new bool(false);
|
|
||||||
std::cout << *m1 << std::endl;
|
|
||||||
|
|
||||||
datatuple t;
|
|
||||||
std::cout << "size of datatuple:\t" << sizeof(datatuple) << std::endl;
|
|
||||||
|
|
||||||
t.key = (datatuple::key_t) malloc(10);
|
|
||||||
const char * str = "12345678";
|
|
||||||
strcpy((char*)t.key, (str));
|
|
||||||
|
|
||||||
t.keylen = strlen((char*)t.key);
|
|
||||||
|
|
||||||
t.data = (datatuple::data_t) malloc(10);
|
|
||||||
const char * str2 = "1234567";
|
|
||||||
strcpy((char*)t.data, (str2));
|
|
||||||
|
|
||||||
t.datalen = strlen((char*)t.data);
|
|
||||||
|
|
||||||
std::cout << "size of datatuple:\t" << sizeof(datatuple) << std::endl;
|
|
||||||
std::cout << "keylen:\t" << t.keylen <<
|
|
||||||
"\tdatalen:\t" << t.datalen <<
|
|
||||||
"\t" << t.key <<
|
|
||||||
"\t" << t.data <<
|
|
||||||
std::endl;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,519 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "logserver.h"
|
|
||||||
#include "datatuple.h"
|
|
||||||
|
|
||||||
#include "logstore.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <sys/select.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#undef begin
|
|
||||||
#undef end
|
|
||||||
#undef try
|
|
||||||
|
|
||||||
|
|
||||||
//server codes
|
|
||||||
uint8_t logserver::OP_SUCCESS = 1;
|
|
||||||
uint8_t logserver::OP_FAIL = 2;
|
|
||||||
uint8_t logserver::OP_SENDING_TUPLE = 3;
|
|
||||||
|
|
||||||
//client codes
|
|
||||||
uint8_t logserver::OP_FIND = 4;
|
|
||||||
uint8_t logserver::OP_INSERT = 5;
|
|
||||||
|
|
||||||
uint8_t logserver::OP_DONE = 6;
|
|
||||||
|
|
||||||
uint8_t logserver::OP_INVALID = 32;
|
|
||||||
|
|
||||||
void *serverLoop(void *args);
|
|
||||||
|
|
||||||
void logserver::startserver(logtable *ltable)
|
|
||||||
{
|
|
||||||
sys_alive = true;
|
|
||||||
this->ltable = ltable;
|
|
||||||
|
|
||||||
selcond = new pthread_cond_t;
|
|
||||||
pthread_cond_init(selcond, 0);
|
|
||||||
|
|
||||||
//initialize threads
|
|
||||||
for(int i=0; i<nthreads; i++)
|
|
||||||
{
|
|
||||||
struct pthread_item *worker_th = new pthread_item;
|
|
||||||
th_list.push_back(worker_th);
|
|
||||||
|
|
||||||
worker_th->th_handle = new pthread_t;
|
|
||||||
struct pthread_data *worker_data = new pthread_data;
|
|
||||||
worker_th->data = worker_data;
|
|
||||||
|
|
||||||
worker_data->idleth_queue = &idleth_queue;
|
|
||||||
worker_data->ready_queue = &ready_queue;
|
|
||||||
worker_data->work_queue = &work_queue;
|
|
||||||
|
|
||||||
worker_data->qlock = qlock;
|
|
||||||
|
|
||||||
worker_data->selcond = selcond;
|
|
||||||
|
|
||||||
worker_data->th_cond = new pthread_cond_t;
|
|
||||||
pthread_cond_init(worker_data->th_cond,0);
|
|
||||||
|
|
||||||
worker_data->th_mut = new pthread_mutex_t;
|
|
||||||
pthread_mutex_init(worker_data->th_mut,0);
|
|
||||||
|
|
||||||
worker_data->workitem = new int;
|
|
||||||
*(worker_data->workitem) = -1;
|
|
||||||
|
|
||||||
worker_data->table_lock = lsmlock;
|
|
||||||
|
|
||||||
worker_data->ltable = ltable;
|
|
||||||
|
|
||||||
worker_data->sys_alive = &sys_alive;
|
|
||||||
|
|
||||||
pthread_create(worker_th->th_handle, 0, thread_work_fn, worker_th);
|
|
||||||
|
|
||||||
idleth_queue.push(*worker_th);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//start server socket
|
|
||||||
sdata = new serverth_data;
|
|
||||||
sdata->server_socket = &serversocket;
|
|
||||||
sdata->server_port = server_port;
|
|
||||||
sdata->idleth_queue = &idleth_queue;
|
|
||||||
sdata->ready_queue = &ready_queue;
|
|
||||||
sdata->selcond = selcond;
|
|
||||||
sdata->qlock = qlock;
|
|
||||||
|
|
||||||
pthread_create(&server_thread, 0, serverLoop, sdata);
|
|
||||||
|
|
||||||
//start monitoring loop
|
|
||||||
eventLoop();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void logserver::stopserver()
|
|
||||||
{
|
|
||||||
//close the server socket
|
|
||||||
//stops receiving data on the server socket
|
|
||||||
shutdown(serversocket, 0);
|
|
||||||
|
|
||||||
//wait for all threads to be idle
|
|
||||||
while(idleth_queue.size() != nthreads)
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
//set the system running flag to false
|
|
||||||
sys_alive = false;
|
|
||||||
for(int i=0; i<nthreads; i++)
|
|
||||||
{
|
|
||||||
pthread_item *idle_th = th_list[i];
|
|
||||||
|
|
||||||
//wake up the thread
|
|
||||||
pthread_mutex_lock(idle_th->data->th_mut);
|
|
||||||
pthread_cond_signal(idle_th->data->th_cond);
|
|
||||||
pthread_mutex_unlock(idle_th->data->th_mut);
|
|
||||||
//wait for it to join
|
|
||||||
pthread_join(*(idle_th->th_handle), 0);
|
|
||||||
//free the thread variables
|
|
||||||
pthread_cond_destroy(idle_th->data->th_cond);
|
|
||||||
delete idle_th->data->th_cond;
|
|
||||||
delete idle_th->data->th_mut;
|
|
||||||
delete idle_th->data->workitem;
|
|
||||||
delete idle_th->data;
|
|
||||||
delete idle_th->th_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
th_list.clear();
|
|
||||||
|
|
||||||
//close(serversocket);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void logserver::eventLoop()
|
|
||||||
{
|
|
||||||
|
|
||||||
fd_set readfs;
|
|
||||||
std::vector<int> sel_list;
|
|
||||||
|
|
||||||
int maxfd;
|
|
||||||
|
|
||||||
struct timeval Timeout;
|
|
||||||
struct timespec ts;
|
|
||||||
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
//clear readset
|
|
||||||
FD_ZERO(&readfs);
|
|
||||||
maxfd = -1;
|
|
||||||
|
|
||||||
ts.tv_nsec = 250000; //nanosec
|
|
||||||
ts.tv_sec = 0;
|
|
||||||
|
|
||||||
//Timeout.tv_usec = 250; /* microseconds */
|
|
||||||
//Timeout.tv_sec = 0; /* seconds */
|
|
||||||
|
|
||||||
//update select set
|
|
||||||
pthread_mutex_lock(qlock);
|
|
||||||
|
|
||||||
while(ready_queue.size() == 0)
|
|
||||||
{
|
|
||||||
pthread_cond_wait(selcond, qlock);
|
|
||||||
//pthread_cond_timedwait(selcond, qlock, &ts);
|
|
||||||
//printf("awoke\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//new connections + processed conns are in ready_queue
|
|
||||||
//add them to select list
|
|
||||||
while(ready_queue.size() > 0)
|
|
||||||
{
|
|
||||||
sel_list.push_back(ready_queue.front());
|
|
||||||
ready_queue.pop();
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(qlock);
|
|
||||||
|
|
||||||
//ready select set
|
|
||||||
for(std::vector<int>::const_iterator itr=sel_list.begin();
|
|
||||||
itr != sel_list.end(); itr++)
|
|
||||||
{
|
|
||||||
if(maxfd < *itr)
|
|
||||||
maxfd = *itr;
|
|
||||||
FD_SET(*itr, &readfs);
|
|
||||||
}
|
|
||||||
|
|
||||||
//select events
|
|
||||||
int sel_res = select(maxfd+1, &readfs, NULL, NULL, NULL);// &Timeout);
|
|
||||||
//printf("sel_res %d %d\n", sel_res, errno);
|
|
||||||
//fflush(stdout);
|
|
||||||
//job assignment to threads
|
|
||||||
|
|
||||||
for(int i=0; i<sel_list.size(); i++ )
|
|
||||||
{
|
|
||||||
int currsock = sel_list[i];
|
|
||||||
|
|
||||||
if (FD_ISSET(currsock, &readfs))
|
|
||||||
{
|
|
||||||
//printf("sock %d ready\n", currsock);
|
|
||||||
pthread_mutex_lock(qlock);
|
|
||||||
|
|
||||||
if(idleth_queue.size() > 0) //assign the job to an indle thread
|
|
||||||
{
|
|
||||||
pthread_item idle_th = idleth_queue.front();
|
|
||||||
idleth_queue.pop();
|
|
||||||
|
|
||||||
//wake up the thread to do work
|
|
||||||
pthread_mutex_lock(idle_th.data->th_mut);
|
|
||||||
//set the job of the idle thread
|
|
||||||
*(idle_th.data->workitem) = currsock;
|
|
||||||
pthread_cond_signal(idle_th.data->th_cond);
|
|
||||||
pthread_mutex_unlock(idle_th.data->th_mut);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//insert the given element to the work queue
|
|
||||||
work_queue.push(currsock);
|
|
||||||
printf("work queue size:\t%d\n", work_queue.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
//remove from the sel_list
|
|
||||||
sel_list.erase(sel_list.begin()+i);
|
|
||||||
i--;
|
|
||||||
|
|
||||||
pthread_mutex_unlock(qlock);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void *serverLoop(void *args)
|
|
||||||
{
|
|
||||||
|
|
||||||
serverth_data *sdata = (serverth_data*)args;
|
|
||||||
|
|
||||||
int sockfd; //socket descriptor
|
|
||||||
struct sockaddr_in serv_addr;
|
|
||||||
struct sockaddr_in cli_addr;
|
|
||||||
int newsockfd; //newly created
|
|
||||||
socklen_t clilen = sizeof(cli_addr);
|
|
||||||
|
|
||||||
|
|
||||||
//open a socket
|
|
||||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if (sockfd < 0)
|
|
||||||
{
|
|
||||||
printf("ERROR opening socket\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
|
||||||
serv_addr.sin_family = AF_INET;
|
|
||||||
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
serv_addr.sin_port = htons(sdata->server_port);
|
|
||||||
|
|
||||||
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
|
|
||||||
{
|
|
||||||
printf("ERROR on binding.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//start listening on the server socket
|
|
||||||
//second arg is the max number of coonections waiting in queue
|
|
||||||
if(listen(sockfd,SOMAXCONN)==-1)
|
|
||||||
{
|
|
||||||
printf("ERROR on listen.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("LSM Server listenning...\n");
|
|
||||||
|
|
||||||
*(sdata->server_socket) = sockfd;
|
|
||||||
int flag, result;
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
|
|
||||||
if (newsockfd < 0)
|
|
||||||
{
|
|
||||||
printf("ERROR on accept.\n");
|
|
||||||
return 0; // we probably want to continue instead of return here (when not debugging)
|
|
||||||
}
|
|
||||||
|
|
||||||
flag = 1;
|
|
||||||
result = setsockopt(newsockfd, /* socket affected */
|
|
||||||
IPPROTO_TCP, /* set option at TCP level */
|
|
||||||
TCP_NODELAY, /* name of option */
|
|
||||||
(char *) &flag, /* the cast is historical
|
|
||||||
cruft */
|
|
||||||
sizeof(int)); /* length of option value */
|
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
printf("ERROR on setting socket option TCP_NODELAY.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char clientip[20];
|
|
||||||
inet_ntop(AF_INET, (void*) &(cli_addr.sin_addr), clientip, 20);
|
|
||||||
printf("Connection from:\t%s\n", clientip);
|
|
||||||
|
|
||||||
//printf("Number of idle threads %d\n", idleth_queue.size());
|
|
||||||
|
|
||||||
pthread_mutex_lock(sdata->qlock);
|
|
||||||
|
|
||||||
//insert the given element to the ready queue
|
|
||||||
sdata->ready_queue->push(newsockfd);
|
|
||||||
|
|
||||||
if(sdata->ready_queue->size() == 1) //signal the event loop
|
|
||||||
pthread_cond_signal(sdata->selcond);
|
|
||||||
|
|
||||||
pthread_mutex_unlock(sdata->qlock);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void readfromsocket(int sockd, byte *buf, int count)
|
|
||||||
{
|
|
||||||
|
|
||||||
int n = 0;
|
|
||||||
while( n < count )
|
|
||||||
{
|
|
||||||
n += read( sockd, buf + n, count - n);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void writetosocket(int sockd, byte *buf, int count)
|
|
||||||
{
|
|
||||||
int n = 0;
|
|
||||||
while( n < count )
|
|
||||||
{
|
|
||||||
n += write( sockd, buf + n, count - n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void * thread_work_fn( void * args)
|
|
||||||
{
|
|
||||||
pthread_item * item = (pthread_item *) args;
|
|
||||||
|
|
||||||
pthread_mutex_lock(item->data->th_mut);
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
while(*(item->data->workitem) == -1)
|
|
||||||
{
|
|
||||||
if(!*(item->data->sys_alive))
|
|
||||||
break;
|
|
||||||
pthread_cond_wait(item->data->th_cond, item->data->th_mut); //wait for job
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(!*(item->data->sys_alive))
|
|
||||||
{
|
|
||||||
//printf("thread quitted.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//step 1: read the opcode
|
|
||||||
uint8_t opcode;
|
|
||||||
ssize_t n = read(*(item->data->workitem), &opcode, sizeof(uint8_t));
|
|
||||||
assert( n == sizeof(uint8_t));
|
|
||||||
assert( opcode < logserver::OP_INVALID );
|
|
||||||
|
|
||||||
if( opcode == logserver::OP_DONE ) //close the conn on failure
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(item->data->qlock);
|
|
||||||
printf("client done. conn closed. (%d, %d, %d, %d)\n",
|
|
||||||
n, errno, *(item->data->workitem), item->data->work_queue->size());
|
|
||||||
close(*(item->data->workitem));
|
|
||||||
|
|
||||||
if(item->data->work_queue->size() > 0)
|
|
||||||
{
|
|
||||||
int new_work = item->data->work_queue->front();
|
|
||||||
item->data->work_queue->pop();
|
|
||||||
printf("work queue size:\t%d\n", item->data->work_queue->size());
|
|
||||||
*(item->data->workitem) = new_work;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//set work to -1
|
|
||||||
*(item->data->workitem) = -1;
|
|
||||||
//add self to idle queue
|
|
||||||
item->data->idleth_queue->push(*item);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_cond_signal(item->data->selcond);
|
|
||||||
|
|
||||||
pthread_mutex_unlock(item->data->qlock);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//step 2: read the tuple from client
|
|
||||||
datatuple tuple;
|
|
||||||
tuple.keylen = (uint32_t*)malloc(sizeof(uint32_t));
|
|
||||||
tuple.datalen = (uint32_t*)malloc(sizeof(uint32_t));
|
|
||||||
|
|
||||||
//read the key length
|
|
||||||
n = read(*(item->data->workitem), tuple.keylen, sizeof(uint32_t));
|
|
||||||
assert( n == sizeof(uint32_t));
|
|
||||||
//read the data length
|
|
||||||
n = read(*(item->data->workitem), tuple.datalen, sizeof(uint32_t));
|
|
||||||
assert( n == sizeof(uint32_t));
|
|
||||||
|
|
||||||
//read the key
|
|
||||||
tuple.key = (byte*) malloc(*tuple.keylen);
|
|
||||||
readfromsocket(*(item->data->workitem), (byte*) tuple.key, *tuple.keylen);
|
|
||||||
//read the data
|
|
||||||
if(!tuple.isDelete() && opcode != logserver::OP_FIND)
|
|
||||||
{
|
|
||||||
tuple.data = (byte*) malloc(*tuple.datalen);
|
|
||||||
readfromsocket(*(item->data->workitem), (byte*) tuple.data, *tuple.datalen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tuple.data = 0;
|
|
||||||
|
|
||||||
//step 3: process the tuple
|
|
||||||
//pthread_mutex_lock(item->data->table_lock);
|
|
||||||
//readlock(item->data->table_lock,0);
|
|
||||||
|
|
||||||
if(opcode == logserver::OP_INSERT)
|
|
||||||
{
|
|
||||||
//insert/update/delete
|
|
||||||
item->data->ltable->insertTuple(tuple);
|
|
||||||
//unlock the lsmlock
|
|
||||||
//pthread_mutex_unlock(item->data->table_lock);
|
|
||||||
//unlock(item->data->table_lock);
|
|
||||||
//step 4: send response
|
|
||||||
uint8_t rcode = logserver::OP_SUCCESS;
|
|
||||||
n = write(*(item->data->workitem), &rcode, sizeof(uint8_t));
|
|
||||||
assert(n == sizeof(uint8_t));
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(opcode == logserver::OP_FIND)
|
|
||||||
{
|
|
||||||
//find the tuple
|
|
||||||
datatuple *dt = item->data->ltable->findTuple(-1, tuple.key, *tuple.keylen);
|
|
||||||
//unlock the lsmlock
|
|
||||||
//pthread_mutex_unlock(item->data->table_lock);
|
|
||||||
//unlock(item->data->table_lock);
|
|
||||||
|
|
||||||
if(dt == 0) //tuple deleted
|
|
||||||
{
|
|
||||||
dt = (datatuple*) malloc(sizeof(datatuple));
|
|
||||||
dt->keylen = (uint32_t*) malloc(2*sizeof(uint32_t) + *tuple.keylen);
|
|
||||||
*dt->keylen = *tuple.keylen;
|
|
||||||
dt->datalen = dt->keylen + 1;
|
|
||||||
dt->key = (datatuple::key_t) (dt->datalen+1);
|
|
||||||
memcpy((byte*) dt->key, (byte*) tuple.key, *tuple.keylen);
|
|
||||||
dt->setDelete();
|
|
||||||
}
|
|
||||||
|
|
||||||
//send the reply code
|
|
||||||
uint8_t rcode = logserver::OP_SENDING_TUPLE;
|
|
||||||
n = write(*(item->data->workitem), &rcode, sizeof(uint8_t));
|
|
||||||
assert(n == sizeof(uint8_t));
|
|
||||||
|
|
||||||
//send the tuple
|
|
||||||
writetosocket(*(item->data->workitem), (byte*) dt->keylen, dt->byte_length());
|
|
||||||
|
|
||||||
//free datatuple
|
|
||||||
free(dt->keylen);
|
|
||||||
free(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
//close the socket
|
|
||||||
//close(*(item->data->workitem));
|
|
||||||
|
|
||||||
//free the tuple
|
|
||||||
free(tuple.keylen);
|
|
||||||
free(tuple.datalen);
|
|
||||||
free(tuple.key);
|
|
||||||
free(tuple.data);
|
|
||||||
|
|
||||||
//printf("socket %d: work completed.\n", *(item->data->workitem));
|
|
||||||
|
|
||||||
pthread_mutex_lock(item->data->qlock);
|
|
||||||
|
|
||||||
//add conn desc to ready queue
|
|
||||||
item->data->ready_queue->push(*(item->data->workitem));
|
|
||||||
//printf("ready queue size: %d sock(%d)\n", item->data->ready_queue->size(), *(item->data->workitem));
|
|
||||||
if(item->data->ready_queue->size() == 1) //signal the event loop
|
|
||||||
pthread_cond_signal(item->data->selcond);
|
|
||||||
|
|
||||||
if(item->data->work_queue->size() > 0)
|
|
||||||
{
|
|
||||||
int new_work = item->data->work_queue->front();
|
|
||||||
item->data->work_queue->pop();
|
|
||||||
printf("work queue size:\t%d\n", item->data->work_queue->size());
|
|
||||||
*(item->data->workitem) = new_work;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//set work to -1
|
|
||||||
*(item->data->workitem) = -1;
|
|
||||||
//add self to idle queue
|
|
||||||
item->data->idleth_queue->push(*item);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(item->data->qlock);
|
|
||||||
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(item->data->th_mut);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
163
logserver_pers.h
163
logserver_pers.h
|
@ -1,163 +0,0 @@
|
||||||
#ifndef _LOGSERVER_H_
|
|
||||||
#define _LOGSERVER_H_
|
|
||||||
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
//#include "logstore.h"
|
|
||||||
|
|
||||||
#include "datatuple.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stasis/transactional.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#undef begin
|
|
||||||
#undef try
|
|
||||||
#undef end
|
|
||||||
|
|
||||||
class logtable;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct pthread_item;
|
|
||||||
|
|
||||||
struct pthread_data {
|
|
||||||
std::queue<pthread_item> *idleth_queue;
|
|
||||||
std::queue<int> *ready_queue;
|
|
||||||
std::queue<int> *work_queue;
|
|
||||||
pthread_mutex_t * qlock;
|
|
||||||
|
|
||||||
pthread_cond_t *selcond;
|
|
||||||
|
|
||||||
pthread_cond_t * th_cond;
|
|
||||||
pthread_mutex_t * th_mut;
|
|
||||||
|
|
||||||
int *workitem; //id of the socket to work
|
|
||||||
|
|
||||||
//pthread_mutex_t * table_lock;
|
|
||||||
rwl *table_lock;
|
|
||||||
logtable *ltable;
|
|
||||||
bool *sys_alive;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pthread_item{
|
|
||||||
pthread_t * th_handle;
|
|
||||||
pthread_data *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//struct work_item
|
|
||||||
//{
|
|
||||||
// int sockd; //socket id
|
|
||||||
// datatuple in_tuple; //request
|
|
||||||
// datatuple out_tuple; //response
|
|
||||||
//};
|
|
||||||
|
|
||||||
struct serverth_data
|
|
||||||
{
|
|
||||||
int *server_socket;
|
|
||||||
int server_port;
|
|
||||||
std::queue<pthread_item> *idleth_queue;
|
|
||||||
std::queue<int> *ready_queue;
|
|
||||||
|
|
||||||
pthread_cond_t *selcond;
|
|
||||||
|
|
||||||
pthread_mutex_t *qlock;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void * thread_work_fn( void *);
|
|
||||||
|
|
||||||
class logserver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//server codes
|
|
||||||
static uint8_t OP_SUCCESS;
|
|
||||||
static uint8_t OP_FAIL;
|
|
||||||
static uint8_t OP_SENDING_TUPLE;
|
|
||||||
|
|
||||||
//client codes
|
|
||||||
static uint8_t OP_FIND;
|
|
||||||
static uint8_t OP_INSERT;
|
|
||||||
|
|
||||||
static uint8_t OP_DONE;
|
|
||||||
|
|
||||||
static uint8_t OP_INVALID;
|
|
||||||
|
|
||||||
public:
|
|
||||||
logserver(int nthreads, int server_port){
|
|
||||||
this->nthreads = nthreads;
|
|
||||||
this->server_port = server_port;
|
|
||||||
//lsmlock = new pthread_mutex_t;
|
|
||||||
//pthread_mutex_init(lsmlock,0);
|
|
||||||
|
|
||||||
lsmlock = initlock();
|
|
||||||
|
|
||||||
qlock = new pthread_mutex_t;
|
|
||||||
pthread_mutex_init(qlock,0);
|
|
||||||
|
|
||||||
ltable = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
~logserver()
|
|
||||||
{
|
|
||||||
//delete lsmlock;
|
|
||||||
deletelock(lsmlock);
|
|
||||||
delete qlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startserver(logtable *ltable);
|
|
||||||
|
|
||||||
void stopserver();
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
//main loop of server
|
|
||||||
//accept connections, assign jobs to threads
|
|
||||||
//void dispatchLoop();
|
|
||||||
|
|
||||||
void eventLoop();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
int server_port;
|
|
||||||
|
|
||||||
int nthreads;
|
|
||||||
|
|
||||||
bool sys_alive;
|
|
||||||
|
|
||||||
int serversocket; //server socket file descriptor
|
|
||||||
|
|
||||||
//ccqueue<int> conn_queue; //list of active connections (socket list)
|
|
||||||
|
|
||||||
//ccqueue<pthread_item> idleth_queue; //list of idle threads
|
|
||||||
|
|
||||||
std::queue<int> ready_queue; //connections to go inside select
|
|
||||||
std::queue<int> work_queue; //connections to be processed by worker threads
|
|
||||||
std::queue<pthread_item> idleth_queue;
|
|
||||||
pthread_mutex_t *qlock;
|
|
||||||
|
|
||||||
pthread_t server_thread;
|
|
||||||
serverth_data *sdata;
|
|
||||||
pthread_cond_t *selcond; //server loop cond
|
|
||||||
|
|
||||||
std::vector<pthread_item *> th_list; // list of threads
|
|
||||||
|
|
||||||
rwl *lsmlock; //lock for using lsm table
|
|
||||||
|
|
||||||
logtable *ltable;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,409 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "logserver.h"
|
|
||||||
#include "datatuple.h"
|
|
||||||
|
|
||||||
#include "logstore.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#undef begin
|
|
||||||
#undef end
|
|
||||||
#undef try
|
|
||||||
|
|
||||||
|
|
||||||
//server codes
|
|
||||||
uint8_t logserver::OP_SUCCESS = 1;
|
|
||||||
uint8_t logserver::OP_FAIL = 2;
|
|
||||||
uint8_t logserver::OP_SENDING_TUPLE = 3;
|
|
||||||
|
|
||||||
//client codes
|
|
||||||
uint8_t logserver::OP_FIND = 4;
|
|
||||||
uint8_t logserver::OP_INSERT = 5;
|
|
||||||
|
|
||||||
uint8_t logserver::OP_INVALID = 32;
|
|
||||||
|
|
||||||
|
|
||||||
void logserver::startserver(logtable *ltable)
|
|
||||||
{
|
|
||||||
sys_alive = true;
|
|
||||||
this->ltable = ltable;
|
|
||||||
//initialize threads
|
|
||||||
for(int i=0; i<nthreads; i++)
|
|
||||||
{
|
|
||||||
struct pthread_item *worker_th = new pthread_item;
|
|
||||||
th_list.push_back(worker_th);
|
|
||||||
|
|
||||||
worker_th->th_handle = new pthread_t;
|
|
||||||
struct pthread_data *worker_data = new pthread_data;
|
|
||||||
worker_th->data = worker_data;
|
|
||||||
|
|
||||||
worker_data->idleth_queue = &idleth_queue;
|
|
||||||
|
|
||||||
worker_data->conn_queue = &conn_queue;
|
|
||||||
|
|
||||||
worker_data->qlock = qlock;
|
|
||||||
|
|
||||||
worker_data->th_cond = new pthread_cond_t;
|
|
||||||
pthread_cond_init(worker_data->th_cond,0);
|
|
||||||
|
|
||||||
worker_data->th_mut = new pthread_mutex_t;
|
|
||||||
pthread_mutex_init(worker_data->th_mut,0);
|
|
||||||
|
|
||||||
worker_data->workitem = new int;
|
|
||||||
*(worker_data->workitem) = -1;
|
|
||||||
|
|
||||||
worker_data->table_lock = lsmlock;
|
|
||||||
|
|
||||||
worker_data->ltable = ltable;
|
|
||||||
|
|
||||||
worker_data->sys_alive = &sys_alive;
|
|
||||||
|
|
||||||
pthread_create(worker_th->th_handle, 0, thread_work_fn, worker_th);
|
|
||||||
|
|
||||||
idleth_queue.push(*worker_th);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchLoop();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void logserver::stopserver()
|
|
||||||
{
|
|
||||||
//close the server socket
|
|
||||||
//stops receiving data on the server socket
|
|
||||||
shutdown(serversocket, 0);
|
|
||||||
|
|
||||||
//wait for all threads to be idle
|
|
||||||
while(idleth_queue.size() != nthreads)
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
//set the system running flag to false
|
|
||||||
sys_alive = false;
|
|
||||||
for(int i=0; i<nthreads; i++)
|
|
||||||
{
|
|
||||||
pthread_item *idle_th = th_list[i];
|
|
||||||
|
|
||||||
//wake up the thread
|
|
||||||
pthread_mutex_lock(idle_th->data->th_mut);
|
|
||||||
pthread_cond_signal(idle_th->data->th_cond);
|
|
||||||
pthread_mutex_unlock(idle_th->data->th_mut);
|
|
||||||
//wait for it to join
|
|
||||||
pthread_join(*(idle_th->th_handle), 0);
|
|
||||||
//free the thread variables
|
|
||||||
pthread_cond_destroy(idle_th->data->th_cond);
|
|
||||||
delete idle_th->data->th_cond;
|
|
||||||
delete idle_th->data->th_mut;
|
|
||||||
delete idle_th->data->workitem;
|
|
||||||
delete idle_th->data;
|
|
||||||
delete idle_th->th_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
th_list.clear();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void logserver::dispatchLoop()
|
|
||||||
{
|
|
||||||
|
|
||||||
int sockfd; //socket descriptor
|
|
||||||
struct sockaddr_in serv_addr;
|
|
||||||
struct sockaddr_in cli_addr;
|
|
||||||
int newsockfd; //newly created
|
|
||||||
socklen_t clilen = sizeof(cli_addr);
|
|
||||||
|
|
||||||
|
|
||||||
//open a socket
|
|
||||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if (sockfd < 0)
|
|
||||||
{
|
|
||||||
printf("ERROR opening socket\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
|
||||||
serv_addr.sin_family = AF_INET;
|
|
||||||
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
serv_addr.sin_port = htons(server_port);
|
|
||||||
|
|
||||||
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
|
|
||||||
{
|
|
||||||
printf("ERROR on binding.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//start listening on the server socket
|
|
||||||
//second arg is the max number of coonections waiting in queue
|
|
||||||
if(listen(sockfd,SOMAXCONN)==-1)
|
|
||||||
{
|
|
||||||
printf("ERROR on listen.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("LSM Server listenning...\n");
|
|
||||||
|
|
||||||
serversocket = sockfd;
|
|
||||||
int flag, result;
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
|
|
||||||
if (newsockfd < 0)
|
|
||||||
{
|
|
||||||
printf("ERROR on accept.\n");
|
|
||||||
return; // we probably want to continue instead of return here (when not debugging)
|
|
||||||
}
|
|
||||||
|
|
||||||
flag = 1;
|
|
||||||
result = setsockopt(newsockfd, /* socket affected */
|
|
||||||
IPPROTO_TCP, /* set option at TCP level */
|
|
||||||
TCP_NODELAY, /* name of option */
|
|
||||||
(char *) &flag, /* the cast is historical
|
|
||||||
cruft */
|
|
||||||
sizeof(int)); /* length of option value */
|
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
printf("ERROR on setting socket option TCP_NODELAY.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char clientip[20];
|
|
||||||
inet_ntop(AF_INET, (void*) &(cli_addr.sin_addr), clientip, 20);
|
|
||||||
//printf("Connection from:\t%s\n", clientip);
|
|
||||||
|
|
||||||
//printf("Number of idle threads %d\n", idleth_queue.size());
|
|
||||||
|
|
||||||
pthread_mutex_lock(qlock);
|
|
||||||
|
|
||||||
if(idleth_queue.size() > 0)
|
|
||||||
{
|
|
||||||
pthread_item idle_th = idleth_queue.front();
|
|
||||||
idleth_queue.pop();
|
|
||||||
|
|
||||||
//wake up the thread to do work
|
|
||||||
pthread_mutex_lock(idle_th.data->th_mut);
|
|
||||||
//set the job of the idle thread
|
|
||||||
*(idle_th.data->workitem) = newsockfd;
|
|
||||||
pthread_cond_signal(idle_th.data->th_cond);
|
|
||||||
pthread_mutex_unlock(idle_th.data->th_mut);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//insert the given element to the queue
|
|
||||||
conn_queue.push(newsockfd);
|
|
||||||
//printf("Number of queued connections:\t%d\n", conn_queue.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(qlock);
|
|
||||||
|
|
||||||
/*
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
pthread_item idle_th = idleth_queue.pop();
|
|
||||||
//wake up the thread to do work
|
|
||||||
pthread_mutex_lock(idle_th.data->th_mut);
|
|
||||||
//set the job of the idle thread
|
|
||||||
*(idle_th.data->workitem) = newsockfd;
|
|
||||||
pthread_cond_signal(idle_th.data->th_cond);
|
|
||||||
pthread_mutex_unlock(idle_th.data->th_mut);
|
|
||||||
|
|
||||||
}
|
|
||||||
catch(int empty_exception)
|
|
||||||
{
|
|
||||||
//insert the given element to the queue
|
|
||||||
conn_queue.push(newsockfd);
|
|
||||||
//printf("Number of queued connections:\t%d\n", conn_queue.size());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void readfromsocket(int sockd, byte *buf, int count)
|
|
||||||
{
|
|
||||||
|
|
||||||
int n = 0;
|
|
||||||
while( n < count )
|
|
||||||
{
|
|
||||||
n += read( sockd, buf + n, count - n);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void writetosocket(int sockd, byte *buf, int count)
|
|
||||||
{
|
|
||||||
int n = 0;
|
|
||||||
while( n < count )
|
|
||||||
{
|
|
||||||
n += write( sockd, buf + n, count - n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void * thread_work_fn( void * args)
|
|
||||||
{
|
|
||||||
pthread_item * item = (pthread_item *) args;
|
|
||||||
|
|
||||||
pthread_mutex_lock(item->data->th_mut);
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
while(*(item->data->workitem) == -1)
|
|
||||||
{
|
|
||||||
if(!*(item->data->sys_alive))
|
|
||||||
break;
|
|
||||||
pthread_cond_wait(item->data->th_cond, item->data->th_mut); //wait for job
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(!*(item->data->sys_alive))
|
|
||||||
{
|
|
||||||
//printf("thread quitted.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//step 1: read the opcode
|
|
||||||
uint8_t opcode;
|
|
||||||
ssize_t n = read(*(item->data->workitem), &opcode, sizeof(uint8_t));
|
|
||||||
assert( n == sizeof(uint8_t));
|
|
||||||
assert( opcode < logserver::OP_INVALID );
|
|
||||||
|
|
||||||
//step 2: read the tuple from client
|
|
||||||
datatuple tuple;
|
|
||||||
tuple.keylen = (uint32_t*)malloc(sizeof(uint32_t));
|
|
||||||
tuple.datalen = (uint32_t*)malloc(sizeof(uint32_t));
|
|
||||||
|
|
||||||
//read the key length
|
|
||||||
n = read(*(item->data->workitem), tuple.keylen, sizeof(uint32_t));
|
|
||||||
assert( n == sizeof(uint32_t));
|
|
||||||
//read the data length
|
|
||||||
n = read(*(item->data->workitem), tuple.datalen, sizeof(uint32_t));
|
|
||||||
assert( n == sizeof(uint32_t));
|
|
||||||
|
|
||||||
//read the key
|
|
||||||
tuple.key = (byte*) malloc(*tuple.keylen);
|
|
||||||
readfromsocket(*(item->data->workitem), (byte*) tuple.key, *tuple.keylen);
|
|
||||||
//read the data
|
|
||||||
if(!tuple.isDelete() && opcode != logserver::OP_FIND)
|
|
||||||
{
|
|
||||||
tuple.data = (byte*) malloc(*tuple.datalen);
|
|
||||||
readfromsocket(*(item->data->workitem), (byte*) tuple.data, *tuple.datalen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tuple.data = 0;
|
|
||||||
|
|
||||||
//step 3: process the tuple
|
|
||||||
//pthread_mutex_lock(item->data->table_lock);
|
|
||||||
//readlock(item->data->table_lock,0);
|
|
||||||
|
|
||||||
if(opcode == logserver::OP_INSERT)
|
|
||||||
{
|
|
||||||
//insert/update/delete
|
|
||||||
item->data->ltable->insertTuple(tuple);
|
|
||||||
//unlock the lsmlock
|
|
||||||
//pthread_mutex_unlock(item->data->table_lock);
|
|
||||||
//unlock(item->data->table_lock);
|
|
||||||
//step 4: send response
|
|
||||||
uint8_t rcode = logserver::OP_SUCCESS;
|
|
||||||
n = write(*(item->data->workitem), &rcode, sizeof(uint8_t));
|
|
||||||
assert(n == sizeof(uint8_t));
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(opcode == logserver::OP_FIND)
|
|
||||||
{
|
|
||||||
//find the tuple
|
|
||||||
datatuple *dt = item->data->ltable->findTuple(-1, tuple.key, *tuple.keylen);
|
|
||||||
//unlock the lsmlock
|
|
||||||
//pthread_mutex_unlock(item->data->table_lock);
|
|
||||||
//unlock(item->data->table_lock);
|
|
||||||
|
|
||||||
if(dt == 0) //tuple deleted
|
|
||||||
{
|
|
||||||
dt = (datatuple*) malloc(sizeof(datatuple));
|
|
||||||
dt->keylen = (uint32_t*) malloc(2*sizeof(uint32_t) + *tuple.keylen);
|
|
||||||
*dt->keylen = *tuple.keylen;
|
|
||||||
dt->datalen = dt->keylen + 1;
|
|
||||||
dt->key = (datatuple::key_t) (dt->datalen+1);
|
|
||||||
memcpy((byte*) dt->key, (byte*) tuple.key, *tuple.keylen);
|
|
||||||
dt->setDelete();
|
|
||||||
}
|
|
||||||
|
|
||||||
//send the reply code
|
|
||||||
uint8_t rcode = logserver::OP_SENDING_TUPLE;
|
|
||||||
n = write(*(item->data->workitem), &rcode, sizeof(uint8_t));
|
|
||||||
assert(n == sizeof(uint8_t));
|
|
||||||
|
|
||||||
//send the tuple
|
|
||||||
writetosocket(*(item->data->workitem), (byte*) dt->keylen, dt->byte_length());
|
|
||||||
|
|
||||||
//free datatuple
|
|
||||||
free(dt->keylen);
|
|
||||||
free(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
//close the socket
|
|
||||||
close(*(item->data->workitem));
|
|
||||||
|
|
||||||
//free the tuple
|
|
||||||
free(tuple.keylen);
|
|
||||||
free(tuple.datalen);
|
|
||||||
free(tuple.key);
|
|
||||||
free(tuple.data);
|
|
||||||
|
|
||||||
//printf("socket %d: work completed.\n", *(item->data->workitem));
|
|
||||||
|
|
||||||
pthread_mutex_lock(item->data->qlock);
|
|
||||||
|
|
||||||
if(item->data->conn_queue->size() > 0)
|
|
||||||
{
|
|
||||||
int new_work = item->data->conn_queue->front();
|
|
||||||
item->data->conn_queue->pop();
|
|
||||||
*(item->data->workitem) = new_work;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//set work to -1
|
|
||||||
*(item->data->workitem) = -1;
|
|
||||||
//add self to idle queue
|
|
||||||
item->data->idleth_queue->push(*item);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(item->data->qlock);
|
|
||||||
|
|
||||||
/*
|
|
||||||
//check if there is new work this thread can do
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int new_work = item->data->conn_queue->pop();
|
|
||||||
*(item->data->workitem) = new_work; //set new work
|
|
||||||
//printf("socket %d: new work found.\n", *(item->data->workitem));
|
|
||||||
}
|
|
||||||
catch(int empty_exception)
|
|
||||||
{
|
|
||||||
//printf("socket %d: no new work found.\n", *(item->data->workitem));
|
|
||||||
//set work to -1
|
|
||||||
*(item->data->workitem) = -1;
|
|
||||||
//add self to idle queue
|
|
||||||
item->data->idleth_queue->push(*item);
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(item->data->th_mut);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,198 +0,0 @@
|
||||||
#ifndef _LOGSERVER_H_
|
|
||||||
#define _LOGSERVER_H_
|
|
||||||
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
//#include "logstore.h"
|
|
||||||
|
|
||||||
#include "datatuple.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stasis/transactional.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#undef begin
|
|
||||||
#undef try
|
|
||||||
#undef end
|
|
||||||
|
|
||||||
class logtable;
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class ccqueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ccqueue()
|
|
||||||
{
|
|
||||||
qmut = new pthread_mutex_t;
|
|
||||||
pthread_mutex_init(qmut,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int size()
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(qmut);
|
|
||||||
int qsize = m_queue.size();
|
|
||||||
pthread_mutex_unlock(qmut);
|
|
||||||
return qsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
//inserts a copy of the given element to the queue
|
|
||||||
void push(const T &item)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(qmut);
|
|
||||||
m_queue.push(item);
|
|
||||||
pthread_mutex_unlock(qmut);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//returns a copy of the next element
|
|
||||||
//deletes the copy in the queue
|
|
||||||
//throws an exception with -1 on empty queue
|
|
||||||
T pop() throw (int)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(qmut);
|
|
||||||
|
|
||||||
if(m_queue.size() > 0)
|
|
||||||
{
|
|
||||||
T item = m_queue.front();
|
|
||||||
m_queue.pop();
|
|
||||||
pthread_mutex_unlock(qmut);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pthread_mutex_unlock(qmut);
|
|
||||||
throw(-1);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
~ccqueue()
|
|
||||||
{
|
|
||||||
delete qmut;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
std::queue<T> m_queue;
|
|
||||||
|
|
||||||
pthread_mutex_t *qmut;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pthread_item;
|
|
||||||
|
|
||||||
struct pthread_data {
|
|
||||||
std::queue<pthread_item> *idleth_queue;
|
|
||||||
std::queue<int> *conn_queue;
|
|
||||||
pthread_mutex_t * qlock;
|
|
||||||
|
|
||||||
pthread_cond_t * th_cond;
|
|
||||||
pthread_mutex_t * th_mut;
|
|
||||||
|
|
||||||
int *workitem; //id of the socket to work
|
|
||||||
|
|
||||||
//pthread_mutex_t * table_lock;
|
|
||||||
rwl *table_lock;
|
|
||||||
logtable *ltable;
|
|
||||||
bool *sys_alive;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pthread_item{
|
|
||||||
pthread_t * th_handle;
|
|
||||||
pthread_data *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct work_item
|
|
||||||
{
|
|
||||||
int sockd; //socket id
|
|
||||||
datatuple in_tuple; //request
|
|
||||||
datatuple out_tuple; //response
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void * thread_work_fn( void *);
|
|
||||||
|
|
||||||
class logserver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//server codes
|
|
||||||
static uint8_t OP_SUCCESS;
|
|
||||||
static uint8_t OP_FAIL;
|
|
||||||
static uint8_t OP_SENDING_TUPLE;
|
|
||||||
|
|
||||||
//client codes
|
|
||||||
static uint8_t OP_FIND;
|
|
||||||
static uint8_t OP_INSERT;
|
|
||||||
|
|
||||||
static uint8_t OP_INVALID;
|
|
||||||
|
|
||||||
public:
|
|
||||||
logserver(int nthreads, int server_port){
|
|
||||||
this->nthreads = nthreads;
|
|
||||||
this->server_port = server_port;
|
|
||||||
//lsmlock = new pthread_mutex_t;
|
|
||||||
//pthread_mutex_init(lsmlock,0);
|
|
||||||
|
|
||||||
lsmlock = initlock();
|
|
||||||
|
|
||||||
qlock = new pthread_mutex_t;
|
|
||||||
pthread_mutex_init(qlock,0);
|
|
||||||
|
|
||||||
ltable = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
~logserver()
|
|
||||||
{
|
|
||||||
//delete lsmlock;
|
|
||||||
deletelock(lsmlock);
|
|
||||||
delete qlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startserver(logtable *ltable);
|
|
||||||
|
|
||||||
void stopserver();
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
//main loop of server
|
|
||||||
//accept connections, assign jobs to threads
|
|
||||||
void dispatchLoop();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
int server_port;
|
|
||||||
|
|
||||||
int nthreads;
|
|
||||||
|
|
||||||
bool sys_alive;
|
|
||||||
|
|
||||||
int serversocket; //server socket file descriptor
|
|
||||||
|
|
||||||
//ccqueue<int> conn_queue; //list of active connections (socket list)
|
|
||||||
|
|
||||||
//ccqueue<pthread_item> idleth_queue; //list of idle threads
|
|
||||||
|
|
||||||
std::queue<int> conn_queue;
|
|
||||||
std::queue<pthread_item> idleth_queue;
|
|
||||||
pthread_mutex_t *qlock;
|
|
||||||
|
|
||||||
std::vector<pthread_item *> th_list; // list of threads
|
|
||||||
|
|
||||||
rwl *lsmlock; //lock for using lsm table
|
|
||||||
|
|
||||||
logtable *ltable;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in a new issue