complete redis client command: list/transaction/connection/pubsub; add redis_pool/redis_manger samples

This commit is contained in:
ubuntu14 2015-01-18 08:03:30 -08:00
parent 5e81e4bd4d
commit b6bbade6e1
28 changed files with 2197 additions and 233 deletions

View File

@ -1,6 +1,10 @@
修改历史列表:
------------------------------------------------------------------------
273) 2015.1.17-1.18
273.1) feature: 实现了 list/pubsub/connection/transaction redist 客户端命令
273.2) feature: redis 客户端库中的 redis_key 类增加了 migrate/move 支持
272) 2015.1.16
272.1) feature: redis 客户端连接池及连接池集群测试通过

View File

@ -132,11 +132,13 @@
#include "acl_cpp/connpool/connect_manager.hpp"
#include "acl_cpp/connpool/connect_monitor.hpp"
#include "acl_cpp/redis/redis_client.hpp"
#include "acl_cpp/redis/redis_pool.hpp"
#include "acl_cpp/redis/redis_manager.hpp"
#include "acl_cpp/redis/redis_client.hpp"
#include "acl_cpp/redis/redis_result.hpp"
#include "acl_cpp/redis/redis_key.hpp"
#include "acl_cpp/redis/redis_hash.hpp"
#include "acl_cpp/redis/redis_string.hpp"
#include "acl_cpp/redis/redis_list.hpp"
#include "acl_cpp/redis/redis_pubsub.hpp"
#include "acl_cpp/redis/redis_transaction.hpp"

View File

@ -27,12 +27,16 @@ public:
void close();
const redis_result* run(const string& request);
const redis_result* run(const string& request, size_t nobjs = 1);
const string& build_request(size_t argc, const char* argv[],
size_t argv_lens[], string* buf = NULL);
/*******************************************************************/
const string& build_request(const std::vector<string>& args,
string* buf = NULL);
const string& build_request(const std::vector<const char*>& args,
const std::vector<size_t>& lens, string* buf = NULL);
/*******************************************************************/
const string& build(const char* cmd, const char* key,
@ -81,7 +85,6 @@ public:
size_t argc, string* buf = NULL);
/*******************************************************************/
/*******************************************************************/
const string& build(const char* cmd, const char* key,
const std::vector<string>& names, string* buf = NULL);
@ -101,7 +104,6 @@ public:
size_t argc, string* buf = NULL);
/*******************************************************************/
/*******************************************************************/
protected:
// »ùÀàÐ麯Êý
@ -125,6 +127,7 @@ private:
void argv_space(size_t n);
redis_result* get_objects(size_t nobjs);
redis_result* get_object();
redis_result* get_error();
redis_result* get_status();

View File

@ -0,0 +1,40 @@
#pragma once
#include "acl_cpp/acl_cpp_define.hpp"
namespace acl
{
class redis_client;
class redis_result;
class ACL_CPP_API redis_connection
{
public:
redis_connection(redis_client* conn = NULL);
~redis_connection();
const redis_result* get_result() const
{
return result_;
}
void set_client(redis_client* conn);
redis_client* get_client() const
{
return conn_;
}
/////////////////////////////////////////////////////////////////////
bool auth(const char* passwd);
bool select(int dbnum);
bool ping();
bool echo(const char* s);
bool quit();
private:
redis_client* conn_;
const redis_result* result_;
};
} // namespace acl

View File

@ -16,6 +16,8 @@ public:
redis_hash(redis_client* conn = NULL);
~redis_hash();
void reset();
const redis_result* get_result() const
{
return result_;
@ -42,7 +44,6 @@ public:
bool hmset(const char* key, const std::map<int, string>& attrs);
bool hmset(const char* key, const std::map<int, char*>& attrs);
bool hmset(const char* key, const std::map<int, const char*>& attrs);
bool hmset(const string& req);
/////////////////////////////////////////////////////////////////////
@ -67,7 +68,6 @@ public:
std::vector<string>* result = NULL);
bool hmget(const char* key, const char* names[], const size_t lens[],
size_t argc, std::vector<string>* result = NULL);
bool hmget(const string& req, std::vector<string>* result = NULL);
/**
* hmget true hmget
@ -90,14 +90,12 @@ public:
const char* value, size_t value_len);
int hset(const char* key, const char* name, size_t name_len,
const char* value, size_t value_len);
int hset(const string& req);
int hsetnx(const char* key, const char* name, const char* value);
int hsetnx(const char* key, const char* name,
const char* value, size_t value_len);
int hsetnx(const char* key, const char* name, size_t name_len,
const char* value, size_t value_len);
int hsetnx(const string& req);
bool hget(const char* key, const char* name, string& result);
bool hget(const char* key, const char* name,
@ -117,7 +115,6 @@ public:
int hdel(const char* key, const std::vector<string>& names);
int hdel(const char* key, const std::vector<char*>& names);
int hdel(const char* key, const std::vector<const char*>& names);
int hdel(const string& req);
bool hincrby(const char* key, const char* name,
long long int inc, long long int* result = NULL);
@ -136,6 +133,12 @@ public:
private:
redis_client* conn_;
const redis_result* result_;
bool hmset(const string& req);
bool hmget(const string& req, std::vector<string>* result = NULL);
int hset(const string& req);
int hsetnx(const string& req);
int hdel(const string& req);
};
} // namespace acl

View File

@ -25,6 +25,8 @@ public:
redis_key(redis_client* conn = NULL);
~redis_key();
void reset();
void set_client(redis_client* conn);
redis_client* get_client() const
@ -47,7 +49,6 @@ public:
int del(const char* keys[], size_t argc);
int del(const int keys[], size_t argc);
int del(const char* keys[], const size_t lens[], size_t argc);
int del(const string& req);
/**
* KEY
@ -84,9 +85,16 @@ public:
*/
redis_key_t type(const char* key);
bool migrate(const char* key, const char* addr, unsigned dest_db,
unsigned timeout, const char* option = NULL);
int move(const char* key, unsigned dest_db);
private:
redis_client* conn_;
const redis_result* result_;
int del(const string& req);
};
} // namespace acl

View File

@ -5,6 +5,7 @@ namespace acl
{
class redis_client;
class redis_result;
class ACL_CPP_API redis_list
{
@ -12,13 +13,107 @@ public:
redis_list(redis_client* conn = NULL);
~redis_list();
void reset();
const redis_result* get_result() const
{
return result_;
}
void set_client(redis_client* conn);
redis_client* get_client() const
{
return conn_;
}
/////////////////////////////////////////////////////////////////////
int llen(const char* key);
bool lindex(const char* key, size_t idx, string& buf,
bool* exist = NULL);
bool lset(const char* key, size_t idx, const char* value);
bool lset(const char* key, size_t idx, const char* value, size_t len);
int linsert_before(const char* key, const char* pivot,
const char* value);
int linsert_before(const char* key, const char* pivot,
size_t pivot_len, const char* value, size_t value_len);
int linsert_after(const char* key, const char* pivot,
const char* value);
int linsert_after(const char* key, const char* pivot,
size_t pivot_len, const char* value, size_t value_len);
int lpush(const char* key, const char* first_value, ...);
int lpush(const char* key, const char* values[], size_t argc);
int lpush(const char* key, const std::vector<string>& values);
int lpush(const char* key, const std::vector<char*>& values);
int lpush(const char* key, const std::vector<const char*>& values);
int lpush(const char* key, const char* values[], size_t lens[],
size_t argc);
int rpush(const char* key, const char* first_value, ...);
int rpush(const char* key, const char* values[], size_t argc);
int rpush(const char* key, const std::vector<string>& values);
int rpush(const char* key, const std::vector<char*>& values);
int rpush(const char* key, const std::vector<const char*>& values);
int rpush(const char* key, const char* values[], size_t lens[],
size_t argc);
int lpushx(const char* key, const char* value);
int lpushx(const char* key, const char* value, size_t len);
int rpushx(const char* key, const char* value);
int rpushx(const char* key, const char* value, size_t len);
int lpop(const char* key, string& buf);
int rpop(const char* key, string& buf);
bool blpop(std::pair<string, string>& result, size_t timeout,
const char* first_key, ...);
bool blpop(const std::vector<const char*>& keys, size_t timeout,
std::pair<string, string>& result);
bool blpop(const std::vector<char*>& keys, size_t timeout,
std::pair<string, string>& result);
bool blpop(const std::vector<string>& keys, size_t timeout,
std::pair<string, string>& result);
bool brpop(std::pair<string, string>& result, size_t timeout,
const char* first_key, ...);
bool brpop(const std::vector<const char*>& keys, size_t timeout,
std::pair<string, string>& result);
bool brpop(const std::vector<char*>& keys, size_t timeout,
std::pair<string, string>& result);
bool brpop(const std::vector<string>& keys, size_t timeout,
std::pair<string, string>& result);
bool rpoplpush(const char* src, const char* dst, string* buf = NULL);
bool brpoplpush(const char* src, const char* dst, size_t timeout,
string* buf = NULL);
bool lrange(const char* key, size_t start, size_t end,
std::vector<string>& result);
int lrem(const char* key, int count, const char* value);
int lrem(const char* key, int count, const char* value, size_t len);
bool ltrim(const char* key, size_t start, size_t end);
private:
redis_client* conn_;
const redis_result* result_;
int linsert(const char* key, const char* pos, const char* pivot,
size_t pivot_len, const char* value, size_t value_len);
int push(const string& req);
int pushx(const char* cmd, const char* key,
const char* value, size_t len);
int pop(const char* cmd, const char* key, string& buf);
bool bpop(const char* cmd, const std::vector<const char*>& keys,
size_t timeout, std::pair<string, string>& result);
bool bpop(const char* cmd, const std::vector<string>& keys,
size_t timeout, std::pair<string, string>& result);
bool bpop(const string& req, std::pair<string, string>& result);
};
} // namespace acl

View File

@ -0,0 +1,55 @@
#pragma once
#include "acl_cpp/acl_cpp_define.hpp"
namespace acl
{
class redis_client;
class redis_result;
class string;
class ACL_CPP_API redis_pubsub
{
public:
redis_pubsub(redis_client* conn = NULL);
~redis_pubsub();
void reset();
void set_client(redis_client* conn);
redis_client* get_client() const
{
return conn_;
}
const redis_result* get_result() const
{
return result_;
}
/////////////////////////////////////////////////////////////////////
/**
*
* @return {int}
* -1
* 0
* > 0
*/
int publish(const char* channel, const char* msg, size_t len);
int subscribe(const char* first_channel, ...);
int subscribe(const std::vector<string>& channels);
int unsubscribe(const char* first_channel, ...);
int unsubscribe(const std::vector<string>& channels);
bool get_message(string& channel, string& msg);
private:
redis_client* conn_;
const redis_result* result_;
int subscribe(const char* cmd, const std::vector<string>& channels);
int check_channel(const redis_result* obj, const char* cmd,
const string& channel);
};
} // namespace acl

View File

@ -112,10 +112,10 @@ public:
/**
* REDIS_RESULT_ARRAY
* @param idx {size_t*}
* @param size {size_t*}
* @return {const const redis_result*}
*/
const redis_result** get_children(size_t* idx) const;
const redis_result** get_children(size_t* size) const;
/**
* REDIS_RESULT_ARRAY
@ -133,12 +133,12 @@ public:
return pool_;
}
void reset();
private:
~redis_result();
friend class redis_client;
void reset();
redis_result& set_type(redis_result_t type);
redis_result& set_size(size_t size);
redis_result& put(const char* buf, size_t len);

View File

@ -16,6 +16,8 @@ public:
redis_string(redis_client* conn = NULL);
~redis_string();
void reset();
const redis_result* get_result() const
{
return result_;
@ -46,7 +48,9 @@ public:
int append(const char* key, const char* value, size_t size);
bool get(const char* key, string& buf);
bool get(const char* key, size_t len, string& buf);
const redis_result* get(const char* key);
const redis_result* get(const char* key, size_t len);
bool getset(const char* key, const char* value, string& buf);
bool getset(const char* key, size_t key_len,
@ -94,14 +98,6 @@ public:
int bitop_or(const char* destkey, const char* keys[], size_t size);
int bitop_xor(const char* destkey, const char* keys[], size_t size);
int bitop(const char* op, const char* destkey,
const std::vector<string>& keys);
int bitop(const char* op, const char* destkey,
const std::vector<const char*>& keys);
int bitop(const char* op, const char* destkey,
const char* keys[], size_t size);
int bitop(const string& req);
/////////////////////////////////////////////////////////////////////
bool mset(const std::map<string, string>& objs);
@ -115,7 +111,6 @@ public:
bool mset(const char* keys[], const char* values[], size_t argc);
bool mset(const char* keys[], const size_t keys_len[],
const char* values[], const size_t values_len[], size_t argc);
bool mset(const string& req);
/////////////////////////////////////////////////////////////////////
@ -130,7 +125,6 @@ public:
int msetnx(const char* keys[], const char* values[], size_t argc);
int msetnx(const char* keys[], const size_t keys_len[],
const char* values[], const size_t values_len[], size_t argc);
int msetnx(const string& req);
/////////////////////////////////////////////////////////////////////
@ -152,7 +146,6 @@ public:
bool mget(const char* keys[], const size_t keys_len[], size_t argc,
std::vector<string>* result = NULL);
bool mget(const string& req, std::vector<string>* result = NULL);
size_t mget_size() const;
const char* mget_value(size_t i, size_t* len = NULL) const;
const redis_result* mget_result(size_t i) const;
@ -176,6 +169,17 @@ public:
private:
redis_client* conn_;
const redis_result* result_;
int bitop(const char* op, const char* destkey,
const std::vector<string>& keys);
int bitop(const char* op, const char* destkey,
const std::vector<const char*>& keys);
int bitop(const char* op, const char* destkey,
const char* keys[], size_t size);
int bitop(const string& req);
bool mset(const string& req);
int msetnx(const string& req);
bool mget(const string& req, std::vector<string>* result = NULL);
};
} // namespace acl

View File

@ -0,0 +1,50 @@
#pragma once
#include "acl_cpp/acl_cpp_define.hpp"
#include <vector>
#include "acl_cpp/stdlib/string.hpp"
namespace acl
{
class redis_client;
class redis_result;
class ACL_CPP_API redis_transaction
{
public:
redis_transaction(redis_client* conn = NULL);
~redis_transaction();
void reset();
void set_client(redis_client* conn);
redis_client* get_client() const
{
return conn_;
}
const redis_result* get_result() const
{
return result_;
}
/////////////////////////////////////////////////////////////////////
bool watch(const std::vector<string>& keys);
bool unwatch(const std::vector<string>& keys);
bool multi();
bool exec();
bool discard();
bool queue_cmd(const char* cmd, const char* argv[],
const size_t lens[], size_t argc);
size_t get_size();
const redis_result* get_child(size_t i, string* cmd);
private:
redis_client* conn_;
const redis_result* result_;
std::vector<string> cmds_;
};
} // namespace acl

View File

@ -299,14 +299,17 @@ copy $(TargetName).pdb ..\dist\lib\win32\$(TargetName).pdb /Y
<ClCompile Include="src\mime\rfc822.cpp" />
<ClCompile Include="src\queue\queue_file.cpp" />
<ClCompile Include="src\queue\queue_manager.cpp" />
<ClCompile Include="src\redis\redic_connection.cpp" />
<ClCompile Include="src\redis\redis_client.cpp" />
<ClCompile Include="src\redis\redis_hash.cpp" />
<ClCompile Include="src\redis\redis_key.cpp" />
<ClCompile Include="src\redis\redis_list.cpp" />
<ClCompile Include="src\redis\redis_manager.cpp" />
<ClCompile Include="src\redis\redis_pool.cpp" />
<ClCompile Include="src\redis\redis_pubsub.cpp" />
<ClCompile Include="src\redis\redis_result.cpp" />
<ClCompile Include="src\redis\redis_string.cpp" />
<ClCompile Include="src\redis\redis_transaction.cpp" />
<ClCompile Include="src\session\memcache_session.cpp" />
<ClCompile Include="src\session\session.cpp" />
<ClCompile Include="src\stdlib\charset_conv.cpp" />
@ -455,13 +458,16 @@ copy $(TargetName).pdb ..\dist\lib\win32\$(TargetName).pdb /Y
<ClInclude Include="include\acl_cpp\queue\queue_file.hpp" />
<ClInclude Include="include\acl_cpp\queue\queue_manager.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_client.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_connection.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_hash.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_key.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_list.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_manager.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_pool.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_pubsub.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_result.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_string.hpp" />
<ClInclude Include="include\acl_cpp\redis\redis_transaction.hpp" />
<ClInclude Include="include\acl_cpp\session\memcache_session.hpp" />
<ClInclude Include="include\acl_cpp\session\session.hpp" />
<ClInclude Include="include\acl_cpp\stdlib\charset_conv.hpp" />

View File

@ -439,6 +439,15 @@
<ClCompile Include="src\redis\redis_manager.cpp">
<Filter>src\redis</Filter>
</ClCompile>
<ClCompile Include="src\redis\redic_connection.cpp">
<Filter>src\redis</Filter>
</ClCompile>
<ClCompile Include="src\redis\redis_pubsub.cpp">
<Filter>src\redis</Filter>
</ClCompile>
<ClCompile Include="src\redis\redis_transaction.cpp">
<Filter>src\redis</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\acl_stdafx.hpp">
@ -972,6 +981,15 @@
<ClInclude Include="include\acl_cpp\redis\redis_manager.hpp">
<Filter>include\redis</Filter>
</ClInclude>
<ClInclude Include="include\acl_cpp\redis\redis_connection.hpp">
<Filter>include\redis</Filter>
</ClInclude>
<ClInclude Include="include\acl_cpp\redis\redis_pubsub.hpp">
<Filter>include\redis</Filter>
</ClInclude>
<ClInclude Include="include\acl_cpp\redis\redis_transaction.hpp">
<Filter>include\redis</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="changes.txt" />

View File

@ -23,6 +23,7 @@ static void test_hmset(acl::redis_hash& option, int n)
attrs[attr2] = val2;
attrs[attr3] = val3;
option.reset();
if (option.hmset(key.c_str(), attrs) == false)
{
printf("hmset error, key: %s\r\n", key.c_str());
@ -56,7 +57,7 @@ static void test_hmget(acl::redis_hash& option, int n)
attrs[2] = attr3.c_str();
result.clear();
option.reset();
if (option.hmget(key, attrs, 3, &result) == false)
{
printf("hmget error\r\n");
@ -94,6 +95,7 @@ static void test_hset(acl::redis_hash& option, int n)
attr.format("attr1");
value.format("value_%s", key.c_str());
option.reset();
if (option.hset(key.c_str(), attr.c_str(),
value.c_str()) < 0)
{
@ -117,6 +119,7 @@ static void test_hsetnx(acl::redis_hash& option, int n)
attr.format("attr4");
value.format("value_%s", key.c_str());
option.reset();
if ((ret = option.hsetnx(key.c_str(), attr.c_str(),
value.c_str())) <0)
{
@ -140,6 +143,7 @@ static void test_hget(acl::redis_hash& option, int n)
attr.format("attr1");
value.clear();
option.reset();
if (option.hget(key.c_str(), attr.c_str(), value) == false)
{
printf("hget key: %s, attr: %s\r\n", key.c_str(),
@ -165,6 +169,7 @@ static void test_hgetall(acl::redis_hash& option, int n)
key.format("%s_%d", __keypre.c_str(), i);
result.clear();
option.reset();
if (option.hgetall(key.c_str(), result) == false)
{
printf("hgetall key: %s\r\n", key.c_str());
@ -191,6 +196,8 @@ static void test_hdel(acl::redis_hash& option, int n)
{
key.format("%s_%d", __keypre.c_str(), i);
attr.format("attr1");
option.reset();
int ret = option.hdel(key.c_str(), attr.c_str(), NULL);
if (ret < 0)
{
@ -211,6 +218,8 @@ static void test_hincrby(acl::redis_hash& option, int n)
{
key.format("hincr_%s_%d", __keypre.c_str(), i);
attr.format("attr1");
option.reset();
if (option.hincrby(key.c_str(), attr.c_str(), 10,
&result) == false)
{
@ -233,6 +242,8 @@ static void test_hincrbyfloat(acl::redis_hash& option, int n)
{
key.format("hincrbyfloat_%s_%d", __keypre.c_str(), i);
attr.format("attr1");
option.reset();
if (option.hincrbyfloat(key.c_str(), attr.c_str(),
8.8, &result) == false)
{
@ -256,6 +267,8 @@ static void test_hkeys(acl::redis_hash& option, int n)
{
key.format("%s_%d", __keypre.c_str(), i);
attrs.clear();
option.reset();
if (option.hkeys(key.c_str(), attrs) == false)
{
printf("hkeys error, key: %s\r\n", key.c_str());
@ -284,6 +297,8 @@ static void test_hexists(acl::redis_hash& option, int n)
{
key.format("%s_%d", __keypre.c_str(), i);
attr.format("attr1");
option.reset();
if (option.hexists(key.c_str(), attr.c_str()) == false)
printf("no hexists key: %s\r\n", key.c_str());
else
@ -299,6 +314,8 @@ static void test_hlen(acl::redis_hash& option, int n)
for (int i = 0; i < n; i++)
{
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
int ret = option.hlen(key.c_str());
if (ret < 0)
{

View File

@ -9,6 +9,7 @@ static void test_del(acl::redis_key& option, int n)
for (int i = 0; i < n; i++)
{
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
int ret = option.del(key.c_str(), NULL);
if (ret < 0)
{
@ -27,6 +28,7 @@ static void test_expire(acl::redis_key& option, int n)
for (int i = 0; i < n; i++)
{
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
if (option.expire(key.c_str(), 100) < 0)
{
printf("expire key: %s error\r\n", key.c_str());
@ -45,6 +47,7 @@ static void test_ttl(acl::redis_key& option, int n)
for (int i = 0; i < n; i++)
{
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
if ((ttl = option.ttl(key.c_str())) < 0)
{
printf("get ttl key: %s error\r\n", key.c_str());
@ -63,6 +66,7 @@ static void test_exists(acl::redis_key& option, int n)
for (int i = 0; i < n; i++)
{
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
if (option.exists(key.c_str()) == false)
printf("no exists key: %s\r\n", key.c_str());
else
@ -77,6 +81,7 @@ static void test_type(acl::redis_key& option, int n)
for (int i = 0; i < n; i++)
{
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
acl::redis_key_t ret = option.type(key.c_str());
if (ret == acl::REDIS_KEY_UNKNOWN)
{
@ -92,7 +97,7 @@ static void test_type(acl::redis_key& option, int n)
static void usage(const char* procname)
{
printf("usage: %s -h[help]\r\n"
"-s redis_addr[127.0.0.1:6380]\r\n"
"-s redis_addr[127.0.0.1:6379]\r\n"
"-n count\r\n"
"-C connect_timeout[default: 10]\r\n"
"-T rw_timeout[default: 10]\r\n"
@ -103,7 +108,7 @@ static void usage(const char* procname)
int main(int argc, char* argv[])
{
int ch, n = 1, conn_timeout = 10, rw_timeout = 10;
acl::string addr("127.0.0.1:6380"), cmd;
acl::string addr("127.0.0.1:6379"), cmd;
while ((ch = getopt(argc, argv, "hs:n:C:T:a:")) > 0)
{

View File

@ -7,6 +7,7 @@ static bool test_del(acl::redis_key& option, int i)
acl::string key;
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
int ret = option.del(key.c_str(), NULL);
if (ret < 0)
{
@ -23,6 +24,7 @@ static bool test_expire(acl::redis_key& option, int i)
acl::string key;
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
if (option.expire(key.c_str(), 100) < 0)
{
printf("expire key: %s error\r\n", key.c_str());
@ -39,6 +41,7 @@ static bool test_ttl(acl::redis_key& option, int i)
int ttl;
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
if ((ttl = option.ttl(key.c_str())) < 0)
{
printf("get ttl key: %s error\r\n", key.c_str());
@ -54,6 +57,7 @@ static bool test_exists(acl::redis_key& option, int i)
acl::string key;
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
if (option.exists(key.c_str()) == false)
{
if (i < 10)
@ -72,6 +76,7 @@ static bool test_type(acl::redis_key& option, int i)
acl::string key;
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
acl::redis_key_t ret = option.type(key.c_str());
if (ret == acl::REDIS_KEY_UNKNOWN)
{

View File

@ -7,6 +7,7 @@ static bool test_del(acl::redis_key& option, int i)
acl::string key;
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
int ret = option.del(key.c_str(), NULL);
if (ret < 0)
{
@ -23,6 +24,7 @@ static bool test_expire(acl::redis_key& option, int i)
acl::string key;
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
if (option.expire(key.c_str(), 100) < 0)
{
printf("expire key: %s error\r\n", key.c_str());
@ -39,6 +41,7 @@ static bool test_ttl(acl::redis_key& option, int i)
int ttl;
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
if ((ttl = option.ttl(key.c_str())) < 0)
{
printf("get ttl key: %s error\r\n", key.c_str());
@ -54,6 +57,7 @@ static bool test_exists(acl::redis_key& option, int i)
acl::string key;
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
if (option.exists(key.c_str()) == false)
{
if (i < 10)
@ -72,6 +76,7 @@ static bool test_type(acl::redis_key& option, int i)
acl::string key;
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
acl::redis_key_t ret = option.type(key.c_str());
if (ret == acl::REDIS_KEY_UNKNOWN)
{

View File

@ -12,6 +12,7 @@ static void test_set(acl::redis_string& option, int n)
key.format("%s_%d", __keypre.c_str(), i);
value.format("value_%s", key.c_str());
option.reset();
if (option.set(key.c_str(), value.c_str()) == false)
{
printf("set key: %s error\r\n", key.c_str());
@ -30,6 +31,8 @@ static void test_setex(acl::redis_string& option, int n, int ttl)
{
key.format("%s_%d", __keypre.c_str(), i);
value.format("value_%s", key.c_str());
option.reset();
if (option.setex(key.c_str(), value.c_str(), ttl) == false)
{
printf("setex key: %s error\r\n", key.c_str());
@ -50,6 +53,7 @@ static void test_setnx(acl::redis_string& option, int n)
key.format("%s_%d", __keypre.c_str(), i);
value.format("_setnx_%s", key.c_str());
option.reset();
int ret = option.setnx(key.c_str(), value.c_str());
if (ret < 0)
{
@ -71,6 +75,7 @@ static void test_append(acl::redis_string& option, int n)
key.format("%s_%d", __keypre.c_str(), i);
value.format("_append_%d", i);
option.reset();
if (option.append(key.c_str(), value.c_str()) < 0)
{
printf("append key: %s\r\n", key.c_str());
@ -90,6 +95,7 @@ static void test_get(acl::redis_string& option, int n)
//key.format("key1_%s_%d", __keypre.c_str(), i);
value.clear();
option.reset();
if (option.get(key.c_str(), value) == false)
{
printf("get key: %s\r\n", key.c_str());
@ -113,6 +119,8 @@ static void test_getset(acl::redis_string& option, int n)
key.format("%s_%d", __keypre.c_str(), i);
value.format("getset_%s", key.c_str());
result.clear();
option.reset();
if (option.getset(key.c_str(), value.c_str(), result) == false)
{
printf("getset error, key: %s\r\n", key.c_str());
@ -131,6 +139,8 @@ static void test_strlen(acl::redis_string& option, int n)
for (int i = 0; i < n; i++)
{
key.format("%s_%d", __keypre.c_str(), i);
option.reset();
int ret = option.str_len(key.c_str());
if (ret < 0)
{
@ -163,6 +173,7 @@ static void test_mset(acl::redis_string& option, int n)
objs[key2] = val2;
objs[key3] = val3;
option.reset();
if (option.mset(objs) == false)
{
printf("mset error\r\n");
@ -195,6 +206,7 @@ static void test_mget(acl::redis_string& option, int n)
keys[2] = key3.c_str();
result.clear();
option.reset();
if (option.mget(keys, 3, &result) == false)
{
printf("mset error\r\n");
@ -241,6 +253,7 @@ static void test_msetnx(acl::redis_string& option, int n)
objs[key2] = val2;
objs[key3] = val3;
option.reset();
ret = option.msetnx(objs);
if (ret < 0)
{
@ -268,6 +281,8 @@ static void test_setrange(acl::redis_string& option, int n)
{
key.format("%s_%d", __keypre.c_str(), i);
value.format("range_value_%s", key.c_str());
option.reset();
ret = option.setrange(key.c_str(), off, value.c_str());
if (ret < 0)
{
@ -290,6 +305,8 @@ static void test_getrange(acl::redis_string& option, int n)
{
key.format("%s_%d", __keypre.c_str(), i);
value.clear();
option.reset();
if (option.getrange(key, start, end, value) == false)
{
printf("getrange error, key: %s, start: %d, end: %d\r\n",
@ -312,6 +329,8 @@ static void test_setbit(acl::redis_string& option, int n)
for (int i = 0; i < n; i++)
{
key.format("bit_%s_%d", __keypre.c_str(), i);
option.reset();
if (option.setbit(key.c_str(), off, 1) == false)
{
printf("setbit error, key: %s, off: %u\r\n",
@ -334,6 +353,8 @@ static void test_getbit(acl::redis_string& option, int n)
for (int i = 0; i < n; i++)
{
key.format("bit_%s_%d", __keypre.c_str(), i);
option.reset();
if (option.getbit(key.c_str(), off, bit) == false)
{
printf("getbit error, key: %s, off: %u\r\n",
@ -356,6 +377,8 @@ static void test_bitcount(acl::redis_string& option, int n)
for (int i = 0; i < n; i++)
{
key.format("bit_%s_%d", __keypre.c_str(), i);
option.reset();
ret = option.bitcount(key.c_str());
if (ret < 0)
{
@ -384,6 +407,7 @@ static void test_bitop_and(acl::redis_string& option, int n)
keys[1] = key2.c_str();
keys[2] = key3.c_str();
option.reset();
ret = option.bitop_and(key.c_str(), keys, 3);
if (ret < 0)
{
@ -412,6 +436,7 @@ static void test_bitop_or(acl::redis_string& option, int n)
keys[1] = key2.c_str();
keys[2] = key3.c_str();
option.reset();
ret = option.bitop_or(key.c_str(), keys, 3);
if (ret < 0)
{
@ -440,6 +465,7 @@ static void test_bitop_xor(acl::redis_string& option, int n)
keys[1] = key2.c_str();
keys[2] = key3.c_str();
option.reset();
ret = option.bitop_xor(key.c_str(), keys, 3);
if (ret < 0)
{
@ -460,6 +486,8 @@ static void test_incr(acl::redis_string& option, int n)
for (int i = 0; i < n; i++)
{
key.format("incr_%s_%d", __keypre.c_str(), i);
option.reset();
if (option.incr(key.c_str(), &result) == false)
{
printf("incr error, key: %s\r\n", key.c_str());
@ -479,6 +507,8 @@ static void test_incrby(acl::redis_string& option, int n)
for (int i = 0; i < n; i++)
{
key.format("incr_%s_%d", __keypre.c_str(), i);
option.reset();
if (option.incrby(key.c_str(), 10, &result) == false)
{
printf("incrby error, key: %s\r\n", key.c_str());
@ -498,6 +528,8 @@ static void test_incrbyfloat(acl::redis_string& option, int n)
for (int i = 0; i < n; i++)
{
key.format("incrbyfloat_%s_%d", __keypre.c_str(), i);
option.reset();
if (option.incrbyfloat(key.c_str(), 8.8, &result) == false)
{
printf("incrbyfloat error, key: %s\r\n", key.c_str());
@ -517,6 +549,8 @@ static void test_decr(acl::redis_string& option, int n)
for (int i = 0; i < n; i++)
{
key.format("incr_%s_%d", __keypre.c_str(), i);
option.reset();
if (option.decr(key.c_str(), &result) == false)
{
printf("decr error, key: %s\r\n", key.c_str());
@ -536,6 +570,8 @@ static void test_decrby(acl::redis_string& option, int n)
for (int i = 0; i < n; i++)
{
key.format("incr_%s_%d", __keypre.c_str(), i);
option.reset();
if (option.decrby(key.c_str(), 10, &result) == false)
{
printf("decrby error, key: %s\r\n", key.c_str());

View File

@ -0,0 +1,273 @@
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="redis_string"
ProjectGUID="{2DABFAD1-114B-4F96-9185-DC0C56A3662D}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\lib_acl\include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;VC2003"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="lib_acl_vc2003d.lib ws2_32.lib"
OutputFile="$(OutDir)/redis_string.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\..\lib\win32;..\..\..\..\dist\lib\win32"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/redis_string.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\lib_acl\include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;VC2003"
RuntimeLibrary="0"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib wsock32.lib lib_acl_vc2003.lib"
OutputFile="$(OutDir)/redis_string.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\..\lib\win32;..\..\..\..\dist\lib\win32"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="DebugDll|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\lib_acl\include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;VC2003;ACL_CPP_DLL;ACL_DLL"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
OutputFile="$(OutDir)/redis_string.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\..\lib\win32"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/redis_string.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Releasedll|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\lib_acl\include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;VC2003;ACL_CPP_DLL;ACL_DLL"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="2"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
OutputFile="$(OutDir)/redis_string.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\..\lib\win32"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/redis_string.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Ô´Îļþ"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\stdafx.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
<FileConfiguration
Name="DebugDll|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
<FileConfiguration
Name="Releasedll|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
</File>
<File
RelativePath=".\redis_string.cpp">
</File>
</Filter>
<Filter
Name="Í·Îļþ"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\stdafx.h">
</File>
</Filter>
<Filter
Name="×ÊÔ´Îļþ"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
<File
RelativePath=".\ReadMe.txt">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,143 @@
#include "acl_stdafx.hpp"
#include "acl_cpp/stdlib/string.hpp"
#include "acl_cpp/stdlib/snprintf.hpp"
#include "acl_cpp/redis/redis_client.hpp"
#include "acl_cpp/redis/redis_result.hpp"
#include "acl_cpp/redis/redis_connection.hpp"
namespace acl
{
redis_connection::redis_connection(redis_client* conn /* = NULL */)
: conn_(conn)
{
}
redis_connection::~redis_connection()
{
}
void redis_connection::set_client(redis_client* conn)
{
conn_ = conn;
}
bool redis_connection::auth(const char* passwd)
{
const char* argv[2];
size_t lens[2];
argv[0] = "AUTH";
lens[0] = strlen(argv[0]);
argv[1] = passwd;
lens[1] = strlen(argv[1]);
const string& req = conn_->build_request(2, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
if (result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* res = result_->get(0);
if (res == NULL || strcasecmp(res, "OK") != 0)
return false;
else
return true;
}
bool redis_connection::select(int dbnum)
{
const char* argv[2];
size_t lens[2];
argv[0] = "SELECT";
lens[0] = strlen(argv[0]);
char buf[21];
(void) safe_snprintf(buf, sizeof(buf), "%d", dbnum);
argv[1] = buf;
lens[1] = strlen(argv[1]);
const string& req = conn_->build_request(2, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
if (result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* res = result_->get(0);
if (res == NULL || strcasecmp(res, "ok") != 0)
return false;
return true;
}
bool redis_connection::ping()
{
const char* argv[1];
size_t lens[1];
argv[0] = "PING";
lens[0] = strlen(argv[0]);
const string& req = conn_->build_request(1, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
if (result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* res = result_->get(0);
if (res == NULL || strcasecmp(res, "PONG") != 0)
return false;
return true;
}
bool redis_connection::echo(const char* s)
{
const char* argv[2];
size_t lens[2];
argv[0] = "ECHO";
lens[0] = strlen(argv[0]);
argv[1] = s;
lens[1] = strlen(argv[1]);
const string& req = conn_->build_request(2, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
if (result_->get_type() != REDIS_RESULT_STRING)
return false;
string buf;
result_->argv_to_string(buf);
if (buf != s)
return false;
else
return true;
}
bool redis_connection::quit()
{
const char* argv[1];
size_t lens[1];
argv[0] = "QUIT";
lens[0] = strlen(argv[0]);
const string& req = conn_->build_request(1, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
if (result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* res = result_->get(0);
if (res == NULL || strcasecmp(res, "OK") != 0)
return false;
conn_->close();
return true;
}
} // namespace acl

View File

@ -220,7 +220,26 @@ redis_result* redis_client::get_object()
}
}
const redis_result* redis_client::run(const string& request)
redis_result* redis_client::get_objects(size_t nobjs)
{
acl_assert(nobjs > 1);
redis_result* objs = new(pool_) redis_result(pool_);
objs->set_type(REDIS_RESULT_ARRAY);
objs->set_size(nobjs);
for (size_t i = 0; i < nobjs; i++)
{
redis_result* obj = get_object();
if (obj == NULL)
return NULL;
objs->put(obj, i);
}
return objs;
}
const redis_result* redis_client::run(const string& request,
size_t nobjs /* = 1 */)
{
// ±¾Á¬½ÓʹÓôÎÊýµÝÔö
used_++;
@ -238,7 +257,7 @@ const redis_result* redis_client::run(const string& request)
return NULL;
}
if (conn_.write(request) == -1)
if (!request.empty() && conn_.write(request) == -1)
{
conn_.close();
if (retry_ && !retried)
@ -251,7 +270,11 @@ const redis_result* redis_client::run(const string& request)
return NULL;
}
result_ = get_object();
if (nobjs > 1)
result_ = get_objects(nobjs);
else
result_ = get_object();
if (result_ != NULL)
return result_;
conn_.close();
@ -282,6 +305,49 @@ const string& redis_client::build_request(size_t argc, const char* argv[],
return *buf;
}
const string& redis_client::build_request(const std::vector<string>& args,
string* buf /* = NULL */)
{
if (buf == NULL)
{
buf = &request_;
buf->clear();
}
buf->format("*%lu\r\n", (unsigned long) args.size());
std::vector<string>::const_iterator cit = args.begin();
for (; cit != args.end(); ++cit)
{
buf->format_append("$%lu\r\n", (unsigned long) (*cit).size());
buf->append(*cit);
buf->append("\r\n");
}
return *buf;
}
const string& redis_client::build_request(const std::vector<const char*>& args,
const std::vector<size_t>& lens, string* buf /* = NULL */)
{
acl_assert(args.size() == lens.size());
if (buf == NULL)
{
buf = &request_;
buf->clear();
}
buf->format("*%lu\r\n", (unsigned long) args.size());
std::vector<const char*>::const_iterator args_cit = args.begin();
std::vector<size_t>::const_iterator lens_cit = lens.begin();
for (; args_cit != args.end(); ++args_cit, ++lens_cit)
{
buf->format_append("$%lu\r\n", (unsigned long) *lens_cit);
buf->append(*args_cit, *lens_cit);
buf->append("\r\n");
}
return *buf;
}
/////////////////////////////////////////////////////////////////////////////
/***************************************************************************/
@ -290,8 +356,6 @@ const string& redis_client::build_request(size_t argc, const char* argv[],
const string& redis_client::build(const char* cmd, const char* key,
const std::map<string, string>& attrs, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + attrs.size() * 2;
if (key != NULL)
argc_++;
@ -327,8 +391,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const std::map<string, char*>& attrs, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + attrs.size() * 2;
if (key != NULL)
argc_++;
@ -364,8 +426,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const std::map<string, const char*>& attrs, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + attrs.size() * 2;
if (key != NULL)
argc_++;
@ -403,8 +463,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const std::map<int, string>& attrs, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + attrs.size() * 2;
if (key != NULL)
argc_++;
@ -442,8 +500,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const std::map<int, char*>& attrs, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + attrs.size() * 2;
if (key != NULL)
argc_++;
@ -481,8 +537,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const std::map<int, const char*>& attrs, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + attrs.size() * 2;
if (key != NULL)
argc_++;
@ -530,8 +584,6 @@ const string& redis_client::build(const char* cmd, const char* key,
(unsigned long) values.size());
}
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + names.size() * 2;
if (key != NULL)
argc_++;
@ -575,8 +627,6 @@ const string& redis_client::build(const char* cmd, const char* key,
(unsigned long) values.size());
}
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + names.size() * 2;
if (key != NULL)
argc_++;
@ -620,8 +670,6 @@ const string& redis_client::build(const char* cmd, const char* key,
(unsigned long) values.size());
}
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + names.size() * 2;
if (key != NULL)
argc_++;
@ -667,8 +715,6 @@ const string& redis_client::build(const char* cmd, const char* key,
(unsigned long) values.size());
}
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + names.size() * 2;
if (key != NULL)
argc_++;
@ -715,8 +761,6 @@ const string& redis_client::build(const char* cmd, const char* key,
(unsigned long) values.size());
}
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + names.size() * 2;
if (key != NULL)
argc_++;
@ -763,8 +807,6 @@ const string& redis_client::build(const char* cmd, const char* key,
(unsigned long) values.size());
}
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + names.size() * 2;
if (key != NULL)
argc_++;
@ -806,8 +848,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const char* names[], const char* values[], size_t argc,
string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + argc * 2;
if (key != NULL)
argc_++;
@ -843,8 +883,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const int names[], const char* values[], size_t argc,
string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + argc * 2;
if (key != NULL)
argc_++;
@ -884,8 +922,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const char* values[], const size_t values_len[],
size_t argc, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + argc * 2;
if (key != NULL)
argc_++;
@ -926,8 +962,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const std::vector<string>& names, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
size_t argc = names.size();
argc_ = 1 + argc;
if (key != NULL)
@ -959,8 +993,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const std::vector<char*>& names, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
size_t argc = names.size();
argc_ = 1 + argc;
if (key != NULL)
@ -992,8 +1024,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const std::vector<const char*>& names, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
size_t argc = names.size();
argc_ = 1 + argc;
if (key != NULL)
@ -1025,8 +1055,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const std::vector<int>& names, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
size_t argc = names.size();
argc_ = 1 + argc;
if (key != NULL)
@ -1061,8 +1089,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const char* names[], size_t argc, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + argc;
if (key != NULL)
argc_++;
@ -1093,8 +1119,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const string& redis_client::build(const char* cmd, const char* key,
const int names[], size_t argc, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + argc;
if (key != NULL)
argc_++;
@ -1129,8 +1153,6 @@ const string& redis_client::build(const char* cmd, const char* key,
const char* names[], const size_t lens[],
size_t argc, string* buf /* = NULL */)
{
reset(); // 重置内存状态,这样可以防止内存膨胀
argc_ = 1 + argc;
if (key != NULL)
argc_++;

View File

@ -22,6 +22,12 @@ redis_hash::~redis_hash()
{
}
void redis_hash::reset()
{
if (conn_ != NULL)
conn_->reset();
}
void redis_hash::set_client(redis_client* conn)
{
conn_ = conn;
@ -224,20 +230,19 @@ int redis_hash::hset(const char* key, const char* name,
int redis_hash::hset(const char* key, const char* name, size_t name_len,
const char* value, size_t value_len)
{
const char* names[1];
size_t names_len[1];
const char* argv[4];
size_t lens[4];
names[0] = name;
names_len[0] = name_len;
argv[0] = "HSET";
lens[0] = sizeof("HSET") - 1;
argv[1] = key;
lens[1] = strlen(key);
argv[2] = name;
lens[2] = name_len;
argv[3] = value;
lens[3] = value_len;
const char* values[1];
size_t values_len[1];
values[0] = value;
values_len[0] = value_len;
const string& req = conn_->build("HSET", key, names, names_len,
values, values_len, 1);
const string& req = conn_->build_request(4, argv, lens);
return hset(req);
}
@ -271,18 +276,19 @@ int redis_hash::hsetnx(const char* key, const char* name,
int redis_hash::hsetnx(const char* key, const char* name, size_t name_len,
const char* value, size_t value_len)
{
const char* names[1];
names[0] = name;
size_t names_len[1];
names_len[0] = name_len;
const char* argv[4];
size_t lens[4];
const char* values[1];
values[0] = value;
size_t values_len[1];
values_len[0] = value_len;
argv[0] = "HSETNX";
lens[0] = sizeof("HSETNX") - 1;
argv[1] = key;
lens[1] = strlen(key);
argv[2] = name;
lens[2] = name_len;
argv[3] = value;
lens[3] = value_len;
const string& req = conn_->build("HSETNX", key, names, names_len,
values, values_len, 1);
const string& req = conn_->build_request(4, argv, lens);
return hsetnx(req);
}
@ -308,12 +314,17 @@ bool redis_hash::hget(const char* key, const char* name, string& result)
bool redis_hash::hget(const char* key, const char* name,
size_t name_len, string& result)
{
const char* names[1];
names[0] = name;
size_t names_len[1];
names_len[0] = name_len;
const char* argv[3];
size_t lens[3];
const string& req = conn_->build("HGET", key, names, names_len, 1);
argv[0] = "HGET";
lens[0] = sizeof("HGET") - 1;
argv[1] = key;
lens[1] = strlen(key);
argv[2] = name;
lens[2] = name_len;
const string& req = conn_->build_request(3, argv, lens);
const redis_result* rr = conn_->run(req);
if (rr == NULL)
return false;

View File

@ -21,6 +21,12 @@ redis_key::~redis_key()
}
void redis_key::reset()
{
if (conn_)
conn_->reset();
}
void redis_key::set_client(redis_client* conn)
{
conn_ = conn;
@ -171,6 +177,81 @@ redis_key_t redis_key::type(const char* key)
}
}
bool redis_key::migrate(const char* key, const char* addr, unsigned dest_db,
unsigned timeout, const char* option /* = NULL */)
{
char addrbuf[64];
safe_snprintf(addrbuf, sizeof(addrbuf), "%s", addr);
char* at = strchr(addrbuf, ':');
if (at == NULL || *(at + 1) == 0)
return false;
*at++ = 0;
int port = atoi(at);
if (port >= 65535 || port <= 0)
return false;
const char* argv[7];
size_t lens[7];
size_t argc = 6;
argv[0] = "MIGRATE";
lens[0] = sizeof("MIGRATE") - 1;
argv[1] = addrbuf;
lens[1] = strlen(addrbuf);
argv[2] = at;
lens[2] = strlen(at);
argv[3] = key;
lens[3] = strlen(key);
char db_s[11];
safe_snprintf(db_s, sizeof(db_s), "%u", dest_db);
argv[4] = db_s;
lens[4] = strlen(db_s);
char timeout_s[11];
safe_snprintf(timeout_s, sizeof(timeout_s), "%u", timeout);
argv[5] = timeout_s;
lens[5] = strlen(timeout_s);
if (option && *option)
{
argv[6] = option;
lens[6] = strlen(option);
argc++;
}
const string& req = conn_->build_request(argc, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* status = result_->get_status();
if (status == NULL || strcasecmp(status, "OK") != 0)
return false;
return true;
}
int redis_key::move(const char* key, unsigned dest_db)
{
const char* argv[3];
size_t lens[3];
argv[0] = "MOVE";
lens[0] = sizeof("MOVE") - 1;
argv[1] = key;
lens[1] = strlen(key);
char db_s[11];
safe_snprintf(db_s, sizeof(db_s), "%u", dest_db);
argv[2] = db_s;
lens[2] = strlen(db_s);
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_INTEGER)
return -1;
return result_->get_integer();
}
/////////////////////////////////////////////////////////////////////////////
} // namespace acl

View File

@ -1,12 +1,20 @@
#include "acl_stdafx.hpp"
#include "acl_cpp/stdlib/string.hpp"
#include "acl_cpp/stdlib/dbuf_pool.hpp"
#include "acl_cpp/stdlib/snprintf.hpp"
#include "acl_cpp/redis/redis_client.hpp"
#include "acl_cpp/redis/redis_result.hpp"
#include "acl_cpp/redis/redis_list.hpp"
namespace acl
{
#define INT_LEN 11
#define LONG_LEN 21
redis_list::redis_list(redis_client* conn /* = NULL */)
: conn_(conn)
, result_(NULL)
{
}
@ -16,4 +24,643 @@ redis_list::~redis_list()
}
void redis_list::reset()
{
if (conn_)
conn_->reset();
}
void redis_list::set_client(redis_client* conn)
{
conn_ = conn;
}
//////////////////////////////////////////////////////////////////////////
int redis_list::llen(const char* key)
{
const char* argv[2];
size_t lens[2];
argv[0] = "LLEN";
lens[0] = sizeof("LLEN") - 1;
argv[1] = key;
lens[1] = strlen(key);
const string& req = conn_->build_request(2, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return -1;
if (result_->get_type() != REDIS_RESULT_INTEGER)
return -1;
return result_->get_integer();
}
bool redis_list::lindex(const char* key, size_t idx, string& buf,
bool* exist/* = NULL */)
{
if (exist)
*exist = false;
const char* argv[3];
size_t lens[3];
argv[0] = "LINDEX";
lens[0] = sizeof("LINDEX") - 1;
argv[1] = key;
lens[1] = strlen(key);
char tmp[LONG_LEN];
(void) safe_snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) idx);
argv[2] = tmp;
lens[2] = strlen(tmp);
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
if (result_->get_type() != REDIS_RESULT_STRING)
return false;
if (result_->argv_to_string(buf) > 0 && exist != NULL)
*exist = true;
return true;
}
bool redis_list::lset(const char* key, size_t idx, const char* value)
{
return lset(key, idx, value, strlen(value));
}
bool redis_list::lset(const char* key, size_t idx,
const char* value, size_t len)
{
const char* argv[4];
size_t lens[4];
argv[0] = "LSET";
lens[0] = sizeof("LSET") - 1;
argv[1] = key;
lens[1] = strlen(key);
char tmp[LONG_LEN];
(void) safe_snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) idx);
argv[2] = tmp;
lens[2] = strlen(tmp);
argv[3] = value;
lens[3] = len;
const string& req = conn_->build_request(4, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
if (result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* res = result_->get_status();
if (res == NULL || strcasecmp(res, "OK") != 0)
return false;
else
return true;
}
int redis_list::linsert_before(const char* key, const char* pivot,
const char* value)
{
return linsert_before(key, pivot, strlen(pivot), value, strlen(value));
}
int redis_list::linsert_before(const char* key, const char* pivot,
size_t pivot_len, const char* value, size_t value_len)
{
return linsert(key, "BEFORE", pivot, pivot_len, value, value_len);
}
int redis_list::linsert_after(const char* key, const char* pivot,
const char* value)
{
return linsert_after(key, pivot, strlen(pivot), value, strlen(value));
}
int redis_list::linsert_after(const char* key, const char* pivot,
size_t pivot_len, const char* value, size_t value_len)
{
return linsert(key, "AFTER", pivot, pivot_len, value, value_len);
}
int redis_list::linsert(const char* key, const char* pos, const char* pivot,
size_t pivot_len, const char* value, size_t value_len)
{
const char* argv[5];
size_t lens[5];
argv[0] = "LINSERT";
lens[0] = sizeof("LINSERT") - 1;
argv[1] = key;
lens[1] = strlen(key);
argv[2] = pos;
lens[2] = strlen(pos);
argv[3] = pivot;
lens[3] = pivot_len;
argv[4] = value;
lens[4] = value_len;
const string& req = conn_->build_request(5, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_INTEGER)
return -1;
return result_->get_integer();
}
int redis_list::lpush(const char* key, const char* first_value, ...)
{
std::vector<const char*> values;
values.push_back(first_value);
va_list ap;
va_start(ap, first_value);
const char* value;
while ((value = va_arg(ap, const char*)) != NULL)
values.push_back(value);
va_end(ap);
return lpush(key, values);
}
int redis_list::lpush(const char* key, const char* values[], size_t argc)
{
const string& req = conn_->build("LPUSH", key, values, argc);
return push(req);
}
int redis_list::lpush(const char* key, const std::vector<string>& values)
{
const string& req = conn_->build("LPUSH", key, values);
return push(req);
}
int redis_list::lpush(const char* key, const std::vector<char*>& values)
{
const string& req = conn_->build("LPUSH", key, values);
return push(req);
}
int redis_list::lpush(const char* key, const std::vector<const char*>& values)
{
const string& req = conn_->build("LPUSH", key, values);
return push(req);
}
int redis_list::lpush(const char* key, const char* values[],
size_t lens[], size_t argc)
{
const string& req = conn_->build("LPUSH", key, values, lens, argc);
return push(req);
}
int redis_list::rpush(const char* key, const char* first_value, ...)
{
std::vector<const char*> values;
values.push_back(first_value);
va_list ap;
va_start(ap, first_value);
const char* value;
while ((value = va_arg(ap, const char*)) != NULL)
values.push_back(value);
va_end(ap);
return rpush(key, values);
}
int redis_list::rpush(const char* key, const char* values[], size_t argc)
{
const string& req = conn_->build("RPUSH", key, values, argc);
return push(req);
}
int redis_list::rpush(const char* key, const std::vector<string>& values)
{
const string& req = conn_->build("RPUSH", key, values);
return push(req);
}
int redis_list::rpush(const char* key, const std::vector<char*>& values)
{
const string& req = conn_->build("RPUSH", key, values);
return push(req);
}
int redis_list::rpush(const char* key, const std::vector<const char*>& values)
{
const string& req = conn_->build("RPUSH", key, values);
return push(req);
}
int redis_list::rpush(const char* key, const char* values[],
size_t lens[], size_t argc)
{
const string& req = conn_->build("RPUSH", key, values, lens, argc);
return push(req);
}
int redis_list::push(const string& req)
{
result_ = conn_->run(req);
if (result_ == NULL)
return -1;
if (result_->get_type() != REDIS_RESULT_INTEGER)
return -1;
return result_->get_integer();
}
int redis_list::lpushx(const char* key, const char* value)
{
return lpushx(key, value, strlen(value));
}
int redis_list::lpushx(const char* key, const char* value, size_t len)
{
return pushx("LPUSHX", key, value, len);
}
int redis_list::rpushx(const char* key, const char* value)
{
return rpushx(key, value, strlen(value));
}
int redis_list::rpushx(const char* key, const char* value, size_t len)
{
return pushx("RPUSHX", key, value, len);
}
int redis_list::pushx(const char* cmd, const char* key,
const char* value, size_t len)
{
const char* argv[3];
size_t lens[3];
argv[0] = cmd;
lens[0] = strlen(cmd);
argv[1] = key;
lens[1] = strlen(key);
argv[2] = value;
lens[2] = len;
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return -1;
if (result_->get_type() != REDIS_RESULT_INTEGER)
return -1;
return result_->get_integer();
}
//////////////////////////////////////////////////////////////////////////
int redis_list::lpop(const char* key, string& buf)
{
return pop("LPOP", key, buf);
}
int redis_list::rpop(const char* key, string& buf)
{
return pop("RPOP", key, buf);
}
int redis_list::pop(const char* cmd, const char* key, string& buf)
{
const char* argv[2];
size_t lens[2];
argv[0] = cmd;
lens[0] = strlen(cmd);
argv[1] = key;
lens[1] = strlen(key);
const string& req = conn_->build_request(2, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return -1;
if (result_->get_type() != REDIS_RESULT_STRING)
return -1;
return result_->argv_to_string(buf);
}
bool redis_list::blpop(std::pair<string, string>& result, size_t timeout,
const char* first_key, ...)
{
std::vector<const char*> keys;
keys.push_back(first_key);
va_list ap;
va_start(ap, first_key);
const char* key;
while ((key = va_arg(ap, const char*)) != NULL)
keys.push_back(key);
va_end(ap);
return blpop(keys, timeout, result);
}
bool redis_list::blpop(const std::vector<char*>& keys, size_t timeout,
std::pair<string, string>& result)
{
return blpop((const std::vector<const char*>&) keys, timeout, result);
}
bool redis_list::blpop(const std::vector<const char*>& keys, size_t timeout,
std::pair<string, string>& result)
{
return bpop("BLPOP", keys, timeout, result);
}
bool redis_list::blpop(const std::vector<string>& keys, size_t timeout,
std::pair<string, string>& result)
{
return bpop("BLPOP", keys, timeout, result);
}
bool redis_list::brpop(std::pair<string, string>& result, size_t timeout,
const char* first_key, ...)
{
std::vector<const char*> keys;
keys.push_back(first_key);
va_list ap;
va_start(ap, first_key);
const char* key;
while ((key = va_arg(ap, const char*)) != NULL)
keys.push_back(key);
va_end(ap);
return brpop(keys, timeout, result);
}
bool redis_list::brpop(const std::vector<char*>& keys, size_t timeout,
std::pair<string, string>& result)
{
return brpop((const std::vector<const char*>&) keys, timeout, result);
}
bool redis_list::brpop(const std::vector<const char*>& keys, size_t timeout,
std::pair<string, string>& result)
{
return bpop("BRPOP", keys, timeout, result);
}
bool redis_list::brpop(const std::vector<string>& keys, size_t timeout,
std::pair<string, string>& result)
{
return bpop("BRPOP", keys, timeout, result);
}
bool redis_list::bpop(const char* cmd, const std::vector<const char*>& keys,
size_t timeout, std::pair<string, string>& result)
{
size_t argc = 2 + keys.size();
dbuf_pool* pool = conn_->get_pool();
const char** args = (const char**)
pool->dbuf_alloc(argc * sizeof(char*));
size_t* lens = (size_t*) pool->dbuf_alloc(argc * sizeof(size_t));
args[0] = cmd;
lens[0] = strlen(cmd);
size_t i = 1;
std::vector<const char*>::const_iterator cit = keys.begin();
for (; cit != keys.end(); ++cit)
{
args[i] = *cit;
lens[i] = strlen(args[i]);
i++;
}
char buf[LONG_LEN];
safe_snprintf(buf, sizeof(buf), "%lu", (unsigned long) timeout);
args[i] = buf;
lens[i] = strlen(args[i]);
const string& req = conn_->build_request(argc, args, lens);
return bpop(req, result);
}
bool redis_list::bpop(const char* cmd, const std::vector<string>& keys,
size_t timeout, std::pair<string, string>& result)
{
size_t argc = 2 + keys.size();
dbuf_pool* pool = conn_->get_pool();
const char** args = (const char**)
pool->dbuf_alloc(argc * sizeof(char*));
size_t* lens = (size_t*) pool->dbuf_alloc(argc * sizeof(size_t));
args[0] = cmd;
lens[0] = strlen(cmd);
size_t i = 1;
std::vector<string>::const_iterator cit = keys.begin();
for (; cit != keys.end(); ++cit)
{
args[i] = (*cit).c_str();
lens[i] = strlen(args[i]);
i++;
}
char buf[LONG_LEN];
safe_snprintf(buf, sizeof(buf), "%lu", (unsigned long) timeout);
args[i] = buf;
lens[i] = strlen(args[i]);
const string& req = conn_->build_request(argc, args, lens);
return bpop(req, result);
}
bool redis_list::bpop(const string& req, std::pair<string, string>& result)
{
result_ = conn_->run(req);
if (result_ == NULL)
return false;
if (result_->get_type() != REDIS_RESULT_ARRAY)
return false;
size_t size = result_->get_size();
if (size == 0)
return false;
if (size != 2)
return false;
const redis_result* first = result_->get_child(0);
const redis_result* second = result_->get_child(1);
if (first == NULL || second == NULL
|| first->get_type() != REDIS_RESULT_STRING
|| second->get_type() != REDIS_RESULT_STRING)
{
return false;
}
string buf;
first->argv_to_string(buf);
result.first = buf;
buf.clear();
second->argv_to_string(buf);
result.second = buf;
return true;
}
bool redis_list::rpoplpush(const char* src, const char* dst,
string* buf /* = NULL */)
{
const char* argv[3];
size_t lens[3];
argv[0] = "RPOPLPUSH";
lens[0] = sizeof("RPOPLPUSH") - 1;
argv[1] = src;
lens[1] = strlen(src);
argv[2] = dst;
lens[2] = strlen(dst);
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_STRING)
return false;
if (buf == NULL)
return true;
result_->argv_to_string(*buf);
return true;
}
bool redis_list::brpoplpush(const char* src, const char* dst,
size_t timeout, string* buf /* = NULL */)
{
const char* argv[4];
size_t lens[4];
argv[0] = "BRPOPLPUSH";
lens[0] = sizeof("BRPOPLPUSH") - 1;
argv[1] = src;
lens[1] = strlen(src);
argv[2] = dst;
lens[2] = strlen(dst);
char tmp[LONG_LEN];
safe_snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) timeout);
argv[3] = tmp;
lens[3] = strlen(argv[3]);
const string& req = conn_->build_request(4, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_STRING)
return false;
if (buf == NULL)
return true;
result_->argv_to_string(*buf);
return true;
}
bool redis_list::lrange(const char* key, size_t start, size_t end,
std::vector<string>& result)
{
const char* argv[4];
size_t lens[4];
argv[0] = "LRANGE";
lens[0] = sizeof("LRANGE") - 1;
argv[1] = key;
lens[1] = strlen(key);
char start_s[LONG_LEN], end_s[LONG_LEN];
safe_snprintf(start_s, sizeof(start_s), "%lu", (unsigned long) start);
safe_snprintf(end_s, sizeof(end_s), "%lu", (unsigned long) end);
argv[2] = start_s;
lens[2] = strlen(start_s);
argv[3] = end_s;
lens[3] = strlen(end_s);
const string& req = conn_->build_request(4, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_ARRAY)
return false;
size_t size;
const redis_result** children = result_->get_children(&size);
if (children == NULL)
return true;
string buf;
for (size_t i = 0; i < size; i++)
{
const redis_result* rr = children[i];
rr->argv_to_string(buf);
result.push_back(buf);
buf.clear();
}
return true;
}
int redis_list::lrem(const char* key, int count, const char* value)
{
return lrem(key, count, value, strlen(value));
}
int redis_list::lrem(const char* key, int count, const char* value, size_t len)
{
const char* argv[4];
size_t lens[4];
argv[0] = "LREM";
lens[0] = sizeof("LREM") - 1;
argv[1] = key;
lens[1] = strlen(key);
char buf[INT_LEN];
safe_snprintf(buf, sizeof(buf), "%d", count);
argv[2] = buf;
lens[2] = strlen(buf);
argv[3] = value;
lens[3] = len;
const string& req = conn_->build_request(4, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_INTEGER)
return -1;
return result_->get_integer();
}
bool redis_list::ltrim(const char* key, size_t start, size_t end)
{
const char* argv[4];
size_t lens[4];
argv[0] = "LTRIM";
lens[0] = sizeof("LTRIM") - 1;
argv[1] = key;
lens[1] = strlen(key);
char start_s[LONG_LEN], end_s[LONG_LEN];
safe_snprintf(start_s, sizeof(start_s), "%lu", (unsigned long) start);
safe_snprintf(end_s, sizeof(end_s), "%lu", (unsigned long) end);
argv[2] = start_s;
lens[2] = strlen(start_s);
argv[3] = end_s;
lens[3] = strlen(end_s);
const string& req = conn_->build_request(4, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* status = result_->get_status();
if (status == NULL || strcasecmp(status, "OK") != 0)
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////
} // namespace acl

View File

@ -0,0 +1,192 @@
#include "acl_stdafx.hpp"
#include "acl_cpp/stdlib/dbuf_pool.hpp"
#include "acl_cpp/redis/redis_client.hpp"
#include "acl_cpp/redis/redis_result.hpp"
#include "acl_cpp/redis/redis_pubsub.hpp"
namespace acl
{
redis_pubsub::redis_pubsub(redis_client* conn /* = NULL */)
: conn_(conn)
{
}
redis_pubsub::~redis_pubsub()
{
}
void redis_pubsub::reset()
{
if (conn_)
conn_->reset();
}
void redis_pubsub::set_client(redis_client* conn)
{
conn_ = conn;
}
int redis_pubsub::publish(const char* channel, const char* msg, size_t len)
{
const char* argv[3];
size_t lens[3];
argv[0] = "PUBLISH";
lens[0] = sizeof("PUBLISH") - 1;
argv[1] = channel;
lens[1] = strlen(channel);
argv[2] = msg;
lens[2] = len;
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_INTEGER)
return -1;
return result_->get_integer();
}
int redis_pubsub::subscribe(const char* first_channel, ...)
{
std::vector<string> channels;
channels.push_back(first_channel);
va_list ap;
va_start(ap, first_channel);
const char* channel;
while ((channel = va_arg(ap, const char*)) != NULL)
channels.push_back(channel);
va_end(ap);
return subscribe(channels);
}
int redis_pubsub::subscribe(const std::vector<string>& channels)
{
return subscribe("SUBSCRIBE", channels);
}
int redis_pubsub::unsubscribe(const char* first_channel, ...)
{
std::vector<string> channels;
channels.push_back(first_channel);
va_list ap;
va_start(ap, first_channel);
const char* channel;
while ((channel = va_arg(ap, const char*)) != NULL)
channels.push_back(channel);
va_end(ap);
return unsubscribe(channels);
}
int redis_pubsub::unsubscribe(const std::vector<string>& channels)
{
return subscribe("UNSUBSCRIBE", channels);
}
int redis_pubsub::subscribe(const char* cmd,
const std::vector<string>& channels)
{
size_t argc = 1 + channels.size();
dbuf_pool* pool = conn_->get_pool();
const char** argv = (const char**)
pool->dbuf_alloc(argc * sizeof(char*));
size_t* lens = (size_t *) pool->dbuf_alloc(argc * sizeof(size_t));
argv[0] = cmd;
lens[0] = strlen(cmd);
std::vector<string>::const_iterator cit = channels.begin();
for (size_t i = 1; cit != channels.end(); ++cit, ++i)
{
argv[i] = (*cit).c_str();
lens[i] = (*cit).length();
}
const string& req = conn_->build_request(argc, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_ARRAY)
return -1;
size_t size = result_->get_size();
if (size != channels.size())
return -1;
int nchannels = 0, ret;
for (size_t i = 1; i < size; i++)
{
const redis_result* obj = result_->get_child(i);
if (obj == NULL)
return -1;
if (( ret = check_channel(obj, argv[0], channels[i])) < 0)
return -1;
if (ret > nchannels)
nchannels = ret;
}
return nchannels;
}
int redis_pubsub::check_channel(const redis_result* obj, const char* cmd,
const string& channel)
{
if (obj->get_type() != REDIS_RESULT_ARRAY)
return -1;
const redis_result* rr = obj->get_child(0);
if (rr == NULL || rr->get_type() != REDIS_RESULT_STRING)
return -1;
string buf;
rr->argv_to_string(buf);
if (strcasecmp(buf.c_str(), cmd) != 0)
return -1;
rr = obj->get_child(1);
if (rr == NULL || rr->get_type() != REDIS_RESULT_STRING)
return -1;
buf.clear();
rr->argv_to_string(buf);
if (strcasecmp(cmd, channel.c_str()) != 0)
return -1;
rr = obj->get_child(2);
if (rr == NULL || rr->get_type() != REDIS_RESULT_INTEGER)
return -1;
return result_->get_integer();
}
bool redis_pubsub::get_message(string& channel, string& msg)
{
result_ = conn_->run("");
if (result_ == NULL)
return false;
if (result_->get_type() != REDIS_RESULT_ARRAY)
return false;
size_t size = result_->get_size();
if (size != 3)
return false;
const redis_result* obj = result_->get_child(0);
if (obj == NULL || obj->get_type() != REDIS_RESULT_STRING)
return false;
string tmp;
obj->argv_to_string(tmp);
if (strcasecmp(tmp.c_str(), "message") != 0)
return false;
obj = result_->get_child(1);
if (obj == NULL || obj->get_type() != REDIS_RESULT_STRING)
return false;
obj->argv_to_string(channel);
obj = result_->get_child(2);
if (obj == NULL || obj->get_type() != REDIS_RESULT_STRING)
return false;
obj->argv_to_string(msg);
return true;
}
} // namespace acl

View File

@ -234,10 +234,10 @@ const redis_result* redis_result::get_child(size_t i) const
return children_[i];
}
const redis_result** redis_result::get_children(size_t* idx) const
const redis_result** redis_result::get_children(size_t* size) const
{
if (idx)
*idx = children_idx_;
if (size)
*size = children_idx_;
return children_;
}

View File

@ -25,6 +25,12 @@ redis_string::~redis_string()
}
void redis_string::reset()
{
if (conn_)
conn_->reset();
}
bool redis_string::set(const char* key, const char* value)
{
return set(key, strlen(key), value, strlen(value));
@ -33,16 +39,17 @@ bool redis_string::set(const char* key, const char* value)
bool redis_string::set(const char* key, size_t key_len,
const char* value, size_t value_len)
{
const char* names[2];
size_t lens[2];
const char* argv[3];
size_t lens[3];
names[0] = key;
lens[0] = key_len;
argv[0] = "SET";
lens[0] = sizeof("SET") - 1;
argv[1] = key;
lens[1] = key_len;
argv[2] = value;
lens[2] = value_len;
names[1] = value;
lens[1] = value_len;
const string& req = conn_->build("SET", NULL, names, lens, 2);
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
@ -63,21 +70,23 @@ bool redis_string::setex(const char* key, const char* value, int timeout)
bool redis_string::setex(const char* key, size_t key_len, const char* value,
size_t value_len, int timeout)
{
const char* names[3];
size_t lens[3];
const char* argv[4];
size_t lens[4];
names[0] = key;
lens[0] = key_len;
argv[0] = "SETEX";
lens[0] = sizeof("SETEX") - 1;
argv[1] = key;
lens[1] = key_len;
char buf[INT_LEN];
(void) safe_snprintf(buf, sizeof(buf), "%d", timeout);
names[1] = buf;
lens[1] = strlen(buf);
argv[2] = buf;
lens[2] = strlen(buf);
names[2] = value;
lens[2] = value_len;
argv[3] = value;
lens[3] = value_len;
const string& req = conn_->build("SETEX", NULL, names, lens, 3);
const string& req = conn_->build_request(4, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
@ -98,16 +107,17 @@ int redis_string::setnx(const char* key, const char* value)
int redis_string::setnx(const char* key, size_t key_len,
const char* value, size_t value_len)
{
const char* names[2];
size_t lens[2];
const char* argv[3];
size_t lens[3];
names[0] = key;
lens[0] = key_len;
argv[0] = "SETNX";
lens[0] = sizeof("SETNX") - 1;
argv[1] = key;
lens[1] = key_len;
argv[2] = value;
lens[2] = value_len;
names[1] = value;
lens[1] = value_len;
const string& req = conn_->build("SETNX", NULL, names, lens, 2);
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return -1;
@ -123,16 +133,17 @@ int redis_string::append(const char* key, const char* value)
int redis_string::append(const char* key, const char* value, size_t size)
{
const char* names[2];
size_t lens[2];
const char* argv[3];
size_t lens[3];
names[0] = key;
lens[0] = strlen(key);
argv[0] = "APPEND";
lens[0] = sizeof("APPEND") - 1;
argv[1] = key;
lens[1] = strlen(key);
argv[2] = value;
lens[2] = size;
names[1] = value;
lens[1] = size;
const string& req = conn_->build("APPEND", NULL, names, lens, 2);
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return -1;
@ -143,7 +154,12 @@ int redis_string::append(const char* key, const char* value, size_t size)
bool redis_string::get(const char* key, string& buf)
{
result_ = get(key);
return get(key, strlen(key), buf);
}
bool redis_string::get(const char* key, size_t len, string& buf)
{
result_ = get(key, len);
if (result_ == NULL)
return false;
(void) result_->argv_to_string(buf);
@ -152,10 +168,20 @@ bool redis_string::get(const char* key, string& buf)
const redis_result* redis_string::get(const char* key)
{
const char* keys[1];
keys[0] = key;
return get(key, strlen(key));
}
const string& req = conn_->build("GET", NULL, keys, 1);
const redis_result* redis_string::get(const char* key, size_t len)
{
const char* argv[2];
size_t lens[2];
argv[0] = "GET";
lens[0] = sizeof("GET") - 1;
argv[1] = key;
lens[1] = len;
const string& req = conn_->build_request(2, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return NULL;
@ -172,16 +198,17 @@ bool redis_string::getset(const char* key, const char* value, string& buf)
bool redis_string::getset(const char* key, size_t key_len,
const char* value, size_t value_len, string& buf)
{
const char* names[2];
size_t lens[2];
const char* argv[3];
size_t lens[3];
names[0] = key;
lens[0] = key_len;
argv[0] = "GETSET";
lens[0] = sizeof("GETSET") - 1;
argv[1] = key;
lens[1] = key_len;
argv[2] = value;
lens[2] = value_len;
names[1] = value;
lens[1] = value_len;
const string& req = conn_->build("GETSET", NULL, names, lens, 2);
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
@ -200,13 +227,15 @@ int redis_string::str_len(const char* key)
int redis_string::str_len(const char* key, size_t len)
{
const char* names[1];
size_t lens[1];
const char* argv[2];
size_t lens[2];
names[0] = key;
lens[0] = len;
argv[0] = "STRLEN";
lens[0] = sizeof("STRLEN") - 1;
argv[1] = key;
lens[1] = len;
const string& req = conn_->build("STRLEN", NULL, names, lens, 1);
const string& req = conn_->build_request(2, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return -1;
@ -223,21 +252,23 @@ int redis_string::setrange(const char* key, unsigned offset, const char* value)
int redis_string::setrange(const char* key, size_t key_len, unsigned offset,
const char* value, size_t value_len)
{
const char* names[3];
size_t lens[3];
const char* argv[4];
size_t lens[4];
names[0] = key;
lens[0] = key_len;
argv[0] = "SETRANGE";
lens[0] = sizeof("SETRANGE") - 1;
argv[1] = key;
lens[1] = key_len;
char buf[INT64_LEN];
(void) acl_i64toa(offset, buf, sizeof(buf));
names[1] = buf;
lens[1] = strlen(buf);
argv[2] = buf;
lens[2] = strlen(buf);
names[2] = value;
lens[2] = value_len;
argv[3] = value;
lens[3] = value_len;
const string& req = conn_->build("SETRANGE", NULL, names, lens, 3);
const string& req = conn_->build_request(4, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return -1;
@ -255,22 +286,24 @@ bool redis_string::getrange(const char* key, int start, int end, string& buf)
bool redis_string::getrange(const char* key, size_t key_len,
int start, int end, string& buf)
{
const char* names[3];
size_t lens[3];
const char* argv[4];
size_t lens[4];
names[0] = key;
lens[0] = key_len;
argv[0] = "GETRANGE";
lens[0] = sizeof("GETRANGE") - 1;
argv[1] = key;
lens[1] = key_len;
char start_buf[INT_LEN], end_buf[INT_LEN];
(void) safe_snprintf(start_buf, sizeof(start_buf), "%d", start);
names[1] = start_buf;
lens[1] = strlen(start_buf);
argv[2] = start_buf;
lens[2] = strlen(start_buf);
(void) safe_snprintf(end_buf, sizeof(end_buf), "%d", end);
names[2] = end_buf;
lens[2] = strlen(end_buf);
argv[3] = end_buf;
lens[3] = strlen(end_buf);
const string& req = conn_->build("GETRANGE", NULL, names, lens, 3);
const string& req = conn_->build_request(4, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
@ -289,21 +322,23 @@ bool redis_string::setbit(const char* key, unsigned offset, int bit)
bool redis_string::setbit(const char* key, size_t len, unsigned offset, int bit)
{
const char* names[3];
size_t lens[3];
const char* argv[4];
size_t lens[4];
names[0] = key;
lens[0] = len;
argv[0] = "SETBIT";
lens[0] = sizeof("SETBIT") - 1;
argv[1] = key;
lens[1] = len;
char buf4off[INT_LEN];
(void) safe_snprintf(buf4off, sizeof(buf4off), "%d", offset);
names[1] = buf4off;
lens[1] = strlen(buf4off);
argv[2] = buf4off;
lens[2] = strlen(buf4off);
names[2] = bit ? "1" : "0";
lens[2] = 1;
argv[3] = bit ? "1" : "0";
lens[3] = 1;
const string& req = conn_->build("SETBIT", NULL, names, lens, 3);
const string& req = conn_->build_request(4, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
@ -319,18 +354,20 @@ bool redis_string::getbit(const char* key, unsigned offset, int& bit)
bool redis_string::getbit(const char* key, size_t len, unsigned offset, int& bit)
{
const char* names[2];
size_t lens[2];
const char* argv[3];
size_t lens[3];
names[0] = key;
lens[0] = len;
argv[0] = "GETBIT";
lens[0] = sizeof("GETBIT") - 1;
argv[1] = key;
lens[1] = len;
char buf4off[INT_LEN];
(void) safe_snprintf(buf4off, sizeof(buf4off), "%d", offset);
names[1] = buf4off;
lens[1] = strlen(buf4off);
argv[2] = buf4off;
lens[2] = strlen(buf4off);
const string& req = conn_->build("GETBIT", NULL, names, lens, 2);
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
@ -348,13 +385,15 @@ int redis_string::bitcount(const char* key)
int redis_string::bitcount(const char* key, size_t len)
{
const char* names[1];
size_t lens[1];
const char* argv[2];
size_t lens[2];
names[0] = key;
lens[0] = len;
argv[0] = "BITCOUNT";
lens[0] = sizeof("BITCOUNT") - 1;
argv[1] = key;
lens[1] = len;
const string& req = conn_->build("BITCOUNT", NULL, names, lens, 1);
const string& req = conn_->build_request(2, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return -1;
@ -370,23 +409,25 @@ int redis_string::bitcount(const char* key, int start, int end)
int redis_string::bitcount(const char* key, size_t len, int start, int end)
{
const char* names[3];
size_t lens[3];
const char* argv[4];
size_t lens[4];
names[0] = key;
lens[0] = len;
argv[0] = "BITCOUNT";
lens[0] = sizeof("BITCOUNT") - 1;
argv[1] = key;
lens[1] = len;
char buf4start[INT_LEN];
(void) safe_snprintf(buf4start, sizeof(buf4start), "%d", start);
names[1] = buf4start;
lens[1] = strlen(buf4start);
argv[2] = buf4start;
lens[2] = strlen(buf4start);
char buf4end[INT_LEN];
(void) safe_snprintf(buf4end, sizeof(buf4end), "%d", end);
names[2] = buf4end;
lens[2] = strlen(buf4end);
argv[3] = buf4end;
lens[3] = strlen(buf4end);
const string& req = conn_->build("BITCOUNT", NULL, names, lens, 3);
const string& req = conn_->build_request(4, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return -1;
@ -479,44 +520,83 @@ int redis_string::bitop_xor(const char* destkey, const char* key, ...)
int redis_string::bitop(const char* op, const char* destkey,
const std::vector<string>& keys)
{
std::vector<string> names;
names.push_back(op);
names.push_back(destkey);
size_t argc = 3 + keys.size();
dbuf_pool* pool = conn_->get_pool();
const char** argv = (const char**)
pool->dbuf_alloc(argc * sizeof(char*));
size_t* lens = (size_t*)
pool->dbuf_alloc(argc * sizeof(size_t));
argv[0] = "BITOP";
lens[0] = strlen(argv[0]);
argv[1] = op;
lens[1] = strlen(argv[1]);
argv[2] = destkey;
lens[2] = strlen(argv[2]);
std::vector<string>::const_iterator cit = keys.begin();
for (; cit != keys.end(); ++cit)
names.push_back(*cit);
for (size_t i = 3; cit != keys.end(); ++cit, i++)
{
argv[i] = (*cit).c_str();
lens[i] = strlen(argv[i]);
}
const string& req = conn_->build("BITOP", NULL, names);
const string& req = conn_->build_request(argc, argv, lens);
return bitop(req);
}
int redis_string::bitop(const char* op, const char* destkey,
const std::vector<const char*>& keys)
{
std::vector<const char*> names;
names.push_back(op);
names.push_back(destkey);
size_t argc = 3 + keys.size();
dbuf_pool* pool = conn_->get_pool();
const char** argv = (const char**)
pool->dbuf_alloc(argc * sizeof(char*));
size_t* lens = (size_t*)
pool->dbuf_alloc(argc * sizeof(size_t));
argv[0] = "BITOP";
lens[0] = strlen(argv[0]);
argv[1] = op;
lens[1] = strlen(argv[1]);
argv[2] = destkey;
lens[2] = strlen(argv[2]);
std::vector<const char*>::const_iterator cit = keys.begin();
for (; cit != keys.end(); ++cit)
names.push_back((*cit));
for (size_t i = 3; cit != keys.end(); ++cit, i++)
{
argv[i] = *cit;
lens[i] = strlen(argv[i]);
}
const string& req = conn_->build("BITOP", NULL, names);
const string& req = conn_->build_request(argc, argv, lens);
return bitop(req);
}
int redis_string::bitop(const char* op, const char* destkey,
const char* keys[], size_t size)
{
std::vector<const char*> names;
names.push_back(op);
names.push_back(destkey);
size_t argc = 3 + size;
dbuf_pool* pool = conn_->get_pool();
const char** argv = (const char**)
pool->dbuf_alloc(argc * sizeof(char*));
size_t* lens = (size_t*)
pool->dbuf_alloc(argc * sizeof(size_t));
for (size_t i = 0; i < size; i++)
names.push_back(keys[i]);
argv[0] = "BITOP";
lens[0] = strlen(argv[0]);
argv[1] = op;
lens[1] = strlen(argv[1]);
argv[2] = destkey;
lens[2] = strlen(argv[2]);
const string& req = conn_->build("BITOP", NULL, names);
for (size_t i = 3, j = 0; j < size; i++, j++)
{
argv[i] = keys[j];
lens[i] = strlen(argv[i]);
}
const string& req = conn_->build_request(argc, argv, lens);
return bitop(req);
}
@ -804,15 +884,20 @@ bool redis_string::incrby(const char* key, long long int inc,
bool redis_string::incrbyfloat(const char* key, double inc,
double* result /* = NULL */)
{
const char* keys[1];
keys[0] = key;
const char* argv[3];
size_t lens[3];
argv[0] = "INCRBYFLOAT";
lens[0] = sizeof("INCRBYFLOAT") - 1;
argv[1] = key;
lens[1] = strlen(key);
char buf[FLOAT_LEN];
(void) safe_snprintf(buf, sizeof(buf), "%f", inc);
argv[2] = buf;
lens[2] = strlen(buf);
const char* values[1];
values[0] = buf;
const string& req = conn_->build("INCRBYFLOAT", NULL, keys, values, 1);
const string& req = conn_->build_request(3, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;
@ -840,20 +925,25 @@ bool redis_string::decrby(const char* key, long long int dec,
bool redis_string::incoper(const char* cmd, const char* key, long long int n,
long long int* result)
{
size_t argc = 1;
const char* names[2];
size_t argc = 2;
const char* argv[3];
size_t lens[3];
names[0] = key;
argv[0] = cmd;
lens[0] = strlen(cmd);
argv[1] = key;
lens[1] = strlen(key);
char buf[INT64_LEN];
if (n != 1)
{
(void) acl_i64toa(n, buf, sizeof(buf));
names[1] = buf;
argv[2] = buf;
lens[2] = strlen(buf);
argc++;
}
const string& req = conn_->build(cmd, NULL, names, argc);
const string& req = conn_->build_request(argc, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL)
return false;

View File

@ -0,0 +1,149 @@
#include "acl_stdafx.hpp"
#include "acl_cpp/stdlib/string.hpp"
#include "acl_cpp/redis/redis_client.hpp"
#include "acl_cpp/redis/redis_result.hpp"
#include "acl_cpp/redis/redis_transaction.hpp"
namespace acl
{
redis_transaction::redis_transaction(redis_client* conn /* = NULL */)
: conn_(conn)
, result_(NULL)
{
}
redis_transaction::~redis_transaction()
{
}
void redis_transaction::reset()
{
if (conn_)
conn_->reset();
cmds_.clear();
}
void redis_transaction::set_client(redis_client* conn)
{
conn_ = conn;
}
bool redis_transaction::watch(const std::vector<string>& keys)
{
const string& req = conn_->build("WATCH", NULL, keys);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* status = result_->get_status();
if (status == NULL || strcasecmp(status, "OK") != 0)
return false;
else
return true;
}
bool redis_transaction::unwatch(const std::vector<string>& keys)
{
const string& req = conn_->build("UNWATCH", NULL, keys);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* status = result_->get_status();
if (status == NULL || strcasecmp(status, "OK") != 0)
return false;
else
return true;
}
bool redis_transaction::multi()
{
const char* argv[1];
size_t lens[1];
argv[0] = "MULTI";
lens[0] = sizeof("MULTI") - 1;
const string& req = conn_->build_request(1, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* status = result_->get_status();
if (status == NULL || strcasecmp(status, "OK") != 0)
return false;
return true;
}
bool redis_transaction::exec()
{
const char* argv[1];
size_t lens[1];
argv[0] = "EXEC";
lens[0] = sizeof("EXEC") - 1;
const string& req = conn_->build_request(1, argv, lens);
result_ = conn_->run(req);
if(result_ == NULL || result_->get_type() != REDIS_RESULT_ARRAY)
return false;
size_t size = result_->get_size();
if (size != cmds_.size())
return false;
return true;
}
bool redis_transaction::discard()
{
const char* argv[1];
size_t lens[1];
argv[0] = "DISCARD";
lens[0] = sizeof("DISCARD") - 1;
const string& req = conn_->build_request(1, argv, lens);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* status = result_->get_status();
if (status == NULL || strcasecmp(status, "OK") != 0)
return false;
return true;
}
bool redis_transaction::queue_cmd(const char* cmd, const char* argv[],
const size_t lens[], size_t argc)
{
const string& req = conn_->build(cmd, NULL, argv, lens, argc);
result_ = conn_->run(req);
if (result_ == NULL || result_->get_type() != REDIS_RESULT_STATUS)
return false;
const char* status = result_->get_status();
if (status == NULL || strcasecmp(status, "QUEUED") != 0)
return false;
cmds_.push_back(cmd);
return true;
}
size_t redis_transaction::get_size()
{
if (result_ == NULL)
return 0;
return result_->get_size();
}
const redis_result* redis_transaction::get_child(size_t i, string* cmd)
{
if (cmd != NULL)
{
if (i < cmds_.size())
*cmd = cmds_[i];
}
if (result_ == NULL || result_->get_type() != REDIS_RESULT_ARRAY)
return NULL;
return result_->get_child(i);
}
} // namespace acl