acl/lib_acl_cpp/src/hsocket/hsclient.cpp

480 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "acl_stdafx.hpp"
#ifndef ACL_PREPARE_COMPILE
#include <stdarg.h>
#include "acl_cpp/stdlib/snprintf.hpp"
#include "acl_cpp/stdlib/log.hpp"
#include "acl_cpp/stdlib/string.hpp"
#include "acl_cpp/stdlib/escape.hpp"
#include "acl_cpp/hsocket/hsrow.hpp"
#include "acl_cpp/hsocket/hstable.hpp"
#include "acl_cpp/hsocket/hsproto.hpp"
#include "acl_cpp/hsocket/hserror.hpp"
#include "acl_cpp/hsocket/hsclient.hpp"
#endif
#ifndef ACL_CLIENT_ONLY
namespace acl
{
#define MAX_INT 2147483647
static const char* dummy_ok = "ok";
static const char* dummy_unknown = "uknown error";
hsclient::hsclient(const char* addr, bool cache_enable /* = true */,
bool retry_enable /* = true */)
: debugOn_(false)
, proto_(cache_enable)
, retry_enable_(retry_enable)
, id_max_(0)
, tbl_curr_(NULL)
, error_(HS_ERR_OK)
{
addr_ = acl_mystrdup(addr);
serror_ = dummy_ok;
}
hsclient::~hsclient(void)
{
acl_myfree(addr_);
clear_tables();
}
bool hsclient::open_tbl(const char* dbn, const char* tbl,
const char* idx, const char* flds, bool auto_open /* = true */)
{
string key(dbn);
key << '|' << tbl << '|' << idx << '|' << flds;
key.lower();
if (stream_.opened()) {
std::map<string, hstable*>::iterator it = tables_.find(key);
if (it != tables_.end()) {
tbl_curr_ = it->second;
return true;
}
}
if (!auto_open) {
error_ = HS_ERR_NOT_OPEN;
tbl_curr_ = NULL;
return false;
}
return open_tbl(dbn, tbl, idx, flds, key.c_str());
}
bool hsclient::open_tbl(const char* dbn, const char* tbl,
const char* idx, const char* flds, const char* key)
{
if (!stream_.opened()) {
clear_tables();
if (!stream_.open(addr_, 60, 60)) {
error_ = HS_ERR_CONN;
tbl_curr_ = NULL;
logger_error("open %s error(%s)",
addr_, acl_last_serror());
return false;
}
}
tbl_curr_ = NEW hstable(id_max_++, dbn, tbl, idx, flds);
cond_def_[0] = '=';
cond_def_[1] = 0;
buf_.clear();
buf_ << "P\t" << tbl_curr_->id_ << '\t' << dbn << '\t' << tbl
<< '\t' << idx << '\t' << flds << '\n';
if (!stream_.write(buf_)) {
error_ = HS_ERR_WRITE;
close_stream();
delete tbl_curr_;
tbl_curr_ = NULL;
logger_error("send(%s) to %s error", buf_.c_str(), addr_);
return false;
}
buf_.clear();
if (!stream_.gets(buf_)) {
error_ = HS_ERR_READ;
close_stream();
delete tbl_curr_;
tbl_curr_ = NULL;
logger_error("open error for read from %s", addr_);
return false;
}
bool ret = proto_.parse_respond(tbl_curr_->nfld_, buf_, error_, serror_);
if (ret) {
tables_[key] = tbl_curr_;
} else {
delete tbl_curr_;
tbl_curr_ = NULL;
}
return ret;
}
void hsclient::clear_tables(void)
{
std::map<string, hstable*>::iterator it = tables_.begin();
for (; it != tables_.end(); ++it) {
delete it->second;
}
tables_.clear();
}
void hsclient::close_stream(void)
{
// <20>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
stream_.close();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5>Ѿ<EFBFBD><D1BE>򿪵ı<F2BFAAB5><C4B1><EFBFBD><EFBFBD><EFBFBD>
clear_tables();
}
const std::vector<hsrow*>& hsclient::get(const char* values[], int num,
const char* cond /* = "=" */, int nlimit /* = 0 */,
int noffset /* = 0 */)
{
proto_.reset();
if (tbl_curr_ == NULL) {
error_ = HS_ERR_NOT_OPEN;
logger_error("tbl not opened yet!");
return proto_.get();
} else if (values == NULL || values[0] == NULL) {
error_ = HS_ERR_PARAMS;
logger_error("values null");
return proto_.get();
} else if (num <= 0 || num > tbl_curr_->nfld_) {
error_ = HS_ERR_PARAMS;
logger_error("num(%d) invalid, nfld(%d)",
num, tbl_curr_->nfld_);
return proto_.get();
} else if (cond == NULL || *cond == 0) {
error_ = HS_ERR_PARAMS;
logger_error("cond null");
return proto_.get();
}
if (nlimit <= 0) {
nlimit = MAX_INT;
}
if (noffset < 0) {
noffset = 0;
}
char buf[32], *limit_offset = NULL;
if (nlimit > 1) {
safe_snprintf(buf, sizeof(buf), "%d\t%d", nlimit, noffset);
limit_offset = buf;
}
(void) query(cond, values, num, limit_offset, (char) 0, 0, 0);
return proto_.get();
}
const std::vector<hsrow*>& hsclient::get(const char* first_value, ...)
{
if (tbl_curr_ == NULL) {
error_ = HS_ERR_NOT_OPEN;
logger_error("tbl not opened yet!");
proto_.reset();
return proto_.get();
}
va_list ap;
char *ptr;
va_start(ap, first_value);
tbl_curr_->values_[0] = (char*) first_value;
int i = 1;
while ((ptr = va_arg(ap, char*)) != NULL) {
if (i >= tbl_curr_->nfld_) {
break;
}
tbl_curr_->values_[i] = ptr;
i++;
}
va_end(ap);
return get((const char**) tbl_curr_->values_, i, cond_def_, 0, 0);
}
bool hsclient::mod(const char* values[], int num,
const char* to_values[], int to_num, const char* cond /* = "=" */,
int nlimit /* = 0 */, int noffset /* = 0 */)
{
if (tbl_curr_ == NULL) {
error_ = HS_ERR_NOT_OPEN;
logger_error("tbl not opened yet!");
return false;
} else if (values == NULL || values[0] == NULL) {
error_ = HS_ERR_PARAMS;
logger_error("values null");
return false;
} else if (num <= 0 || num > tbl_curr_->nfld_) {
error_ = HS_ERR_PARAMS;
logger_error("num(%d) invalid, nfld(%d)",
num, tbl_curr_->nfld_);
return false;
} else if (cond == NULL || *cond == 0) {
error_ = HS_ERR_PARAMS;
logger_error("cond null");
return false;
} else if (to_values == NULL || to_values[0] == NULL) {
error_ = HS_ERR_PARAMS;
logger_error("to_values null");
return false;
} else if (to_num <= 0 || to_num > tbl_curr_->nfld_) {
error_ = HS_ERR_PARAMS;
logger_error("to_num(%d) invalid, nfld(%d)",
to_num, tbl_curr_->nfld_);
return false;
}
if (nlimit <= 0) {
nlimit = MAX_INT;
}
if (noffset < 0) {
noffset = 0;
}
char buf[32];
safe_snprintf(buf, sizeof(buf), "%d\t%d", nlimit, noffset);
return query(cond, values, num, buf, 'U', to_values, to_num);
}
bool hsclient::del(const char* values[], int num,
const char* cond /* = "=" */, int nlimit /* = 1 */, int noffset /* = 0 */)
{
if (tbl_curr_ == NULL) {
error_ = HS_ERR_NOT_OPEN;
logger_error("tbl not opened yet!");
return false;
} else if (values == NULL || values[0] == NULL) {
error_ = HS_ERR_PARAMS;
logger_error("values null");
return false;
} else if (num <= 0 || num > tbl_curr_->nfld_) {
error_ = HS_ERR_PARAMS;
logger_error("num(%d) invalid, nfld(%d)",
num, tbl_curr_->nfld_);
return false;
} else if (cond == NULL || *cond == 0) {
error_ = HS_ERR_PARAMS;
logger_error("cond null");
return false;
}
if (nlimit <= 0) {
nlimit = 1;
}
if (noffset < 0) {
noffset = 0;
}
char buf[32], *limit_offset = NULL;
if (nlimit > 1) {
safe_snprintf(buf, sizeof(buf), "%d\t%d", nlimit, noffset);
limit_offset = buf;
}
return query(cond, values, num, limit_offset, 'D', 0, 0);
}
bool hsclient::fmt_del(const char* first_value, ...)
{
if (tbl_curr_ == NULL) {
error_ = HS_ERR_NOT_OPEN;
logger_error("tbl not opened yet!");
return false;
}
va_list ap;
char *ptr;
va_start(ap, first_value);
tbl_curr_->values_[0] = NULL;
int i = 0;
while ((ptr = va_arg(ap, char*)) != NULL) {
if (i >= tbl_curr_->nfld_) {
break;
}
tbl_curr_->values_[i] = ptr;
i++;
}
va_end(ap);
return del((const char**) tbl_curr_->values_, i, cond_def_, 0, 0);
}
bool hsclient::add(const char* values[], int num)
{
if (tbl_curr_ == NULL) {
error_ = HS_ERR_NOT_OPEN;
logger_error("tbl not opened yet!");
return false;
} else if (values == NULL || values[0] == NULL) {
error_ = HS_ERR_PARAMS;
logger_error("input invalid");
return false;
} else if (num <= 0 || num > tbl_curr_->nfld_) {
error_ = HS_ERR_PARAMS;
logger_error("num(%d) invalid, nfld(%d)",
num, tbl_curr_->nfld_);
return false;
}
return query("+", values, num, NULL, 0, NULL, 0);
}
bool hsclient::fmt_add(const char* first_value, ...)
{
if (tbl_curr_ == NULL) {
error_ = HS_ERR_NOT_OPEN;
logger_error("tbl not opened yet!");
return false;
}
va_list ap;
char *ptr;
va_start(ap, first_value);
tbl_curr_->values_[0] = NULL;
int i = 0;
while ((ptr = va_arg(ap, char*)) != NULL) {
if (i >= tbl_curr_->nfld_) {
break;
}
tbl_curr_->values_[i] = ptr;
i++;
}
va_end(ap);
return add((const char**) tbl_curr_->values_, i);
}
bool hsclient::query(const char* oper, const char* values[], int num,
const char* limit_offset, char mop,
const char* to_values[], int to_num)
{
acl_assert(tbl_curr_);
bool retried = false;
while (true) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
hsproto::build_request(buf_, tbl_curr_->id_, oper, values,
num, limit_offset, mop, to_values, to_num);
if (debugOn_) {
printf("%s(%d)>>>send: (%s)\n",
__FUNCTION__, __LINE__, buf_.c_str());
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD>ͨ<EFBFBD>Ų<EFBFBD><C5B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD>
if (chat()) {
break;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD>ͨ<EFBFBD><CDA8>ʧ<EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳʧ<D2B2><CAA7><EFBFBD>򷵻ش<F2B7B5BB><D8B4><EFBFBD>
if (retry_enable_ == false || retried) {
close_stream();
return false;
}
retried = true;
// <20>Ȼ<EFBFBD><C8BB>嵱ǰ<E5B5B1><C7B0><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>Ϣ
string dbn(tbl_curr_->dbn_), tbl(tbl_curr_->tbl_);
string idx(tbl_curr_->idx_), flds(tbl_curr_->flds_);
// <20>ȹرվɵ<D5BE><C9B5><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еı<D0B5><C4B1><EFBFBD><EFBFBD><EFBFBD>
close_stream();
// <20><><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6>󲢴򿪱<F3B2A2B4><F2BFAAB1><EFBFBD><EFBFBD><EFBFBD>
if (!open_tbl(dbn.c_str(), tbl.c_str(), idx.c_str(),
flds.c_str(), true)) {
logger_error("reopen error");
return (false);
}
}
if (debugOn_) {
printf("%s(%d): gets: (%s)\n",
__FUNCTION__, __LINE__, buf_.c_str());
}
return proto_.parse_respond(tbl_curr_->nfld_, buf_, error_, serror_);
}
bool hsclient::chat(void)
{
if (!stream_.write(buf_)) {
error_ = HS_ERR_WRITE;
logger_error("send(%s) error(%s)",
buf_.c_str(), acl_last_serror());
return false;
}
if (!stream_.gets(buf_)) {
error_ = HS_ERR_READ;
logger_error("gets error(%s)", acl_last_serror());
return false;
}
error_ = HS_ERR_OK;
return true;
}
int hsclient::get_error(void) const
{
return error_;
}
const char* hsclient::get_serror(int errnum) const
{
return hserror::get_serror(errnum);
}
const char* hsclient::get_last_serror(void) const
{
if (error_ == 0) {
return dummy_ok;
}
const char* ptr = hserror::get_serror(error_);
if (ptr != dummy_unknown) {
return ptr;
}
return serror_;
}
const char* hsclient::get_addr(void) const
{
return addr_;
}
int hsclient::get_id(void) const
{
if (tbl_curr_ == NULL) {
logger_warn("tbl not open!");
return -1;
}
return tbl_curr_->id_;
}
void hsclient::debug_enable(bool on)
{
debugOn_ = on;
}
} // namespace acl
#endif // ACL_CLIENT_ONLY