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

Commit d6a3473

Browse files
committed
Add implementation for the CLIENT KILL command
1 parent 2cd18b5 commit d6a3473

File tree

4 files changed

+224
-3
lines changed

4 files changed

+224
-3
lines changed

includes/cpp_redis/future_client.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ class future_client {
9393
future blpop(const std::vector<std::string>& keys, int timeout);
9494
future brpop(const std::vector<std::string>& keys, int timeout);
9595
future brpoplpush(const std::string& src, const std::string& dst, int timeout);
96-
// future client_kill() [ip:port] [id client-id] [type normal|master|slave|pubsub] [addr ip:port] [skipme yes/no]
96+
template <typename T, typename... Ts>
97+
future client_kill(const T&, const Ts&...);
9798
future client_list();
9899
future client_getname();
99100
future client_pause(int timeout);
@@ -305,4 +306,11 @@ class future_client {
305306
redis_client m_client;
306307
};
307308

309+
310+
template <typename T, typename... Ts>
311+
future_client::future
312+
future_client::client_kill(const T& arg, const Ts&... args) {
313+
return exec_cmd([=](const rcb_t& cb) -> rc& { return m_client.client_kill(arg, args..., cb); });
314+
}
315+
308316
} //! cpp_redis
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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+
#pragma once
24+
25+
#include <type_traits>
26+
27+
namespace cpp_redis {
28+
namespace helpers {
29+
30+
template <typename T, typename... Args>
31+
struct back {
32+
using type = typename back<Args...>::type;
33+
};
34+
35+
template <typename T>
36+
struct back<T> {
37+
using type = T;
38+
};
39+
40+
template <typename T, typename... Ts>
41+
struct front {
42+
using type = T;
43+
};
44+
45+
template <typename T1, typename T2, typename... Ts>
46+
struct is_type_present {
47+
static constexpr bool value = std::is_same<T1, T2>::value
48+
? true
49+
: is_type_present<T1, Ts...>::value;
50+
};
51+
52+
template <typename T1, typename T2>
53+
struct is_type_present<T1, T2> {
54+
static constexpr bool value = std::is_same<T1, T2>::value;
55+
};
56+
57+
template <typename T, typename... Args>
58+
struct is_different_types {
59+
static constexpr bool value = is_type_present<T, Args...>::value
60+
? false
61+
: is_different_types<Args...>::value;
62+
};
63+
64+
template <typename T1>
65+
struct is_different_types<T1> {
66+
static constexpr bool value = true;
67+
};
68+
} //! helpers
69+
} //! cpp_redis

includes/cpp_redis/redis_client.hpp

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@
3030
#include <string>
3131
#include <vector>
3232

33+
#include <cpp_redis/helpers/variadic_template.hpp>
3334
#include <cpp_redis/logger.hpp>
3435
#include <cpp_redis/network/redis_connection.hpp>
3536
#include <cpp_redis/network/tcp_client_iface.hpp>
37+
#include <cpp_redis/special_command/client_kill_impl.hpp>
3638

3739
namespace cpp_redis {
3840

39-
class redis_client {
41+
class redis_client : public client_kill {
4042
public:
4143
//! ctor & dtor
4244
#ifndef __CPP_REDIS_USE_CUSTOM_TCP_CLIENT
@@ -94,7 +96,13 @@ class redis_client {
9496
redis_client& blpop(const std::vector<std::string>& keys, int timeout, const reply_callback_t& reply_callback = nullptr);
9597
redis_client& brpop(const std::vector<std::string>& keys, int timeout, const reply_callback_t& reply_callback = nullptr);
9698
redis_client& brpoplpush(const std::string& src, const std::string& dst, int timeout, const reply_callback_t& reply_callback = nullptr);
97-
// redis_client& client_kill(const reply_callback_t& reply_callback = nullptr) [ip:port] [id client-id] [type normal|master|slave|pubsub] [addr ip:port] [skipme yes/no]
99+
template <typename T, typename... Ts>
100+
redis_client& client_kill(const std::string& host, int port, const T& arg, const Ts&... args);
101+
redis_client& client_kill(const std::string& host, int port);
102+
template <typename... Ts>
103+
redis_client& client_kill(const char* host, int port, const Ts&... args);
104+
template <typename T, typename... Ts>
105+
redis_client& client_kill(const T&, const Ts&...);
98106
redis_client& client_list(const reply_callback_t& reply_callback = nullptr);
99107
redis_client& client_getname(const reply_callback_t& reply_callback = nullptr);
100108
redis_client& client_pause(int timeout, const reply_callback_t& reply_callback = nullptr);
@@ -332,4 +340,47 @@ class redis_client {
332340
std::atomic<unsigned int> m_callbacks_running = ATOMIC_VAR_INIT(0);
333341
};
334342

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+
}
385+
335386
} //! cpp_redis
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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+
#pragma once
24+
25+
#include <functional>
26+
#include <iostream>
27+
28+
namespace cpp_redis {
29+
class client_kill {
30+
31+
public:
32+
enum class type {
33+
normal,
34+
master,
35+
pubsub,
36+
slave
37+
};
38+
39+
private:
40+
using CB = std::function<void(cpp_redis::reply&)>;
41+
42+
template <typename T>
43+
typename std::enable_if<std::is_same<T, type>::value>::type
44+
client_kill_unpack_arg(std::vector<std::string>& redis_cmd, CB& /* */, type type) {
45+
redis_cmd.emplace_back("TYPE");
46+
std::string type_string;
47+
48+
switch (type) {
49+
case client_kill::type::normal: type_string = "normal"; break;
50+
case client_kill::type::master: type_string = "master"; break;
51+
case client_kill::type::pubsub: type_string = "pubsub"; break;
52+
case client_kill::type::slave: type_string = "slave"; break;
53+
}
54+
55+
redis_cmd.emplace_back(type_string);
56+
}
57+
58+
template <typename T>
59+
typename std::enable_if<std::is_same<T, bool>::value>::type
60+
client_kill_unpack_arg(std::vector<std::string>& redis_cmd, CB& /* */, bool skip) {
61+
redis_cmd.emplace_back("SKIPME");
62+
redis_cmd.emplace_back(skip ? "yes" : "no");
63+
}
64+
65+
template <typename T>
66+
typename std::enable_if<std::is_integral<T>::value>::type
67+
client_kill_unpack_arg(std::vector<std::string>& redis_cmd, CB& /* */, uint64_t id) {
68+
redis_cmd.emplace_back("ID");
69+
redis_cmd.emplace_back(std::to_string(id));
70+
}
71+
72+
template <typename T>
73+
typename std::enable_if<std::is_class<T>::value>::type
74+
client_kill_unpack_arg(std::vector<std::string>& /* */, CB& reply_callback, const T& cb) {
75+
reply_callback = cb;
76+
}
77+
78+
protected:
79+
template <typename T, typename... Ts>
80+
void
81+
client_kill_impl(std::vector<std::string>& redis_cmd, CB& reply, const T& arg, const Ts&... args) {
82+
static_assert(!std::is_class<T>::value, "Reply callback should be in the end of the argument list");
83+
client_kill_unpack_arg<T>(redis_cmd, reply, arg);
84+
client_kill_impl(redis_cmd, reply, args...);
85+
};
86+
87+
template <typename T>
88+
void
89+
client_kill_impl(std::vector<std::string>& redis_cmd, CB& reply, const T& arg) {
90+
client_kill_unpack_arg<T>(redis_cmd, reply, arg);
91+
};
92+
};
93+
} //! cpp_redis

0 commit comments

Comments
 (0)