Пример #1
0
bool beanstalk::beanstalk_open()
{
	if (conn_.opened())
		return true;
	if (conn_.open(addr_, timeout_, 0) == false)
	{
		logger_error("connect server: %s error: %s",
			addr_, last_serror());
		errbuf_.format("connect");
		return false;
	}
	if (tube_used_ && beanstalk_use() == false)
	{
		logger_error("use %s error: %s", tube_used_, last_serror());
		conn_.close();
		return false;
	}

	if (tubes_watched_.empty())
		return true;

	std::vector<char*>::iterator it = tubes_watched_.begin();
	for (; it != tubes_watched_.end(); ++it)
	{
		if (beanstalk_watch(*it) == false)
		{
			logger_error("watch %s failed", *it);
			conn_.close();
			return false;
		}
	}

	return true;
}
Пример #2
0
thread_mutex::thread_mutex(bool recursive /* = true */)
{
	mutex_ = (acl_pthread_mutex_t*)
		acl_mycalloc(1, sizeof(acl_pthread_mutex_t));

#ifdef	ACL_UNIX
	int ret = pthread_mutexattr_init(&mutex_attr_);
	if (ret)
	{
		SET_ERRNO(ret);
		logger_fatal("pthread_mutexattr_init error=%s", last_serror());
	}
	if (recursive && (ret = pthread_mutexattr_settype(&mutex_attr_,
					PTHREAD_MUTEX_RECURSIVE)))
	{
		SET_ERRNO(ret);
		logger_fatal("pthread_mutexattr_settype error=%s", last_serror());
	}
	ret = acl_pthread_mutex_init(mutex_, &mutex_attr_);
	if (ret)
	{
		SET_ERRNO(ret);
		logger_fatal("pthread_mutex_init error=%s", last_serror());
	}
#else
	(void) recursive;
	int ret = acl_pthread_mutex_init(mutex_, NULL);
	if (ret)
	{
		SET_ERRNO(ret);
		logger_fatal("pthread_mutex_init error=%s", last_serror());
	}
#endif
}
Пример #3
0
int open_limit(int limit)
{
	int   rlim_cur = -1;

#ifdef RLIMIT_NOFILE
	struct rlimit rl;

	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
		rlim_cur = getdtablesize();
		msg_warn("%s(%d): getrlimit error: %s, use: %d",
			__FUNCTION__, __LINE__, last_serror(), rlim_cur);
		return rlim_cur;
	}

	if (rl.rlim_max <= 0) {
		rl.rlim_max = 204800;
	}
	rlim_cur = (int) rl.rlim_cur;

	if (limit > 0) {
		if (limit > (int) rl.rlim_max) {
			rl.rlim_cur = rl.rlim_max;
		} else {
			rl.rlim_cur = limit;
		}
		if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
			msg_warn("%s(%d): setrlimit error: %s, limit: %d,"
				" curr: %d", __FUNCTION__, __LINE__,
				last_serror(), limit, rlim_cur);
			return rlim_cur;
		} else {
			return (int) rl.rlim_cur;
		}
	} else if (rl.rlim_max > rl.rlim_cur) {
		rlim_cur = (int) rl.rlim_cur;
		rl.rlim_cur = rl.rlim_max;
		if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
			msg_warn("%s(%d): setrlimit error: %s,"
				" cur: %d, max: %d", __FUNCTION__, __LINE__,
				last_serror(), (int) rl.rlim_cur,
				(int) rl.rlim_max);
			return rlim_cur;
		}

		return (int) rl.rlim_cur;
	} else {
		return (int) rl.rlim_cur;
	}

#else
	rlim_cur = getdtablesize();
	if (rlim_cur < 0) {
		msg_error("%s(%d): getdtablesize(%d) < 0, limit: %d",
			__FUNCTION__, __LINE__, rlim_cur, limit);
	}
	return rlim_cur;
#endif
}
Пример #4
0
const redis_result* redis_client::run(dbuf_pool* pool, const redis_request& req,
	size_t nchildren)
{
	// 重置协议处理状态
	bool retried = false;

	redis_result* result;

	struct iovec* iov = req.get_iovec();
	size_t size = req.get_size();

	while (true)
	{
		if (!conn_.opened() && conn_.open(addr_, conn_timeout_,
			rw_timeout_) == false)
		{
			logger_error("connect server: %s error: %s",
				addr_, last_serror());
			return NULL;
		}

		if (size > 0 && conn_.writev(iov, (int) size) == -1)
		{
			conn_.close();
			if (retry_ && !retried)
			{
				retried = true;
				continue;
			}
			logger_error("write to redis(%s) error: %s",
				addr_, last_serror());
			return NULL;
		}

		if (nchildren >= 1)
			result = get_redis_objects(pool, nchildren);
		else
			result = get_redis_object(pool);

		if (result != NULL)
			return result;

		conn_.close();

		if (!retry_ || retried)
			break;

		retried = true;
	}

	return NULL;
}
Пример #5
0
bool file_tmpl::copy_and_replace(const char* from,
	const char* to, bool exec /* = false */)
{
	tpl_t* tpl = open_tpl(from);
	if (tpl == NULL)
		return false;

	tpl_set_field_fmt_global(tpl, "PROGRAM", "%s", project_name_.c_str());

	string filepath;
	filepath << path_to_ << '/' << to;
	if (tpl_save_as(tpl, filepath.c_str()) != TPL_OK)
	{
		printf("save to %s error: %s\r\n", filepath.c_str(),
			last_serror());
		tpl_free(tpl);
		return false;
	}
	printf("create %s ok.\r\n", filepath.c_str());
	tpl_free(tpl);

	if (exec)
	{
#ifndef	WIN32
		chmod(filepath.c_str(), S_IRUSR | S_IWUSR | S_IXUSR |
			S_IRGRP | S_IWGRP | S_IXGRP);
#endif
	}
	return true;
}
Пример #6
0
redis_result* redis_client::get_redis_object(dbuf_pool* pool)
{
	char ch;
	if (conn_.read(ch) == false)
	{
		logger_warn("read char error: %s, server: %s, fd: %u",
			last_serror(), addr_, (unsigned) conn_.sock_handle());
		return NULL;
	}

	switch (ch)
	{
	case '-':	// ERROR
		return get_redis_error(pool);
	case '+':	// STATUS
		return get_redis_status(pool);
	case ':':	// INTEGER
		return get_redis_integer(pool);
	case '$':	// STRING
		return get_redis_string(pool);
	case '*':	// ARRAY
		return get_redis_array(pool);
	default:	// INVALID
		logger_error("invalid first char: %c, %d", ch, ch);
		return NULL;
	}
}
Пример #7
0
bool mail_attach::save_to(mime_code* coder, string& out)
{
	if (coder)
		build_header(coder->get_encoding_type(), out);
	else
		build_header(NULL, out);

	string buf;
	if (ifstream::load(filepath_.c_str(), &buf) == false)
	{
		logger_error("load %s error %s",
			filepath_.c_str(), last_serror());
		return false;
	}

	if (coder)
	{
		coder->reset();
		coder->encode_update(buf.c_str(), (int) buf.size(), &out);
		coder->encode_finish(&out);
	}
	else
		out.append(buf);

	return true;
}
Пример #8
0
static bool create_http_servlet(file_tmpl& tmpl)
{
	tpl_t* tpl = tmpl.open_tpl("http_servlet.cpp");
	if (tpl == NULL)
		return false;

	printf("Do you want add cookie? y[y/n]: "); fflush(stdout);
	int ch = getchar();
	if (ch != 'n')
		set_cookies(tpl);

	string filepath;
	filepath.format("%s/http_servlet.cpp", tmpl.get_project_name());
	if (tpl_save_as(tpl, filepath.c_str()) != TPL_OK)
	{
		printf("save to %s error: %s\r\n", filepath.c_str(),
			last_serror());
		tpl_free(tpl);
		return false;
	}

	printf("create %s ok.\r\n", filepath.c_str());
	tpl_free(tpl);

	// 设置服务器模板类型
	return create_service(tmpl);
}
Пример #9
0
static int checkfd(EVENT *ev, FILE_EVENT *fe)
{
	struct stat s;

	if (fstat(fe->fd, &s) < 0) {
		msg_info("%s(%d), %s: fd: %d fstat error %s", __FILE__,
			__LINE__, __FUNCTION__, fe->fd, last_serror());
		return -1;
	}

	if (S_ISSOCK(s.st_mode)) {
		return 0;
	}
	if (S_ISFIFO(s.st_mode)) {
		return 0;
	}

	if (S_ISCHR(s.st_mode)) {
		return 0;
	}
	if (isatty(fe->fd)) {
		return 0;
	}

	return ev->checkfd(ev, fe);
}
Пример #10
0
bool master_udp::run_alone(const char* addrs, const char* path /* = NULL */,
	unsigned int count /* = 1 */)
{
	// 每个进程只能有一个实例在运行
	acl_assert(has_called == false);
	has_called = true;
	daemon_mode_ = false;
	__count_limit = count;
	acl_assert(addrs && *addrs);

#ifdef ACL_WINDOWS
	acl_init();
#endif
	ACL_EVENT* eventp = acl_event_new_select(1, 0);
	set_event(eventp);  // 设置基类的事件句柄

	ACL_ARGV* tokens = acl_argv_split(addrs, ";,| \t");
	ACL_ITER iter;

	acl_foreach(iter, tokens)
	{
		const char* addr = (const char*) iter.data;
		ACL_VSTREAM* sstream = acl_vstream_bind(addr, 0);
		if (sstream == NULL)
		{
			logger_error("bind %s error %s",
				addr, last_serror());
			close_sstreams();
			acl_event_free(eventp);
			acl_argv_free(tokens);
			return false;
		}
		acl_event_enable_read(eventp, sstream, 0,
			read_callback, sstream);
		socket_stream* ss = NEW socket_stream();
		if (ss->open(sstream) == false)
			logger_fatal("open stream error!");
		sstream->context = ss;
		sstreams_.push_back(ss);
	}

	acl_argv_free(tokens);

	// 初始化配置参数
	conf_.load(path);

	service_pre_jail(NULL, NULL);
	service_init(NULL, NULL);

	while (!__stop)
		acl_event_loop(eventp);

	service_exit(NULL, NULL);

	// 必须在调用 acl_event_free 前调用 close_sstreams,因为在关闭
	// 网络流对象时依然有对 ACL_EVENT 引擎的使用
	close_sstreams();
	acl_event_free(eventp);
	return true;
}
Пример #11
0
static void thread_init(void)
{
	if (pthread_key_create(&__fiber_key, thread_free) != 0) {
		msg_fatal("%s(%d), %s: pthread_key_create error %s",
			__FILE__, __LINE__, __FUNCTION__, last_serror());
	}
}
Пример #12
0
bool server_socket::open(const char* addr)
{
#ifndef ACL_WINDOWS
	if (strchr(addr, '/') != NULL)
	{
		fd_ = acl_unix_listen(addr, backlog_, block_
			? ACL_BLOCKING : ACL_NON_BLOCKING);
		unix_sock_ = true;
		ACL_SAFE_STRNCPY(addr_, addr, sizeof(addr_));
	}
	else
#endif
		fd_ = acl_inet_listen(addr, backlog_, block_
			? ACL_BLOCKING : ACL_NON_BLOCKING);

	if (fd_ == ACL_SOCKET_INVALID)
	{
		logger_error("listen %s error %s", addr, last_serror());
		unix_sock_ = false;
		ACL_SAFE_STRNCPY(addr_, addr, sizeof(addr_));
		return false;
	}

	if (unix_sock_)
		return true;

	// 之所以再用 getsockname 重新获得一些监听地址,主要是为了应对当输入的 addr 
	// 为 ip:0 的情形,即当给定的地址中的端口为 0 时要求操作系统自动分配一个端口号
	if (acl_getsockname(fd_, addr_, sizeof(addr_)) < 0)
	{
		logger_error("getsockname error: %s", acl_last_serror());
		ACL_SAFE_STRNCPY(addr_, addr, sizeof(addr_));
	}
	return true;
}
Пример #13
0
bool redis_client::open()
{
	if (conn_.opened())
		return true;
	if (conn_.open(addr_, conn_timeout_, rw_timeout_) == false)
	{
		logger_error("connect redis %s error: %s",
			addr_, last_serror());
		return false;
	}

	// 如果连接密码非空,则尝试用该密码向 redis-server 认证合法性
	if (pass_ && *pass_)
	{
		redis_connection connection(this);
		if (connection.auth(pass_) == false)
		{
			logger_error("auth error, addr: %s, passwd: %s",
				addr_, pass_);
			// 此处返回 true,以便于上层使用该连接访问时
			// 由 redis-server 直接给命令报未认证的错训,
			// 从而免得在 redis_command 类中不断地重试连接
			return true;
		}
	}

	return true;
}
Пример #14
0
bool scan_dir::get_cwd(string& out)
{

#ifndef MAX_PATH
#define MAX_PATH	1024
#endif
	char  buf[MAX_PATH];

#ifdef ACL_WINDOWS
	if (::GetCurrentDirectory(MAX_PATH, buf) == 0)
	{
		logger_error("can't get process path: %s", last_serror());
		return false;
	}
#else
	if (::getcwd(buf, sizeof(buf)) == NULL)
	{
		logger_error("can't get process path: %s", last_serror());
		return false;
	}
#endif // ACL_WINDOWS

	// xxx: can this happen ?
	if (buf[0] == 0)
		return false;

	// 去掉尾部的 '/'
	char* end = buf + strlen(buf) - 1;
	while (end > buf)
	{
#ifdef ACL_WINDOWS
		if (*end == '/' || *end == '\\')
			end--;
#else
		if (*end == '/')
			end--;
#endif
		else
			break;
	}

	out = buf;
	return true;
}
Пример #15
0
bool master_aio::run_alone(const char* addrs, const char* path /* = NULL */,
	aio_handle_type ht /* = ENGINE_SELECT */)
{
	acl_assert(__handle == NULL);
	daemon_mode_ = false;
#ifdef WIN32
	acl_init();
#endif
	std::vector<aio_listen_stream*> sstreams;
	ACL_ARGV* tokens = acl_argv_split(addrs, ";,| \t");
	ACL_ITER iter;

	// 初始化配置参数
	conf_.load(path);

	__handle = NEW aio_handle(ht);

	ACL_AIO* aio = __handle->get_handle();
	acl_assert(aio);
	ACL_EVENT* eventp = acl_aio_event(aio);
	set_event(eventp);  // 设置基类的事件句柄

	acl_foreach(iter, tokens)
	{
		const char* addr = (const char*) iter.data;
		aio_listen_stream* sstream = NEW aio_listen_stream(__handle);
		// 监听指定的地址
		if (sstream->open(addr) == false)
		{
			logger_error("listen %s error: %s", addr, last_serror());
			close_all_listener(sstreams);
			// XXX: 为了保证能关闭监听流,应在此处再 check 一下
			__handle->check();
			acl_argv_free(tokens);
			return (false);
		}
		sstream->add_accept_callback(this);
	}
	acl_argv_free(tokens);

	service_pre_jail(NULL);
	service_init(NULL);
	while (true)
	{
		// 如果返回 false 则表示不再继续,需要退出
		if (__handle->check() == false)
		{
			logger("aio_server stop now ...");
			break;
		}
	}
	close_all_listener(sstreams);
	__handle->check();
	service_exit(NULL);
	return true;
}
Пример #16
0
bool tcp_client::open(void)
{
	if (conn_->open(addr_, conn_timeout_, rw_timeout_) == false)
	{
		logger_error("connnect %s error %s", addr_, last_serror());
		return false;
	}

	return true;
}
Пример #17
0
bool file_tmpl::file_copy(const char* from, const char* to_in)
{
	string to_buf;
	to_buf.format("%s/%s", path_to_.c_str(), to_in);

	const char* to = to_buf.c_str();

	if (strcasecmp(from, to) == 0)
	{
		printf("from(%s) == to(%s)\r\n", from, to);
		return false;
	}

	ifstream in;
	if (in.open_read(from) == false)
	{
		printf("open %s error: %s\r\n", from, last_serror());
		return false;
	}

	ofstream out;
	if (out.open_write(to) == false)
	{
		printf("open %s error: %s\r\n", from, last_serror());
		return false;
	}

	string buf;

	while (!in.eof())
	{
		if (in.gets(buf, false) == false)
			break;
		if (out.write(buf) < 0)
		{
			printf("write to %s error: %s\r\n", to, last_serror());
			return false;
		}
	}

	printf("create %s ok\r\n", to);
	return true;
}
Пример #18
0
unsigned beanstalk::beanstalk_watch(const char* tube)
{
	if (conn_.format("watch %s\r\n", tube) == -1)
	{
		logger_error("'watch %s' failed: %s", tube, last_serror());
		errbuf_ = "watch";
		return 0;
	}
	string line(128);
	if (conn_.gets(line) == false)
	{
		logger_error("'watch %s' error(%s): reply ailed",
			last_serror(), tube);
		errbuf_ = "watch";
		return 0;
	}

	ACL_ARGV* tokens = acl_argv_split(line.c_str(), "\t ");
	if (tokens->argc < 2 || strcasecmp(tokens->argv[0], "WATCHING"))
	{
		logger_error("'watch %s' error: %s", tube, line.c_str());
		errbuf_ = tokens->argv[0];
		acl_argv_free(tokens);
		close();
		return 0;
	}

	unsigned n = (unsigned) atoi(tokens->argv[1]);
	acl_argv_free(tokens);

	// 如果服务器返回所关注的队列数为 0,肯定是出错了,因为至少还有一个
	// 缺省队列:default,所以此时需要关闭连接,以尽量消除与本连接相关
	// 的错误,下一个命令会自动进行重连操作以恢复操作过程
	if (n == 0)
	{
		logger_error("'watch %s' error(%s), tube watched is 0",
			line.c_str(), tube);
		errbuf_ = line.c_str();
		close();
	}
	return n;
}
Пример #19
0
bool master_proc::run_alone(const char* addrs, const char* path /* = NULL */,
	int   count /* = 1 */)
{
	// 每个进程只能有一个实例在运行
	acl_assert(has_called == false);
	has_called = true;
	daemon_mode_ = false;
	__count_limit = count;
	acl_assert(addrs && *addrs);

#ifdef ACL_WINDOWS
	acl_cpp_init();
#endif
	ACL_EVENT* eventp = acl_event_new_select(1, 0);
	set_event(eventp);  // 调用基类方法设置事件引擎句柄

	std::vector<ACL_VSTREAM*> sstreams;
	ACL_ARGV* tokens = acl_argv_split(addrs, ";,| \t");
	ACL_ITER iter;

	acl_foreach(iter, tokens)
	{
		const char* addr = (const char*) iter.data;
		ACL_VSTREAM* sstream = acl_vstream_listen(addr, 128);
		if (sstream == NULL)
		{
			logger_error("listen %s error %s",
				addr, last_serror());
			close_all_listener(sstreams);
			acl_argv_free(tokens);
			return false;
		}

		service_on_listen(sstream);
		acl_event_enable_listen(eventp, sstream, 0,
			listen_callback, sstream);
		sstreams.push_back(sstream);
	}
	acl_argv_free(tokens);

	// 初始化配置参数
	conf_.load(path);

	service_pre_jail(NULL, NULL);
	service_init(NULL, NULL);

	while (!__stop)
		acl_event_loop(eventp);

	close_all_listener(sstreams);
	acl_event_free(eventp);
	service_exit(NULL, NULL);
	return true;
}
Пример #20
0
int queue_file::vformat(const char* fmt, va_list ap)
{
	int ret = m_fp->vformat(fmt, ap);
	if (ret == -1)
	{
		logger_error("write to file error(%s)", last_serror());
		return -1;
	}

	nwriten_ += ret;
	return ret;
}
Пример #21
0
bool redis_client::open()
{
	if (conn_.opened())
		return true;
	if (conn_.open(addr_, conn_timeout_, rw_timeout_) == false)
	{
		logger_error("connect redis %s error: %s",
			addr_, last_serror());
		return false;
	}
	return true;
}
Пример #22
0
socket_stream* server_socket::accept(int timeout /* = 0 */)
{
	if (fd_ == ACL_SOCKET_INVALID)
	{
		logger_error("server socket not opened!");
		return NULL;
	}

	if (block_ && timeout > 0)
	{
		if (acl_read_wait(fd_, timeout) == -1)
			return NULL;
	}

	ACL_SOCKET fd = acl_accept(fd_, NULL, 0, NULL);
	if (fd == ACL_SOCKET_INVALID)
	{
		if (block_)
			logger_error("accept error %s", last_serror());
		else if (last_error() != ACL_EAGAIN
			&& last_error() != ACL_EWOULDBLOCK)
		{
			logger_error("accept error %s", last_serror());
		}
		return NULL;
	}

	socket_stream* client = new socket_stream();
	if (client->open(fd) == false)
	{
		logger_error("create socket_stream error!");
		return NULL;
	}

	if (!unix_sock_)
		acl_tcp_set_nodelay(fd);

	return client;
}
Пример #23
0
void stack_free(void *ptr)
{
	int ret;
	size_t pgsz = page_size();

	ptr = (char *) ptr - pgsz;
	ret = mprotect(ptr, page_size(), PROT_READ|PROT_WRITE);
	if (ret != 0) {
		msg_fatal("%s(%d), %s: mprotect error=%s",
			__FILE__, __LINE__, __FUNCTION__, last_serror());
	}
	free(ptr);
}
Пример #24
0
bool thread_mutex::unlock(void)
{
	int ret = acl_pthread_mutex_unlock(mutex_);
	if (ret)
	{
#ifdef ACL_UNIX
		acl_set_error(ret);
		logger_error("pthread_mutex_unlock error %s", last_serror());
#endif
		return false;
	}
	return true;
}
Пример #25
0
void open_dos(void)
{
	if (dos_fp_)
		return;
	// ´ò¿ª DOS ´°¿Ú
	AllocConsole();
	dos_fp_ = freopen("CONOUT$","w+t",stdout);
	if (dos_fp_ == NULL)
	{
		printf("open DOS error %s\r\n", last_serror());
		FreeConsole();
	}
}
Пример #26
0
tpl_t* file_tmpl::open_tpl(const char* filename)
{
	tpl_t* tpl = tpl_alloc();
	string filepath;
	filepath.format("%s/%s", path_from_.c_str(), filename);
	if (tpl_load(tpl, filepath.c_str()) != TPL_OK)
	{
		printf("load file %s error: %s\r\n",
			filepath.c_str(), last_serror());
		tpl_free(tpl);
		return NULL;
	}
	return tpl;
}
Пример #27
0
bool beanstalk::open()
{
	if (conn_.opened())
		return true;

	if (conn_.open(addr_, timeout_, 0) == false)
	{
		logger_error("connect beanstalkd %s error: %s",
			addr_, last_serror());
		errbuf_= "connect";
		return false;
	}
	return true;
}
Пример #28
0
queue_manager::queue_manager(const char* home, const char* queueName,
	unsigned sub_width)
: m_scanDir(NULL)
, m_home(home)
, m_queueName(queueName)
{
	if (sub_width == 0)
		sub_width_ = 2;
	else
		sub_width_ = sub_width;

	string buf = home;
	buf << PATH_SEP << queueName;

	// 先创建根目录
	if (acl_make_dirs(buf.c_str(), 0700) == -1)
		logger_error("create dir: %s error %s", buf.c_str(),
			last_serror());
	else
		logger("create dir: %s ok", buf.c_str());

	char  node[32];
	for (unsigned i = 0; i < sub_width_; i++)
	{
		buf.clear();
		safe_snprintf(node, sizeof(node), "%d", i);
		buf << home << PATH_SEP << queueName
			<< PATH_SEP << node;
		// 创建队列下子目录
		if (acl_make_dirs(buf.c_str(), 0700) == -1)
			logger_error("create dir: %s error %s",
				buf.c_str(), last_serror());
		else
			logger("create dir: %s ok", buf.c_str());
	}
}
Пример #29
0
void *stack_alloc(size_t size)
{
	int    ret;
	char  *ptr = NULL;
	size_t pgsz = page_size();

	size = stack_size(size);
	size += pgsz;

	ret = posix_memalign((void *) &ptr, pgsz, size);
	if (ret != 0) {
		msg_fatal("%s(%d), %s: posix_memalign error %s",
			__FILE__, __LINE__, __FUNCTION__, last_serror());
	}

	ret = mprotect(ptr, pgsz, PROT_NONE);
	if (ret != 0) {
		msg_fatal("%s(%d), %s: mprotect error=%s",
			__FILE__, __LINE__, __FUNCTION__, last_serror());
	}

	ptr += pgsz;
	return ptr;
}
Пример #30
0
bool beanstalk::beanstalk_use()
{
	if (tube_used_ == NULL)
		return true;

	if (conn_.format("use %s\r\n", tube_used_) == -1)
	{
		logger_error("use %s error: %s", tube_used_, last_serror());
		conn_.close();
		errbuf_.format("use");
		return false;
	}
	string line(128);
	if (conn_.gets(line) == false || line.empty())
	{
		conn_.close();
		logger_error("gets from beanstalkd(%s) error: %s",
			addr_, last_serror());
		errbuf_.format("gets");
		return false;
	}

	ACL_ARGV* tokens = acl_argv_split(line.c_str(), "\t ");
	if (tokens->argc < 2 || strcasecmp(tokens->argv[0], "USING")
		|| strcasecmp(tokens->argv[1], tube_used_))
	{
		logger_error("'use %s' error %s", tube_used_, tokens->argv[0]);
		errbuf_ = tokens->argv[0];
		acl_argv_free(tokens);
		close();
		return false;
	}

	acl_argv_free(tokens);
	return true;
}