Commit 0fd859b74253a10ec6dd6c223f01b858db34ea3a

Authored by Hayk Martirosyan
1 parent b4f96a55

Finish code style refactoring for Redox, add license notices

Conform (mostly) to Google C++ guidelines.

Apache license notice and link above each core file.
examples/pub_sub.cpp
  1 +/**
  2 +* Redox example for basic pubsub usage.
  3 +*/
  4 +
1 5 #include <stdlib.h>
2 6 #include <iostream>
3 7 #include "../src/redox.hpp"
... ...
src/command.cpp
1 1 /**
2   -* Redis C++11 wrapper.
  2 +* Redox - A modern, asynchronous, and wicked fast C++11 client for Redis
  3 +*
  4 +* https://github.com/hmartiro/redox
  5 +*
  6 +* Copyright 2015 - Hayk Martirosyan <hayk.mart at gmail dot com>
  7 +*
  8 +* Licensed under the Apache License, Version 2.0 (the "License");
  9 +* you may not use this file except in compliance with the License.
  10 +* You may obtain a copy of the License at
  11 +*
  12 +* http://www.apache.org/licenses/LICENSE-2.0
  13 +*
  14 +* Unless required by applicable law or agreed to in writing, software
  15 +* distributed under the License is distributed on an "AS IS" BASIS,
  16 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17 +* See the License for the specific language governing permissions and
  18 +* limitations under the License.
3 19 */
4 20  
5 21 #include <vector>
... ...
src/command.hpp
1 1 /**
2   -* Redis C++11 wrapper.
  2 +* Redox - A modern, asynchronous, and wicked fast C++11 client for Redis
  3 +*
  4 +* https://github.com/hmartiro/redox
  5 +*
  6 +* Copyright 2015 - Hayk Martirosyan <hayk.mart at gmail dot com>
  7 +*
  8 +* Licensed under the Apache License, Version 2.0 (the "License");
  9 +* you may not use this file except in compliance with the License.
  10 +* You may obtain a copy of the License at
  11 +*
  12 +* http://www.apache.org/licenses/LICENSE-2.0
  13 +*
  14 +* Unless required by applicable law or agreed to in writing, software
  15 +* distributed under the License is distributed on an "AS IS" BASIS,
  16 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17 +* See the License for the specific language governing permissions and
  18 +* limitations under the License.
3 19 */
4 20  
5 21 #pragma once
... ...
src/redox.cpp
1 1 /**
2   -* Redis C++11 wrapper.
  2 +* Redox - A modern, asynchronous, and wicked fast C++11 client for Redis
  3 +*
  4 +* https://github.com/hmartiro/redox
  5 +*
  6 +* Copyright 2015 - Hayk Martirosyan <hayk.mart at gmail dot com>
  7 +*
  8 +* Licensed under the Apache License, Version 2.0 (the "License");
  9 +* you may not use this file except in compliance with the License.
  10 +* You may obtain a copy of the License at
  11 +*
  12 +* http://www.apache.org/licenses/LICENSE-2.0
  13 +*
  14 +* Unless required by applicable law or agreed to in writing, software
  15 +* distributed under the License is distributed on an "AS IS" BASIS,
  16 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17 +* See the License for the specific language governing permissions and
  18 +* limitations under the License.
3 19 */
4 20  
5 21 #include <signal.h>
6   -#include <string.h>
7 22 #include "redox.hpp"
8 23  
9 24 using namespace std;
... ... @@ -126,7 +141,7 @@ void Redox::runEventLoop() {
126 141  
127 142 // Set up asynchronous watcher which we signal every
128 143 // time we add a command
129   - ev_async_init(&watcher_command_, proccessQueuedCommands);
  144 + ev_async_init(&watcher_command_, processQueuedCommands);
130 145 ev_async_start(evloop_, &watcher_command_);
131 146  
132 147 // Set up an async watcher to break the loop
... ... @@ -231,10 +246,6 @@ void Redox::commandCallback(redisAsyncContext* ctx, void* r, void* privdata) {
231 246 c->processReply(reply_obj);
232 247 }
233 248  
234   -/**
235   -* Submit an asynchronous command to the Redox server. Return
236   -* true if succeeded, false otherwise.
237   -*/
238 249 template<class ReplyT>
239 250 bool Redox::submitToServer(Command<ReplyT>* c) {
240 251  
... ... @@ -290,8 +301,6 @@ void Redox::submitCommandCallback(struct ev_loop* loop, ev_timer* timer, int rev
290 301  
291 302 if(c->canceled()) {
292 303  
293   -// logger.info() << "Command " << c << " is completed, stopping event timer.";
294   -
295 304 c->timer_guard_.lock();
296 305 if((c->repeat_ != 0) || (c->after_ != 0))
297 306 ev_timer_stop(loop, &c->timer_);
... ... @@ -307,7 +316,7 @@ void Redox::submitCommandCallback(struct ev_loop* loop, ev_timer* timer, int rev
307 316 }
308 317  
309 318 template<class ReplyT>
310   -bool Redox::proccessQueuedCommand(long id) {
  319 +bool Redox::processQueuedCommand(long id) {
311 320  
312 321 Command<ReplyT>* c = findCommand<ReplyT>(id);
313 322 if(c == nullptr) return false;
... ... @@ -318,7 +327,7 @@ bool Redox::proccessQueuedCommand(long id) {
318 327 } else {
319 328  
320 329 c->timer_.data = (void*)c->id_;
321   - ev_timer_init(&c->timer_, submitCommandCallback <ReplyT>, c->after_, c->repeat_);
  330 + ev_timer_init(&c->timer_, submitCommandCallback<ReplyT>, c->after_, c->repeat_);
322 331 ev_timer_start(evloop_, &c->timer_);
323 332  
324 333 c->timer_guard_.unlock();
... ... @@ -327,26 +336,26 @@ bool Redox::proccessQueuedCommand(long id) {
327 336 return true;
328 337 }
329 338  
330   -void Redox::proccessQueuedCommands(struct ev_loop* loop, ev_async* async, int revents) {
  339 +void Redox::processQueuedCommands(struct ev_loop* loop, ev_async* async, int revents) {
331 340  
332 341 Redox* rdx = (Redox*) ev_userdata(loop);
333 342  
334   - lock_guard<mutex> lg(rdx->queue_guard);
  343 + lock_guard<mutex> lg(rdx->queue_guard_);
335 344  
336   - while(!rdx->command_queue.empty()) {
  345 + while(!rdx->command_queue_.empty()) {
337 346  
338   - long id = rdx->command_queue.front();
339   - rdx->command_queue.pop();
  347 + long id = rdx->command_queue_.front();
  348 + rdx->command_queue_.pop();
340 349  
341   - if(rdx->proccessQueuedCommand<redisReply*>(id)) {}
342   - else if(rdx->proccessQueuedCommand<string>(id)) {}
343   - else if(rdx->proccessQueuedCommand<char*>(id)) {}
344   - else if(rdx->proccessQueuedCommand<int>(id)) {}
345   - else if(rdx->proccessQueuedCommand<long long int>(id)) {}
346   - else if(rdx->proccessQueuedCommand<nullptr_t>(id)) {}
347   - else if(rdx->proccessQueuedCommand<vector<string>>(id)) {}
348   - else if(rdx->proccessQueuedCommand<std::set<string>>(id)) {}
349   - else if(rdx->proccessQueuedCommand<unordered_set<string>>(id)) {}
  350 + if(rdx->processQueuedCommand<redisReply*>(id)) {}
  351 + else if(rdx->processQueuedCommand<string>(id)) {}
  352 + else if(rdx->processQueuedCommand<char*>(id)) {}
  353 + else if(rdx->processQueuedCommand<int>(id)) {}
  354 + else if(rdx->processQueuedCommand<long long int>(id)) {}
  355 + else if(rdx->processQueuedCommand<nullptr_t>(id)) {}
  356 + else if(rdx->processQueuedCommand<vector<string>>(id)) {}
  357 + else if(rdx->processQueuedCommand<std::set<string>>(id)) {}
  358 + else if(rdx->processQueuedCommand<unordered_set<string>>(id)) {}
350 359 else throw runtime_error("Command pointer not found in any queue!");
351 360 }
352 361 }
... ... @@ -416,18 +425,8 @@ bool Redox::del(const string&amp; key) {
416 425 return commandSync("DEL " + key);
417 426 }
418 427  
419   -void Redox::publish(const string topic, const string msg,
420   - function<void(const string&, const string&)> pub_callback,
421   - function<void(const string&, int)> err_callback
422   -) {
423   - command<redisReply*>("PUBLISH " + topic + " " + msg,
424   - [topic, msg, err_callback, pub_callback](Command<redisReply*>& c) {
425   - if(!c.ok()) {
426   - if(err_callback) err_callback(topic, c.status());
427   - }
428   - if(pub_callback) pub_callback(topic, msg);
429   - }
430   - );
  428 +void Redox::publish(const string& topic, const string& msg) {
  429 + command<redisReply*>("PUBLISH " + topic + " " + msg);
431 430 }
432 431  
433 432 } // End namespace redis
... ...
src/redox.hpp
1 1 /**
2   -* Redis C++11 wrapper.
  2 +* Redox - A modern, asynchronous, and wicked fast C++11 client for Redis
  3 +*
  4 +* https://github.com/hmartiro/redox
  5 +*
  6 +* Copyright 2015 - Hayk Martirosyan <hayk.mart at gmail dot com>
  7 +*
  8 +* Licensed under the Apache License, Version 2.0 (the "License");
  9 +* you may not use this file except in compliance with the License.
  10 +* You may obtain a copy of the License at
  11 +*
  12 +* http://www.apache.org/licenses/LICENSE-2.0
  13 +*
  14 +* Unless required by applicable law or agreed to in writing, software
  15 +* distributed under the License is distributed on an "AS IS" BASIS,
  16 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17 +* See the License for the specific language governing permissions and
  18 +* limitations under the License.
3 19 */
4 20  
5 21 #pragma once
... ... @@ -43,7 +59,11 @@ public:
43 59 static const int DISCONNECTED = 2;
44 60 static const int CONNECT_ERROR = 3;
45 61 static const int DISCONNECT_ERROR = 4;
46   -
  62 +
  63 + // ------------------------------------------------
  64 + // Core public API
  65 + // ------------------------------------------------
  66 +
47 67 /**
48 68 * Initializes everything, connects over TCP to a Redis server.
49 69 */
... ... @@ -155,30 +175,15 @@ public:
155 175 bool del(const std::string& key);
156 176  
157 177 /**
158   - * Publish to a topic. All subscribers will be notified.
159   - *
160   - * pub_callback: invoked when successfully published
161   - * err_callback: invoked on some error state
162   - *
163   - * // TODO
  178 + * Redis PUBLISH command wrapper - publish the given message to all subscribers.
  179 + * Non-blocking call.
164 180 */
165   - void publish(const std::string topic, const std::string msg,
166   - std::function<void(const std::string&, const std::string&)> pub_callback = nullptr,
167   - std::function<void(const std::string&, int)> err_callback = nullptr
168   - );
  181 + void publish(const std::string& topic, const std::string& msg);
169 182  
170 183 // ------------------------------------------------
171   - // Public only for Command class
  184 + // Public members
172 185 // ------------------------------------------------
173 186  
174   - // Invoked by Command objects when they are completed
175   - template<class ReplyT>
176   - void remove_active_command(const long id) {
177   - std::lock_guard<std::mutex> lg1(command_map_guard_);
178   - getCommandMap<ReplyT>().erase(id);
179   - commands_deleted_ += 1;
180   - }
181   -
182 187 // Hiredis context, left public to allow low-level access
183 188 redisAsyncContext * ctx_;
184 189  
... ... @@ -194,6 +199,12 @@ public:
194 199  
195 200 private:
196 201  
  202 + // ------------------------------------------------
  203 + // Private methods
  204 + // ------------------------------------------------
  205 +
  206 + // One stop shop for creating commands. The base of all public
  207 + // methods that run commands.
197 208 template<class ReplyT>
198 209 Command<ReplyT>& createCommand(
199 210 const std::string& cmd,
... ... @@ -207,6 +218,56 @@ private:
207 218 void init_ev();
208 219 void init_hiredis();
209 220  
  221 + // Callbacks invoked on server connection/disconnection
  222 + static void connectedCallback(const redisAsyncContext* c, int status);
  223 + static void disconnectedCallback(const redisAsyncContext* c, int status);
  224 +
  225 + // Main event loop, run in a separate thread
  226 + void runEventLoop();
  227 +
  228 + // Return the command map corresponding to the templated reply type
  229 + template<class ReplyT>
  230 + std::unordered_map<long, Command<ReplyT>*>& getCommandMap();
  231 +
  232 + // Return the given Command from the relevant command map, or nullptr if not there
  233 + template<class ReplyT>
  234 + Command<ReplyT>* findCommand(long id);
  235 +
  236 + // Send all commands in the command queue to the server
  237 + static void processQueuedCommands(struct ev_loop* loop, ev_async* async, int revents);
  238 +
  239 + // Process the command with the given ID. Return true if the command had the
  240 + // templated type, and false if it was not in the map of that type.
  241 + template<class ReplyT>
  242 + bool processQueuedCommand(long id);
  243 +
  244 + // Callback given to libev for a Command's timer watcher, to be processed in
  245 + // a deferred or looping state
  246 + template<class ReplyT>
  247 + static void submitCommandCallback(struct ev_loop* loop, ev_timer* timer, int revents);
  248 +
  249 + // Submit an asynchronous command to the Redox server. Return
  250 + // true if succeeded, false otherwise.
  251 + template<class ReplyT>
  252 + static bool submitToServer(Command<ReplyT>* c);
  253 +
  254 + // Callback given to hiredis to invoke when a reply is received
  255 + template<class ReplyT>
  256 + static void commandCallback(redisAsyncContext* ctx, void* r, void* privdata);
  257 +
  258 + // Invoked by Command objects when they are completed. Removes them
  259 + // from the command map.
  260 + template<class ReplyT>
  261 + void remove_active_command(const long id) {
  262 + std::lock_guard<std::mutex> lg1(command_map_guard_);
  263 + getCommandMap<ReplyT>().erase(id);
  264 + commands_deleted_ += 1;
  265 + }
  266 +
  267 + // ------------------------------------------------
  268 + // Private members
  269 + // ------------------------------------------------
  270 +
210 271 // Manage connection state
211 272 std::atomic_int connect_state_ = {NOT_YET_CONNECTED};
212 273 std::mutex connect_lock_;
... ... @@ -258,47 +319,27 @@ private:
258 319 std::unordered_map<long, Command<std::unordered_set<std::string>>*> commands_unordered_set_string_;
259 320 std::mutex command_map_guard_; // Guards access to all of the above
260 321  
261   - // Return the correct map from the above, based on the template specialization
262   - template<class ReplyT>
263   - std::unordered_map<long, Command<ReplyT>*>& getCommandMap();
264   -
265   - // Return the given Command from the relevant command map, or nullptr if not there
266   - template<class ReplyT>
267   - Command<ReplyT>* findCommand(long id);
268   -
269   - std::queue<long> command_queue;
270   - std::mutex queue_guard;
271   - static void proccessQueuedCommands(struct ev_loop* loop, ev_async* async, int revents);
  322 + // Command IDs pending to be sent to the server
  323 + std::queue<long> command_queue_;
  324 + std::mutex queue_guard_;
272 325  
  326 + // Commands use this method to deregister themselves from Redox,
  327 + // give it access to private members
273 328 template<class ReplyT>
274   - bool proccessQueuedCommand(long id);
275   -
276   - void runEventLoop();
277   -
278   - // Callbacks invoked on server connection/disconnection
279   - static void connectedCallback(const redisAsyncContext* c, int status);
280   - static void disconnectedCallback(const redisAsyncContext* c, int status);
281   -
282   - template<class ReplyT>
283   - static void commandCallback(redisAsyncContext* ctx, void* r, void* privdata);
284   -
285   - template<class ReplyT>
286   - static bool submitToServer(Command<ReplyT>* c);
287   -
288   - template<class ReplyT>
289   - static void submitCommandCallback(struct ev_loop* loop, ev_timer* timer, int revents);
290   -
  329 + friend void Command<ReplyT>::freeCommand(Command<ReplyT>* c);
291 330 };
292 331  
293   -// ---------------------------
  332 +// ------------------------------------------------
  333 +// Implementation of templated methods
  334 +// ------------------------------------------------
294 335  
295 336 template<class ReplyT>
296 337 Command<ReplyT>& Redox::createCommand(
297   - const std::string& cmd,
298   - const std::function<void(Command<ReplyT>&)>& callback,
299   - double repeat,
300   - double after,
301   - bool free_memory
  338 + const std::string& cmd,
  339 + const std::function<void(Command<ReplyT>&)>& callback,
  340 + double repeat,
  341 + double after,
  342 + bool free_memory
302 343 ) {
303 344  
304 345 if(!running_) {
... ... @@ -306,20 +347,20 @@ Command&lt;ReplyT&gt;&amp; Redox::createCommand(
306 347 }
307 348  
308 349 commands_created_ += 1;
309   - auto* c = new Command<ReplyT>(this, commands_created_, cmd,
310   - callback, repeat, after, free_memory, logger_);
  350 + auto* c = new Command<ReplyT>(
  351 + this, commands_created_, cmd,
  352 + callback, repeat, after, free_memory, logger_
  353 + );
311 354  
312   - std::lock_guard<std::mutex> lg(queue_guard);
  355 + std::lock_guard<std::mutex> lg(queue_guard_);
313 356 std::lock_guard<std::mutex> lg2(command_map_guard_);
314 357  
315 358 getCommandMap<ReplyT>()[c->id_] = c;
316   - command_queue.push(c->id_);
  359 + command_queue_.push(c->id_);
317 360  
318 361 // Signal the event loop to process this command
319 362 ev_async_send(evloop_, &watcher_command_);
320 363  
321   -// logger.debug() << "Created Command " << c->id << " at " << c;
322   -
323 364 return *c;
324 365 }
325 366  
... ...
src/subscriber.cpp
1 1 /**
2   -* Redis C++11 wrapper.
  2 +* Redox - A modern, asynchronous, and wicked fast C++11 client for Redis
  3 +*
  4 +* https://github.com/hmartiro/redox
  5 +*
  6 +* Copyright 2015 - Hayk Martirosyan <hayk.mart at gmail dot com>
  7 +*
  8 +* Licensed under the Apache License, Version 2.0 (the "License");
  9 +* you may not use this file except in compliance with the License.
  10 +* You may obtain a copy of the License at
  11 +*
  12 +* http://www.apache.org/licenses/LICENSE-2.0
  13 +*
  14 +* Unless required by applicable law or agreed to in writing, software
  15 +* distributed under the License is distributed on an "AS IS" BASIS,
  16 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17 +* See the License for the specific language governing permissions and
  18 +* limitations under the License.
3 19 */
4 20  
5 21 #include <string.h>
... ...
src/subscriber.hpp
1 1 /**
2   -* Redis C++11 wrapper.
  2 +* Redox - A modern, asynchronous, and wicked fast C++11 client for Redis
  3 +*
  4 +* https://github.com/hmartiro/redox
  5 +*
  6 +* Copyright 2015 - Hayk Martirosyan <hayk.mart at gmail dot com>
  7 +*
  8 +* Licensed under the Apache License, Version 2.0 (the "License");
  9 +* you may not use this file except in compliance with the License.
  10 +* You may obtain a copy of the License at
  11 +*
  12 +* http://www.apache.org/licenses/LICENSE-2.0
  13 +*
  14 +* Unless required by applicable law or agreed to in writing, software
  15 +* distributed under the License is distributed on an "AS IS" BASIS,
  16 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17 +* See the License for the specific language governing permissions and
  18 +* limitations under the License.
3 19 */
4 20  
5 21 #pragma once
... ...
test/test.cpp
1 1 /**
2   -* Test suite for Redox using GTest.
  2 +* Redox - A modern, asynchronous, and wicked fast C++11 client for Redis
  3 +*
  4 +* https://github.com/hmartiro/redox
  5 +*
  6 +* Copyright 2015 - Hayk Martirosyan <hayk.mart@gmail.com>
  7 +*
  8 +* Licensed under the Apache License, Version 2.0 (the "License");
  9 +* you may not use this file except in compliance with the License.
  10 +* You may obtain a copy of the License at
  11 +*
  12 +* http://www.apache.org/licenses/LICENSE-2.0
  13 +*
  14 +* Unless required by applicable law or agreed to in writing, software
  15 +* distributed under the License is distributed on an "AS IS" BASIS,
  16 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17 +* See the License for the specific language governing permissions and
  18 +* limitations under the License.
3 19 */
4 20  
5 21 #include <iostream>
... ...