mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-01 19:37:45 +08:00
add a redis tool for redis cluster
This commit is contained in:
parent
82fb1f34ad
commit
0140b69dd1
@ -458,6 +458,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "redis_client_cluster", "lib
|
||||
{FE724EF7-3763-4E78-BDF5-BCBC075719FD} = {FE724EF7-3763-4E78-BDF5-BCBC075719FD}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "redis_tools", "redis_tools", "{C8535C82-3DCB-472E-9E8F-DA769D9375B1}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "redis_builder", "app\redis_tools\redis_builder\redis_builder_vc2012.vcxproj", "{D90DCF51-E219-4BD8-A032-076335675F58}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{6EC1F44E-6A6A-48E9-B699-D7E89B63C8DC} = {6EC1F44E-6A6A-48E9-B699-D7E89B63C8DC}
|
||||
{B40213C2-507C-4C7F-A6E1-B850C9BDC27B} = {B40213C2-507C-4C7F-A6E1-B850C9BDC27B}
|
||||
{FE724EF7-3763-4E78-BDF5-BCBC075719FD} = {FE724EF7-3763-4E78-BDF5-BCBC075719FD}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{C65ABD0D-658D-4FE6-8221-4400B8387F27}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
changes.txt = changes.txt
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
@ -1537,6 +1551,21 @@ Global
|
||||
{E3280617-6D0D-4639-9014-31BCD4ADFADC}.Template|Win32.ActiveCfg = DebugDll|Win32
|
||||
{E3280617-6D0D-4639-9014-31BCD4ADFADC}.Template|Win32.Build.0 = DebugDll|Win32
|
||||
{E3280617-6D0D-4639-9014-31BCD4ADFADC}.Template|x64.ActiveCfg = DebugDll|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.DebugDll|Win32.ActiveCfg = DebugDll|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.DebugDll|Win32.Build.0 = DebugDll|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.DebugDll|x64.ActiveCfg = DebugDll|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Release|Win32.Build.0 = Release|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Release|x64.ActiveCfg = Release|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Releasedll|Win32.ActiveCfg = ReleaseDll|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Releasedll|Win32.Build.0 = ReleaseDll|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Releasedll|x64.ActiveCfg = ReleaseDll|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Template|Win32.ActiveCfg = DebugDll|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Template|Win32.Build.0 = DebugDll|Win32
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58}.Template|x64.ActiveCfg = DebugDll|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -1602,6 +1631,7 @@ Global
|
||||
{4B58485B-D846-4485-9C5E-7F2304D71701} = {267F658E-44AF-4080-8577-EFCE99A5E030}
|
||||
{D232833B-57A9-4167-B37C-A4594953F93D} = {3CC8D45A-8E3F-4F5C-A7DF-4D8027E4EA9C}
|
||||
{84376B60-FF20-4FD0-967E-C568FC2FBC53} = {3CC8D45A-8E3F-4F5C-A7DF-4D8027E4EA9C}
|
||||
{C8535C82-3DCB-472E-9E8F-DA769D9375B1} = {3CC8D45A-8E3F-4F5C-A7DF-4D8027E4EA9C}
|
||||
{3C74E826-5E72-48A1-9DFD-777F4A7C9E1F} = {D232833B-57A9-4167-B37C-A4594953F93D}
|
||||
{B59C7CB6-5708-4522-B833-CEB160AA4817} = {D232833B-57A9-4167-B37C-A4594953F93D}
|
||||
{2DABFAD1-114B-4F96-9185-DC0C56A3662D} = {C799E376-2F01-4877-AF18-7F3CC8B95792}
|
||||
@ -1623,5 +1653,6 @@ Global
|
||||
{97BC2502-5B1C-44B4-8809-83A268306FA1} = {14531A45-383C-4CCF-870B-B5C867A314F2}
|
||||
{5EA23ADB-6481-4CA1-9C31-7D92036DFD47} = {14531A45-383C-4CCF-870B-B5C867A314F2}
|
||||
{E3280617-6D0D-4639-9014-31BCD4ADFADC} = {14531A45-383C-4CCF-870B-B5C867A314F2}
|
||||
{D90DCF51-E219-4BD8-A032-076335675F58} = {C8535C82-3DCB-472E-9E8F-DA769D9375B1}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
6
app/redis_tools/Makefile
Normal file
6
app/redis_tools/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
all:
|
||||
@(cd redis_builder; make)
|
||||
|
||||
clean:
|
||||
@(cd redis_builder; make clean)
|
5
app/redis_tools/redis_builder/Makefile
Normal file
5
app/redis_tools/redis_builder/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
include ./Makefile.in
|
||||
ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD)
|
||||
EXTLIBS += -L/usr/local/lib -liconv
|
||||
endif
|
||||
PROG = redis_builder
|
113
app/redis_tools/redis_builder/Makefile.in
Normal file
113
app/redis_tools/redis_builder/Makefile.in
Normal file
@ -0,0 +1,113 @@
|
||||
CC = g++
|
||||
|
||||
CFLAGS = -c -g -W -Wall -Wcast-qual -Wcast-align \
|
||||
-Wno-long-long \
|
||||
-Wpointer-arith -Werror -Wshadow -O3 \
|
||||
-D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -D_USE_FAST_MACRO
|
||||
|
||||
###########################################################
|
||||
#Check system:
|
||||
# Linux, SunOS, Solaris, BSD variants, AIX, HP-UX
|
||||
SYSLIB = -lpthread -lcrypt -lz
|
||||
CHECKSYSRES = @echo "Unknow system type!";exit 1
|
||||
UNIXNAME = $(shell uname -sm)
|
||||
OSTYPE = $(shell uname -p)
|
||||
RPATH = linux64
|
||||
|
||||
ifeq ($(CC),)
|
||||
CC = gcc
|
||||
endif
|
||||
|
||||
# For FreeBSD
|
||||
ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD)
|
||||
ifeq ($(findstring gcc, $(CC)), gcc)
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
endif
|
||||
CFLAGS += -DFREEBSD -D_REENTRANT
|
||||
SYSLIB = -lcrypt -lpthread -lz
|
||||
RPATH = freebsd
|
||||
endif
|
||||
|
||||
#Path for Linux
|
||||
ifeq ($(findstring Linux, $(UNIXNAME)), Linux)
|
||||
ifeq ($CC, "gcc")
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
endif
|
||||
ifeq ($(findstring i686, $(OSTYPE)), i686)
|
||||
RPATH = linux32
|
||||
endif
|
||||
ifeq ($(findstring x86_64, $(OSTYPE)), x86_64)
|
||||
RPATH = linux64
|
||||
endif
|
||||
CFLAGS += -DLINUX2 -D_REENTRANT
|
||||
endif
|
||||
|
||||
#Path for SunOS
|
||||
ifeq ($(findstring SunOS, $(UNIXNAME)), SunOS)
|
||||
ifeq ($(findstring 86, $(UNIXNAME)), 86)
|
||||
SYSLIB += -lsocket -lnsl -lrt
|
||||
endif
|
||||
ifeq ($(findstring sun4u, $(UNIXNAME)), sun4u)
|
||||
SYSLIB += -lsocket -lnsl -lrt
|
||||
endif
|
||||
ifeq ($CC, "gcc")
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
endif
|
||||
CFLAGS += -DSUNOS5 -D_REENTRANT
|
||||
RPATH = sunos_x86
|
||||
endif
|
||||
|
||||
#Path for HP-UX
|
||||
ifeq ($(findstring HP-UX, $(UNIXNAME)), HP-UX)
|
||||
ifeq ($CC, "gcc")
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
endif
|
||||
CFLAGS += -DHP_UX -DHPUX11
|
||||
PLAT_NAME=hp-ux
|
||||
endif
|
||||
|
||||
#Find system type.
|
||||
ifneq ($(SYSPATH),)
|
||||
CHECKSYSRES = @echo "System is $(shell uname -sm)"
|
||||
endif
|
||||
###########################################################
|
||||
|
||||
CFLAGS += -I../../../lib_acl/include -I../../../lib_protocol/include \
|
||||
-I../../../lib_acl_cpp/include -I.
|
||||
EXTLIBS =
|
||||
LDFLAGS = -L../../../lib_acl_cpp/lib -l_acl_cpp \
|
||||
-L../../../lib_protocol/lib -l_protocol \
|
||||
-L../../../lib_acl/lib -l_acl \
|
||||
$(EXTLIBS) $(SYSLIB) -rdynamic
|
||||
|
||||
COMPILE = $(CC) $(CFLAGS)
|
||||
LINK = $(CC) $(OBJ) $(LDFLAGS)
|
||||
###########################################################
|
||||
OBJ_PATH = .
|
||||
|
||||
#Project's objs
|
||||
SRC = $(wildcard *.cpp) $(wildcard pull_mode/*.cpp) $(wildcard push_mode/*.cpp)
|
||||
OBJ = $(patsubst %.cpp, $(OBJ_PATH)/%.o, $(notdir $(SRC)))
|
||||
|
||||
$(OBJ_PATH)/%.o: %.cpp
|
||||
$(COMPILE) $< -o $@
|
||||
$(OBJ_PATH)/%.o: pull_mode/%.cpp
|
||||
$(COMPILE) $< -o $@
|
||||
$(OBJ_PATH)/%.o: push_mode/%.cpp
|
||||
$(COMPILE) $< -o $@
|
||||
|
||||
.PHONY = all clean
|
||||
all: RM $(OBJ)
|
||||
$(LINK) -o $(PROG)
|
||||
@echo ""
|
||||
@echo "All ok! Output:$(PROG)"
|
||||
@echo ""
|
||||
RM:
|
||||
rm -f $(PROG)
|
||||
clean:
|
||||
rm -f $(PROG)
|
||||
rm -f $(OBJ)
|
||||
install:
|
||||
cp $(PROG) ../../../dist/master/libexec/$(RPATH)/
|
||||
cp $(PROG).cf ../../../dist/master/conf/service/
|
||||
###########################################################
|
47
app/redis_tools/redis_builder/ReadMe.txt
Normal file
47
app/redis_tools/redis_builder/ReadMe.txt
Normal file
@ -0,0 +1,47 @@
|
||||
A redis tool for redis cluster, which can help to build a new redis cluster,
|
||||
add one new redis node to the existing one or cluster, show the information
|
||||
of the redis cluster about nodes and slots. Below are the using method of
|
||||
the tool:
|
||||
1) show help information:
|
||||
./redis_build -h
|
||||
usage: redis_builder.exe -h[help]
|
||||
-s redis_addr[ip:port]
|
||||
-a cmd[nodes|slots|create|add_node|del_node|node_id]
|
||||
-N new_node[ip:port]
|
||||
-S [add node as slave]
|
||||
-f configure_file
|
||||
|
||||
for samples:
|
||||
./redis_builder -s 127.0.0.1:6379 -a create -f cluster.xml
|
||||
./redis_builder -s 127.0.0.1:6379 -a nodes
|
||||
./redis_builder -s 127.0.0.1:6379 -a slots
|
||||
./redis_builder -s 127.0.0.1:6379 -a del_node -I node_id
|
||||
./redis_builder -s 127.0.0.1:6379 -a node_id
|
||||
./redis_builder -s 127.0.0.1:6379 -a add_node -N 127.0.0.1:6380 -S
|
||||
|
||||
2) build a new redis cluster after all of the redis nodes started:
|
||||
./redis_builder -a create -f cluster.xml
|
||||
|
||||
the cluster.xml's content just like:
|
||||
<?xml version="1.0"?>
|
||||
<xml>
|
||||
<node addr = "192.168.136.172:16380">
|
||||
<node addr = "192.168.136.172:16381" />
|
||||
<node addr = "192.168.136.172:16382" />
|
||||
</node>
|
||||
<node addr = "192.168.136.172:16383">
|
||||
<node addr = "192.168.136.172:16384" />
|
||||
<node addr = "192.168.136.172:16385" />
|
||||
</node>
|
||||
<node addr = "192.168.136.172:16386">
|
||||
<node addr = "192.168.136.172:16387" />
|
||||
<node addr = "192.168.136.172:16388" />
|
||||
</node>
|
||||
</xml>
|
||||
|
||||
3) add a new slave redis node to the master node:
|
||||
./redis_builder -s 127.0.0.1:6379 -a add_node -S -N 127.0.0.1:6380
|
||||
'-s' specifys the existing master node,
|
||||
'-S' specifys the new redis node added was as a slave node,
|
||||
'-N' specify the new redis addr to be added
|
||||
'-a' specify the cmd of this tool
|
15
app/redis_tools/redis_builder/cluster.xml
Normal file
15
app/redis_tools/redis_builder/cluster.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<xml>
|
||||
<node addr = "192.168.136.172:16380">
|
||||
<node addr = "192.168.136.172:16381" />
|
||||
<node addr = "192.168.136.172:16382" />
|
||||
</node>
|
||||
<node addr = "192.168.136.172:16383">
|
||||
<node addr = "192.168.136.172:16384" />
|
||||
<node addr = "192.168.136.172:16385" />
|
||||
</node>
|
||||
<node addr = "192.168.136.172:16386">
|
||||
<node addr = "192.168.136.172:16387" />
|
||||
<node addr = "192.168.136.172:16388" />
|
||||
</node>
|
||||
</xml>
|
146
app/redis_tools/redis_builder/main.cpp
Normal file
146
app/redis_tools/redis_builder/main.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
#include "stdafx.h"
|
||||
#include "redis_status.h"
|
||||
#include "redis_builder.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void usage(const char* procname)
|
||||
{
|
||||
printf("usage: %s -h[help]\r\n"
|
||||
"-s redis_addr[ip:port]\r\n"
|
||||
"-a cmd[nodes|slots|create|add_node|del_node|node_id]\r\n"
|
||||
"-N new_node[ip:port]\r\n"
|
||||
"-S [add node as slave]\r\n"
|
||||
"-f configure_file\r\n",
|
||||
procname);
|
||||
|
||||
printf("\r\nfor samples:\r\n"
|
||||
"%s -s 127.0.0.1:6379 -a create -f cluster.xml\r\n"
|
||||
"%s -s 127.0.0.1:6379 -a nodes\r\n"
|
||||
"%s -s 127.0.0.1:6379 -a slots\r\n"
|
||||
"%s -s 127.0.0.1:6379 -a del_node -I node_id\r\n"
|
||||
"%s -s 127.0.0.1:6379 -a node_id\r\n"
|
||||
"%s -s 127.0.0.1:6379 -a add_node -N 127.0.0.1:6380 -S\r\n",
|
||||
procname, procname, procname, procname, procname, procname);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// initiation the acl library
|
||||
acl::acl_cpp_init();
|
||||
acl::log::stdout_open(true);
|
||||
|
||||
int ch;
|
||||
bool add_slave = false;
|
||||
acl::string addr, cmd, conf, new_addr, node_id;
|
||||
|
||||
while ((ch = getopt(argc, argv, "hs:a:f:N:SI:")) > 0)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
case 's':
|
||||
addr = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
cmd = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
conf = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
new_addr = optarg;
|
||||
break;
|
||||
case 'S':
|
||||
add_slave = true;
|
||||
break;
|
||||
case 'I':
|
||||
node_id = optarg;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int conn_timeout = 10, rw_timeout = 120;
|
||||
acl::redis_client client(addr, conn_timeout, rw_timeout);
|
||||
acl::redis redis(&client);
|
||||
|
||||
if (cmd == "nodes")
|
||||
{
|
||||
if (addr.empty())
|
||||
{
|
||||
printf("usage: %s -s ip:port -a nodes\r\n", argv[0]);
|
||||
goto END;
|
||||
}
|
||||
redis_status status(addr, conn_timeout, rw_timeout);
|
||||
status.show_nodes(redis);
|
||||
}
|
||||
else if (cmd == "slots")
|
||||
{
|
||||
if (addr.empty())
|
||||
{
|
||||
printf("usage: %s -a ip:port -a slots\r\n", argv[0]);
|
||||
goto END;
|
||||
}
|
||||
redis_status status(addr, conn_timeout, rw_timeout);
|
||||
status.show_slots(redis);
|
||||
}
|
||||
else if (cmd == "create")
|
||||
{
|
||||
if (conf.empty())
|
||||
{
|
||||
printf("usage: %s -a create -f cluster.xml\r\n", argv[0]);
|
||||
goto END;
|
||||
}
|
||||
redis_builder builder;
|
||||
builder.build(conf.c_str());
|
||||
}
|
||||
else if (cmd == "add_node")
|
||||
{
|
||||
if (addr.empty() || new_addr.empty())
|
||||
{
|
||||
printf("usage: %s -s ip:port -a add_node -N ip:port -S\r\n", argv[0]);
|
||||
goto END;
|
||||
}
|
||||
redis_builder builder;
|
||||
builder.add_node(addr, new_addr, add_slave);
|
||||
}
|
||||
else if (cmd == "del_node")
|
||||
{
|
||||
if (addr.empty() || node_id.empty())
|
||||
{
|
||||
printf("usage: %s -s ip:port -a del_node -I nod_id\r\n", argv[0]);
|
||||
goto END;
|
||||
}
|
||||
redis_builder builder;
|
||||
builder.del_node(addr, node_id);
|
||||
}
|
||||
else if (cmd == "node_id")
|
||||
{
|
||||
if (addr.empty())
|
||||
{
|
||||
printf("usage: %s -s ip:port -a node_id\r\n", argv[0]);
|
||||
goto END;
|
||||
}
|
||||
node_id.clear();
|
||||
redis_builder builder;
|
||||
if (builder.get_node_id(addr, node_id) == false)
|
||||
printf("can't get node id, addr: %s\r\n", addr.c_str());
|
||||
else
|
||||
printf("addr: %s, node_id: %s\r\n", addr.c_str(),
|
||||
node_id.c_str());
|
||||
}
|
||||
else
|
||||
printf("unknown cmd: %s\r\n", cmd.c_str());
|
||||
|
||||
END:
|
||||
|
||||
#ifdef WIN32
|
||||
printf("enter any key to exit\r\n");
|
||||
getchar();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
548
app/redis_tools/redis_builder/redis_builder.cpp
Normal file
548
app/redis_tools/redis_builder/redis_builder.cpp
Normal file
@ -0,0 +1,548 @@
|
||||
#include "stdafx.h"
|
||||
#include "redis_status.h"
|
||||
#include "redis_builder.h"
|
||||
|
||||
#define MAX_SLOTS 16384
|
||||
|
||||
redis_builder::redis_builder(int meet_wait /* = 100 */)
|
||||
: meet_wait_(meet_wait)
|
||||
, last_check_(0)
|
||||
{
|
||||
}
|
||||
|
||||
redis_builder::~redis_builder(void)
|
||||
{
|
||||
std::vector<acl::redis_node*>::iterator it = masters_.begin();
|
||||
for (; it != masters_.end(); ++it)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool redis_builder::add_node(const char* addr,
|
||||
const char* new_node_addr, bool slave)
|
||||
{
|
||||
acl::redis_client client(new_node_addr);
|
||||
acl::redis redis(&client);
|
||||
|
||||
acl::string buf(addr);
|
||||
const std::vector<acl::string>& tokens = buf.split2(":");
|
||||
if (tokens.size() != 2)
|
||||
{
|
||||
printf("invalid addr: %s\r\n", addr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// CLUSTER MEET master node
|
||||
if (!redis.cluster_meet(tokens[0].c_str(), atoi(tokens[1].c_str())))
|
||||
{
|
||||
printf("cluster meet %s %s error: %s\r\n",
|
||||
tokens[0].c_str(), tokens[1].c_str(),
|
||||
redis.result_error());
|
||||
return false;
|
||||
}
|
||||
|
||||
// wait for the master recognizing the slave
|
||||
while (true)
|
||||
{
|
||||
if (cluster_meeting(redis, addr) == true)
|
||||
break;
|
||||
acl_doze(meet_wait_);
|
||||
}
|
||||
|
||||
if (!slave)
|
||||
return true;
|
||||
|
||||
acl::string node_id;
|
||||
if (get_node_id(addr, node_id) == false)
|
||||
{
|
||||
printf("can't get master(%s)'s node_id\r\n", addr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (redis.cluster_replicate(node_id.c_str()) == false)
|
||||
{
|
||||
printf("cluster replicate id: %s, error: %s, "
|
||||
"master_addr: %s, slave_addr: %s\r\n",
|
||||
node_id.c_str(), redis.result_error(),
|
||||
addr, new_node_addr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool redis_builder::del_node(const char* addr, const char* node_id)
|
||||
{
|
||||
acl::redis_client client(addr);
|
||||
acl::redis redis(&client);
|
||||
if (redis.cluster_forget(node_id) == false)
|
||||
{
|
||||
printf("del node: %s error: %s, addr: %s\r\n",
|
||||
node_id, redis.result_error(), addr);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool redis_builder::build(const char* conf)
|
||||
{
|
||||
if (load(conf) == false)
|
||||
return false;
|
||||
|
||||
if (masters_.empty())
|
||||
{
|
||||
printf("no nodes available\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("===================================================\r\n");
|
||||
|
||||
return build_cluster();
|
||||
}
|
||||
|
||||
bool redis_builder::load(const char* conf)
|
||||
{
|
||||
acl::string buf;
|
||||
|
||||
// load xml information from local file
|
||||
if (acl::ifstream::load(conf, &buf) == false)
|
||||
{
|
||||
printf("load configure error: %s, file: %s\r\n",
|
||||
acl::last_serror(), conf);
|
||||
return false;
|
||||
}
|
||||
/* <xml>
|
||||
* <node addr="ip:port">
|
||||
* <node addr="ip:port" />
|
||||
* <node addr="ip:port" />
|
||||
* ...
|
||||
* </node>
|
||||
* <node addr="ip:port">
|
||||
* <node addr="ip:port" />
|
||||
* <node addr="ip:port" />
|
||||
* ...
|
||||
* </node>
|
||||
* ...
|
||||
* </xml>
|
||||
*/
|
||||
// parse the xml data
|
||||
acl::xml xml(buf.c_str());
|
||||
|
||||
// get the master redis nodes
|
||||
const char* tags = "xml/node";
|
||||
const std::vector<acl::xml_node*>& nodes = xml.getElementsByTags(tags);
|
||||
|
||||
if (nodes.empty())
|
||||
{
|
||||
printf("nodes null\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// iterate all the master nodes including their's slaves
|
||||
std::vector<acl::xml_node*>::const_iterator cit;
|
||||
for (cit = nodes.begin(); cit != nodes.end(); ++cit)
|
||||
{
|
||||
acl::redis_node* master = create_master(**cit);
|
||||
if (master != NULL)
|
||||
masters_.push_back(master);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
acl::redis_node* redis_builder::create_master(acl::xml_node& node)
|
||||
{
|
||||
const char* addr = node.attr_value("addr");
|
||||
if (addr == NULL || *addr == 0)
|
||||
{
|
||||
printf("no addr in the master node\r\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printf(">>> master: %s\r\n", addr);
|
||||
|
||||
acl::redis_node* master = new acl::redis_node;
|
||||
master->set_addr(addr);
|
||||
|
||||
// iterate all the slaves of the master, and add them to master
|
||||
acl::xml_node* child = node.first_child();
|
||||
while (child != NULL)
|
||||
{
|
||||
acl::redis_node* slave = create_slave(*child);
|
||||
if (slave != NULL)
|
||||
master->add_slave(slave);
|
||||
child = node.next_child();
|
||||
}
|
||||
|
||||
//const std::vector<acl::redis_node*>* slaves = master->get_slaves();
|
||||
//printf(">>>slave's size: %d\r\n", (int) slaves->size());
|
||||
return master;
|
||||
}
|
||||
|
||||
acl::redis_node* redis_builder::create_slave(acl::xml_node& node)
|
||||
{
|
||||
const char* addr = node.attr_value("addr");
|
||||
if (addr == NULL || *addr == 0)
|
||||
{
|
||||
printf("no addr in the slave addr\r\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printf("\tslave: %s\r\n", addr);
|
||||
acl::redis_node* slave = new acl::redis_node;
|
||||
slave->set_addr(addr);
|
||||
return slave;
|
||||
}
|
||||
|
||||
bool redis_builder::build_cluster()
|
||||
{
|
||||
if (masters_.empty())
|
||||
{
|
||||
printf("no master available!\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t range = MAX_SLOTS / masters_.size();
|
||||
size_t begin = 0, end = MAX_SLOTS % masters_.size() + range -1;
|
||||
|
||||
// build every master node, and connect all of its slaves.
|
||||
|
||||
std::vector<acl::redis_node*>::iterator it;
|
||||
for (it = masters_.begin(); it != masters_.end(); ++it)
|
||||
{
|
||||
if (it != masters_.begin())
|
||||
printf("----------------------------------------\r\n");
|
||||
|
||||
(*it)->add_slot_range(begin, end);
|
||||
if (build_master(**it) == false)
|
||||
return false;
|
||||
begin = end + 1;
|
||||
end = end + range;
|
||||
}
|
||||
|
||||
it = masters_.begin();
|
||||
acl::redis_client client((*it)->get_addr());
|
||||
acl::redis master(&client);
|
||||
|
||||
// let one master to connect all other master nodes
|
||||
|
||||
printf("===================================================\r\n");
|
||||
printf("Meeting all masters and slaves ...\r\n");
|
||||
|
||||
std::vector<acl::redis_node*> all_slaves;
|
||||
std::vector<acl::redis_node*>::const_iterator cit;
|
||||
|
||||
for (++it; it != masters_.end(); ++it)
|
||||
{
|
||||
if (cluster_meet(master, **it) == false)
|
||||
return false;
|
||||
const std::vector<acl::redis_node*>* slaves = (*it)->get_slaves();
|
||||
for (cit = slaves->begin(); cit != slaves->end(); ++cit)
|
||||
all_slaves.push_back(*cit);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
int nwait = 0;
|
||||
for (cit = all_slaves.begin(); cit != all_slaves.end(); ++cit)
|
||||
{
|
||||
if ((*cit)->is_connected())
|
||||
continue;
|
||||
if (cluster_meeting(master, (*cit)->get_addr()) == false)
|
||||
nwait++;
|
||||
else
|
||||
(*cit)->set_connected(true);
|
||||
}
|
||||
if (nwait == 0)
|
||||
break;
|
||||
acl_doze(meet_wait_);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
printf("===================================================\r\n");
|
||||
printf("All nodes of cluster:\r\n");
|
||||
|
||||
const std::map<acl::string, acl::redis_node*>* nodes;
|
||||
if ((nodes = master.cluster_nodes())== NULL)
|
||||
{
|
||||
printf("can't get cluster nodes, addr: %s\r\n",
|
||||
client.get_stream()->get_peer(true));
|
||||
return false;
|
||||
}
|
||||
|
||||
redis_status::show_nodes(nodes);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool redis_builder::cluster_meet(acl::redis& redis,
|
||||
const acl::redis_node& node)
|
||||
{
|
||||
acl::string buf(node.get_addr());
|
||||
const std::vector<acl::string>& tokens = buf.split2(":");
|
||||
if (tokens.size() != 2)
|
||||
{
|
||||
printf("invalid master_addr: %s\r\n", node.get_addr());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!redis.cluster_meet(tokens[0].c_str(), atoi(tokens[1].c_str())))
|
||||
{
|
||||
printf("cluster meet %s %s error: %s\r\n",
|
||||
tokens[0].c_str(), tokens[1].c_str(),
|
||||
redis.result_error());
|
||||
return false;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (cluster_meeting(redis, node.get_addr()) == true)
|
||||
break;
|
||||
acl_doze(meet_wait_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool redis_builder::build_master(acl::redis_node& master)
|
||||
{
|
||||
acl::redis_client client(master.get_addr());
|
||||
acl::redis redis(&client);
|
||||
|
||||
if (master_set_slots(redis, master) == false)
|
||||
return false;
|
||||
|
||||
const char* id = myself_id(redis);
|
||||
if (id == NULL || *id == 0)
|
||||
{
|
||||
printf("null id, master addr: %s\r\n", master.get_addr());
|
||||
return false;
|
||||
}
|
||||
master.set_id(id);
|
||||
|
||||
printf("Build master: %s, %s\r\n", id, master.get_addr());
|
||||
|
||||
const std::vector<acl::redis_node*>* slaves = master.get_slaves();
|
||||
std::vector<acl::redis_node*>::const_iterator cit;
|
||||
for (cit = slaves->begin(); cit != slaves->end(); ++cit)
|
||||
{
|
||||
if (add_slave(master, **cit) == false)
|
||||
return false;
|
||||
}
|
||||
printf("Build master OK\r\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool redis_builder::add_slave(const acl::redis_node& master,
|
||||
const acl::redis_node& slave)
|
||||
{
|
||||
acl::redis_client client(slave.get_addr());
|
||||
acl::redis redis(&client);
|
||||
const char* master_addr = master.get_addr();
|
||||
if (master_addr == NULL || *master_addr == 0)
|
||||
{
|
||||
printf("master addr null\r\n");
|
||||
return false;
|
||||
}
|
||||
acl::string buf(master_addr);
|
||||
const std::vector<acl::string>& tokens = buf.split2(":");
|
||||
if (tokens.size() != 2)
|
||||
{
|
||||
printf("invalid master_addr: %s\r\n", master_addr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// CLUSTER MEET master node
|
||||
if (!redis.cluster_meet(tokens[0].c_str(), atoi(tokens[1].c_str())))
|
||||
{
|
||||
printf("cluster meet %s %s error: %s\r\n",
|
||||
tokens[0].c_str(), tokens[1].c_str(),
|
||||
redis.result_error());
|
||||
return false;
|
||||
}
|
||||
|
||||
// wait for the master recognizing the slave
|
||||
while (true)
|
||||
{
|
||||
if (cluster_meeting(redis, master_addr) == true)
|
||||
break;
|
||||
acl_doze(meet_wait_);
|
||||
}
|
||||
|
||||
if (redis.cluster_replicate(master.get_id()) == false)
|
||||
{
|
||||
printf("cluster replicate id: %s, error: %s, addr: %s\r\n",
|
||||
master.get_id(), redis.result_error(),
|
||||
slave.get_addr());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
acl::redis_node* redis_builder::find_slave(const acl::redis_node* node,
|
||||
const char* addr, size_t& nslaves)
|
||||
{
|
||||
const std::vector<acl::redis_node*>* slaves = node->get_slaves();
|
||||
nslaves += slaves->size();
|
||||
std::vector<acl::redis_node*>::const_iterator cit;
|
||||
for (cit = slaves->begin(); cit != slaves->end(); ++cit)
|
||||
{
|
||||
if (strcasecmp((*cit)->get_addr(), addr) == 0)
|
||||
return *cit;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool redis_builder::cluster_meeting(acl::redis& redis, const char* addr)
|
||||
{
|
||||
acl::socket_stream* conn = redis.get_client()->get_stream();
|
||||
if (conn == NULL)
|
||||
{
|
||||
printf("connection disconnected!\r\n");
|
||||
return false;
|
||||
}
|
||||
const char* myaddr = conn->get_peer(true);
|
||||
const std::map<acl::string, acl::redis_node*>* nodes;
|
||||
if ((nodes = redis.cluster_nodes())== NULL)
|
||||
{
|
||||
printf("can't get cluster nodes, addr: %s\r\n", myaddr);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t nslaves = 0;
|
||||
acl::redis_node* node = NULL;
|
||||
std::map<acl::string, acl::redis_node*>::const_iterator cit;
|
||||
for (cit = nodes->begin(); cit != nodes->end(); ++cit)
|
||||
{
|
||||
if (strcasecmp(cit->second->get_addr(), addr) == 0)
|
||||
{
|
||||
node = cit->second;
|
||||
break;
|
||||
}
|
||||
|
||||
node = find_slave(cit->second, addr, nslaves);
|
||||
if (node != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (node == NULL)
|
||||
{
|
||||
//show_nodes(nodes);
|
||||
|
||||
time_t now = time(NULL);
|
||||
if (now - last_check_ >= 1)
|
||||
{
|
||||
printf("%s waiting for %s, nodes: %d, %d\r\n", myaddr,
|
||||
addr, (int) nodes->size(), (int) nslaves);
|
||||
last_check_ = now;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* type = node->get_type();
|
||||
if (strcasecmp(type, "slave") && strcasecmp(type, "master"))
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
if (now - last_check_ >= 1)
|
||||
{
|
||||
printf("%s meeting with %s, status: %s\r\n",
|
||||
myaddr, addr, type);
|
||||
last_check_ = now;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("%s meet with %s OK, status: %s\r\n", myaddr, addr, type);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool redis_builder::master_set_slots(acl::redis& redis,
|
||||
acl::redis_node& master)
|
||||
{
|
||||
const std::vector<std::pair<size_t, size_t> >& slots
|
||||
= master.get_slots();
|
||||
if (slots.size() != 1)
|
||||
{
|
||||
printf("invalid slots's size: %d, addr: %s\r\n",
|
||||
(int) slots.size(), master.get_addr());
|
||||
return false;
|
||||
}
|
||||
const std::pair<size_t, size_t> slot = slots[0];
|
||||
size_t min_slot = slot.first, max_slot = slot.second;
|
||||
size_t n = max_slot - min_slot + 1;
|
||||
int *slot_array = (int*) malloc(sizeof(int) * n);
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
slot_array[i] = (int)min_slot;
|
||||
min_slot++;
|
||||
}
|
||||
|
||||
if (redis.cluster_addslots(slot_array, n) == false)
|
||||
{
|
||||
printf("addslots error: %s, addr: %s, slots: %d, %d\r\n",
|
||||
redis.result_error(), master.get_addr(),
|
||||
(int) min_slot, (int) max_slot);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool redis_builder::get_node_id(const char* addr, acl::string& node_id)
|
||||
{
|
||||
acl::redis_client client(addr);
|
||||
acl::redis redis(&client);
|
||||
const char* ptr = myself_id(redis);
|
||||
if (ptr == NULL || *ptr == 0)
|
||||
{
|
||||
printf("null node_id from addr: %s\r\n", addr);
|
||||
return false;
|
||||
}
|
||||
|
||||
node_id = ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* redis_builder::myself_id(acl::redis& redis)
|
||||
{
|
||||
acl::socket_stream* conn = redis.get_client()->get_stream();
|
||||
if (conn == NULL)
|
||||
{
|
||||
printf("connection disconnected!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* addr = conn->get_peer(true);
|
||||
|
||||
const std::map<acl::string, acl::redis_node*>* nodes =
|
||||
redis.cluster_nodes();
|
||||
if (nodes == NULL)
|
||||
{
|
||||
printf("cluster_nodes null, addr: %s\r\n", addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::map<acl::string, acl::redis_node*>::const_iterator it;
|
||||
|
||||
for (it = nodes->begin(); it != nodes->end(); ++it)
|
||||
{
|
||||
const acl::redis_node* node = it->second;
|
||||
if (node->is_myself())
|
||||
return node->get_id();
|
||||
}
|
||||
|
||||
printf("cluster_nodes no myself id, addr: %s\r\n", addr);
|
||||
|
||||
return NULL;
|
||||
}
|
59
app/redis_tools/redis_builder/redis_builder.h
Normal file
59
app/redis_tools/redis_builder/redis_builder.h
Normal file
@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class redis_builder
|
||||
{
|
||||
public:
|
||||
redis_builder(int meet_wait = 100);
|
||||
~redis_builder(void);
|
||||
|
||||
bool build(const char* conf);
|
||||
|
||||
bool add_node(const char* addr, const char* new_node_addr, bool slave);
|
||||
bool del_node(const char* addr, const char* node_id);
|
||||
|
||||
// get the node's id of the given addr
|
||||
bool get_node_id(const char* addr, acl::string& node_id);
|
||||
// get the current node's ID
|
||||
const char* myself_id(acl::redis& redis);
|
||||
|
||||
private:
|
||||
int meet_wait_;
|
||||
std::vector<acl::redis_node*> masters_;
|
||||
time_t last_check_;
|
||||
|
||||
// load the cluster.xml configure and create redis nodes for creating
|
||||
bool load(const char* conf);
|
||||
|
||||
// create one master node according to one xml node of configure
|
||||
acl::redis_node* create_master(acl::xml_node& node);
|
||||
|
||||
// create one slave node
|
||||
acl::redis_node* create_slave(acl::xml_node& node);
|
||||
|
||||
// begin build the redis cluster, connect all redis nodes
|
||||
bool build_cluster();
|
||||
|
||||
// allocate slots for every master, and let its slaves connect
|
||||
// to their master node
|
||||
bool build_master(acl::redis_node& master);
|
||||
|
||||
// let one node meet to another one
|
||||
bool cluster_meet(acl::redis& redis, const acl::redis_node& node);
|
||||
|
||||
// check the MEET status between the current node and the other one
|
||||
bool cluster_meeting(acl::redis& redis, const char* addr);
|
||||
|
||||
// add slots to one master node
|
||||
bool master_set_slots(acl::redis& redis, acl::redis_node& master);
|
||||
|
||||
// add one slave to its master node, let the slave MEET its master,
|
||||
// and make the slave REPLICATE its master.
|
||||
bool add_slave(const acl::redis_node& master,
|
||||
const acl::redis_node& slave);
|
||||
|
||||
// check if the given addr was in the node's slave
|
||||
acl::redis_node* find_slave(const acl::redis_node* node,
|
||||
const char* addr, size_t& nslaves);
|
||||
};
|
25
app/redis_tools/redis_builder/redis_builder_vc2012.sln
Normal file
25
app/redis_tools/redis_builder/redis_builder_vc2012.sln
Normal file
@ -0,0 +1,25 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dispatch_manager", "dispatch_manager_vc2012.vcxproj", "{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
DebugDll|Win32 = DebugDll|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
ReleaseDll|Win32 = ReleaseDll|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.ActiveCfg = DebugDll|Win32
|
||||
{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.Build.0 = DebugDll|Win32
|
||||
{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.Build.0 = Release|Win32
|
||||
{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.ActiveCfg = ReleaseDll|Win32
|
||||
{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.Build.0 = ReleaseDll|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
198
app/redis_tools/redis_builder/redis_builder_vc2012.vcxproj
Normal file
198
app/redis_tools/redis_builder/redis_builder_vc2012.vcxproj
Normal file
@ -0,0 +1,198 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="DebugDll|Win32">
|
||||
<Configuration>DebugDll</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="ReleaseDll|Win32">
|
||||
<Configuration>ReleaseDll</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D90DCF51-E219-4BD8-A032-076335675F58}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectName>redis_builder</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>Debug\</OutDir>
|
||||
<IntDir>Debug\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>Release\</OutDir>
|
||||
<IntDir>Release\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|Win32'">
|
||||
<OutDir>$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|Win32'">
|
||||
<OutDir>$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>lib_acl_cpp_vc2012d.lib;lib_acl_vc2012d.lib;lib_protocol_vc2012d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)redis_builder.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)redis_builder.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>lib_acl_cpp_vc2012.lib;lib_acl_vc2012.lib;lib_protocol_vc2012.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)redis_builder.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>lib_acl_cpp.lib;lib_acl.lib;lib_protocol.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)redis_builder.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>copy ..\..\..\dist\lib\win32\lib_acl.dll $(OutDir) /Y
|
||||
copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y
|
||||
copy ..\..\..\dist\lib\win32\lib_protocol.dll $(OutDir) /Y</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>lib_acl_cpp_d.lib;lib_acl_d.lib;lib_protocol_d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)redis_builder.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)redis_builder.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>copy ..\..\..\dist\lib\win32\lib_acl_d.dll $(OutDir) /Y
|
||||
copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y
|
||||
copy ..\..\..\dist\lib\win32\lib_protocol_d.dll $(OutDir) /Y</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="redis_builder.cpp" />
|
||||
<ClCompile Include="redis_status.cpp" />
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="redis_builder.h" />
|
||||
<ClInclude Include="redis_status.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="redis_builder.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="redis_status.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="redis_builder.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="redis_status.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
120
app/redis_tools/redis_builder/redis_status.cpp
Normal file
120
app/redis_tools/redis_builder/redis_status.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include "stdafx.h"
|
||||
#include "redis_status.h"
|
||||
|
||||
redis_status::redis_status(const char* addr, int conn_timeout, int rw_timeout)
|
||||
: addr_(addr)
|
||||
, conn_timeout_(conn_timeout)
|
||||
, rw_timeout_(rw_timeout)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
redis_status::~redis_status(void)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void redis_status::show_nodes()
|
||||
{
|
||||
acl::redis_client client(addr_, conn_timeout_, rw_timeout_);
|
||||
acl::redis redis(&client);
|
||||
|
||||
show_nodes(redis);
|
||||
}
|
||||
|
||||
void redis_status::show_nodes(acl::redis& redis)
|
||||
{
|
||||
const std::map<acl::string, acl::redis_node*>* masters;
|
||||
if ((masters = redis.cluster_nodes())== NULL)
|
||||
printf("can't get cluster nodes\r\n");
|
||||
else
|
||||
show_nodes(masters);
|
||||
}
|
||||
|
||||
void redis_status::show_slave_nodes(
|
||||
const std::vector<acl::redis_node*>& slaves)
|
||||
{
|
||||
std::vector<acl::redis_node*>::const_iterator cit;
|
||||
for (cit = slaves.begin(); cit != slaves.end(); ++cit)
|
||||
{
|
||||
printf("slave, id: %s, addr: %s, master_id: %s\r\n",
|
||||
(*cit)->get_id(), (*cit)->get_addr(),
|
||||
(*cit)->get_master_id());
|
||||
}
|
||||
}
|
||||
|
||||
void redis_status::show_master_slots(const acl::redis_node* master)
|
||||
{
|
||||
const std::vector<std::pair<size_t, size_t> >& slots =
|
||||
master->get_slots();
|
||||
|
||||
std::vector<std::pair<size_t, size_t> >::const_iterator cit;
|
||||
for (cit = slots.begin(); cit != slots.end(); ++cit)
|
||||
printf("slots range: %d-%d\r\n",
|
||||
(int) (*cit).first, (int) (*cit).second);
|
||||
}
|
||||
|
||||
bool redis_status::show_nodes(
|
||||
const std::map<acl::string, acl::redis_node*>* masters)
|
||||
{
|
||||
const std::vector<acl::redis_node*>* slaves;
|
||||
std::map<acl::string, acl::redis_node*>::const_iterator cit;
|
||||
for (cit = masters->begin(); cit != masters->end(); ++cit)
|
||||
{
|
||||
if (cit != masters->begin())
|
||||
printf("---------------------------------------\r\n");
|
||||
|
||||
printf("master, id: %s, addr: %s\r\n",
|
||||
cit->first.c_str(), cit->second->get_addr());
|
||||
show_master_slots(cit->second);
|
||||
slaves = cit->second->get_slaves();
|
||||
show_slave_nodes(*slaves);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void redis_status::show_slots()
|
||||
{
|
||||
acl::redis_client client(addr_, conn_timeout_, rw_timeout_);
|
||||
acl::redis redis(&client);
|
||||
|
||||
show_slots(redis);
|
||||
}
|
||||
|
||||
bool redis_status::show_slots(acl::redis& redis)
|
||||
{
|
||||
const std::vector<acl::redis_slot*>* slots = redis.cluster_slots();
|
||||
if (slots == NULL)
|
||||
return false;
|
||||
|
||||
std::vector<acl::redis_slot*>::const_iterator cit;
|
||||
|
||||
for (cit = slots->begin(); cit != slots->end(); ++cit)
|
||||
{
|
||||
printf("=========================================\r\n");
|
||||
printf("master: ip: %s, port: %d, slots: %d - %d\r\n",
|
||||
(*cit)->get_ip(), (*cit)->get_port(),
|
||||
(int) (*cit)->get_slot_min(),
|
||||
(int) (*cit)->get_slot_max());
|
||||
show_slaves_slots(*cit);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void redis_status::show_slaves_slots(const acl::redis_slot* slot)
|
||||
{
|
||||
const std::vector<acl::redis_slot*>& slaves = slot->get_slaves();
|
||||
std::vector<acl::redis_slot*>::const_iterator cit;
|
||||
for (cit = slaves.begin(); cit != slaves.end(); ++cit)
|
||||
{
|
||||
printf("slave: ip: %s, port: %d, slots: %d - %d\r\n",
|
||||
(*cit)->get_ip(), (*cit)->get_port(),
|
||||
(int) (*cit)->get_slot_min(),
|
||||
(int) (*cit)->get_slot_max());
|
||||
}
|
||||
}
|
24
app/redis_tools/redis_builder/redis_status.h
Normal file
24
app/redis_tools/redis_builder/redis_status.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
class redis_status
|
||||
{
|
||||
public:
|
||||
redis_status(const char* addr, int conn_timeout, int rw_timeout);
|
||||
~redis_status(void);
|
||||
|
||||
void show_nodes();
|
||||
static void show_nodes(acl::redis& redis);
|
||||
static bool show_nodes(const std::map<acl::string,
|
||||
acl::redis_node*>* masters);
|
||||
static void show_master_slots(const acl::redis_node* master);
|
||||
static void show_slave_nodes(const std::vector<acl::redis_node*>& slaves);
|
||||
|
||||
void show_slots();
|
||||
static bool show_slots(acl::redis& redis);
|
||||
static void show_slaves_slots(const acl::redis_slot* slot);
|
||||
|
||||
private:
|
||||
acl::string addr_;
|
||||
int conn_timeout_;
|
||||
int rw_timeout_;
|
||||
};
|
8
app/redis_tools/redis_builder/stdafx.cpp
Normal file
8
app/redis_tools/redis_builder/stdafx.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : 只包括标准包含文件的源文件
|
||||
// master_threads.pch 将成为预编译头
|
||||
// stdafx.obj 将包含预编译类型信息
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: 在 STDAFX.H 中
|
||||
//引用任何所需的附加头文件,而不是在此文件中引用
|
16
app/redis_tools/redis_builder/stdafx.h
Normal file
16
app/redis_tools/redis_builder/stdafx.h
Normal file
@ -0,0 +1,16 @@
|
||||
// stdafx.h : 标准系统包含文件的包含文件,
|
||||
// 或是常用但不常更改的项目特定的包含文件
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//#include <iostream>
|
||||
//#include <tchar.h>
|
||||
|
||||
// TODO: 在此处引用程序要求的附加头文件
|
||||
|
||||
#include "acl_cpp/lib_acl.hpp"
|
||||
#include "lib_acl.h"
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
修改历史列表:
|
||||
------------------------------------------------------------------------
|
||||
82) 2015.4.19
|
||||
82.1) app/redis_tools: 用于 redis 集群管理的工具
|
||||
|
||||
81) 2015.3.29 --- acl 3.1.1 版本发布!
|
||||
|
||||
80) 2015.2.8
|
||||
|
@ -1,6 +1,9 @@
|
||||
修改历史列表:
|
||||
|
||||
------------------------------------------------------------------------
|
||||
301) 2015.4.19
|
||||
301.1) feature: 完善了 redis_cluster 集群管理类
|
||||
|
||||
300) 2015.4.12
|
||||
300.1) comment: 完善了 redis 模块的英文注释
|
||||
|
||||
|
@ -301,10 +301,9 @@ private:
|
||||
std::map<string, redis_node*> masters_;
|
||||
|
||||
redis_node* get_node(string& line);
|
||||
redis_node* get_master_node(std::vector<string>& tokens);
|
||||
void add_slot_range(redis_node* node, char* slots);
|
||||
redis_node* get_slave_node(std::vector<string>& tokens);
|
||||
void free_masters();
|
||||
redis_node* get_slave(const std::vector<string>& tokens);
|
||||
|
||||
private:
|
||||
std::vector<redis_node*> slaves_;
|
||||
|
@ -16,32 +16,79 @@ class ACL_CPP_API redis_node
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* 构造函数
|
||||
* constructor
|
||||
* @param id {const char*} 集群中某个 redis 结点的唯一标识符
|
||||
* the unique ID for one redis node in the redis cluster
|
||||
* @param addr {const char*} 集群中某个 redis 结点的监听地址
|
||||
* the listening addr for one redis node in redis cluster
|
||||
* 当使用此构造函数实例化类对象时,需要调用 set_id 和 set_addr 方法设置
|
||||
* 该 redis 结点的唯一标识符及服务监听地址,同时还可调用其它的 set_xxx 设置方法
|
||||
*/
|
||||
redis_node(const char* id, const char* addr);
|
||||
redis_node(const redis_node& node);
|
||||
redis_node();
|
||||
~redis_node();
|
||||
|
||||
/**
|
||||
* 除了在构造函数中的参数中传入该结点的 ID 标识符外,还可以通过此函数设置
|
||||
* set the node's ID
|
||||
* @param id {const char*} 集群中 redis 结点的唯一标识符
|
||||
* the unique ID for one redis node in the reids cluster
|
||||
* @return {redis_node&}
|
||||
*/
|
||||
redis_node& set_id(const char* id);
|
||||
|
||||
/**
|
||||
* 除了在构造函数中的参数中传入该结点的地址外,还可以通过此函数设置
|
||||
* set the node's listening addr
|
||||
* @param addr {const char*} 集群中 redis 结点的服务地址,格式:ip:port
|
||||
* the listening addr of one redis node in the reids cluster
|
||||
* @return {redis_node&}
|
||||
*/
|
||||
redis_node& set_addr(const char* addr);
|
||||
|
||||
/**
|
||||
* 设置当前结点的类型
|
||||
* set the current node's type
|
||||
* @param type {const char*}
|
||||
* @return {redis_node&}
|
||||
*/
|
||||
redis_node& set_type(const char* type);
|
||||
|
||||
/**
|
||||
* 设置当前结点是否为当前的连接对象
|
||||
* set if the current node is belonging to the current connection
|
||||
* @param yesno {bool}
|
||||
* @return {redis_node&}
|
||||
*/
|
||||
redis_node& set_myself(bool yesno);
|
||||
|
||||
/**
|
||||
* 当本结点为从结点时,设置当前结点的主结点
|
||||
* setting current slave node's master node
|
||||
* @param master {const redis_node*} 主结点对象
|
||||
* the redis master node of the current slave in cluster
|
||||
* @return {redis_node&}
|
||||
*/
|
||||
void set_master(const redis_node* master);
|
||||
redis_node& set_master(const redis_node* master);
|
||||
|
||||
/**
|
||||
* 设置当前结点正处于握手阶段
|
||||
* set the current node being in handshaking status
|
||||
* @param yesno {bool}
|
||||
* @return {redis_node&}
|
||||
*/
|
||||
redis_node& set_handshaking(bool yesno);
|
||||
|
||||
/**
|
||||
* 设置当前结点处于连线状态
|
||||
* set the node been connected in the cluster
|
||||
* @param yesno {bool}
|
||||
* @return {redis_node&}
|
||||
*/
|
||||
redis_node& set_connected(bool yesno);
|
||||
|
||||
/**
|
||||
* 当本结点为从结点时,设置当前结点的主结点标识符
|
||||
* setting current node's master node when the node is slave node
|
||||
* @param id {const char*} 主结点唯一标识符
|
||||
* the unique ID of the master node
|
||||
* @return {redis_node&}
|
||||
*/
|
||||
void set_master_id(const char* id);
|
||||
redis_node& set_master_id(const char* id);
|
||||
|
||||
/**
|
||||
* 当本结点为主结点时,添加一个从结点
|
||||
@ -89,6 +136,46 @@ public:
|
||||
*/
|
||||
const std::vector<std::pair<size_t, size_t> >& get_slots() const;
|
||||
|
||||
/**
|
||||
* 获得当前结点的类型
|
||||
* get the node's type
|
||||
* @return {const char*}
|
||||
*/
|
||||
const char* get_type() const
|
||||
{
|
||||
return type_.c_str();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前结点是否为当前的连接对象结点
|
||||
* check if the node belongs to the current connection
|
||||
* @return {bool}
|
||||
*/
|
||||
bool is_myself() const
|
||||
{
|
||||
return myself_;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前结点是否正处于握手阶段
|
||||
* check if the node is in handshaking status
|
||||
* @return {bool}
|
||||
*/
|
||||
bool is_handshaking() const
|
||||
{
|
||||
return handshaking_;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前结点是否已经处于连线状态
|
||||
* check if the node is connected in the cluster
|
||||
* @return {bool}
|
||||
*/
|
||||
bool is_connected() const
|
||||
{
|
||||
return connected_;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当本结点为从结点时,获得该从结点的主结点对象
|
||||
* get the current slave's master node
|
||||
@ -116,7 +203,7 @@ public:
|
||||
*/
|
||||
const std::vector<redis_node*>* get_slaves() const
|
||||
{
|
||||
return (master_ && master_ == this) ? &slaves_ : NULL;
|
||||
return &slaves_;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -152,6 +239,10 @@ public:
|
||||
private:
|
||||
string id_;
|
||||
string addr_;
|
||||
string type_;
|
||||
bool myself_;
|
||||
bool handshaking_;
|
||||
bool connected_;
|
||||
const redis_node* master_;
|
||||
string master_id_;
|
||||
std::vector<redis_node*> slaves_;
|
||||
|
@ -638,8 +638,7 @@ const std::vector<redis_node*>* redis_cluster::cluster_slaves(const char* node)
|
||||
node_type = ptr + 1;
|
||||
if (strcasecmp(node_type, "slave") != 0)
|
||||
continue;
|
||||
|
||||
redis_node* slave = get_slave_node(tokens);
|
||||
redis_node* slave = get_slave(tokens);
|
||||
if (slave != NULL)
|
||||
slaves_.push_back(slave);
|
||||
}
|
||||
@ -647,6 +646,21 @@ const std::vector<redis_node*>* redis_cluster::cluster_slaves(const char* node)
|
||||
return &slaves_;
|
||||
}
|
||||
|
||||
redis_node* redis_cluster::get_slave(const std::vector<string>& tokens)
|
||||
{
|
||||
if (tokens.size() < 8)
|
||||
return NULL;
|
||||
|
||||
redis_node* node = NEW redis_node;
|
||||
node->set_id(tokens[0].c_str());
|
||||
node->set_addr(tokens[1].c_str());
|
||||
node->set_myself(false);
|
||||
node->set_connected(strcasecmp(tokens[7].c_str(), "connected") == 0);
|
||||
node->set_master_id(tokens[3].c_str());
|
||||
node->set_type("slave");
|
||||
return node;
|
||||
}
|
||||
|
||||
void redis_cluster::free_slaves()
|
||||
{
|
||||
std::vector<redis_node*>::iterator it = slaves_.begin();
|
||||
@ -712,51 +726,61 @@ const std::map<string, redis_node*>* redis_cluster::cluster_nodes()
|
||||
// 94e5d32cbcc9539cc1539078ca372094c14f9f49 127.0.0.1:16380 myself,master - 0 0 1 connected 0-9 11-5460
|
||||
// e7b21f65e8d0d6e82dee026de29e499bb518db36 127.0.0.1:16381 slave d52ea3cb4cdf7294ac1fb61c696ae6483377bcfc 0 1428410625373 73 connected
|
||||
// 6a78b47b2e150693fc2bed8578a7ca88b8f1e04c 127.0.0.1:16383 myself,slave 94e5d32cbcc9539cc1539078ca372094c14f9f49 0 0 4 connected
|
||||
|
||||
// 70a2cd8936a3d28d94b4915afd94ea69a596376a :16381 myself,master - 0 0 0 connected
|
||||
|
||||
redis_node* redis_cluster::get_node(string& line)
|
||||
{
|
||||
std::vector<string>& tokens = line.split2(" ");
|
||||
if (tokens.size() < 3)
|
||||
if (tokens.size() < 8)
|
||||
{
|
||||
logger_warn("invalid tokens's size: %d < 8",
|
||||
(int) tokens.size());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool myself = false;
|
||||
char* node_type = tokens[2].c_str();
|
||||
char* ptr = strchr(node_type, ',');
|
||||
if (ptr != NULL && *(ptr + 1) != 0)
|
||||
node_type = ptr + 1;
|
||||
{
|
||||
*ptr++ = 0;
|
||||
if (strcasecmp(node_type, "myself") == 0)
|
||||
myself = true;
|
||||
node_type = ptr;
|
||||
}
|
||||
|
||||
redis_node* node = NEW redis_node;
|
||||
node->set_id(tokens[0].c_str());
|
||||
node->set_addr(tokens[1].c_str());
|
||||
node->set_myself(myself);
|
||||
node->set_connected(strcasecmp(tokens[7].c_str(), "connected") == 0);
|
||||
node->set_master_id(tokens[3].c_str());
|
||||
|
||||
if (strcasecmp(node_type, "master") == 0)
|
||||
return get_master_node(tokens);
|
||||
{
|
||||
node->set_master(node);
|
||||
node->set_type("master");
|
||||
masters_[tokens[0]] = node;
|
||||
size_t n = tokens.size();
|
||||
for (size_t i = 8; i < n; i++)
|
||||
add_slot_range(node, tokens[i].c_str());
|
||||
}
|
||||
else if (strcasecmp(node_type, "slave") == 0)
|
||||
return get_slave_node(tokens);
|
||||
node->set_type("slave");
|
||||
else if (strcasecmp(node_type, "handshake") == 0)
|
||||
{
|
||||
node->set_master(node);
|
||||
node->set_type("handshake");
|
||||
node->set_handshaking(true);
|
||||
masters_[tokens[0]] = node;
|
||||
size_t n = tokens.size();
|
||||
for (size_t i = 8; i < n; i++)
|
||||
add_slot_range(node, tokens[i].c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger_error("unknown node type: %s", node_type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
logger_warn("unknown node type: %s", node_type);
|
||||
|
||||
redis_node* redis_cluster::get_master_node(std::vector<string>& tokens)
|
||||
{
|
||||
if (tokens.size() < 9)
|
||||
{
|
||||
logger_warn("invalid tokens's size: %d", (int) tokens.size());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::map<string, redis_node*>::const_iterator cit;
|
||||
if ((cit = masters_.find(tokens[0].c_str())) != masters_.end())
|
||||
{
|
||||
logger_warn("already exists master: %s", tokens[0].c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
redis_node* node = NEW redis_node(tokens[0].c_str(), tokens[1].c_str());
|
||||
node->set_master(node);
|
||||
|
||||
masters_[tokens[0]] = node;
|
||||
|
||||
size_t n = tokens.size();
|
||||
for (size_t i = 8; i < n; i++)
|
||||
add_slot_range(node, tokens[i].c_str());
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -783,19 +807,6 @@ void redis_cluster::add_slot_range(redis_node* node, char* slots)
|
||||
node->add_slot_range(slot_min, slot_max);
|
||||
}
|
||||
|
||||
redis_node* redis_cluster::get_slave_node(std::vector<string>& tokens)
|
||||
{
|
||||
if (tokens.size() < 4)
|
||||
{
|
||||
logger_warn("invalid tokens's size: %d", (int) tokens.size());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
redis_node* node = NEW redis_node(tokens[0].c_str(), tokens[1].c_str());
|
||||
node->set_master_id(tokens[3].c_str());
|
||||
return node;
|
||||
}
|
||||
|
||||
void redis_cluster::free_masters()
|
||||
{
|
||||
std::map<string, redis_node*>::iterator it = masters_.begin();
|
||||
|
@ -5,31 +5,12 @@
|
||||
namespace acl
|
||||
{
|
||||
|
||||
redis_node::redis_node(const char* id, const char* addr)
|
||||
: id_(id)
|
||||
, addr_(addr)
|
||||
redis_node::redis_node()
|
||||
: myself_(false)
|
||||
, handshaking_(false)
|
||||
, connected_(false)
|
||||
, master_(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
redis_node::redis_node(const redis_node& node)
|
||||
{
|
||||
id_ = node.get_id();
|
||||
addr_ = node.get_addr();
|
||||
master_ = node.get_master();
|
||||
const std::vector<redis_node*>* slaves = node.get_slaves();
|
||||
if (slaves != NULL)
|
||||
{
|
||||
std::vector<redis_node*>::const_iterator cit;
|
||||
for (cit = slaves_.begin(); cit != slaves_.end(); ++cit)
|
||||
slaves_.push_back(*cit);
|
||||
}
|
||||
|
||||
const std::vector<std::pair<size_t, size_t> >& slots = node.get_slots();
|
||||
std::vector<std::pair<size_t, size_t> >::const_iterator cit2;
|
||||
for (cit2 = slots.begin(); cit2 != slots.end(); ++cit2)
|
||||
slots_.push_back(*cit2);
|
||||
}
|
||||
|
||||
redis_node::~redis_node()
|
||||
@ -37,15 +18,53 @@ redis_node::~redis_node()
|
||||
|
||||
}
|
||||
|
||||
void redis_node::set_master(const redis_node* master)
|
||||
redis_node& redis_node::set_id(const char* id)
|
||||
{
|
||||
master_ = master;
|
||||
id_ = id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void redis_node::set_master_id(const char* id)
|
||||
redis_node& redis_node::set_addr(const char* addr)
|
||||
{
|
||||
addr_ = addr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
redis_node& redis_node::set_type(const char* type)
|
||||
{
|
||||
type_ = type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
redis_node& redis_node::set_myself(bool yesno)
|
||||
{
|
||||
myself_ = yesno;
|
||||
return *this;
|
||||
}
|
||||
|
||||
redis_node& redis_node::set_handshaking(bool yesno)
|
||||
{
|
||||
handshaking_ = yesno;
|
||||
return *this;
|
||||
}
|
||||
|
||||
redis_node& redis_node::set_connected(bool yesno)
|
||||
{
|
||||
connected_ = yesno;
|
||||
return *this;
|
||||
}
|
||||
|
||||
redis_node& redis_node::set_master(const redis_node* master)
|
||||
{
|
||||
master_ = master;
|
||||
return *this;
|
||||
}
|
||||
|
||||
redis_node& redis_node::set_master_id(const char* id)
|
||||
{
|
||||
if (id && *id)
|
||||
master_id_ = id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool redis_node::add_slave(redis_node* slave)
|
||||
@ -55,11 +74,20 @@ bool redis_node::add_slave(redis_node* slave)
|
||||
std::vector<redis_node*>::const_iterator cit;
|
||||
for (cit = slaves_.begin(); cit != slaves_.end(); ++cit)
|
||||
{
|
||||
if (*cit == slave
|
||||
|| strcmp(slave->get_id(), (*cit)->get_id()) == 0)
|
||||
if (*cit == slave)
|
||||
{
|
||||
logger_warn("slave exists, id: %s, addr: %s",
|
||||
(*cit)->get_id(), (*cit)->get_addr());
|
||||
printf("slave exists: %s, id: %s, addr: %s\r\n",
|
||||
slave->get_id(), (*cit)->get_id(),
|
||||
(*cit)->get_addr());
|
||||
return false;
|
||||
}
|
||||
if ((*slave->get_id()) == 0)
|
||||
continue;
|
||||
if (strcmp(slave->get_id(), (*cit)->get_id()) == 0)
|
||||
{
|
||||
printf("slave exists: %s, id: %s, addr: %s\r\n",
|
||||
slave->get_id(), (*cit)->get_id(),
|
||||
(*cit)->get_addr());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user