Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ else()
set(datadir data)
endif()

if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR lib${LIB_SUFFIX})
endif(NOT DEFINED CMAKE_INSTALL_LIBDIR)

set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix ${CMAKE_INSTALL_PREFIX})
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
Expand Down Expand Up @@ -61,10 +65,6 @@ install (DIRECTORY "${CMAKE_SOURCE_DIR}/include/${PROJECT_NAME}" DESTINATION inc
set_target_properties(${PROJECT_NAME}-static PROPERTIES COMPILE_DEFINITIONS_RELEASE "DATADIR=\"${datadir}\"")
set_target_properties(${PROJECT_NAME}-static PROPERTIES COMPILE_DEFINITIONS_DEBUG "DATADIR=\"${CMAKE_SOURCE_DIR}/data\"")

if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR lib${LIB_SUFFIX})
endif(NOT DEFINED CMAKE_INSTALL_LIBDIR)

install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" DESTINATION ${libdir}/pkgconfig)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/data/lua" DESTINATION ${datadir})

Expand Down
2 changes: 1 addition & 1 deletion examples/ha_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ using namespace redis3m;

int main(int argc, char **argv)
{
connection_pool::ptr_t pool = connection_pool::create("<yoursentinel>", "test");
connection_pool::ptr_t pool = connection_pool::create_timeout("sentinel1,sentinel2,sentinel3", "test", 26379, 1, 500000); //1 sec + 500000 usec [1.5 sec] timeout

connection::ptr_t c = pool->get(connection::MASTER);
c->run(command("SET") << "foo" << "bar");
Expand Down
23 changes: 23 additions & 0 deletions include/redis3m/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <redis3m/reply.h>
#include <vector>
#include <memory>
#include <sys/time.h>

struct redisContext;

Expand All @@ -26,6 +27,20 @@ class connection: utils::noncopyable
public:
typedef std::shared_ptr<connection> ptr_t;

/**
* @brief Create and open a new connection with Timeout
* @param host hostname or ip of redis server, default localhost
* @param port port of redis server, default: 6379
* @param timeval timeout interval struct, default: 1 second
* @return
*/
inline static ptr_t create_timeout(const std::string& host="localhost",
const unsigned int port=6379,
const struct timeval timeout=defaultTimeout())

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency with the rest of the project, I'd like create_timeout instead of createTimeout. So underscore syntax. Is it a problem for you?

Also, why not using std::chrono time intervals instead of struct timeval? Could it be more C++11 friendly?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I can change to create_timeout.

I used struct timeval because that what is used by hiredis redisConnectWithTimeout
struct timeval timeout = { 1, 500000 }; // 1.5 seconds c = redisConnectWithTimeout(hostname, port, timeout);

{
return ptr_t(new connection(host, port, timeout));
}

/**
* @brief Create and open a new connection
* @param host hostname or ip of redis server, default localhost
Expand Down Expand Up @@ -99,10 +114,18 @@ class connection: utils::noncopyable

private:
friend class connection_pool;
connection(const std::string& host, const unsigned port, const struct timeval timeout);
connection(const std::string& host, const unsigned int port);
connection(const std::string& path);

role_t _role;
redisContext *c;

static timeval defaultTimeout(){
struct timeval to;
to.tv_sec = 1;
to.tv_usec = 0;
return to;
}
};
}
26 changes: 26 additions & 0 deletions include/redis3m/connection_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ namespace redis3m {
public:
typedef std::shared_ptr<connection_pool> ptr_t;

/**
* @brief Create a new connection_pool with Timeout
* @param sentinel_host Can be a single host or a list separate by commas,
* if an host has multiple IPs, connection_pool tries all of them
* @param master_name Master to lookup
* @param sentinel_port Sentinel port, default 26379
* @param to_sec Timeout seconds, default 1
* @param to_usec Timeout microseconds, default 0
* @return
*/
static inline ptr_t create_timeout(const std::string& sentinel_host,
const std::string& master_name,
unsigned int sentinel_port=26379,
time_t to_sec=1,
long int to_usec=0)
{
return ptr_t(new connection_pool(sentinel_host, master_name, sentinel_port, to_sec, to_usec));
}

/**
* @brief Create a new connection_pool
* @param sentinel_host Can be a single host or a list separate by commas,
Expand Down Expand Up @@ -105,6 +124,11 @@ namespace redis3m {
inline void set_password(const std::string& value) { password = value; }

private:
connection_pool(const std::string& sentinel_host,
const std::string& master_name,
unsigned int sentinel_port,
time_t to_sec,
long int to_usec);
connection_pool(const std::string& sentinel_host,
const std::string& master_name,
unsigned int sentinel_port);
Expand All @@ -119,6 +143,8 @@ namespace redis3m {

std::vector<std::string> sentinel_hosts;
unsigned int sentinel_port;
time_t to_sec;
long int to_usec;
std::string master_name;
std::string password;
unsigned int _database;
Expand Down
55 changes: 55 additions & 0 deletions redis3m.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Name: redis3m
Version: 2.0
Release: 1%{?dist}
Summary: A C++ Redis client
Group: System Environment/Libraries
License: Apache 2.0
URL: https://github.com/luca3m/redis3m
Source: redis3m-master.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Packager: Alexander Hurd <hurdad@gmail.com>

%description
A C++ Redis client

%package devel
Summary: Development files for %{name}
Group: Development/Libraries

%description devel
The %{name}-devel package contains libraries and header files for
developing applications that use %{name}.

%prep
%setup -q -n redis3m-master

%build
cmake -DCMAKE_INSTALL_PREFIX=/usr -DLIB_SUFFIX=64 .
make %{?_smp_mflags}

%install
make install DESTDIR=%{buildroot}

%post
ldconfig

%postun
ldconfig

%clean
%{__rm} -rf %{buildroot}

%files
%defattr(-,root,root,-)
%{_datadir}/
%{_libdir}/*.so.*

%files devel
%defattr(-,root,root,-)
%{_includedir}/redis3m
%{_libdir}/*.so
%{_libdir}/pkgconfig/redis3m.pc

%changelog
* Mon Apr 4 2016 Alexander Hurd <hurdad@gmail.com> 1.0.1-1
- Initial specfile writeup.
10 changes: 10 additions & 0 deletions src/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@

using namespace redis3m;

connection::connection(const std::string& host, const unsigned port, const struct timeval timeout)
{
c = redisConnectWithTimeout(host.c_str(), port, timeout);
if (c->err != REDIS_OK)
{
redisFree(c);
throw unable_to_connect();
}
}

connection::connection(const std::string& host, const unsigned port)
{
c = redisConnect(host.c_str(), port);
Expand Down
65 changes: 50 additions & 15 deletions src/connection_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,49 @@

using namespace redis3m;

connection_pool::connection_pool(const std::string& sentinel_host,
const std::string& master_name,
unsigned int sentinel_port,
time_t to_sec,
long int to_usec):
master_name(master_name),
sentinel_port(sentinel_port),
to_sec(to_sec),
to_usec(to_usec),
password(""),
_database(0)
{
#ifndef NO_BOOST
boost::algorithm::split(sentinel_hosts, sentinel_host, boost::is_any_of(","), boost::token_compress_on);
#else //http://stackoverflow.com/questions/5167625/splitting-a-c-stdstring-using-tokens-e-g
std::string s;
std::istringstream f(sentinel_host.c_str());
while (std::getline(f, s, ',')) {
std::cout << s << std::endl;
sentinel_hosts.push_back(s);
}
#endif
}

connection_pool::connection_pool(const std::string& sentinel_host,
const std::string& master_name,
unsigned int sentinel_port):
master_name(master_name),
sentinel_port(sentinel_port),
to_sec(-1),
to_usec(-1),
password(""),
_database(0)
{
#ifndef NO_BOOST
boost::algorithm::split(sentinel_hosts, sentinel_host, boost::is_any_of(","), boost::token_compress_on);
#else //http://stackoverflow.com/questions/5167625/splitting-a-c-stdstring-using-tokens-e-g
std::string s;
std::istringstream f(sentinel_host.c_str());
while (std::getline(f, s, ',')) {
std::cout << s << std::endl;
sentinel_hosts.push_back(s);
}
std::string s;
std::istringstream f(sentinel_host.c_str());
while (std::getline(f, s, ',')) {
std::cout << s << std::endl;
sentinel_hosts.push_back(s);
}
#endif
}

Expand Down Expand Up @@ -148,7 +174,16 @@ connection::ptr_t connection_pool::sentinel_connection()
#endif
try
{
return connection::create(real_sentinel, sentinel_port);
if(to_usec >= 0 && to_sec >= 0){ //check for valid timeout values
struct timeval to;
to.tv_sec = to_sec;
to.tv_usec = to_usec;
return connection::create_timeout(real_sentinel, sentinel_port, to);
}
else
{
return connection::create(real_sentinel, sentinel_port); //normal connection
}
} catch (const unable_to_connect& )
{
#ifndef NO_BOOST
Expand All @@ -164,33 +199,33 @@ connection::ptr_t connection_pool::sentinel_connection()

connection::role_t connection_pool::get_role(connection::ptr_t conn)
{
static const
static const
#ifndef NO_BOOST
boost::regex
#else
std::regex
std::regex
#endif
role_searcher("\r\nrole:([a-z]+)\r\n");
role_searcher("\r\nrole:([a-z]+)\r\n");

reply r = conn->run(command("ROLE"));
std::string role_s;

if (r.type() == reply::type_t::ERROR
#ifndef NO_BOOST
&& boost::algorithm::find_first(r.str(),"unknown"))
&& boost::algorithm::find_first(r.str(),"unknown"))
#else
&& (r.str().find("unknown") != std::string::npos) )
&& (r.str().find("unknown") != std::string::npos) )
#endif
{
logging::debug("Old redis, doesn't support ROLE command");
reply r = conn->run(command("INFO") << "replication");
#ifndef NO_BOOST
boost::smatch results;
if (boost::regex_search(r.str(), results, role_searcher))
#else
std::smatch results;
if (std::regex_search(r.str(), results, role_searcher))
std::smatch results;
if (std::regex_search(r.str(), results, role_searcher))
#endif
{
role_s = results[1];
Expand Down