From a8dcee6fef5a89512916e7f9d734fd224f8d71ac Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja@tarantool.org> Date: Thu, 25 Dec 2014 17:58:38 +0300 Subject: [PATCH] Rename libcore to libserver. libcore is a thick a thick bundle with almost everything. Rename it to libserver. Extract the minimal server core with fibers & exceptions into libcore. Add a prototype unit test for fibers. --- src/CMakeLists.txt | 41 ++++++++++--------- src/box/CMakeLists.txt | 2 + src/box/bitset_index.cc | 1 - src/box/cluster.cc | 1 - src/box/engine.cc | 1 - src/box/engine.h | 1 - src/box/engine_memtx.cc | 1 - src/box/engine_sophia.cc | 1 - src/{ => box}/errcode.c | 1 + src/{ => box}/errcode.h | 16 +++++--- src/box/error.cc | 75 +++++++++++++++++++++++++++++++++++ src/box/error.h | 85 ++++++++++++++++++++++++++++++++++++++++ src/box/hash_index.cc | 1 - src/box/index.cc | 1 - src/box/index.h | 1 - src/box/iproto.cc | 18 ++++----- src/box/iproto_port.cc | 14 ++++++- src/box/iproto_port.h | 2 +- src/box/key_def.cc | 1 - src/box/key_def.h | 2 +- src/box/lua/error.cc | 2 +- src/box/replication.cc | 1 + src/box/rtree_index.cc | 1 - src/box/schema.h | 3 +- src/box/session.cc | 1 - src/box/sophia_index.cc | 1 - src/box/space.cc | 1 - src/box/space.h | 1 - src/box/tree_index.cc | 1 - src/box/tuple.cc | 1 - src/box/tuple_update.cc | 2 +- src/box/vclock.h | 2 +- src/box/xrow.cc | 1 - src/coeio.cc | 24 ++++++++++++ src/coeio.h | 13 ++++++ src/coio.cc | 3 +- src/coro.cc | 3 +- src/evio.cc | 2 +- src/exception.cc | 61 +++++++++++----------------- src/exception.h | 63 +++++------------------------ src/fiber.cc | 35 ++--------------- src/fiber.h | 15 ++----- src/iobuf.cc | 3 +- src/lib/small/mempool.h | 6 +-- src/lib/small/region.h | 3 +- src/lib/small/small.h | 3 +- src/lua/fiber.cc | 5 ++- src/lua/init.cc | 2 +- src/lua/trigger.cc | 2 +- src/lua/utils.cc | 8 ++++ src/lua/utils.h | 14 ++++--- src/pickle.h | 29 -------------- test/box/session.result | 4 +- test/unit/CMakeLists.txt | 10 +++-- test/unit/fiber.cc | 10 +++++ test/unit/fiber.result | 0 56 files changed, 350 insertions(+), 252 deletions(-) rename src/{ => box}/errcode.c (98%) rename src/{ => box}/errcode.h (97%) create mode 100644 src/box/error.cc create mode 100644 src/box/error.h create mode 100644 test/unit/fiber.cc create mode 100644 test/unit/fiber.result diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0028d08b1..18784fd0ba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,9 +42,25 @@ add_custom_target(ragel WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND ragel -G2 src/uri.rl -o src/uri.c) -set (common_sources +set (core_sources + say.cc memory.cc fiber.cc + exception.cc + coro.cc + object.cc + assoc.c + ) + +add_library(core STATIC ${core_sources}) +target_link_libraries(core + salad small + ${LIBEV_LIBRARIES} + ${LIBEIO_LIBRARIES} + ${LIBCORO_LIBRARIES} +) + +set (server_sources util.cc find_path.c sio.cc @@ -54,15 +70,9 @@ set (common_sources iobuf.cc coio_buf.cc pickle.cc - coro.cc stat.cc - object.cc - exception.cc ipc.cc errinj.cc - errcode.c - assoc.c - say.cc fio.c crc32.c random.c @@ -90,19 +100,16 @@ set (common_sources ) if (ENABLE_TRACE) - set (common_sources ${common_sources} trace.c) + set (server_sources ${server_sources} trace.c) endif() -set_source_files_compile_flags(${common_sources}) -add_library(core STATIC ${common_sources}) -target_link_libraries(core pthread) +set_source_files_compile_flags(${server_sources}) +add_library(server STATIC ${server_sources}) +target_link_libraries(server core pthread) -set (common_libraries core small salad misc bitset msgpuck) +set (common_libraries server core misc bitset msgpuck) list(APPEND common_libraries - ${LIBEV_LIBRARIES} - ${LIBEIO_LIBRARIES} - ${LIBCORO_LIBRARIES} ${LIBGOPT_LIBRARIES} ${LIBCJSON_LIBRARIES} ${LIBYAML_LIBRARIES} @@ -110,10 +117,6 @@ list(APPEND common_libraries ${LUAJIT_LIB} ) -set (THREAD_LIB pthread) - -set (common_libraries ${common_libraries} ${THREAD_LIB}) - if (TARGET_OS_LINUX OR TARGET_OS_DEBIAN_FREEBSD) set (common_libraries ${common_libraries} dl) endif() diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt index 764d85c154..7ec1dcf708 100644 --- a/src/box/CMakeLists.txt +++ b/src/box/CMakeLists.txt @@ -20,6 +20,8 @@ add_library(box iproto.cc iproto_constants.c iproto_port.cc + errcode.c + error.cc xrow.cc xlog.cc tuple.cc diff --git a/src/box/bitset_index.cc b/src/box/bitset_index.cc index 992af64cde..4b04adb8d5 100644 --- a/src/box/bitset_index.cc +++ b/src/box/bitset_index.cc @@ -32,7 +32,6 @@ #include <string.h> #include "tuple.h" -#include "exception.h" #include "bitset/index.h" static inline struct tuple * diff --git a/src/box/cluster.cc b/src/box/cluster.cc index 031ecff6a6..56490b4ce8 100644 --- a/src/box/cluster.cc +++ b/src/box/cluster.cc @@ -29,7 +29,6 @@ #include "box.h" #include "cluster.h" #include "recovery.h" -#include "exception.h" /** * Globally unique identifier of this cluster. diff --git a/src/box/engine.cc b/src/box/engine.cc index ffa5283039..13cb149224 100644 --- a/src/box/engine.cc +++ b/src/box/engine.cc @@ -28,7 +28,6 @@ */ #include "engine.h" #include "space.h" -#include "exception.h" #include "salad/rlist.h" #include <stdlib.h> #include <string.h> diff --git a/src/box/engine.h b/src/box/engine.h index 478ea0e043..c811cef6d5 100644 --- a/src/box/engine.h +++ b/src/box/engine.h @@ -28,7 +28,6 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include <exception.h> #include "index.h" struct space; diff --git a/src/box/engine_memtx.cc b/src/box/engine_memtx.cc index 2118b15d14..2011f03742 100644 --- a/src/box/engine_memtx.cc +++ b/src/box/engine_memtx.cc @@ -36,7 +36,6 @@ #include "rtree_index.h" #include "bitset_index.h" #include "space.h" -#include "exception.h" #include "salad/rlist.h" #include <stdlib.h> #include <string.h> diff --git a/src/box/engine_sophia.cc b/src/box/engine_sophia.cc index efccbb2a58..a8c158dfbc 100644 --- a/src/box/engine_sophia.cc +++ b/src/box/engine_sophia.cc @@ -36,7 +36,6 @@ #include "index.h" #include "sophia_index.h" #include "space.h" -#include "exception.h" #include "salad/rlist.h" #include <sophia.h> #include <stdlib.h> diff --git a/src/errcode.c b/src/box/errcode.c similarity index 98% rename from src/errcode.c rename to src/box/errcode.c index 9cc3615e73..e90747e439 100644 --- a/src/errcode.c +++ b/src/box/errcode.c @@ -27,6 +27,7 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include "errcode.h" #define ERRCODE_RECORD_MEMBER(s, f, d) { \ .errstr = #s, \ diff --git a/src/errcode.h b/src/box/errcode.h similarity index 97% rename from src/errcode.h rename to src/box/errcode.h index a128fe3319..7d0f973c1a 100644 --- a/src/errcode.h +++ b/src/box/errcode.h @@ -1,5 +1,5 @@ -#ifndef TARANTOOL_ERRCODE_H_INCLUDED -#define TARANTOOL_ERRCODE_H_INCLUDED +#ifndef TARANTOOL_BOX_ERRCODE_H_INCLUDED +#define TARANTOOL_BOX_ERRCODE_H_INCLUDED /* * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following @@ -32,14 +32,16 @@ #include "trivia/util.h" +#ifdef __cplusplus +extern "C" { +#endif + struct errcode_record { const char *errstr; const char *errdesc; uint8_t errflags; }; -enum { TNT_ERRMSG_MAX = 512 }; - /* * To add a new error code to Tarantool, extend this array. * @@ -172,4 +174,8 @@ static inline const char *tnt_errcode_desc(uint32_t errcode) return tnt_error_codes[errcode].errdesc; } -#endif /* TARANTOOL_ERRCODE_H_INCLUDED */ +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TARANTOOL_BOX_ERRCODE_H_INCLUDED */ diff --git a/src/box/error.cc b/src/box/error.cc new file mode 100644 index 0000000000..f3fc39e74e --- /dev/null +++ b/src/box/error.cc @@ -0,0 +1,75 @@ +/* + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "error.h" +#include <stdio.h> +#include <typeinfo> + +ClientError::ClientError(const char *file, unsigned line, uint32_t errcode, ...) + : Exception(file, line) +{ + m_errcode = errcode; + va_list ap; + va_start(ap, errcode); + vsnprintf(m_errmsg, sizeof(m_errmsg) - 1, + tnt_errcode_desc(m_errcode), ap); + m_errmsg[sizeof(m_errmsg) - 1] = 0; + va_end(ap); +} + +ClientError::ClientError(const char *file, unsigned line, const char *msg, + uint32_t errcode) + : Exception(file, line) +{ + m_errcode = errcode; + strncpy(m_errmsg, msg, sizeof(m_errmsg) - 1); + m_errmsg[sizeof(m_errmsg) - 1] = 0; +} + +void +ClientError::log() const +{ + _say(S_ERROR, m_file, m_line, NULL, "%s: %s", tnt_errcode_str(m_errcode), + m_errmsg); +} + + +uint32_t +ClientError::get_code_for_foreign_exception(const Exception *e) +{ + if (typeid(*e) == typeid(OutOfMemory)) + return ER_MEMORY_ISSUE; + return ER_PROC_LUA; +} + +ErrorInjection::ErrorInjection(const char *file, unsigned line, const char *msg) + : LoggedError(file, line, ER_INJECTION, msg) +{ + /* nothing */ +} + diff --git a/src/box/error.h b/src/box/error.h new file mode 100644 index 0000000000..908e46c320 --- /dev/null +++ b/src/box/error.h @@ -0,0 +1,85 @@ +#ifndef TARANTOOL_BOX_ERROR_H_INCLUDED +#define TARANTOOL_BOX_ERROR_H_INCLUDED +/* + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "errcode.h" +#include "exception.h" + +class ClientError: public Exception { +public: + virtual void raise() + { + throw this; + } + + virtual void log() const; + + int + errcode() const + { + return m_errcode; + } + + ClientError(const char *file, unsigned line, uint32_t errcode, ...); + /* A special constructor for lbox_raise */ + ClientError(const char *file, unsigned line, const char *msg, + uint32_t errcode); + + static uint32_t get_code_for_foreign_exception(const Exception *e); +private: + /* client errno code */ + int m_errcode; +}; + +class LoggedError: public ClientError { +public: + template <typename ... Args> + LoggedError(const char *file, unsigned line, uint32_t errcode, Args ... args) + : ClientError(file, line, errcode, args...) + { + /* TODO: actually calls ClientError::log */ + log(); + } +}; + +class IllegalParams: public LoggedError { +public: + template <typename ... Args> + IllegalParams(const char *file, unsigned line, const char *format, + Args ... args) + :LoggedError(file, line, ER_ILLEGAL_PARAMS, + format, args...) {} +}; + +class ErrorInjection: public LoggedError { +public: + ErrorInjection(const char *file, unsigned line, const char *msg); +}; + +#endif /* TARANTOOL_BOX_ERROR_H_INCLUDED */ diff --git a/src/box/hash_index.cc b/src/box/hash_index.cc index 75b60d2bc4..3591a3ff43 100644 --- a/src/box/hash_index.cc +++ b/src/box/hash_index.cc @@ -29,7 +29,6 @@ #include "hash_index.h" #include "say.h" #include "tuple.h" -#include "exception.h" #include "errinj.h" #include "third_party/PMurHash.h" diff --git a/src/box/index.cc b/src/box/index.cc index 209d92aa73..c577549b8e 100644 --- a/src/box/index.cc +++ b/src/box/index.cc @@ -33,7 +33,6 @@ #include "sophia_index.h" #include "tuple.h" #include "say.h" -#include "exception.h" #include "schema.h" STRS(iterator_type, ITERATOR_TYPE); diff --git a/src/box/index.h b/src/box/index.h index a86fd2f1c7..7b609c3a05 100644 --- a/src/box/index.h +++ b/src/box/index.h @@ -33,7 +33,6 @@ #include "object.h" #include "key_def.h" -#include "exception.h" struct tuple; diff --git a/src/box/iproto.cc b/src/box/iproto.cc index b7a371d67c..c2b04236d9 100644 --- a/src/box/iproto.cc +++ b/src/box/iproto.cc @@ -34,8 +34,6 @@ #include "iproto_port.h" #include "tarantool.h" -#include "exception.h" -#include "errcode.h" #include "fiber.h" #include "say.h" #include "evio.h" @@ -584,7 +582,7 @@ iproto_flush(struct iobuf *iobuf, int fd, struct obuf_svp *svp) nwr = sio_writev(fd, iov, iovcnt); sio_add_to_iov(iov, svp->iov_len); - } catch (Exception *) { + } catch (SocketError *) { sio_add_to_iov(iov, svp->iov_len); throw; } @@ -660,7 +658,7 @@ iproto_process_dml(struct iproto_request *ireq) iproto_port_init(&port, out, ireq->header.sync); try { box_process((struct port *) &port, &ireq->request); - } catch (ClientError *e) { + } catch (Exception *e) { if (port.found) obuf_rollback_to_svp(out, &port.svp); iproto_reply_error(out, e, ireq->header.sync); @@ -714,7 +712,7 @@ iproto_process_admin(struct iproto_request *ireq) tnt_raise(ClientError, ER_UNKNOWN_REQUEST_TYPE, (uint32_t) ireq->header.type); } - } catch (ClientError *e) { + } catch (Exception *e) { say_error("admin command error: %s", e->errmsg()); iproto_reply_error(&iobuf->out, e, ireq->header.sync); } @@ -763,7 +761,11 @@ iproto_process_connect(struct iproto_request *request) IPROTO_GREETING_SIZE); if (! rlist_empty(&session_on_connect)) session_run_on_connect_triggers(con->session); - } catch (ClientError *e) { + } catch (SocketError *e) { + e->log(); + iproto_connection_close(con); + return; + } catch (Exception *e) { iproto_reply_error(&iobuf->out, e, request->header.type); try { iproto_flush(iobuf, fd, &con->write_pos); @@ -772,10 +774,6 @@ iproto_process_connect(struct iproto_request *request) } iproto_connection_close(con); return; - } catch (Exception *e) { - e->log(); - iproto_connection_close(con); - return; } /* * Connect is synchronous, so no one could have been diff --git a/src/box/iproto_port.cc b/src/box/iproto_port.cc index b1f227dd1d..d2810a08b5 100644 --- a/src/box/iproto_port.cc +++ b/src/box/iproto_port.cc @@ -77,17 +77,27 @@ iproto_reply_ping(struct obuf *out, uint64_t sync) obuf_dup(out, &reply, sizeof(reply)); } +static inline uint32_t +get_errcode(const Exception *e) +{ + const ClientError *error = dynamic_cast<const ClientError *>(e); + if (error) + return error->errcode(); + return ClientError::get_code_for_foreign_exception(e); +} + void -iproto_reply_error(struct obuf *out, const ClientError *e, uint64_t sync) +iproto_reply_error(struct obuf *out, const Exception *e, uint64_t sync) { uint32_t msg_len = strlen(e->errmsg()); + uint32_t errcode = get_errcode(e); struct iproto_header_bin header = iproto_header_bin; struct iproto_body_bin body = iproto_error_bin; uint32_t len = sizeof(header) - 5 + sizeof(body) + msg_len; header.v_len = mp_bswap_u32(len); - header.v_code = mp_bswap_u32(iproto_encode_error(e->errcode())); + header.v_code = mp_bswap_u32(iproto_encode_error(errcode)); header.v_sync = mp_bswap_u64(sync); body.v_data_len = mp_bswap_u32(msg_len); diff --git a/src/box/iproto_port.h b/src/box/iproto_port.h index 0613854abf..9349f71c60 100644 --- a/src/box/iproto_port.h +++ b/src/box/iproto_port.h @@ -86,6 +86,6 @@ iproto_reply_ping(struct obuf *out, uint64_t sync); /** Send an error packet back. */ void -iproto_reply_error(struct obuf *out, const ClientError *e, uint64_t sync); +iproto_reply_error(struct obuf *out, const Exception *e, uint64_t sync); #endif /* TARANTOOL_IPROTO_PORT_H_INCLUDED */ diff --git a/src/box/key_def.cc b/src/box/key_def.cc index 7a071d490e..54b655dccb 100644 --- a/src/box/key_def.cc +++ b/src/box/key_def.cc @@ -31,7 +31,6 @@ #include "schema.h" #include <stdlib.h> #include <stdio.h> -#include "exception.h" const char *field_type_strs[] = {"UNKNOWN", "NUM", "STR", "ARRAY", "NUMBER", ""}; STRS(index_type, ENUM_INDEX_TYPE); diff --git a/src/box/key_def.h b/src/box/key_def.h index b347740c54..574b2651c0 100644 --- a/src/box/key_def.h +++ b/src/box/key_def.h @@ -30,7 +30,7 @@ */ #include "trivia/util.h" #include "salad/rlist.h" -#include <exception.h> +#include "error.h" #include "msgpuck/msgpuck.h" #define RB_COMPACT 1 #include "third_party/rb.h" diff --git a/src/box/lua/error.cc b/src/box/lua/error.cc index 00d3baabef..6c817a6f38 100644 --- a/src/box/lua/error.cc +++ b/src/box/lua/error.cc @@ -35,10 +35,10 @@ extern "C" { } /* extern "C" */ #include <fiber.h> -#include <errcode.h> #include <errinj.h> #include "lua/utils.h" +#include "box/error.h" static int lbox_raise(lua_State *L) diff --git a/src/box/replication.cc b/src/box/replication.cc index ab7bbaa299..dd54ab0167 100644 --- a/src/box/replication.cc +++ b/src/box/replication.cc @@ -51,6 +51,7 @@ #include "box/vclock.h" #include "scoped_guard.h" #include "xrow.h" +#include "coeio.h" /** Replication topology * ---------------------- diff --git a/src/box/rtree_index.cc b/src/box/rtree_index.cc index 5869d24d00..a54ec9ffc2 100644 --- a/src/box/rtree_index.cc +++ b/src/box/rtree_index.cc @@ -29,7 +29,6 @@ #include "rtree_index.h" #include "tuple.h" #include "space.h" -#include "exception.h" #include "errinj.h" #include "fiber.h" #include "small/small.h" diff --git a/src/box/schema.h b/src/box/schema.h index cbd77926c2..201293ec78 100644 --- a/src/box/schema.h +++ b/src/box/schema.h @@ -28,7 +28,7 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include "exception.h" +#include "error.h" #include <stdio.h> /* snprintf */ enum schema_id { @@ -163,5 +163,4 @@ func_by_name(const char *name, uint32_t name_len) bool schema_find_grants(const char *type, uint32_t id); - #endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H */ diff --git a/src/box/session.cc b/src/box/session.cc index 28df060602..b0f9519760 100644 --- a/src/box/session.cc +++ b/src/box/session.cc @@ -32,7 +32,6 @@ #include "assoc.h" #include "trigger.h" -#include "exception.h" #include "random.h" #include <sys/socket.h> #include "user.h" diff --git a/src/box/sophia_index.cc b/src/box/sophia_index.cc index ebe9abb726..8191090c1f 100644 --- a/src/box/sophia_index.cc +++ b/src/box/sophia_index.cc @@ -30,7 +30,6 @@ #include "say.h" #include "tuple.h" #include "scoped_guard.h" -#include "exception.h" #include "errinj.h" #include "schema.h" #include "space.h" diff --git a/src/box/space.cc b/src/box/space.cc index 8350b8cdd4..413bfc03c4 100644 --- a/src/box/space.cc +++ b/src/box/space.cc @@ -29,7 +29,6 @@ #include "space.h" #include <stdlib.h> #include <string.h> -#include <exception.h> #include "tuple.h" #include "scoped_guard.h" #include "trigger.h" diff --git a/src/box/space.h b/src/box/space.h index f171e68ca8..d6168e611d 100644 --- a/src/box/space.h +++ b/src/box/space.h @@ -32,7 +32,6 @@ #include "key_def.h" #include "engine.h" #include "salad/rlist.h" -#include <exception.h> struct space { struct access access[BOX_USER_MAX]; diff --git a/src/box/tree_index.cc b/src/box/tree_index.cc index d877a09e46..122e068bba 100644 --- a/src/box/tree_index.cc +++ b/src/box/tree_index.cc @@ -29,7 +29,6 @@ #include "tree_index.h" #include "tuple.h" #include "space.h" -#include "exception.h" #include "errinj.h" #include "memory.h" #include "fiber.h" diff --git a/src/box/tuple.cc b/src/box/tuple.cc index d00728e2c8..0791038dbc 100644 --- a/src/box/tuple.cc +++ b/src/box/tuple.cc @@ -33,7 +33,6 @@ #include "key_def.h" #include "tuple_update.h" -#include <exception.h> #include <stdio.h> /** Global table of tuple formats */ diff --git a/src/box/tuple_update.cc b/src/box/tuple_update.cc index 6026259d2f..df68bb3bbd 100644 --- a/src/box/tuple_update.cc +++ b/src/box/tuple_update.cc @@ -33,7 +33,7 @@ #include "third_party/queue.h" #include "salad/rope.h" -#include <exception.h> +#include "error.h" #include "msgpuck/msgpuck.h" /** UPDATE request implementation. diff --git a/src/box/vclock.h b/src/box/vclock.h index 4318b54bad..d438a7bdfd 100644 --- a/src/box/vclock.h +++ b/src/box/vclock.h @@ -192,7 +192,7 @@ vclockset_isearch(vclockset_t *set, struct vclock *key) #if defined(__cplusplus) } /* extern "C" */ -#include "exception.h" +#include "error.h" /** * Allocate a new vclock object and initialize it diff --git a/src/box/xrow.cc b/src/box/xrow.cc index 1f5761d313..aedc8d19d3 100644 --- a/src/box/xrow.cc +++ b/src/box/xrow.cc @@ -28,7 +28,6 @@ */ #include "xrow.h" #include "msgpuck/msgpuck.h" -#include "exception.h" #include "fiber.h" #include "tt_uuid.h" #include "vclock.h" diff --git a/src/coeio.cc b/src/coeio.cc index 9ff1293226..6ea8282244 100644 --- a/src/coeio.cc +++ b/src/coeio.cc @@ -283,3 +283,27 @@ coeio_resolve(int socktype, const char *host, const char *port, return NULL; return result; } + +ssize_t +cord_cojoin_cb(va_list ap) +{ + struct cord *cord = va_arg(ap, struct cord *); + void *retval = NULL; + int res = tt_pthread_join(cord->id, &retval); + return res; +} + +int +cord_cojoin(struct cord *cord) +{ + assert(cord() != cord); /* Can't join self. */ + int rc = coeio_custom(cord_cojoin_cb, TIMEOUT_INFINITY, cord); + if (rc == 0 && cord->exception) { + Exception::move(cord, cord()); + cord_destroy(cord); + cord()->exception->raise(); /* re-throw exception from cord */ + } + cord_destroy(cord); + return rc; +} + diff --git a/src/coeio.h b/src/coeio.h index 6536063c55..da7d18ce0d 100644 --- a/src/coeio.h +++ b/src/coeio.h @@ -67,4 +67,17 @@ coeio_resolve(int socktype, const char *host, const char *port, #if defined(__cplusplus) } #endif + +struct cord; +/** + * \brief Yield until \a cord has terminated. + * If \a cord has terminated with an uncaught exception + * **re-throws** this exception in the calling cord/fiber. + * \param cord cord + * \sa pthread_join() + * \return 0 on success + */ +int +cord_cojoin(struct cord *cord); + #endif /* TARANTOOL_COEIO_H_INCLUDED */ diff --git a/src/coio.cc b/src/coio.cc index b8b5e5edd2..e2903365f1 100644 --- a/src/coio.cc +++ b/src/coio.cc @@ -410,7 +410,7 @@ coio_flush(int fd, struct iovec *iov, ssize_t offset, int iovcnt) sio_add_to_iov(iov, -offset); nwr = sio_writev(fd, iov, iovcnt); sio_add_to_iov(iov, offset); - } catch (Exception *e) { + } catch (SocketError *e) { sio_add_to_iov(iov, offset); throw; } @@ -578,6 +578,7 @@ coio_service_on_accept(struct evio_service *evio_service, iobuf = iobuf_new(iobuf_name); f = fiber_new(fiber_name, service->handler); } catch (Exception *e) { + e->log(); say_error("can't create a handler fiber, dropping client connection"); evio_close(loop(), &coio); if (iobuf) diff --git a/src/coro.cc b/src/coro.cc index 74bdb283c9..eb3aebaafc 100644 --- a/src/coro.cc +++ b/src/coro.cc @@ -51,8 +51,7 @@ tarantool_coro_create(struct tarantool_coro *coro, + slab_sizeof(); if (coro->stack == NULL) { - tnt_raise(LoggedError, ER_MEMORY_ISSUE, - sizeof(coro->stack_size), + tnt_raise(OutOfMemory, sizeof(coro->stack_size), "mmap", "coro stack"); } diff --git a/src/evio.cc b/src/evio.cc index 7ce4e681b1..1d3cbead4a 100644 --- a/src/evio.cc +++ b/src/evio.cc @@ -297,7 +297,7 @@ evio_service_init(ev_loop *loop, struct uri u; if (uri_parse(&u, uri) || u.service == NULL) - tnt_raise(IllegalParams, "invalid uri for bind: %s", uri); + tnt_raise(SocketError, -1, "invalid uri for bind: %s", uri); snprintf(service->serv, sizeof(service->serv), "%.*s", (int) u.service_len, u.service); diff --git a/src/exception.cc b/src/exception.cc index aefc9f26e5..a9e45e42c6 100644 --- a/src/exception.cc +++ b/src/exception.cc @@ -33,10 +33,10 @@ #include <stdio.h> #include <string.h> #include <errno.h> +#include <typeinfo> -/* Statically allocate out-of-memory exception */ -ClientError out_of_memory(__FILE__, __LINE__, ER_MEMORY_ISSUE, 0, - "exception", "new"); +static OutOfMemory out_of_memory(__FILE__, __LINE__, + sizeof(OutOfMemory), "malloc", "exception"); void * Exception::operator new(size_t size) @@ -56,7 +56,7 @@ Exception::operator new(size_t size) } free(cord->exception); } - cord->exception = (ClientError *) malloc(size); + cord->exception = (Exception *) malloc(size); if (cord->exception) { cord->exception_size = size; return cord->exception; @@ -112,9 +112,17 @@ Exception::Exception(const Exception& e) memcpy(m_errmsg, e.m_errmsg, sizeof(m_errmsg)); } +void +Exception::log() const +{ + _say(S_ERROR, m_file, m_line, "%s %s", + typeid(*this).name(), m_errmsg); +} + + SystemError::SystemError(const char *file, unsigned line) : Exception(file, line), - m_errnum(errno) + m_errno(errno) { /* nothing */ } @@ -137,42 +145,17 @@ SystemError::init(const char *format, va_list ap) void SystemError::log() const { - _say(S_SYSERROR, m_file, m_line, strerror(m_errnum), "SystemError %s", + _say(S_SYSERROR, m_file, m_line, strerror(m_errno), "SystemError %s", m_errmsg); } - -ClientError::ClientError(const char *file, unsigned line, uint32_t errcode, ...) - : Exception(file, line) -{ - m_errcode = errcode; - va_list ap; - va_start(ap, errcode); - vsnprintf(m_errmsg, sizeof(m_errmsg) - 1, - tnt_errcode_desc(m_errcode), ap); - m_errmsg[sizeof(m_errmsg) - 1] = 0; - va_end(ap); -} - -ClientError::ClientError(const char *file, unsigned line, const char *msg, - uint32_t errcode) - : Exception(file, line) +OutOfMemory::OutOfMemory(const char *file, unsigned line, + size_t amount, const char *allocator, + const char *object) + :SystemError(file, line) { - m_errcode = errcode; - strncpy(m_errmsg, msg, sizeof(m_errmsg) - 1); - m_errmsg[sizeof(m_errmsg) - 1] = 0; + m_errno = ENOMEM; + snprintf(m_errmsg, sizeof(m_errmsg), + "Failed to allocate %u bytes in %s for %s", + (unsigned) amount, allocator, object); } - -void -ClientError::log() const -{ - _say(S_ERROR, m_file, m_line, NULL, "%s: %s", tnt_errcode_str(m_errcode), - m_errmsg); -} - -ErrorInjection::ErrorInjection(const char *file, unsigned line, const char *msg) - : LoggedError(file, line, ER_INJECTION, msg) -{ - /* nothing */ -} - diff --git a/src/exception.h b/src/exception.h index d9afb096db..c241523a2a 100644 --- a/src/exception.h +++ b/src/exception.h @@ -30,11 +30,12 @@ */ #include "object.h" #include <stdarg.h> -#include "errcode.h" #include "say.h" struct cord; +enum { TNT_ERRMSG_MAX = 512 }; + class Exception: public Object { public: void *operator new(size_t size); @@ -51,7 +52,7 @@ class Exception: public Object { return m_errmsg; } - virtual void log() const = 0; + virtual void log() const; virtual ~Exception() {} static void init(struct cord *cord); @@ -84,7 +85,7 @@ class SystemError: public Exception { int errnum() const { - return m_errnum; + return m_errno; } virtual void log() const; @@ -98,60 +99,16 @@ class SystemError: public Exception { void init(const char *format, va_list ap); -private: +protected: /* system errno */ - int m_errnum; -}; - -class ClientError: public Exception { -public: - virtual void raise() - { - throw this; - } - - virtual void log() const; - - int - errcode() const - { - return m_errcode; - } - - ClientError(const char *file, unsigned line, uint32_t errcode, ...); - /* A special constructor for lbox_raise */ - ClientError(const char *file, unsigned line, const char *msg, - uint32_t errcode); -private: - /* client errno code */ - int m_errcode; -}; - -extern ClientError out_of_memory; - -class LoggedError: public ClientError { -public: - template <typename ... Args> - LoggedError(const char *file, unsigned line, uint32_t errcode, Args ... args) - : ClientError(file, line, errcode, args...) - { - /* TODO: actually calls ClientError::log */ - log(); - } -}; - -class IllegalParams: public LoggedError { -public: - template <typename ... Args> - IllegalParams(const char *file, unsigned line, const char *format, - Args ... args) - :LoggedError(file, line, ER_ILLEGAL_PARAMS, - format, args...) {} + int m_errno; }; -class ErrorInjection: public LoggedError { +class OutOfMemory: public SystemError { public: - ErrorInjection(const char *file, unsigned line, const char *msg); + OutOfMemory(const char *file, unsigned line, + size_t amount, const char *allocator, + const char *object); }; #define tnt_raise(...) tnt_raise0(__VA_ARGS__) diff --git a/src/fiber.cc b/src/fiber.cc index b8b2dd07d8..b6f7109b53 100644 --- a/src/fiber.cc +++ b/src/fiber.cc @@ -33,11 +33,9 @@ #include <string.h> #include "say.h" -#include "stat.h" #include "assoc.h" #include "memory.h" #include "trigger.h" -#include "coeio.h" static struct cord main_cord; __thread struct cord *cord_ptr = NULL; @@ -76,12 +74,13 @@ fiber_call(struct fiber *callee, ...) va_end(callee->f_data); } -void +bool fiber_checkstack() { struct cord *cord = cord(); if (cord->sp + 1 - cord->stack >= FIBER_CALL_STACK) - tnt_raise(ClientError, ER_FIBER_STACK); + return true; + return false; } /** Interrupt a synchronous wait of a fiber inside the event loop. @@ -397,10 +396,7 @@ fiber_loop(void *data __attribute__((unused))) } catch (Exception *e) { e->log(); } catch (...) { - /* - * This can only happen in case of a bug - * server bug. - */ + /* This can only happen in case of a server bug. */ say_error("fiber `%s': unknown exception", fiber_name(fiber())); panic("fiber `%s': exiting", fiber_name(fiber())); @@ -638,29 +634,6 @@ cord_join(struct cord *cord) return res; } -ssize_t -cord_cojoin_cb(va_list ap) -{ - struct cord *cord = va_arg(ap, struct cord *); - void *retval = NULL; - int res = tt_pthread_join(cord->id, &retval); - return res; -} - -int -cord_cojoin(struct cord *cord) -{ - assert(cord() != cord); /* Can't join self. */ - int rc = coeio_custom(cord_cojoin_cb, TIMEOUT_INFINITY, cord); - if (rc == 0 && cord->exception) { - Exception::move(cord, cord()); - cord_destroy(cord); - cord()->exception->raise(); /* re-throw exception from cord */ - } - cord_destroy(cord); - return rc; -} - void fiber_init(void) { diff --git a/src/fiber.h b/src/fiber.h index c6433d0b90..3f72521aef 100644 --- a/src/fiber.h +++ b/src/fiber.h @@ -202,23 +202,14 @@ cord_start(struct cord *cord, const char *name, int cord_join(struct cord *cord); -/** - * \brief Yield until \a cord has terminated. - * If \a cord has terminated with an uncaught exception - * **re-throws** this exception in the calling cord/fiber. - * \param cord cord - * \sa pthread_join() - * \return 0 on success - */ -int -cord_cojoin(struct cord *cord); - static inline void cord_set_name(const char *name) { snprintf(cord()->name, FIBER_NAME_MAX, "%s", name); } +void +cord_destroy(struct cord *cord); void fiber_init(void); void fiber_free(void); @@ -233,7 +224,7 @@ fiber_name(struct fiber *f) return region_name(&f->gc); } -void +bool fiber_checkstack(); void fiber_yield(void); diff --git a/src/iobuf.cc b/src/iobuf.cc index 4f565693b4..07027ffffd 100644 --- a/src/iobuf.cc +++ b/src/iobuf.cc @@ -100,8 +100,7 @@ static inline void obuf_init_pos(struct obuf *buf, size_t pos) { if (pos >= IOBUF_IOV_MAX) { - tnt_raise(LoggedError, ER_MEMORY_ISSUE, buf->pos, - "obuf_init_pos", "iovec"); + tnt_raise(OutOfMemory, buf->pos, "obuf_init_pos", "iovec"); } buf->iov[pos].iov_base = NULL; buf->iov[pos].iov_len = 0; diff --git a/src/lib/small/mempool.h b/src/lib/small/mempool.h index d465efa43c..8ce0056953 100644 --- a/src/lib/small/mempool.h +++ b/src/lib/small/mempool.h @@ -65,7 +65,7 @@ extern "C" { * ---------------- * The only type of failure which can occur is a failure to * allocate memory. In case of such error, an exception - * (ClientError, ER_OUT_OF_RESOURCES) is raised. _nothrow() + * (OutOfMemory) is raised. _nothrow() * version of mempool_alloc() returns NULL rather than raises an * error in case of failure. */ @@ -284,8 +284,8 @@ mempool_alloc(struct mempool *pool) { void *ptr = mempool_alloc_nothrow(pool); if (ptr == NULL) - tnt_raise(LoggedError, ER_MEMORY_ISSUE, - pool->objsize, "mempool", "new slab"); + tnt_raise(OutOfMemory, pool->objsize, + "mempool", "new slab"); return ptr; } diff --git a/src/lib/small/region.h b/src/lib/small/region.h index e06fbd4d4e..11adb988b7 100644 --- a/src/lib/small/region.h +++ b/src/lib/small/region.h @@ -232,8 +232,7 @@ region_alloc(struct region *region, size_t size) { void *ptr = region_alloc_nothrow(region, size); if (ptr == NULL) - tnt_raise(LoggedError, ER_MEMORY_ISSUE, - size, "region", "new slab"); + tnt_raise(OutOfMemory, size, "region", "new slab"); return ptr; } diff --git a/src/lib/small/small.h b/src/lib/small/small.h index 6d77797b22..2efcab7e9d 100644 --- a/src/lib/small/small.h +++ b/src/lib/small/small.h @@ -277,8 +277,7 @@ smalloc(struct small_alloc *alloc, size_t size, const char *where) { void *ptr = smalloc_nothrow(alloc, size); if (ptr == NULL) - tnt_raise(LoggedError, ER_MEMORY_ISSUE, - size, "slab allocator", where); + tnt_raise(OutOfMemory, size, "slab allocator", where); return ptr; } diff --git a/src/lua/fiber.cc b/src/lua/fiber.cc index 67094fba81..82e6ad1752 100644 --- a/src/lua/fiber.cc +++ b/src/lua/fiber.cc @@ -294,7 +294,10 @@ lbox_fiber_create(struct lua_State *L) { if (lua_gettop(L) < 1 || !lua_isfunction(L, 1)) luaL_error(L, "fiber.create(function, ...): bad arguments"); - fiber_checkstack(); + if (fiber_checkstack()) { + lua_pushstring(L, "out of fiber stack"); + tnt_raise(LuajitError, L); + } struct fiber *f = fiber_new("lua", box_lua_fiber_run); /* Not a system fiber. */ diff --git a/src/lua/init.cc b/src/lua/init.cc index 7a39e454b7..f01a95f592 100644 --- a/src/lua/init.cc +++ b/src/lua/init.cc @@ -414,7 +414,7 @@ run_script(va_list ap) } try { lbox_call(L, lua_gettop(L) - 1, 0); - } catch (ClientError *e) { + } catch (Exception *e) { panic("%s", e->errmsg()); } diff --git a/src/lua/trigger.cc b/src/lua/trigger.cc index 3fafdd1cc4..a3bd8303ed 100644 --- a/src/lua/trigger.cc +++ b/src/lua/trigger.cc @@ -90,7 +90,7 @@ lbox_trigger_reset(struct lua_State *L, int top, luaL_unref(L, LUA_REGISTRYINDEX, (intptr_t) trg->data); } else if (lua_isfunction(L, top)) { - tnt_raise(ClientError, ER_NO_SUCH_TRIGGER); + luaL_error(L, "trigger reset: Trigger is not found"); } /* * During update of a trigger, we must preserve its diff --git a/src/lua/utils.cc b/src/lua/utils.cc index 61f2786be6..6f68a5fc25 100644 --- a/src/lua/utils.cc +++ b/src/lua/utils.cc @@ -688,3 +688,11 @@ tarantool_lua_utils_init(struct lua_State *L) fpconv_init(); return 0; } + +LuajitError::LuajitError(const char *file, unsigned line, + struct lua_State *L) + :Exception(file, line) +{ + const char *msg = lua_tostring(L, -1); + snprintf(m_errmsg, sizeof(m_errmsg), "%s", msg ? msg : ""); +} diff --git a/src/lua/utils.h b/src/lua/utils.h index 055f87b11d..d023c32266 100644 --- a/src/lua/utils.h +++ b/src/lua/utils.h @@ -430,11 +430,12 @@ tarantool_lua_utils_init(struct lua_State *L); } /* extern "C" */ #include "exception.h" +class LuajitError: public Exception { +public: + LuajitError(const char *file, unsigned line, + struct lua_State *L); +}; -/** - * A wrapper around lua_call() which converts Lua error(...) - * to ER_PROC_LUA - */ static inline void lbox_call(struct lua_State *L, int nargs, int nreturns) { @@ -445,14 +446,15 @@ lbox_call(struct lua_State *L, int nargs, int nreturns) throw; } catch (...) { /* Convert Lua error to a Tarantool exception. */ - const char *msg = lua_tostring(L, -1); - tnt_raise(ClientError, ER_PROC_LUA, msg ? msg : ""); + tnt_raise(LuajitError, L); } } /** * Single global lua_State shared by core and modules. * Created with tarantool_lua_init(). + * const char *msg = lua_tostring(L, -1); + * snprintf(m_errmsg, sizeof(m_errmsg), "%s", msg ? msg : ""); */ extern struct lua_State *tarantool_L; diff --git a/src/pickle.h b/src/pickle.h index 24315f945c..8c015b7bca 100644 --- a/src/pickle.h +++ b/src/pickle.h @@ -37,7 +37,6 @@ * tuple and iproto binary formats. * * load_* - no boundary checking - * pick_* - throws exception if no data in the buffer */ static inline uint32_t @@ -48,34 +47,6 @@ load_u32(const char **data) return *b; } -#define pick_u(bits) \ -static inline uint##bits##_t \ -pick_u##bits(const char **begin, const char *end) \ -{ \ - if (end - *begin < (bits)/8) \ - tnt_raise(IllegalParams, \ - "packet too short (expected "#bits" bits)");\ - uint##bits##_t r = *(uint##bits##_t *)*begin; \ - *begin += (bits)/8; \ - return r; \ -} - -pick_u(8) -pick_u(16) -pick_u(32) -pick_u(64) - -static inline const char * -pick_str(const char **data, const char *end, uint32_t size) -{ - const char *str = *data; - if (str + size > end) - tnt_raise(IllegalParams, - "packet too short (expected a field)"); - *data += size; - return str; -} - #define pack_u(bits) \ static inline char * \ pack_u##bits(char *buf, uint##bits##_t val) \ diff --git a/test/box/session.result b/test/box/session.result index 49e15c2196..eb905aca72 100644 --- a/test/box/session.result +++ b/test/box/session.result @@ -80,11 +80,11 @@ session.on_disconnect() ... session.on_connect(function() end, function() end) --- -- error: Trigger is not found +- error: 'trigger reset: Trigger is not found' ... session.on_disconnect(function() end, function() end) --- -- error: Trigger is not found +- error: 'trigger reset: Trigger is not found' ... session.on_connect(1, 2) --- diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 0df204d057..1091ee26dd 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -49,12 +49,16 @@ target_link_libraries(rtree_itr.test) add_executable(matras.test matras.cc) target_link_libraries(matras.test small) add_executable(vclock.test vclock.cc test.c - ${CMAKE_SOURCE_DIR}/src/box/vclock.c) -target_link_libraries(vclock.test core small - ${LIBEV_LIBRARIES} ${LIBEIO_LIBRARIES} ${LIBCORO_LIBRARIES}) + ${CMAKE_SOURCE_DIR}/src/box/vclock.c + ${CMAKE_SOURCE_DIR}/src/box/errcode.c + ${CMAKE_SOURCE_DIR}/src/box/error.cc) +target_link_libraries(vclock.test core small) add_executable(quota.test quota.cc test.c) target_link_libraries(quota.test pthread) +add_executable(fiber.test fiber.cc) +target_link_libraries(fiber.test core) + set(MSGPUCK_DIR ${PROJECT_SOURCE_DIR}/src/lib/msgpuck/) add_executable(msgpack.test ${MSGPUCK_DIR}/test/msgpuck.c diff --git a/test/unit/fiber.cc b/test/unit/fiber.cc new file mode 100644 index 0000000000..d851007323 --- /dev/null +++ b/test/unit/fiber.cc @@ -0,0 +1,10 @@ +#include "memory.h" +#include "fiber.h" +int main() +{ + memory_init(); + fiber_init(); + fiber_free(); + memory_free(); + return 0; +} diff --git a/test/unit/fiber.result b/test/unit/fiber.result new file mode 100644 index 0000000000..e69de29bb2 -- GitLab