From d0ebca641773120c7574d5f67c51e9ae3a8d4185 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja@tarantool.org> Date: Mon, 17 Dec 2012 20:22:00 +0400 Subject: [PATCH] Provide a unique session identifier in fibers, box.fiber.sid(). --- include/fiber.h | 20 ++++++++++++++++++++ include/tarantool.h | 6 ++++++ src/admin.m | 1 + src/admin.rl | 1 + src/box/box.m | 8 ++++++++ src/fiber.m | 1 + src/iproto.m | 5 +++++ src/lua/init.m | 13 +++++++++++++ test/box/fiber.result | 21 +++++++++++++++++++++ test/box/fiber.test | 11 +++++++++++ 10 files changed, 87 insertions(+) diff --git a/include/fiber.h b/include/fiber.h index debae0dd54..1ef42904df 100644 --- a/include/fiber.h +++ b/include/fiber.h @@ -69,7 +69,18 @@ struct fiber { struct tarantool_coro coro; /* A garbage-collected memory pool. */ struct palloc_pool *gc_pool; + /** Fiber id. */ uint32_t fid; + /** + * Session id of the session the fiber is running + * on behalf of. The concept of an associated session + * is similar to the concept of controlling tty + * in a UNIX process. When a fiber is created, + * its sid is 0. If it's running a request on behalf + * of a user connection, it's sid is changed to module- + * generated identifier of the session. + */ + uint32_t sid; struct rlist link; struct rlist state; @@ -128,4 +139,13 @@ struct tbuf; void fiber_info(struct tbuf *out); void fiber_schedule(ev_watcher *watcher, int event __attribute__((unused))); +/** + * Attach this fiber to a session identified by sid. + */ +static inline void +fiber_set_sid(struct fiber *f, uint32_t sid) +{ + f->sid = sid; +} + #endif /* TARANTOOL_FIBER_H_INCLUDED */ diff --git a/include/tarantool.h b/include/tarantool.h index 4fc14067f8..a24561673d 100644 --- a/include/tarantool.h +++ b/include/tarantool.h @@ -46,6 +46,12 @@ int mod_cat(const char *filename); void mod_snapshot(struct log_io *, struct fio_batch *batch); void mod_info(struct tbuf *out); const char *mod_status(void); +/** + * Issue a new session identifier - + * called by the networking layer + * when a new connection is established. + */ +uint32_t mod_sid(); extern int snapshot_pid; extern struct tarantool_cfg cfg; diff --git a/src/admin.m b/src/admin.m index 5b95ab7583..31c92d08ed 100644 --- a/src/admin.m +++ b/src/admin.m @@ -1888,6 +1888,7 @@ admin_handler(va_list ap) { struct ev_io coio = va_arg(ap, struct ev_io); struct iobuf *iobuf = va_arg(ap, struct iobuf *); + fiber_set_sid(fiber, mod_sid()); lua_State *L = lua_newthread(tarantool_L); int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX); @try { diff --git a/src/admin.rl b/src/admin.rl index efebc095a3..752a09a37e 100644 --- a/src/admin.rl +++ b/src/admin.rl @@ -329,6 +329,7 @@ admin_handler(va_list ap) { struct ev_io coio = va_arg(ap, struct ev_io); struct iobuf *iobuf = va_arg(ap, struct iobuf *); + fiber_set_sid(fiber, mod_sid()); lua_State *L = lua_newthread(tarantool_L); int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX); @try { diff --git a/src/box/box.m b/src/box/box.m index 8d6668944c..ffba2b7eb9 100644 --- a/src/box/box.m +++ b/src/box/box.m @@ -543,3 +543,11 @@ mod_status(void) { return status; } + + +uint32_t +mod_sid() +{ + static uint32_t sid = 1; + return sid++; +} diff --git a/src/fiber.m b/src/fiber.m index 693203f443..6fd21fd7e8 100644 --- a/src/fiber.m +++ b/src/fiber.m @@ -429,6 +429,7 @@ fiber_create(const char *name, void (*f) (va_list)) if (++last_used_fid < 100) last_used_fid = 100; fiber->fid = last_used_fid; + fiber->sid = 0; fiber->flags = 0; fiber->waiter = NULL; fiber_set_name(fiber, name); diff --git a/src/iproto.m b/src/iproto.m index 1e622ef106..bbaed4aaa8 100644 --- a/src/iproto.m +++ b/src/iproto.m @@ -32,6 +32,7 @@ #include <stdarg.h> #include <stdio.h> +#include "tarantool.h" #include "exception.h" #include "errcode.h" #include "fiber.h" @@ -254,6 +255,8 @@ struct iproto_session mod_process_func *handler; struct ev_io input; struct ev_io output; + /** Mod session id. */ + uint32_t sid; }; SLIST_HEAD(, iproto_session) iproto_session_cache = @@ -297,6 +300,7 @@ iproto_session_create(const char *name, int fd, mod_process_func *param) session->iobuf[1] = iobuf_create(name); session->parse_size = 0; session->write_pos = obuf_create_svp(&session->iobuf[0]->out); + session->sid = mod_sid(); return session; } @@ -618,6 +622,7 @@ restart: continue; } @try { + fiber_set_sid(fiber, session->sid); iproto_reply(&port, *session->handler, &iobuf->out, header); } @finally { iobuf->in.pos += sizeof(*header) + header->len; diff --git a/src/lua/init.m b/src/lua/init.m index 527c67ce98..50b56c3a69 100644 --- a/src/lua/init.m +++ b/src/lua/init.m @@ -568,6 +568,14 @@ lbox_fiber_id(struct lua_State *L) return 1; } +static int +lbox_fiber_sid(struct lua_State *L) +{ + struct fiber *f = lua_gettop(L) ? lbox_checkfiber(L, 1) : fiber; + lua_pushinteger(L, f->sid); + return 1; +} + static struct lua_State * box_lua_fiber_get_coro(struct lua_State *L, struct fiber *f) { @@ -680,6 +688,8 @@ lbox_fiber_detach(struct lua_State *L) /* Clear the caller, to avoid a reference leak. */ /* Request a detach. */ lua_pushinteger(L, DETACH); + /* A detached fiber has no associated session. */ + fiber_set_sid(fiber, 0); fiber_yield_to(caller); return 0; } @@ -788,6 +798,7 @@ lbox_fiber_create(struct lua_State *L) " reached"); struct fiber *f = fiber_create("lua", box_lua_fiber_run); + fiber_set_sid(f, fiber->sid); /* Initially the fiber is cancellable */ f->flags |= FIBER_USER_MODE | FIBER_CANCELLABLE; @@ -1037,6 +1048,7 @@ lbox_fiber_testcancel(struct lua_State *L) static const struct luaL_reg lbox_fiber_meta [] = { {"id", lbox_fiber_id}, + {"sid", lbox_fiber_sid}, {"name", lbox_fiber_name}, {"__gc", lbox_fiber_gc}, {NULL, NULL} @@ -1046,6 +1058,7 @@ static const struct luaL_reg fiberlib[] = { {"sleep", lbox_fiber_sleep}, {"self", lbox_fiber_self}, {"id", lbox_fiber_id}, + {"sid", lbox_fiber_sid}, {"find", lbox_fiber_find}, {"cancel", lbox_fiber_cancel}, {"testcancel", lbox_fiber_testcancel}, diff --git a/test/box/fiber.result b/test/box/fiber.result index b44c7713d2..efe9afecf3 100644 --- a/test/box/fiber.result +++ b/test/box/fiber.result @@ -201,3 +201,24 @@ lua box.fiber.find(920) lua box.space[0]:truncate() --- ... +lua box.fiber.sid() > 0 +--- + - true +... +lua f = box.fiber.create(function() box.fiber.detach() failed = box.fiber.sid() ~= 0 end) +--- +... +lua box.fiber.resume(f) +--- +... +lua failed +--- + - false +... +lua f = box.fiber.create(function() if box.fiber.sid() == 0 then error('wrong sid') end end) +--- +... +lua box.fiber.resume(f) +--- + - true +... diff --git a/test/box/fiber.test b/test/box/fiber.test index bdd160e8fa..ff6b2e9f79 100644 --- a/test/box/fiber.test +++ b/test/box/fiber.test @@ -1,4 +1,5 @@ # encoding: tarantool +import sys # A test case for a race condition between ev_schedule # and wal_schedule fiber schedulers. # The same fiber should not be scheduled by ev_schedule (e.g. @@ -79,3 +80,13 @@ exec admin "lua box.fiber.find(900)" exec admin "lua box.fiber.find(910)" exec admin "lua box.fiber.find(920)" exec admin "lua box.space[0]:truncate()" + +# check fiber.sid() and fiber.id() +exec admin "lua box.fiber.sid() > 0" +exec admin "lua f = box.fiber.create(function() box.fiber.detach() failed = box.fiber.sid() ~= 0 end)" +exec admin "lua box.fiber.resume(f)" +exec admin "lua failed" +exec admin "lua f = box.fiber.create(function() if box.fiber.sid() == 0 then error('wrong sid') end end)" +exec admin "lua box.fiber.resume(f)" + + -- GitLab