Пример #1
0
static void
mm_event_kqueue_poll(struct mm_event_kqueue *event_backend, mm_timeout_t timeout)
{
	ENTER();
	DEBUG("poll: changes: %d, timeout: %lu", event_backend->nevents, (unsigned long) timeout);

	// Calculate the event wait timeout.
	struct timespec ts;
	ts.tv_sec = timeout / 1000000;
	ts.tv_nsec = (timeout % 1000000) * 1000;

	// Publish the log before a possible sleep.
	mm_log_relay();

	// Poll the system for events.
	int n = kevent(event_backend->event_fd,
		       event_backend->events, event_backend->nevents,
		       event_backend->events, MM_EVENT_KQUEUE_NEVENTS,
		       &ts);

	DEBUG("kevent changed: %d, received: %d", event_backend->nevents, n);

	if (n < 0) {
		if (errno == EINTR)
			mm_warning(errno, "kevent");
		else
			mm_error(errno, "kevent");
		event_backend->nevents = 0;
	} else {
		event_backend->nevents = n;
	}

	LEAVE();
}
Пример #2
0
void
mm_libcall(const char *name)
{
	static __thread int recursion_guard = 0;
	if (!recursion_guard) {
		++recursion_guard;
		mm_warning(0,
			"attempt to call a standard library function "
			"overridden by MainMemory: '%s'", name);
		--recursion_guard;
	}
}
Пример #3
0
static mm_value_t
mc_reader_routine(struct mm_work *work)
{
	ENTER();

	struct mm_net_socket *sock = mm_net_reader_socket(work);
	struct mc_state *state = containerof(sock, struct mc_state, sock.sock);

	// Try to get some input w/o blocking.
	mm_net_set_read_timeout(&state->sock.sock, 0);
	ssize_t n = mm_netbuf_fill(&state->sock, 1);
	mm_net_set_read_timeout(&state->sock.sock, MC_READ_TIMEOUT);

retry:
	// Get out of here if there is no more input available.
	if (n <= 0) {
		if (n == 0 || (errno != EAGAIN && errno != ETIMEDOUT))
			state->error = true;

		// If the socket is closed queue a quit command.
		if (state->error && !mm_net_is_reader_shutdown(sock)) {
			struct mc_command *command = mc_command_create(state);
			command->type = &mc_command_ascii_quit;
			mc_process_command(state, command);
		}
		goto leave;
	}

	// Initialize the parser.
	struct mm_buffer_reader safepoint;
	mm_netbuf_capture_read_pos(&state->sock, &safepoint);
	mc_protocol_t protocol = mc_getprotocol(state);

	state->command = NULL;

	// Try to parse the received input.
	bool rc;
parse:
	if (protocol == MC_PROTOCOL_BINARY)
		rc = mc_binary_parse(state);
	else
		rc = mc_parser_parse(state);

	if (!rc) {
		if (state->command != NULL) {
			mc_command_destroy(state->command);
			state->command = NULL;
		}
		if (state->trash) {
			mm_netbuf_reset(&state->sock);
			mm_warning(0, "disconnect an odd client");
			goto leave;
		}

		// The input is incomplete, try to get some more.
		mm_netbuf_restore_read_pos(&state->sock, &safepoint);
		n = mm_netbuf_fill(&state->sock, 1);
		goto retry;
	}

	// Process the parsed command.
	mc_process_command(state, state->command);

	// If there is more input in the buffer then try to parse
	// the next command.
	if (!mm_netbuf_empty(&state->sock)) {
		state->command = NULL;
		// Update the safe consumed input position.
		mm_netbuf_capture_read_pos(&state->sock, &safepoint);
		goto parse;
	}

	// Transmit buffered results and compact the output buffer storage.
	mm_netbuf_flush(&state->sock);
	mm_netbuf_compact_write_buf(&state->sock);

	// Compact the input buffer storage.
	mm_netbuf_compact_read_buf(&state->sock);

leave:
	LEAVE();
	return 0;
}