events::events(const string& redis_host, unsigned short redis_port) { this->redis = redisAsyncConnect(redis_host.c_str(), redis_port); this->redis_pubsub = redisAsyncConnect(redis_host.c_str(), redis_port); if (this->redis->err || this->redis_pubsub->err) { throw string("Redis Async cannot connect."); } this->loop = ev_loop_new(EVBACKEND_POLL | EVBACKEND_SELECT); redisLibevAttach(this->loop, this->redis); redisLibevAttach(this->loop, this->redis_pubsub); }
redisAsyncContext * redis_nginx_open_context(u_char *host, int port, int database, u_char *password, redisAsyncContext **context) { redisAsyncContext *ac = NULL; if ((context == NULL) || (*context == NULL) || (*context)->err) { ac = redisAsyncConnect((const char *)host, port); if (ac == NULL) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "redis_nginx_adapter: could not allocate the redis context for %s:%d", host, port); return NULL; } if (ac->err) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "redis_nginx_adapter: could not create the redis context for %s:%d - %s", host, port, ac->errstr); redisAsyncFree(ac); return NULL; } redis_nginx_event_attach(ac); if (context != NULL) { *context = ac; } if(password) { redisAsyncCommand(ac, redis_nginx_auth_callback, context, AUTH_COMMAND, password); } redisAsyncCommand(ac, redis_nginx_select_callback, context, SELECT_DATABASE_COMMAND, database); } else { ac = *context; } return ac; }
void connect() { if(redisContext_) { throw IllegalStateException("Error redisContext already created"); } state_ = REDISREQUEST_CONNECTING; ScopedMutexLock(lockRedis_); redisContext_ = redisAsyncConnect(host_.c_str(), port_); if (redisContext_->err) { _LOG_DEBUG("REDIS CONNECT FAILED (CREATE ERROR): %s:%d, err = %x, this = %p" , host_.c_str(), port_, redisContext_->err, this); state_ = REDISREQUEST_CONNECTFAILED; //fire_onRedisRequest_Error(redisContext_->err, "connect error", NULL); // disconnectCallback() is called later soon.. // error process will be executed by that function. } redisContext_->data = this; redisLibeventAttach(redisContext_, (struct event_base *)ioService_->coreHandle()); redisAsyncSetConnectCallback(redisContext_, connectCallback); redisAsyncSetDisconnectCallback(redisContext_, disconnectCallback); timerObj_->setTimer(TIMER_ID_CONNECTION_TIMEOUT, DEFAULT_CONNECT_TIMEOUT, false); _LOG_DEBUG("redis connect start : %s:%d, flag = 0x%x, fd = %d, context = %p, this = %p" , host_.c_str(), port_, redisContext_->c.flags, redisContext_->c.fd, redisContext_, this); }
/* public methods */ bool _redis_init(struct cachefs *fs) { redisContext *c; redisReply *reply; handle = (struct redis_handler*) malloc(sizeof(struct redis_handler)); handle->redis_ip = g_strdup(fs->redis_ip); handle->redis_port = fs->redis_port; if (handle) { handle->conn = redis_connection(handle); if (handle->conn == NULL){ return false; } /* set async connection for pub/sub */ handle->async = redisAsyncConnect(handle->redis_ip, handle->redis_port); if (handle->async->err) { _cachefs_write_error("redis error in setting async operation : %s\n", c->errstr); return false; } struct event_base *base = event_base_new(); handle->event_base = base; pthread_create(&handle->redis_thread, NULL, redis_subscribe, fs); /* PING server */ reply = redisCommandAlive(handle, "PING"); if ((reply == NULL) || (strlen(reply->str) <= 0)){ return false; } freeReplyObject(reply); } handle->lock = g_mutex_new(); return true; }
int rxs_signal_init(rxs_signal* s, const char* ip, uint16_t port) { if (!s) { return -1; } if (!ip) { return -2; } if (!port) { return -3; } s->connected = 0; s->loop = (uv_loop_t*)uv_default_loop(); if (!s->loop) { printf("Error: cannot get default uv loop for signaling.\n"); return -4; } s->redis = redisAsyncConnect(ip, port); if (!s->redis) { printf("Error: cannot create hiredis context for signaling.\n"); return -5; } if (s->redis->err) { printf("Error: something went wrong when trying to connect to redis: %s\n", s->redis->errstr); return -6; } /* @todo - add error checks */ redisLibuvAttach(s->redis, s->loop); redisAsyncSetConnectCallback(s->redis, connect_callback); redisAsyncSetDisconnectCallback(s->redis, disconnect_callback); return 0; }
// async redisAsyncContext* RedisClientPool::createAsync(aeEventLoop *loop) { try { redisAsyncContext * ret = redisAsyncConnect(address_.c_str(), port_); if (ret != NULL && ret->err) { stringstream stream; stream << "reconnect Error: " << ret->err; LOG(ERROR, stream.str()); // FIXME: no need to free // redisFree(ret); // 建立错误直接返回NULL ret = NULL; return ret; } // 设置连接断开的回调函数 redisAsyncSetDisconnectCallback(ret, redisAsyncDisconnectCallback); // 在第一次创建链接的时候做Attach操作 redisAeAttach(loop, ret); return ret; } catch (std::exception &e) { return NULL; } }
bool AsyncRedisMgr::redis_init() { m_redis_base = event_base_new(); if (m_redis_base == NULL) { LOG4CPLUS_ERROR(logger,"create event base fail."); return false; } m_redis_context = redisAsyncConnect(m_redis_host.c_str(),m_redis_port); if (m_redis_context != NULL && m_redis_context->err) { LOG4CPLUS_ERROR(logger,"connect redis fail: "<<m_redis_context->errstr); return false; } if(redisLibeventAttach(m_redis_context,m_redis_base) != REDIS_OK) { LOG4CPLUS_ERROR(logger,"when we bind the redisconext with eventbase fail."); return false; } return true; }
// async bool RedisClientPool::ReconnectAsync(redisAsyncContext* rc, aeEventLoop *loop) { DestroyAsync(rc); try { rc = redisAsyncConnect(address_.c_str(), port_); //fprintf(stderr, "connect redisContext->err: %d\n", rc->err); if (rc != NULL && rc->err != 0) { stringstream stream; stream << "reconnect Error: " << rc->errstr; LOG(ERROR, stream.str()); // 建立错误直接返回NULL // FIXME: no need to free? // redisFree(rc); return false; } redisAsyncSetDisconnectCallback(rc, redisAsyncDisconnectCallback); // 在重连成功后做Attach操作 redisAeAttach(loop, rc); } catch (std::exception &e) { stringstream stream; stream << "reconnect server faild!!"; LOG(ERROR, stream.str()); return false; } return true; }
int RedisAsyncConn::DoConnect() { m_state = CONNECTING; int retry = 0; while (true) { m_async_context = redisAsyncConnect(m_server_ip.c_str(), m_server_port); if (m_async_context->err) { LOG(ERROR) << "RedisAsyncConn::DoConnect() error=" << m_async_context->errstr << ", retry=" << retry; redisAsyncDisconnect(m_async_context); if (++retry > m_max_retry_times) { return REDIS_ASYNC_CONN_ERR; } } else { break; } } g_async_conn_map.insert(make_pair(m_async_context, this)); RedisNetlibAttach(m_async_context, NetEventLoop::GetInstance()); redisAsyncSetConnectCallback(m_async_context, ConnectCallback); redisAsyncSetDisconnectCallback(m_async_context, DisconnectCallback); LOG(DEBUG) << "RedisAsyncConn::DoConnect() server_ip=" << m_server_ip << ", server_port=" << m_server_port << ", handle=" << m_async_context->c.fd; return REDIS_ASYNC_CONN_OK; }
bool Redox::connect(const string &host, const int port, function<void(int)> connection_callback) { host_ = host; port_ = port; user_connection_callback_ = connection_callback; if (!initEv()) return false; // Connect over TCP ctx_ = redisAsyncConnect(host.c_str(), port); if (!initHiredis()) return false; event_loop_thread_ = thread([this] { runEventLoop(); }); // Block until connected and running the event loop, or until // a connection error happens and the event loop exits { unique_lock<mutex> ul(running_lock_); running_waiter_.wait(ul, [this] { unique_lock<mutex>(connect_lock_); return running_.load() || connect_state_ == CONNECT_ERROR; }); } // Return if succeeded { unique_lock<mutex> ul(connect_lock_); return connect_state_ == CONNECTED; } }
gpointer rspamd_redis_runtime (struct rspamd_task *task, struct rspamd_statfile_config *stcf, gboolean learn, gpointer c) { struct redis_stat_ctx *ctx = REDIS_CTX (c); struct redis_stat_runtime *rt; struct upstream *up; rspamd_inet_addr_t *addr; g_assert (ctx != NULL); g_assert (stcf != NULL); if (learn && ctx->write_servers == NULL) { msg_err_task ("no write servers defined for %s, cannot learn", stcf->symbol); return NULL; } if (learn) { up = rspamd_upstream_get (ctx->write_servers, RSPAMD_UPSTREAM_MASTER_SLAVE, NULL, 0); } else { up = rspamd_upstream_get (ctx->read_servers, RSPAMD_UPSTREAM_ROUND_ROBIN, NULL, 0); } if (up == NULL) { msg_err_task ("no upstreams reachable"); return NULL; } rt = rspamd_mempool_alloc0 (task->task_pool, sizeof (*rt)); rspamd_redis_expand_object (ctx->redis_object, ctx, task, &rt->redis_object_expanded); rt->selected = up; rt->task = task; rt->ctx = ctx; rt->stcf = stcf; addr = rspamd_upstream_addr (up); g_assert (addr != NULL); rt->redis = redisAsyncConnect (rspamd_inet_address_to_string (addr), rspamd_inet_address_get_port (addr)); if (rt->redis == NULL) { msg_err_task ("cannot connect redis"); return NULL; } redisLibeventAttach (rt->redis, task->ev_base); rspamd_redis_maybe_auth (ctx, rt->redis); return rt; }
void uq_redis_connect(EV_P) { pubContext = redisAsyncConnect("127.0.0.1", 6379); if (pubContext->err) { fprintf(stderr, "Redis Error %s\n", pubContext->errstr); exit(1); } redisLibevAttach(EV_A_ pubContext); redisAsyncSetConnectCallback(pubContext, connectCallback); }
void redis_disconnect_callback(const redisAsyncContext* c, int status) { struct nbd_handle* handle; if (c->data) { handle = (struct nbd_handle*) c->data; } else { fprintf_light_red(stderr, "FATAL: Handle not passed to disconnect " "callback.\n"); assert(c->data != NULL); return; } if (status != REDIS_OK) { if (c->err == REDIS_ERR_EOF) /* probably standard timeout, reconnect */ { fprintf_red(stderr, "Redis server disconnected us.\n"); if ((handle->redis_c = redisAsyncConnect(handle->redis_server, handle->redis_port)) != NULL) { fprintf_blue(stderr, "New Redis context, attaching to " "libevent.\n"); handle->redis_c->data = c->data; redisLibeventAttach(handle->redis_c, handle->eb); fprintf_blue(stderr, "Setting disconnect callback.\n"); if (redisAsyncSetDisconnectCallback(handle->redis_c, &redis_disconnect_callback) != REDIS_ERR) { assert(redisAsyncCommand(handle->redis_c, &redis_async_callback, NULL, "select %d", handle->redis_db) == REDIS_OK); fprintf_light_blue(stderr, "Successfully reconnected to " "the Redis server.\n"); } else { fprintf_light_red(stderr, "Error setting disconnect " "callback handler for Redis.\n"); } } else { fprintf_light_red(stderr, "Error trying to reconnect to " "Redis.\n"); } return; } fprintf_light_red(stderr, "FATAL ERROR DISCONNECTION FROM REDIS\n"); fprintf_light_blue(stderr, "Error: %s\n", c->errstr); assert(false); } }
redisAsyncContext* initRedis(const char *adrr, u16 port) { redisAsyncContext *ctx=redisAsyncConnect(adrr, port); if(ctx->err) { /* Let *c leak for now... */ die("Error: %s\n", ctx->errstr); } return ctx; }
static int dispatch_conn_context_init(conn_context *cc, char *host, int port) { cc->ctx = NULL; cc->actx = NULL; cc->actx = redisAsyncConnect(host, port); if (cc->actx == NULL) { return VRT_ERROR; } return VRT_OK; }
void setupDatabase(void) { db = redisAsyncConnect("127.0.0.1", 6379); if(db == NULL || db->err) { if(db) { fprintf(stderr, "Connection error: %s\n", db->errstr); } else { fprintf(stderr, "Connection error: can't allocate redis context\n"); } exit(1); } }
void RedisProxy::connect() { if(_connected) { return; } SLOG(DEBUG) << "redis connect begin..."; _context = redisAsyncConnect(_ip.c_str(), _port); if(!_context) { SLOG(WARNING) << "allocate redis async connection fail!"; return; } if(_context->err != 0) { SLOG(WARNING) << "connect fail[" << _context->err << "]"; redisAsyncFree(_context); _context = nullptr; return; } _context->data = this; _context->ev.data = this; _context->ev.addRead = RedisProxy::redis_add_read; _context->ev.delRead = RedisProxy::redis_del_read; _context->ev.addWrite = RedisProxy::redis_add_write; _context->ev.delWrite = RedisProxy::redis_del_write; _context->ev.cleanup = RedisProxy::redis_cleanup; _read_io = std::make_shared<IO>(_context->c.fd, EV_READ, false);//FIXME:add EV_ET in future _read_io->on_read([this]() { LOG(INFO) << "on read"; redisAsyncHandleRead(_context); }); _write_io = std::make_shared<IO>(_context->c.fd, EV_WRITE, false);//FIXME:add EV_ET in future LOG(INFO) << "redis fd:" << _context->c.fd; _write_io->on_write([this]() { LOG(INFO) << "on write"; redisAsyncHandleWrite(_context); }); _connected = get_local_loop()->add_io(_read_io, false) && get_local_loop()->add_io(_write_io, false); redisAsyncSetConnectCallback(_context, RedisProxy::handle_connect); redisAsyncSetDisconnectCallback(_context, RedisProxy::handle_disconnect); }
int main (int argc, char **argv) { signal(SIGPIPE, SIG_IGN); struct event_base *base = event_base_new(); const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1"; int port = (argc > 2) ? atoi(argv[2]) : 6379; const char *subname = (argc > 3) ? argv[3] : "test"; redisAsyncContext *c = redisAsyncConnect(hostname, port); if (c->err) { /* Let *c leak for now... */ printf("Error: %s\n", c->errstr); return 1; } g_yuv_size = 1920*1080*3/2; g_yuv = malloc(g_yuv_size); start_time = time((time_t*)NULL); now_time = time((time_t*)NULL); // init pipe if(pipe(pipe_fd)){ printf("pipe error\n"); return -1; } // create thread pthread_attr_t attr; struct sched_param param; pthread_t tsk_id; pthread_attr_init(&attr); pthread_attr_setschedpolicy(&attr, SCHED_FIFO); pthread_attr_getschedparam(&attr, ¶m); pthread_create(&tsk_id, &attr, (void *)thread_function, NULL); // event redisLibeventAttach(c,base); redisAsyncSetConnectCallback(c,connectCallback); redisAsyncSetDisconnectCallback(c,disconnectCallback); redisAsyncCommand(c, subCallback, (char*) "sub", "SMEMSUBSCRIBE %s", subname); event_base_dispatch(base); return 0; }
static void rspamd_redis_async_stat_cb (struct rspamd_stat_async_elt *elt, gpointer d) { struct redis_stat_ctx *ctx; struct rspamd_redis_stat_elt *redis_elt = elt->ud; struct rspamd_redis_stat_cbdata *cbdata; rspamd_inet_addr_t *addr; g_assert (redis_elt != NULL); ctx = redis_elt->ctx; if (redis_elt->cbdata) { /* We have some other process pending */ rspamd_redis_async_cbdata_cleanup (redis_elt->cbdata); } /* Disable further events unless needed */ elt->enabled = FALSE; cbdata = g_slice_alloc0 (sizeof (*cbdata)); cbdata->selected = rspamd_upstream_get (ctx->read_servers, RSPAMD_UPSTREAM_ROUND_ROBIN, NULL, 0); g_assert (cbdata->selected != NULL); addr = rspamd_upstream_addr (cbdata->selected); g_assert (addr != NULL); cbdata->redis = redisAsyncConnect (rspamd_inet_address_to_string (addr), rspamd_inet_address_get_port (addr)); g_assert (cbdata->redis != NULL); redisLibeventAttach (cbdata->redis, redis_elt->ev_base); cbdata->inflight = 1; cbdata->cur = ucl_object_typed_new (UCL_OBJECT); cbdata->elt = redis_elt; cbdata->cur_keys = g_ptr_array_new (); redis_elt->cbdata = cbdata; /* XXX: deal with timeouts maybe */ /* Get keys in redis that match our symbol */ rspamd_redis_maybe_auth (ctx, cbdata->redis); redisAsyncCommand (cbdata->redis, rspamd_redis_stat_keys, cbdata, "SMEMBERS %s_keys", ctx->stcf->symbol); }
static client createClient(void) { client c = zmalloc(sizeof(struct _client)); c->context = redisAsyncConnect(config.hostip,config.hostport); c->context->data = c; redisAsyncSetDisconnectCallback(c->context,clientDisconnected); if (c->context->err) { fprintf(stderr,"Connect: %s\n",c->context->errstr); exit(1); } redisAeAttach(config.el,c->context); listAddNodeTail(config.clients,c); issueRequest(c); return c; }
void *command_thread(void *arg) { signal(SIGPIPE, SIG_IGN); struct event_base *base = event_base_new(); printf("starting sub conn\n"); redisAsyncContext *c = redisAsyncConnect(REDIS_HOST, REDIS_HOST_PORT); if (c->err) { printf("REDIS not connected: %s\n", c->errstr); } redisLibeventAttach(c, base); redisAsyncCommand(c, message_handler, NULL, "SUBSCRIBE housekeeping"); event_base_dispatch(base); return 0; }
int main (int argc, char **argv) { signal(SIGPIPE, SIG_IGN); redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); if (c->err) { /* Let *c leak for now... */ printf("Error: %s\n", c->errstr); return 1; } redisLibevAttach(EV_DEFAULT_ c); redisAsyncSetConnectCallback(c,connectCallback); redisAsyncSetDisconnectCallback(c,disconnectCallback); redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); ev_loop(EV_DEFAULT_ 0); return 0; }
static int new_connect( struct cnt_pool *pool, uintptr_t **cite, va_list *ap ) { char *host = va_arg(*ap, char *); int port = va_arg(*ap, int); redisAsyncContext *c = redisAsyncConnect (host, port); if (!c || c->err) { /* Let *c leak for now... */ x_printf (E, "Error: %s\n", c->errstr); free (c); *cite = NULL; return -1; } redisLibevAttach(NULL, c); redisAsyncSetConnectCallback(c, _connectCallback); redisAsyncSetDisconnectCallback(c, _disconnectCallback); *cite = (uintptr_t *)c; return 0; }
/** \brief SCConfLogReopenAsyncRedis() Open or re-opens connection to redis for logging. * \param log_ctx Log file context allocated by caller */ static int SCConfLogReopenAsyncRedis(LogFileCtx *log_ctx) { SCLogRedisContext * ctx = log_ctx->redis; const char *redis_server = log_ctx->redis_setup.server; int redis_port = log_ctx->redis_setup.port; /* only try to reconnect once per second */ if (ctx->tried >= time(NULL)) { return -1; } ctx->async = redisAsyncConnect(redis_server, redis_port); if (ctx->ev_base != NULL) { event_base_free(ctx->ev_base); } if (ctx->async == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "Error allocate redis async."); ctx->tried = time(NULL); return -1; } if (ctx->async != NULL && ctx->async->err) { SCLogError(SC_ERR_SOCKET, "Error setting to redis async: [%s].", ctx->async->errstr); ctx->tried = time(NULL); return -1; } ctx->ev_base = event_base_new(); if (ctx->ev_base == NULL) { ctx->tried = time(NULL); redisAsyncFree(ctx->async); ctx->async = NULL; return -1; } redisLibeventAttach(ctx->async, ctx->ev_base); log_ctx->redis = ctx; log_ctx->Close = SCLogFileCloseRedis; return 0; }
/*Inicia conexao com o Redis e configura as funcoes de callback no libEvent*/ void initRedis( const char * channel, char * id) { signal(SIGPIPE, SIG_IGN); struct event_base *base = event_base_new(); strcpy(globalChannel, channel); setMyID(id); redisAsyncContext * redis = redisAsyncConnect("127.0.0.1", 6379); if ( redis->err ) { printf("Erro conectando no redis %s\n", redis->errstr); exit(EXIT_FAILURE); } initStdin( channel); redisLibeventAttach( redis,base); redisAsyncSetConnectCallback(redis, connectCallback); redisAsyncSetDisconnectCallback( redis,disconnectCallback); event_base_dispatch(base); }
int main() { signal(SIGPIPE, SIG_IGN); redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); if (c->err) { /* Let *c leak for now... */ printf("Error: %s\n", c->errstr); return 1; } redisLibevAttach(EV_DEFAULT_ c); redisAsyncSetConnectCallback(c,connectCallback); redisAsyncSetDisconnectCallback(c,disconnectCallback); // redisAsyncCommand(c, getCallback, (char*)"sub", "SUBSCRIBE name"); new ChatRoom(c, {"79153060652", "79030072726", "79853672651"}); ev_loop(EV_DEFAULT_ 0); return 0; }
int main (int argc, char **argv) { signal(SIGPIPE, SIG_IGN); redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); if (c->err) { /* Let *c leak for now... */ printf("Error: %s\n", c->errstr); return 1; } loop = aeCreateEventLoop(); redisAeAttach(loop, c); redisAsyncSetConnectCallback(c,connectCallback); redisAsyncSetDisconnectCallback(c,disconnectCallback); redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); aeMain(loop); return 0; }
int main (int argc, char **argv) { signal(SIGPIPE, SIG_IGN); struct event_base *base = event_base_new(); redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); if (c->err) { /* Let *c leak for now... */ printf("Error: %s\n", c->errstr); return 1; } redisLibeventAttach(c,base); redisAsyncSetConnectCallback(c,connectCallback); redisAsyncSetDisconnectCallback(c,disconnectCallback); redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); event_base_dispatch(base); return 0; }
int main (int argc, char **argv) { if (argc < 2) { printf("error need channel to be specified\n"); return 1; } signal(SIGPIPE, SIG_IGN); struct event_base *base = event_base_new(); redisAsyncContext *c = redisAsyncConnect("pub-redis-13387.us-east-1-4.6.ec2.redislabs.com", 13387); redisContext *cs = redisConnect("pub-redis-13387.us-east-1-4.6.ec2.redislabs.com", 13387); if (c->err) { printf("error: %s\n", c->errstr); return 1; } redisLibeventAttach(c, base); redisAsyncCommand(c, onMessage, cs, "SUBSCRIBE %s",argv[1]); event_base_dispatch(base); return 0; }
void func(const std::string& commandStr) { g_SubscribeMutex.lock(); struct event_base *m_base = event_base_new(); redisAsyncContext *m_redis = redisAsyncConnect("127.0.0.1", 6379); if (m_redis->err) { /* Let *c leak for now... */ printf("Error: %s\n", m_redis->errstr); } redisAsyncCommand(m_redis,authCallback, (char*) "auth", "auth %s", "014006"); redisLibeventAttach(m_redis, m_base); redisAsyncSetConnectCallback(m_redis, connectCallback); redisAsyncSetDisconnectCallback(m_redis, disconnectCallback); redisAsyncCommand(m_redis, subscribeCallback, (char*) "sub", commandStr.c_str()); g_SubscribeMutex.unlock(); event_base_dispatch(m_base); }