Commit cb37f24f13758ce21f8db7cad87b4a1bb3070789

Authored by Hayk Martirosyan
1 parent a8a81ee7

Add unix sockets constructor

README.md
@@ -22,7 +22,8 @@ high-performance applications. It is built on top of [hiredis](https://github.co @@ -22,7 +22,8 @@ high-performance applications. It is built on top of [hiredis](https://github.co
22 ## Performance Benchmarks 22 ## Performance Benchmarks
23 Benchmarks are given by averaging the results of five trials of various programs 23 Benchmarks are given by averaging the results of five trials of various programs
24 in `examples/`. The results are on an AWS t2.medium instance running Ubuntu 14.04 (64-bit). 24 in `examples/`. The results are on an AWS t2.medium instance running Ubuntu 14.04 (64-bit).
25 -During these tests, Redox communicated with a local Redis server over TCP. 25 +During these tests, Redox communicated with a local Redis server over TCP. Results are
  26 +slightly faster using Unix sockets.
26 27
27 * 100 repeating asynchronous commands (`speed_test_async_multi`): **710,014 commands/s** 28 * 100 repeating asynchronous commands (`speed_test_async_multi`): **710,014 commands/s**
28 * One repeating asynchronous command (`speed_test_async`): **195,159 commands/s** 29 * One repeating asynchronous command (`speed_test_async`): **195,159 commands/s**
src/command.hpp
@@ -70,7 +70,7 @@ public: @@ -70,7 +70,7 @@ public:
70 */ 70 */
71 void free(); 71 void free();
72 72
73 - void process_reply(); 73 + void process_reply(redisReply* r);
74 74
75 ev_timer* get_timer() { 75 ev_timer* get_timer() {
76 std::lock_guard<std::mutex> lg(timer_guard); 76 std::lock_guard<std::mutex> lg(timer_guard);
@@ -94,7 +94,6 @@ private: @@ -94,7 +94,6 @@ private:
94 ev_timer timer; 94 ev_timer timer;
95 std::mutex timer_guard; 95 std::mutex timer_guard;
96 96
97 -  
98 // Make sure we don't free resources until details taken care of 97 // Make sure we don't free resources until details taken care of
99 std::mutex free_guard; 98 std::mutex free_guard;
100 99
@@ -120,10 +119,11 @@ Command&lt;ReplyT&gt;::Command( @@ -120,10 +119,11 @@ Command&lt;ReplyT&gt;::Command(
120 } 119 }
121 120
122 template<class ReplyT> 121 template<class ReplyT>
123 -void Command<ReplyT>::process_reply() { 122 +void Command<ReplyT>::process_reply(redisReply* r) {
124 123
125 free_guard.lock(); 124 free_guard.lock();
126 125
  126 + reply_obj = r;
127 invoke_callback(); 127 invoke_callback();
128 128
129 pending--; 129 pending--;
src/redox.cpp
@@ -45,18 +45,14 @@ void Redox::disconnected_callback(const redisAsyncContext *ctx, int status) { @@ -45,18 +45,14 @@ void Redox::disconnected_callback(const redisAsyncContext *ctx, int status) {
45 if(rdx->user_connection_callback) rdx->user_connection_callback(rdx->connect_state); 45 if(rdx->user_connection_callback) rdx->user_connection_callback(rdx->connect_state);
46 } 46 }
47 47
48 -Redox::Redox(  
49 - const string& host, const int port,  
50 - std::function<void(int)> connection_callback  
51 -) : host(host), port(port), user_connection_callback(connection_callback) {  
52 -  
53 - // libev setup 48 +void Redox::init_ev() {
54 signal(SIGPIPE, SIG_IGN); 49 signal(SIGPIPE, SIG_IGN);
55 evloop = ev_loop_new(EVFLAG_AUTO); 50 evloop = ev_loop_new(EVFLAG_AUTO);
56 ev_set_userdata(evloop, (void*)this); // Back-reference 51 ev_set_userdata(evloop, (void*)this); // Back-reference
  52 +}
  53 +
  54 +void Redox::init_hiredis() {
57 55
58 - // Create a redisAsyncContext  
59 - ctx = redisAsyncConnect(host.c_str(), port);  
60 ctx->data = (void*)this; // Back-reference 56 ctx->data = (void*)this; // Back-reference
61 57
62 if (ctx->err) { 58 if (ctx->err) {
@@ -74,6 +70,32 @@ Redox::Redox( @@ -74,6 +70,32 @@ Redox::Redox(
74 redisAsyncSetDisconnectCallback(ctx, Redox::disconnected_callback); 70 redisAsyncSetDisconnectCallback(ctx, Redox::disconnected_callback);
75 } 71 }
76 72
  73 +Redox::Redox(
  74 + const string& host, const int port,
  75 + std::function<void(int)> connection_callback
  76 +) : host(host), port(port), user_connection_callback(connection_callback) {
  77 +
  78 + init_ev();
  79 +
  80 + // Connect over TCP
  81 + ctx = redisAsyncConnect(host.c_str(), port);
  82 +
  83 + init_hiredis();
  84 +}
  85 +
  86 +Redox::Redox(
  87 + const std::string& path,
  88 + std::function<void(int)> connection_callback = nullptr
  89 +) : path(path), user_connection_callback(connection_callback) {
  90 +
  91 + init_ev();
  92 +
  93 + // Connect over unix sockets
  94 + ctx = redisAsyncConnectUnix(path.c_str());
  95 +
  96 + init_hiredis();
  97 +}
  98 +
77 void Redox::run_event_loop() { 99 void Redox::run_event_loop() {
78 100
79 // Events to connect to Redox 101 // Events to connect to Redox
@@ -200,8 +222,7 @@ void Redox::command_callback(redisAsyncContext *ctx, void *r, void *privdata) { @@ -200,8 +222,7 @@ void Redox::command_callback(redisAsyncContext *ctx, void *r, void *privdata) {
200 return; 222 return;
201 } 223 }
202 224
203 - c->reply_obj = reply_obj;  
204 - c->process_reply(); 225 + c->process_reply(reply_obj);
205 226
206 // Increment the Redox object command counter 227 // Increment the Redox object command counter
207 rdx->cmd_count++; 228 rdx->cmd_count++;
@@ -340,7 +361,7 @@ void Redox::command(const string&amp; cmd) { @@ -340,7 +361,7 @@ void Redox::command(const string&amp; cmd) {
340 361
341 bool Redox::command_blocking(const string& cmd) { 362 bool Redox::command_blocking(const string& cmd) {
342 Command<redisReply*>* c = command_blocking<redisReply*>(cmd); 363 Command<redisReply*>* c = command_blocking<redisReply*>(cmd);
343 - bool succeeded = (c->status() == REDOX_OK); 364 + bool succeeded = c->ok();
344 c->free(); 365 c->free();
345 return succeeded; 366 return succeeded;
346 } 367 }
src/redox.hpp
@@ -48,6 +48,14 @@ public: @@ -48,6 +48,14 @@ public:
48 const int port = REDIS_DEFAULT_PORT, 48 const int port = REDIS_DEFAULT_PORT,
49 std::function<void(int)> connection_callback = nullptr 49 std::function<void(int)> connection_callback = nullptr
50 ); 50 );
  51 +
  52 + /**
  53 + * Initialize everything, connect over unix sockets to a Redis server.
  54 + */
  55 + Redox(
  56 + const std::string& path,
  57 + std::function<void(int)> connection_callback
  58 + );
51 ~Redox(); 59 ~Redox();
52 60
53 /** 61 /**
@@ -173,10 +181,17 @@ public: @@ -173,10 +181,17 @@ public:
173 181
174 private: 182 private:
175 183
176 - // Redox server 184 + // Redox server over TCP
177 std::string host; 185 std::string host;
178 int port; 186 int port;
179 187
  188 + // Redox server over unix
  189 + std::string path;
  190 +
  191 + // Setup code for the constructors
  192 + void init_ev();
  193 + void init_hiredis();
  194 +
180 // Manage connection state 195 // Manage connection state
181 std::atomic_int connect_state = {REDOX_NOT_YET_CONNECTED}; 196 std::atomic_int connect_state = {REDOX_NOT_YET_CONNECTED};
182 std::mutex connect_lock; 197 std::mutex connect_lock;
@@ -315,9 +330,7 @@ Command&lt;ReplyT&gt;* Redox::command_blocking(const std::string&amp; cmd) { @@ -315,9 +330,7 @@ Command&lt;ReplyT&gt;* Redox::command_blocking(const std::string&amp; cmd) {
315 0, 0, false // No repeats, don't free memory 330 0, 0, false // No repeats, don't free memory
316 ); 331 );
317 332
318 - // Wait until a callback is invoked  
319 cv.wait(lk, [&status] { return status != REDOX_UNINIT; }); 333 cv.wait(lk, [&status] { return status != REDOX_UNINIT; });
320 -  
321 c->reply_val = val; 334 c->reply_val = val;
322 c->reply_status = status; 335 c->reply_status = status;
323 336