mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-25 12:43:09 +00:00
reconnect
This commit is contained in:
@@ -68,7 +68,7 @@ _read_queue(struct connection_pool * pool, int timeout) {
|
|||||||
void *
|
void *
|
||||||
connection_poll(struct connection_pool * pool, int timeout) {
|
connection_poll(struct connection_pool * pool, int timeout) {
|
||||||
if (pool->queue_head >= pool->queue_len) {
|
if (pool->queue_head >= pool->queue_len) {
|
||||||
if (_read_queue(pool, timeout) == -1) {
|
if (_read_queue(pool, timeout) <= 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
@@ -36,6 +37,13 @@ _open(lua_State *L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_close(lua_State *L) {
|
||||||
|
int fd = luaL_checkinteger(L,1);
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_write(lua_State *L) {
|
_write(lua_State *L) {
|
||||||
int fd = luaL_checkinteger(L,1);
|
int fd = luaL_checkinteger(L,1);
|
||||||
@@ -101,21 +109,36 @@ _push(lua_State *L) {
|
|||||||
buf = lua_touserdata(L,2);
|
buf = lua_touserdata(L,2);
|
||||||
size = luaL_checkinteger(L,3);
|
size = luaL_checkinteger(L,3);
|
||||||
}
|
}
|
||||||
buffer->read = 0;
|
int old_size = buffer->size - buffer->read;
|
||||||
if (size + buffer->size > buffer->cap) {
|
if (size + old_size > buffer->cap) {
|
||||||
if (buffer->cap == 0) {
|
if (buffer->cap == 0) {
|
||||||
lua_rawgetp(L, LUA_REGISTRYINDEX, _delete);
|
lua_rawgetp(L, LUA_REGISTRYINDEX, _delete);
|
||||||
lua_setmetatable(L, 1);
|
lua_setmetatable(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer->buffer = realloc(buffer->buffer, buffer->size + size);
|
if (buffer->read == 0) {
|
||||||
|
buffer->buffer = realloc(buffer->buffer, size+old_size);
|
||||||
|
memcpy(buffer->buffer + old_size , buf , size);
|
||||||
|
buffer->size += size;
|
||||||
|
} else {
|
||||||
|
char * new_buffer = malloc(size + old_size);
|
||||||
|
memcpy(new_buffer, buffer->buffer + buffer->read, old_size);
|
||||||
|
memcpy(new_buffer + old_size , buf, size);
|
||||||
|
free(buffer->buffer);
|
||||||
|
buffer->buffer = new_buffer;
|
||||||
|
buffer->read = 0;
|
||||||
|
buffer->size = old_size + size;
|
||||||
|
}
|
||||||
|
} else if (buffer->size + size > buffer->cap) {
|
||||||
|
memmove(buffer->buffer, buffer->buffer + buffer->read, old_size);
|
||||||
|
memcpy(buffer->buffer + old_size, buf, size);
|
||||||
|
buffer->read = 0;
|
||||||
|
buffer->size = old_size + size;
|
||||||
|
} else {
|
||||||
memcpy(buffer->buffer + buffer->size, buf, size);
|
memcpy(buffer->buffer + buffer->size, buf, size);
|
||||||
buffer->size += size;
|
buffer->size += size;
|
||||||
buffer->cap = buffer->size;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
memcpy(buffer->buffer+buffer->size, buf, size);
|
|
||||||
buffer->size += size;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,29 +173,16 @@ _readline(lua_State *L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
_yield(lua_State *L) {
|
|
||||||
luaL_checktype(L,1,LUA_TUSERDATA);
|
|
||||||
struct buffer * buffer = lua_touserdata(L,1);
|
|
||||||
if (buffer->read) {
|
|
||||||
int size = buffer->size - buffer->read;
|
|
||||||
memmove(buffer->buffer, buffer->buffer + buffer->read, size);
|
|
||||||
buffer->size -= buffer->read;
|
|
||||||
buffer->read = 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
luaopen_socket_c(lua_State *L) {
|
luaopen_socket_c(lua_State *L) {
|
||||||
luaL_Reg l[] = {
|
luaL_Reg l[] = {
|
||||||
{ "open", _open },
|
{ "open", _open },
|
||||||
|
{ "close", _close },
|
||||||
{ "write", _write },
|
{ "write", _write },
|
||||||
{ "new", _new },
|
{ "new", _new },
|
||||||
{ "push", _push },
|
{ "push", _push },
|
||||||
{ "read", _read },
|
{ "read", _read },
|
||||||
{ "readline", _readline },
|
{ "readline", _readline },
|
||||||
{ "yield", _yield },
|
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
luaL_checkversion(L);
|
luaL_checkversion(L);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -114,6 +115,7 @@ _poll(struct connection_server * server) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
|
connection_del(server->pool, c->fd);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
skynet_send(server->ctx, NULL, c->addr, 0x7fffffff, NULL, 0, DONTCOPY);
|
skynet_send(server->ctx, NULL, c->addr, 0x7fffffff, NULL, 0, DONTCOPY);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -9,14 +9,15 @@ function socket.connect(addr)
|
|||||||
local ip, port = string.match(addr,"([^:]+):(.+)")
|
local ip, port = string.match(addr,"([^:]+):(.+)")
|
||||||
port = tonumber(port)
|
port = tonumber(port)
|
||||||
fd = c.open(ip,port)
|
fd = c.open(ip,port)
|
||||||
|
if fd == nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
skynet.send(".connection","ADD "..fd.." "..skynet.self())
|
skynet.send(".connection","ADD "..fd.." "..skynet.self())
|
||||||
object = c.new()
|
object = c.new()
|
||||||
end
|
end
|
||||||
|
|
||||||
function socket.push(msg,sz)
|
function socket.push(msg,sz)
|
||||||
if msg == nil then
|
if msg then
|
||||||
socket.close()
|
|
||||||
else
|
|
||||||
c.push(object, msg, sz)
|
c.push(object, msg, sz)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -33,13 +34,12 @@ function socket.write(...)
|
|||||||
c.write(fd, ...)
|
c.write(fd, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function socket.yield()
|
|
||||||
c.yield(object)
|
|
||||||
end
|
|
||||||
|
|
||||||
function socket.close()
|
function socket.close()
|
||||||
skynet.send(".connection","DEL "..fd)
|
if fd then
|
||||||
fd = nil
|
c.close(fd)
|
||||||
|
skynet.send(".connection","DEL "..fd)
|
||||||
|
fd = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return socket
|
return socket
|
||||||
|
|||||||
@@ -24,13 +24,6 @@ local function select_db(id)
|
|||||||
assert(result and ok == "OK")
|
assert(result and ok == "OK")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function init()
|
|
||||||
socket.connect(redis_server)
|
|
||||||
if redis_db then
|
|
||||||
select_db(redis_db)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local request_queue = { head = 1, tail = 1 }
|
local request_queue = { head = 1, tail = 1 }
|
||||||
|
|
||||||
local function push_request_queue(reply)
|
local function push_request_queue(reply)
|
||||||
@@ -51,6 +44,26 @@ local function response(...)
|
|||||||
skynet.send(reply[2],reply[1],skynet.pack(...))
|
skynet.send(reply[2],reply[1],skynet.pack(...))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function readline(sep)
|
||||||
|
while true do
|
||||||
|
local line = socket.readline(sep)
|
||||||
|
if line then
|
||||||
|
return line
|
||||||
|
end
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function readbytes(bytes)
|
||||||
|
while true do
|
||||||
|
local block = socket.read(bytes)
|
||||||
|
if block then
|
||||||
|
return block
|
||||||
|
end
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local redcmd = {}
|
local redcmd = {}
|
||||||
|
|
||||||
redcmd[42] = function(data) -- '*'
|
redcmd[42] = function(data) -- '*'
|
||||||
@@ -61,15 +74,9 @@ redcmd[42] = function(data) -- '*'
|
|||||||
end
|
end
|
||||||
local bulk = {}
|
local bulk = {}
|
||||||
for i = 1,n do
|
for i = 1,n do
|
||||||
local line = socket.readline "\r\n"
|
local line = readline "\r\n"
|
||||||
if line == nil then
|
|
||||||
return "BLOCK"
|
|
||||||
end
|
|
||||||
local bytes = tonumber(string.sub(line,2) + 2)
|
local bytes = tonumber(string.sub(line,2) + 2)
|
||||||
local data = socket.read(bytes)
|
local data = readbytes(bytes)
|
||||||
if data == nil then
|
|
||||||
return "BLOCK"
|
|
||||||
end
|
|
||||||
table.insert(bulk, string.sub(data,1,-3))
|
table.insert(bulk, string.sub(data,1,-3))
|
||||||
end
|
end
|
||||||
response(true, bulk)
|
response(true, bulk)
|
||||||
@@ -81,10 +88,7 @@ redcmd[36] = function(data) -- '$'
|
|||||||
response(true,nil)
|
response(true,nil)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local firstline = socket.read(bytes+2)
|
local firstline = readbytes(bytes+2)
|
||||||
if firstline == nil then
|
|
||||||
return "BLOCK"
|
|
||||||
end
|
|
||||||
response(true,string.sub(firstline,1,-3))
|
response(true,string.sub(firstline,1,-3))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -101,31 +105,51 @@ redcmd[58] = function(data) -- ':'
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function split_package()
|
local function split_package()
|
||||||
local result = socket.readline "\r\n"
|
while true do
|
||||||
if result == nil then
|
local result = readline "\r\n"
|
||||||
return
|
local firstchar = string.byte(result)
|
||||||
|
local data = string.sub(result,2)
|
||||||
|
local f = redcmd[firstchar]
|
||||||
|
assert(f)
|
||||||
|
f(data)
|
||||||
end
|
end
|
||||||
local firstchar = string.byte(result)
|
end
|
||||||
local data = string.sub(result,2)
|
|
||||||
local f = redcmd[firstchar]
|
local function init()
|
||||||
assert(f)
|
while socket.connect(redis_server) do
|
||||||
if f(data) then
|
print("Connect failed : "..redis_server)
|
||||||
return
|
skynet.sleep(1000)
|
||||||
end
|
end
|
||||||
socket.yield()
|
if redis_db then
|
||||||
return true
|
select_db(redis_db)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local split_co = coroutine.create(split_package)
|
||||||
|
|
||||||
|
local function reconnect()
|
||||||
|
init()
|
||||||
|
for i = request_queue.head, request_queue.tail-1 do
|
||||||
|
local request = request_queue[i]
|
||||||
|
socket.write(request[3])
|
||||||
|
end
|
||||||
|
split_co = coroutine.create(split_package)
|
||||||
end
|
end
|
||||||
|
|
||||||
skynet.filter(
|
skynet.filter(
|
||||||
function(session, address , msg, sz)
|
function(session, address , msg, sz)
|
||||||
if session == 0x7fffffff then
|
if session == 0x7fffffff then
|
||||||
|
if msg == nil then
|
||||||
|
skynet.timeout(0, reconnect)
|
||||||
|
return
|
||||||
|
end
|
||||||
socket.push(msg,sz)
|
socket.push(msg,sz)
|
||||||
while split_package() do end
|
coroutine.resume(split_co)
|
||||||
elseif session < 0 then
|
elseif session < 0 then
|
||||||
local message = { skynet.unpack(msg,sz) }
|
local message = { skynet.unpack(msg,sz) }
|
||||||
local cmd = compose_message(message)
|
local cmd = compose_message(message)
|
||||||
socket.write(cmd)
|
socket.write(cmd)
|
||||||
push_request_queue { -session , address }
|
push_request_queue { -session , address, cmd }
|
||||||
else
|
else
|
||||||
return session, address, msg , sz
|
return session, address, msg , sz
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user