Skip to content
This repository was archived by the owner on Apr 6, 2019. It is now read-only.

Commit fb9675e

Browse files
author
Simon Ninon
committed
Clang-Format, code style consistency and move .hpp into ipp to remove inheritance.
1 parent ce29703 commit fb9675e

File tree

7 files changed

+266
-143
lines changed

7 files changed

+266
-143
lines changed

examples/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,6 @@ target_link_libraries(cpp_redis_subscriber cpp_redis)
5454

5555
add_executable(cpp_redis_logger logger.cpp)
5656
target_link_libraries(cpp_redis_logger cpp_redis)
57+
58+
add_executable(kill_client kill_client.cpp)
59+
target_link_libraries(kill_client cpp_redis)

examples/kill_client.cpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// The MIT License (MIT)
2+
//
3+
// Copyright (c) 2015-2017 Simon Ninon <[email protected]>
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
#include <cpp_redis/cpp_redis>
24+
25+
#include <iostream>
26+
#include <sstream>
27+
28+
#ifdef _WIN32
29+
#include <Winsock2.h>
30+
#endif /* _WIN32 */
31+
32+
int
33+
main(void) {
34+
#ifdef _WIN32
35+
//! Windows netword DLL init
36+
WORD version = MAKEWORD(2, 2);
37+
WSADATA data;
38+
39+
if (WSAStartup(version, &data) != 0) {
40+
std::cerr << "WSAStartup() failure" << std::endl;
41+
return -1;
42+
}
43+
#endif /* _WIN32 */
44+
45+
cpp_redis::redis_client client;
46+
47+
client.connect("127.0.0.1", 6379, [](cpp_redis::redis_client&) {
48+
std::cout << "client disconnected (disconnection handler)" << std::endl;
49+
});
50+
51+
//! client kill ip:port
52+
client.client_list([&client](cpp_redis::reply& reply) {
53+
std::string addr;
54+
std::stringstream ss(reply.as_string());
55+
56+
ss >> addr >> addr;
57+
58+
std::string host = std::string(addr.begin() + addr.find('=') + 1, addr.begin() + addr.find(':'));
59+
int port = std::stoi(std::string(addr.begin() + addr.find(':') + 1, addr.end()));
60+
61+
client.client_kill(host, port, [](cpp_redis::reply& reply) {
62+
std::cout << reply << std::endl; //! OK
63+
});
64+
65+
client.commit();
66+
});
67+
68+
client.sync_commit();
69+
std::this_thread::sleep_for(std::chrono::seconds(1));
70+
71+
if (not client.is_connected()) {
72+
client.connect("127.0.0.1", 6379, [](cpp_redis::redis_client&) {
73+
std::cout << "client disconnected (disconnection handler)" << std::endl;
74+
});
75+
}
76+
77+
//! client kill filter
78+
client.client_list([&client](cpp_redis::reply& reply) {
79+
std::string id_str;
80+
std::stringstream ss(reply.as_string());
81+
82+
ss >> id_str;
83+
84+
uint64_t id = std::stoi(std::string(id_str.begin() + id_str.find('=') + 1, id_str.end()));
85+
client.client_kill(id, false, cpp_redis::redis_client::type::normal, [](cpp_redis::reply& reply) {
86+
std::cout << reply << std::endl; //! 1
87+
});
88+
89+
client.commit();
90+
});
91+
92+
client.sync_commit();
93+
std::this_thread::sleep_for(std::chrono::seconds(1));
94+
95+
#ifdef _WIN32
96+
WSACleanup();
97+
#endif /* _WIN32 */
98+
99+
return 0;
100+
}

includes/cpp_redis/future_client.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,12 @@ template <typename T, typename... Ts>
311311
future_client::future
312312
future_client::client_kill(const T arg, const Ts... args) {
313313

314-
/** gcc 4.8 doesn't handle variadic template capture arguments (appears in 4.9), so std::bind should capture all arguments
315-
* because of the compiler.
316-
*/
314+
//! gcc 4.8 doesn't handle variadic template capture arguments (appears in 4.9)
315+
//! so std::bind should capture all arguments because of the compiler.
317316
return exec_cmd(std::bind([this](T arg, Ts... args, const rcb_t& cb) -> rc& {
318317
return m_client.client_kill(arg, args..., cb);
319318
},
320319
arg, args..., std::placeholders::_1));
321320
}
322321

323-
} //! cpp_redis
322+
} // namespace cpp_redis
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// The MIT License (MIT)
2+
//
3+
// Copyright (c) 2015-2017 Simon Ninon <[email protected]>
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
#include <functional>
24+
#include <iostream>
25+
26+
namespace cpp_redis {
27+
28+
template <typename T>
29+
typename std::enable_if<std::is_same<T, enum redis_client::type>::value>::type
30+
redis_client::client_kill_unpack_arg(std::vector<std::string>& redis_cmd, reply_callback_t&, enum type type) {
31+
redis_cmd.emplace_back("TYPE");
32+
std::string type_string;
33+
34+
switch (type) {
35+
case type::normal: type_string = "normal"; break;
36+
case type::master: type_string = "master"; break;
37+
case type::pubsub: type_string = "pubsub"; break;
38+
case type::slave: type_string = "slave"; break;
39+
}
40+
41+
redis_cmd.emplace_back(type_string);
42+
}
43+
44+
template <typename T>
45+
typename std::enable_if<std::is_same<T, bool>::value>::type
46+
redis_client::client_kill_unpack_arg(std::vector<std::string>& redis_cmd, reply_callback_t&, bool skip) {
47+
redis_cmd.emplace_back("SKIPME");
48+
redis_cmd.emplace_back(skip ? "yes" : "no");
49+
}
50+
51+
template <typename T>
52+
typename std::enable_if<std::is_integral<T>::value>::type
53+
redis_client::client_kill_unpack_arg(std::vector<std::string>& redis_cmd, reply_callback_t&, uint64_t id) {
54+
redis_cmd.emplace_back("ID");
55+
redis_cmd.emplace_back(std::to_string(id));
56+
}
57+
58+
template <typename T>
59+
typename std::enable_if<std::is_class<T>::value>::type
60+
redis_client::client_kill_unpack_arg(std::vector<std::string>&, reply_callback_t& reply_callback, const T& cb) {
61+
reply_callback = cb;
62+
}
63+
64+
template <typename T, typename... Ts>
65+
void
66+
redis_client::client_kill_impl(std::vector<std::string>& redis_cmd, reply_callback_t& reply, const T& arg, const Ts&... args) {
67+
static_assert(!std::is_class<T>::value, "Reply callback should be in the end of the argument list");
68+
client_kill_unpack_arg<T>(redis_cmd, reply, arg);
69+
client_kill_impl(redis_cmd, reply, args...);
70+
};
71+
72+
template <typename T>
73+
void
74+
redis_client::client_kill_impl(std::vector<std::string>& redis_cmd, reply_callback_t& reply, const T& arg) {
75+
client_kill_unpack_arg<T>(redis_cmd, reply, arg);
76+
};
77+
78+
template <typename T, typename... Ts>
79+
inline redis_client&
80+
redis_client::client_kill(const T& arg, const Ts&... args) {
81+
static_assert(helpers::is_different_types<T, Ts...>::value, "Should only have one distinct value per filter type");
82+
static_assert(!(std::is_class<T>::value && std::is_same<T, typename helpers::back<T, Ts...>::type>::value), "Should have at least one filter");
83+
84+
std::vector<std::string> redis_cmd({"CLIENT", "KILL"});
85+
reply_callback_t reply_cb = nullptr;
86+
client_kill_impl<T, Ts...>(redis_cmd, reply_cb, arg, args...);
87+
88+
return send(redis_cmd, reply_cb);
89+
}
90+
91+
template <typename T, typename... Ts>
92+
inline redis_client&
93+
redis_client::client_kill(const std::string& host, int port, const T& arg, const Ts&... args) {
94+
static_assert(helpers::is_different_types<T, Ts...>::value, "Should only have one distinct value per filter type");
95+
std::vector<std::string> redis_cmd({"CLIENT", "KILL"});
96+
97+
//! If we have other type than lambda, then it's a filter
98+
if (!std::is_class<T>::value) {
99+
redis_cmd.emplace_back("ADDR");
100+
}
101+
102+
redis_cmd.emplace_back(host + ":" + std::to_string(port));
103+
reply_callback_t reply_cb = nullptr;
104+
client_kill_impl<T, Ts...>(redis_cmd, reply_cb, arg, args...);
105+
106+
return send(redis_cmd, reply_cb);
107+
}
108+
109+
inline redis_client&
110+
redis_client::client_kill(const std::string& host, int port) {
111+
return client_kill(host, port, reply_callback_t(nullptr));
112+
}
113+
114+
template <typename... Ts>
115+
inline redis_client&
116+
redis_client::client_kill(const char* host, int port, const Ts&... args) {
117+
return client_kill(std::string(host), port, args...);
118+
}
119+
120+
} // namespace cpp_redis

includes/cpp_redis/network/tcp_client_iface.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222

2323
#pragma once
2424

25+
#include <cstdint>
2526
#include <functional>
2627
#include <string>
2728
#include <vector>
28-
#include <cstdint>
2929

3030
namespace cpp_redis {
3131

includes/cpp_redis/redis_client.hpp

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,10 @@
3434
#include <cpp_redis/logger.hpp>
3535
#include <cpp_redis/network/redis_connection.hpp>
3636
#include <cpp_redis/network/tcp_client_iface.hpp>
37-
#include <cpp_redis/special_command/client_kill_impl.hpp>
3837

3938
namespace cpp_redis {
4039

41-
class redis_client : public client_kill {
40+
class redis_client {
4241
public:
4342
//! ctor & dtor
4443
#ifndef __CPP_REDIS_USE_CUSTOM_TCP_CLIENT
@@ -51,6 +50,16 @@ class redis_client : public client_kill {
5150
redis_client(const redis_client&) = delete;
5251
redis_client& operator=(const redis_client&) = delete;
5352

53+
public:
54+
//! client type
55+
//! used for client kill
56+
enum class type {
57+
normal,
58+
master,
59+
pubsub,
60+
slave
61+
};
62+
5463
public:
5564
//! handle connection
5665
typedef std::function<void(redis_client&)> disconnection_handler_t;
@@ -310,6 +319,32 @@ class redis_client : public client_kill {
310319
// redis_client& hscan(const reply_callback_t& reply_callback = nullptr) key cursor [match pattern] [count count]
311320
// redis_client& zscan(const reply_callback_t& reply_callback = nullptr) key cursor [match pattern] [count count]
312321

322+
private:
323+
//! client kill impl
324+
template <typename T>
325+
typename std::enable_if<std::is_same<T, enum type>::value>::type
326+
client_kill_unpack_arg(std::vector<std::string>& redis_cmd, reply_callback_t&, enum type type);
327+
328+
template <typename T>
329+
typename std::enable_if<std::is_same<T, bool>::value>::type
330+
client_kill_unpack_arg(std::vector<std::string>& redis_cmd, reply_callback_t&, bool skip);
331+
332+
template <typename T>
333+
typename std::enable_if<std::is_integral<T>::value>::type
334+
client_kill_unpack_arg(std::vector<std::string>& redis_cmd, reply_callback_t&, uint64_t id);
335+
336+
template <typename T>
337+
typename std::enable_if<std::is_class<T>::value>::type
338+
client_kill_unpack_arg(std::vector<std::string>&, reply_callback_t& reply_callback, const T& cb);
339+
340+
template <typename T, typename... Ts>
341+
void
342+
client_kill_impl(std::vector<std::string>& redis_cmd, reply_callback_t& reply, const T& arg, const Ts&... args);
343+
344+
template <typename T>
345+
void
346+
client_kill_impl(std::vector<std::string>& redis_cmd, reply_callback_t& reply, const T& arg);
347+
313348
private:
314349
//! receive & disconnection handlers
315350
void connection_receive_handler(network::redis_connection&, reply& reply);
@@ -340,47 +375,6 @@ class redis_client : public client_kill {
340375
std::atomic<unsigned int> m_callbacks_running = ATOMIC_VAR_INIT(0);
341376
};
342377

343-
template <typename T, typename... Ts>
344-
inline redis_client&
345-
redis_client::client_kill(const T& arg, const Ts&... args) {
346-
static_assert(helpers::is_different_types<T, Ts...>::value, "Should only have one distinct value per filter type");
347-
static_assert(!(std::is_class<T>::value && std::is_same<T, typename helpers::back<T, Ts...>::type>::value), "Should have at least one filter");
348-
349-
std::vector<std::string> redis_cmd({"CLIENT", "KILL"});
350-
reply_callback_t reply_cb = nullptr;
351-
client_kill_impl<T, Ts...>(redis_cmd, reply_cb, arg, args...);
352-
353-
return send(redis_cmd, reply_cb);
354-
}
355-
356-
template <typename T, typename... Ts>
357-
inline redis_client&
358-
redis_client::client_kill(const std::string& host, int port, const T& arg, const Ts&... args) {
359-
static_assert(helpers::is_different_types<T, Ts...>::value, "Should only have one distinct value per filter type");
360-
std::vector<std::string> redis_cmd({"CLIENT", "KILL"});
361-
362-
/** If we have other type than lambda, then it's a filter
363-
*/
364-
if (!std::is_class<T>::value) {
365-
redis_cmd.emplace_back("ADDR");
366-
}
367-
368-
redis_cmd.emplace_back(host + ":" + std::to_string(port));
369-
reply_callback_t reply_cb = nullptr;
370-
client_kill_impl<T, Ts...>(redis_cmd, reply_cb, arg, args...);
371-
372-
return send(redis_cmd, reply_cb);
373-
}
374-
375-
inline redis_client&
376-
redis_client::client_kill(const std::string& host, int port) {
377-
return client_kill(host, port, reply_callback_t(nullptr));
378-
}
379-
380-
template <typename... Ts>
381-
inline redis_client&
382-
redis_client::client_kill(const char* host, int port, const Ts&... args) {
383-
return client_kill(std::string(host), port, args...);
384-
}
378+
} // namespace cpp_redis
385379

386-
} //! cpp_redis
380+
#include <cpp_redis/impl/redis_client.ipp>

0 commit comments

Comments
 (0)