Пример #1
0
void io_stream_t::run() const {
	proto.run(name);

	if(multiaccept) {
		size_t bq_n = scheduler.bq_n();

		char const *fmt = log::number_fmt(bq_n);

		for(size_t i = 0; i < bq_n; ++i) {
			try {
				string_t _name = string_t::ctor_t(5).print(i, fmt);
				log::handler_t handler(_name);

				int _fd = ::dup(fd);
				if(_fd < 0)
					throw exception_sys_t(log::error, errno, "dup: %m");

				fd_guard_t _fd_guard(_fd);

				bq_job(&io_stream_t::loop)(*this, _fd, false)->run(scheduler.bq_thr(i));

				_fd_guard.relax();
			}
			catch(exception_t const &) { }
		}
	}
	else {
		int _fd = ::dup(fd);
		if(_fd < 0)
			throw exception_sys_t(log::error, errno, "dup: %m");

		loop(_fd, true);
	}
}
Пример #2
0
void io_stream_t::init() {
	netaddr_t const &netaddr = bind_addr();

	fd = socket(netaddr.sa->sa_family, SOCK_STREAM, 0);
	if(fd < 0)
		throw exception_sys_t(log::error, errno, "socket: %m");

	try {
		bq_fd_setup(fd);
		fd_setup(fd);

		if(reuse_addr) {
			int i = 1;
			if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
				throw exception_sys_t(log::error, errno, "setsockopt, SO_REUSEADDR, 1: %m");
		}

		if(::bind(fd, netaddr.sa, netaddr.sa_len) < 0)
			throw exception_sys_t(log::error, errno, "bind: %m");

		if(::listen(fd, listen_backlog) < 0)
			throw exception_sys_t(log::error, errno, "listen: %m");

	}
	catch(...) {
		::close(fd);
		fd = -1;
		throw;
	}

	stat.init();
	proto.init(name);
}
Пример #3
0
bq_thr_t::impl_t::impl_t(
	size_t _maxevs, interval_t _timeout, bq_cont_count_t &_cont_count,
	bq_post_activate_t *_post_activate
) :
	cont_count(_cont_count), post_activate(_post_activate),
	thread(0), tid(0),
	maxevs(_maxevs), timeout(_timeout), stat(), entry() {

	efd = epoll_create(maxevs);
	if(efd < 0)
		throw exception_sys_t(log::error, errno, "bq_thr_t::impl_t::impl_t, epoll_create: %m");

	if(::pipe(sig_fds) < 0)
		throw exception_sys_t(log::error, errno, "bq_thr_t::impl_t::impl_t, pipe: %m");

	bq_fd_setup(sig_fds[0]);
	bq_fd_setup(sig_fds[1]);

	epoll_event ev;
	ev.events = POLLIN;
	ev.data.ptr = NULL;

	if(epoll_ctl(efd, EPOLL_CTL_ADD, sig_fds[0], &ev) < 0)
		throw exception_sys_t(log::error, errno, "bq_thr_t::impl_t::impl_t, epoll_ctl, add: %m");
}
Пример #4
0
file_t::file_t(char const *name, string_t const &header) :
	ref_cnt(0), fd(-1), used(false), id() {

	if(config::check)
		return;

	fd = ::open(name, O_WRONLY | O_APPEND | O_CREAT, 0644);
	if(fd < 0)
		throw exception_sys_t(log::error, errno, "open (%s): %m", name);

	fd_guard_t guard(fd);

	id = id_t(fd, used);
	if(!id)
		throw exception_sys_t(log::error, errno, "fstat (%s): %m", name);

	if(::flock(fd, LOCK_SH | LOCK_NB) < 0)
		throw exception_sys_t(log::error, errno, "flock (%s): %m", name);

	if(header) {
		if(::write(fd, header.ptr(), header.size()) < 0)
			throw exception_sys_t(log::error, errno, "write (%s): %m", name);
	}

	guard.relax();
}
Пример #5
0
void link_t::loop() {
	timeval_t last_conn = timeval_long_ago;

	while(true) {
		try {
			{
				timeval_t now = timeval_current();
				interval_t to_sleep = conn_timeout - (timeval_current() - last_conn);

				if(to_sleep > interval_zero && bq_sleep(&to_sleep) < 0)
					throw exception_sys_t(log::error, errno, "bq_sleep: %m");

			}

			last_conn = timeval_current();

			netaddr_t const &netaddr = remote_netaddr();

			int fd = socket(netaddr.sa->sa_family, SOCK_STREAM, 0);
			if(fd < 0)
				throw exception_sys_t(remote_errors, errno, "socket: %m");

			fd_guard_t fd_guard(fd);

			bq_fd_setup(fd);

			interval_t timeout = conn_timeout;

			if(bq_connect(fd, netaddr.sa, netaddr.sa_len, &timeout) < 0)
				throw exception_sys_t(remote_errors, errno, "connect: %m");

			log_debug("connected");

			bq_conn_fd_t conn(fd, ctl(), remote_errors, /* dup = */ true);

			proto_instance->proc(conn);
		}
		catch(exception_sys_t const &ex) {
			if(ex.errno_val == ECANCELED)
				throw;

			ex.log();
		}
		catch(exception_t const &ex) {
			ex.log();
		}
	}
}
Пример #6
0
void bq_job_base_t::__create(pthread_t *pthread, pthread_attr_t *attr) {
	int err = pthread_create(pthread, attr, &__run_thr, this);
	if(err) {
		delete this;
		throw exception_sys_t(log::error, err, "pthread_create: %m");
	}
}
Пример #7
0
int method_datagram_t::connect_fd() {
    const netaddr_t& addr = target_addr();

    int fd = socket(addr.sa->sa_family, SOCK_DGRAM, 0);
    if(fd < 0) {
        throw exception_sys_t(log::error, errno, "socket: %m");
    }

    bq_fd_setup(fd);

    if(bq_connect(fd, addr.sa, addr.sa_len, NULL) < 0) {
        throw exception_sys_t(log::error, errno, "connect: %m");
    }

    return fd;
}
Пример #8
0
void scheduler_t::init() {
	sched_param sp = { priority };

	size_t i = 0;
	try {
		char const *fmt = log::number_fmt(threads);

		for(; i < threads; ++i) {
			string_t name = string_t::ctor_t(5).print(i, fmt);
			log::handler_t handler(name);

			bq_thrs[i].init(
				event_buf_size, timeout_prec, cont_count, tname, post_activate()
			);

			if(need_set_priority)
				if(sched_setscheduler(bq_thrs[i].get_tid(), policy, &sp) < 0)
					throw exception_sys_t(log::error, errno, "sched_setscheduler: %m");
		}
	}
	catch(...) {
		bq_thr_t::stop();

		bq_thrs[i].fini();

		while(i)
			bq_thrs[--i].fini();

		throw;
	}

	init_ext();
}
Пример #9
0
size_t in_fd_t::readv(iovec *iov, size_t cnt) {
	ssize_t res = ::readv(fd, iov, cnt);

	if(res < 0)
		throw exception_sys_t(get_log_level(), errno, "readv: %m");

	return res;
}
void io_zcluster_status_test_t::run() {
    int c = 0;
    while(true) {
        string_t status = string_t::ctor_t(16).print(c++);
        cluster_status_.update(status);
        interval_t to_sleep = (random_U() % 10) * interval_second;
        if(bq_sleep(&to_sleep) < 0) {
            throw exception_sys_t(log::error, errno, "bq_sleep: %m");
        }
    }
}
Пример #11
0
void io_logger_file_t::run() const {
	while(true) {
		interval_t t = check_interval;

		log_debug("tick");

		if(bq_sleep(&t) < 0)
			throw exception_sys_t(log::error, errno, "bq_sleep: %m");

		check();
	}
}
Пример #12
0
ref_t<pi_ext_t> wait_pool_t::data_t::wait(interval_t* timeout) {
    bq_cond_guard_t guard(cond_);
    while(!reply_) {
        if(!bq_success(cond_.wait(timeout))) {
            if(errno != ETIMEDOUT) {
                throw exception_sys_t(log::error, errno, "wait_pool::data_t.wait: %m");
            }
            return reply_;
        }
    }
    
    return reply_;
}
Пример #13
0
	inline char *alloc() {
		{
			spinlock_guard_t guard(spinlock);
			++wnum;

			if(num) {
				item_t *item = pool;
				pool = item->next;
				--num;

				return item->stack();
			}
		}

		thr::tstate_t *tstate = thr::tstate;
		thr::state_t old_state;

		if(tstate)
			old_state = tstate->set(thr::mmap);

		char *stack = (char *)mmap(
			NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
			MAP_PRIVATE | MAP_ANONYMOUS, -1, 0
		);

		if(stack == MAP_FAILED)
			throw exception_sys_t(log::error, errno, "mmap: %m");

		if (mprotect(stack, PAGE_SIZE, 0) < 0)
			throw exception_sys_t(log::error, errno, "mprotect: %m");

		if(tstate)
			tstate->set(old_state);

		return stack;
	}
Пример #14
0
void io_stream_t::loop(int afd, bool conswitch) const {
	fd_guard_t fd_guard(afd);
	timeval_t last_poll = timeval::current();

	while(true) {
		bool poll_before = false;

		if(force_poll.is_real()) {
			timeval_t now = timeval::current();
			if(now - last_poll > force_poll) {
				poll_before = true;
				last_poll = now;
			}
		}

		netaddr_t *netaddr = new_netaddr();

		int nfd = bq_accept(afd, netaddr->sa, &netaddr->sa_len, NULL, poll_before);

		if(nfd < 0) {
			delete netaddr;
			throw exception_sys_t(log::error, errno, "accept: %m");
		}

		try {
			string_t _name = string_t::ctor_t(netaddr->print_len()).print(*netaddr);

			++stat.conns();

			bq_thr_t *thr = aux_scheduler
				? aux_scheduler->bq_thr()
				: (conswitch ? scheduler.bq_thr() : bq_thr_get())
			;
			log::handler_t handler(_name);
			bq_job(&io_stream_t::conn_proc)(*this, nfd, netaddr)->run(thr);
		}
		catch(exception_t const &ex) {
			::close(nfd);
			delete netaddr;
		}
		catch(...) {
			::close(nfd);
			delete netaddr;
			throw;
		}
	}
}
Пример #15
0
	inline setup_caps_t(string_t const &, config_t const &config) {
		if(config::check)
			return;

#if LINUX_CAPS
		uint32_t caps_keep = config.keep.value;

		if(caps_keep) {
			if(prctl(PR_SET_KEEPCAPS, 1) < 0)
					throw exception_sys_t(log::error, errno, "prctl(PR_SET_KEEPCAPS, 1): %m");
		}
#endif

		for(config::list_t<rlimit_t>::ptr_t rptr = config.rlimits; rptr; ++rptr) {
			rlimit_t const &rlim = rptr.val();
			struct rlimit r;

			r.rlim_cur = r.rlim_max = rlim.val < sizeval_unlimited ? (rlim_t)rlim.val : RLIM_INFINITY;

			if(setrlimit(rlim.id, &r) < 0)
				throw exception_sys_t(log::error, errno, "setrlimit: %m");
		}

		gid_t gid = config.group.id;

		if(gid) {
			if(setgroups(1, &gid) < 0)
				throw exception_sys_t(log::error, errno, "setgroups: %m");

			if(setregid(gid, gid) < 0)
				throw exception_sys_t(log::error, errno, "setregid: %m");
		}

		uid_t uid = config.user.id;

		if(uid) {
			if(setreuid(uid, uid) < 0)
				throw exception_sys_t(log::error, errno, "setreuid: %m");
		}

#if LINUX_CAPS
		if(caps_keep) {
			__user_cap_header_struct hdr;
			__user_cap_data_struct data;

			hdr.version = _LINUX_CAPABILITY_VERSION;
			hdr.pid = 0;

			data.effective = data.permitted = caps_keep;
			data.inheritable = 0;

			if(::capset(&hdr, &data) < 0)
				throw exception_sys_t(log::error, errno, "capset: %m");

			if(prctl(PR_SET_KEEPCAPS, 0) < 0)
				throw exception_sys_t(log::error, errno, "prctl(PR_SET_KEEPCAPS, 0): %m");

			if(prctl(PR_SET_DUMPABLE, 1) < 0)
				throw exception_sys_t(log::error, errno, "prctl(PR_SET_DUMPABLE, 1): %m");
		}
#endif
	}
Пример #16
0
void bq_thr_t::impl_t::loop() {
	tid = thr::id;
	current = this;
	thr::tstate = &stat.tstate();

	epoll_event evs[maxevs];
	int timeoit_msec = timeout / interval::millisecond;

	struct heaps_t {
		bq_heap_t common, ready;

		inline heaps_t() : common(), ready() { }

		inline void insert(bq_heap_t::item_t *item) {
			bq_heap_t *heap = item->heap;
			if(heap) {
				if(item->ready) {
					if(heap == &ready) return;
				}
				else {
					if(heap == &common) return;
				}

				heap->remove(item);
			}

			(item->ready ? ready : common).insert(item);
		}

		inline void remove(bq_heap_t::item_t *item) {
			bq_heap_t *heap = item->heap;
			if(heap)
				heap->remove(item);
		}

		inline bq_heap_t::item_t *head(timeval_t const &now, bool work) {
			bq_heap_t::item_t *citem = common.head();
			bq_heap_t::item_t *ritem = ready.head();

			if(work) {
				if(citem && citem->time_to >= now)
					citem = NULL;

				if(ritem) {
					if(!citem || citem->time_to >= ritem->time_to)
						return ritem;
				}
			}
			else {
				if(ritem)
					return ritem;
			}

			return citem;
		}
	} heaps;

	while(work || bq_cont_count()) {
		int n = epoll_wait(efd, evs, maxevs, timeoit_msec);
		if(n < 0) {
			if(errno != EINTR)
				throw exception_sys_t(log::error, errno, "bq_thr_t::impl_t::loop, epoll_wait: %m");
			n = 0;
		}

		stat.tstate().set(thr::run);

		for(int i = 0; i < n; ++i) {
			void *ptr = evs[i].data.ptr;
			if(ptr) {
				poll_item_t *item = (poll_item_t *)ptr;

				item->events = evs[i].events & ~(EPOLLET | EPOLLONESHOT);

					// may be "item->ready = true; heaps.insert(item);"
				entry.set_ready(item);
			}
			else {
				char buf[1024];
				if(::read(sig_fds[0], buf, sizeof(buf)) < 0) {
					if(errno != EAGAIN)
						log_error("bq_thr_t::impl_t::clear: %m");
				}
			}
		}

		while(true) {
			bq_heap_t::item_t *item = NULL;
			while((item = entry.remove()))
				heaps.insert(item);

			timeval_t time = timeval::current();

			if(!(item = heaps.head(time, work)))
				break;

			heaps.remove(item);

			++stat.acts();

			if(item->ready) {
				if(item->timeout)
					*item->timeout =
						item->time_to > time ? item->time_to - time : interval::zero;

				item->err = bq_ok;
			}
			else {
				if(item->timeout) *item->timeout = interval::zero;

				item->err = work ? bq_timeout : bq_not_available;
			}

			bq_cont_activate(item->cont);
		}

		stat.tstate().set(thr::idle);
	}

	thr::tstate = NULL;
	current = NULL;
	tid = 0;
}
Пример #17
0
void bq_job_base_t::__create(bq_thr_t *bq_thr) {
	if(!bq_success(bq_cont_create(bq_thr, &__run_bq, this))) {
		delete this;
		throw exception_sys_t(log::error, errno, "bq_cont_create: %m");
	}
}