Пример #1
0
/*
  startup a copy of smbd as a child daemon
*/
static void s3fs_task_init(struct task_server *task)
{
	const char *fileserver_conf;
	struct tevent_req *req;
	const char *smbd_path;
	const char *smbd_cmd[2] = { NULL, NULL };

	task_server_set_title(task, "task[s3fs_parent]");

	/* create a smb.conf for smbd to use */
	fileserver_conf = generate_smb_conf(task);

	smbd_path = talloc_asprintf(task, "%s/smbd", dyn_SBINDIR);
	smbd_cmd[0] = smbd_path;

	/* start it as a child process */
	req = samba_runcmd_send(task, task->event_ctx, timeval_zero(), 1, 0,
				smbd_cmd,
				"--configfile", fileserver_conf,
				"--foreground",
				debug_get_output_is_stdout()?"--log-stdout":NULL,
				NULL);
	if (req == NULL) {
		DEBUG(0, ("Failed to start smbd as child daemon\n"));
		goto failed;
	}

	tevent_req_set_callback(req, file_server_smbd_done, task);

	DEBUG(1,("Started file server smbd with config %s\n", fileserver_conf));
	return;
failed:
	task_server_terminate(task, "Failed to startup s3fs smb task", true);
}
Пример #2
0
/*
  construct an event driven local ctdb_call

  this is used so that locally processed ctdb_call requests are processed
  in an event driven manner
*/
struct ctdb_call_state *ctdb_call_local_send(struct ctdb_db_context *ctdb_db, 
					     struct ctdb_call *call,
					     struct ctdb_ltdb_header *header,
					     TDB_DATA *data)
{
	struct ctdb_call_state *state;
	struct ctdb_context *ctdb = ctdb_db->ctdb;
	int ret;

	state = talloc_zero(ctdb_db, struct ctdb_call_state);
	CTDB_NO_MEMORY_NULL(ctdb, state);

	talloc_steal(state, data->dptr);

	state->state = CTDB_CALL_DONE;
	state->node = ctdb->nodes[ctdb->vnn];
	state->call = *call;
	state->ctdb_db = ctdb_db;

	ret = ctdb_call_local(ctdb_db, &state->call, header, data, ctdb->vnn);
	talloc_steal(state, state->call.reply_data.dptr);

	event_add_timed(ctdb->ev, state, timeval_zero(), call_local_trigger, state);

	return state;
}
Пример #3
0
_PUBLIC_ void composite_done(struct composite_context *ctx)
{
	if (!ctx->used_wait && !ctx->async.fn) {
		tevent_add_timer(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx);
	}
	ctx->state = COMPOSITE_STATE_DONE;
	if (ctx->async.fn != NULL) {
		ctx->async.fn(ctx);
	}
}
Пример #4
0
/*
	Just try locking/unlocking a single record once
*/
static void fetch_lock_once(struct ctdb_context *ctdb, struct event_context *ev, uint32_t generation)
{
	TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
	TDB_DATA key, data;
	struct ctdb_record_handle *h;
	struct ctdb_ltdb_header *header;
	int ret;

	key.dptr = discard_const(TESTKEY);
	key.dsize = strlen(TESTKEY);

	printf("Trying to fetch lock the record ...\n");

	h = ctdb_fetch_readonly_lock(ctdb_db, tmp_ctx, key, &data, false);
	if (h == NULL) {
		printf("Failed to fetch record '%s' on node %d\n", 
	       		(const char *)key.dptr, ctdb_get_pnn(ctdb));
		talloc_free(tmp_ctx);
		exit(10);
	}

	printf("Record fetchlocked.\n");
	header = talloc_memdup(tmp_ctx, ctdb_header_from_record_handle(h), sizeof(*header));
       	printf("RSN:%d\n", (int)header->rsn);
	talloc_free(h);
	printf("Record released.\n");

	printf("Write new record with RSN+10\n");
	header->rsn += 10;
	data.dptr = (void *)talloc_asprintf(tmp_ctx, "%d", (int)header->rsn);
	data.dsize = strlen((char *)data.dptr);

	ret = ctdb_ctrl_updaterecord(ctdb, ctdb, timeval_zero(), CTDB_CURRENT_NODE, ctdb_db, key, header, data);
	if (ret != 0) {
		printf("Failed to writerecord,  ret==%d\n", ret);	
		exit(1);
	}

	printf("re-fetch the record\n");
	h = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, &data);
	if (h == NULL) {
		printf("Failed to fetch record '%s' on node %d\n", 
	       		(const char *)key.dptr, ctdb_get_pnn(ctdb));
		talloc_free(tmp_ctx);
		exit(10);
	}

	printf("Record fetchlocked.\n");
	header = talloc_memdup(tmp_ctx, ctdb_header_from_record_handle(h), sizeof(*header));
       	printf("RSN:%d\n", (int)header->rsn);
	talloc_free(h);
	printf("Record released.\n");

	talloc_free(tmp_ctx);
}
Пример #5
0
static bool recalc_brl_timeout(void)
{
	struct blocking_lock_record *blr;
	struct timeval next_timeout;

	TALLOC_FREE(brl_timeout);

	next_timeout = timeval_zero();	

	for (blr = blocking_lock_queue; blr; blr = blr->next) {
		if (timeval_is_zero(&blr->expire_time)) {
			/*
			 * If we're blocked on pid 0xFFFFFFFF this is
			 * a POSIX lock, so calculate a timeout of
			 * 10 seconds into the future.
			 */
                        if (blr->blocking_pid == 0xFFFFFFFF) {
				struct timeval psx_to = timeval_current_ofs(10, 0);
				next_timeout = timeval_min(&next_timeout, &psx_to);
                        }

			continue;
		}

		if (timeval_is_zero(&next_timeout)) {
			next_timeout = blr->expire_time;
		}
		else {
			next_timeout = timeval_min(&next_timeout,
						   &blr->expire_time);
		}
	}

	if (timeval_is_zero(&next_timeout)) {
		DEBUG(10, ("Next timeout = Infinite.\n"));
		return True;
	}

	if (DEBUGLVL(10)) {
		struct timeval cur, from_now;

		cur = timeval_current();
		from_now = timeval_until(&cur, &next_timeout);
		DEBUG(10, ("Next timeout = %d.%d seconds from now.\n",
		    (int)from_now.tv_sec, (int)from_now.tv_usec));
	}

	if (!(brl_timeout = event_add_timed(smbd_event_context(), NULL,
					    next_timeout,
					    brl_timeout_fn, NULL))) {
		return False;
	}

	return True;
}
Пример #6
0
/*
  re-enable receiving 
*/
_PUBLIC_ void packet_recv_enable(struct packet_context *pc)
{
	if (pc->recv_need_enable) {
		pc->recv_need_enable = false;
		TEVENT_FD_READABLE(pc->fde);
	}
	pc->recv_disable = false;
	if (pc->num_read != 0 && pc->packet_size >= pc->num_read) {
		tevent_add_timer(pc->ev, pc, timeval_zero(), packet_next_event, pc);
	}
}
Пример #7
0
/*
  shutdown and try to restart a connection to a node after it has been
  disconnected
*/
static void ctdb_tcp_restart(struct ctdb_node *node)
{
    struct ctdb_tcp_node *tnode = talloc_get_type(
                                      node->private_data, struct ctdb_tcp_node);

    DEBUG(DEBUG_NOTICE,("Tearing down connection to dead node :%d\n", node->pnn));

    ctdb_tcp_stop_connection(node);

    tnode->connect_te = tevent_add_timer(node->ctdb->ev, tnode,
                                         timeval_zero(),
                                         ctdb_tcp_node_connect, node);
}
Пример #8
0
_PUBLIC_ struct timeval timeval_until(const struct timeval *tv1,
				      const struct timeval *tv2)
{
	struct timeval t;
	if (timeval_compare(tv1, tv2) >= 0) {
		return timeval_zero();
	}
	t.tv_sec = tv2->tv_sec - tv1->tv_sec;
	if (tv1->tv_usec > tv2->tv_usec) {
		t.tv_sec--;
		t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
	} else {
		t.tv_usec = tv2->tv_usec - tv1->tv_usec;
	}
	return t;
}
Пример #9
0
_PUBLIC_ void composite_continue(struct composite_context *ctx,
				 struct composite_context *new_ctx,
				 void (*continuation)(struct composite_context *),
				 void *private_data)
{
	if (composite_nomem(new_ctx, ctx)) return;
	new_ctx->async.fn = continuation;
	new_ctx->async.private_data = private_data;

	/* if we are setting up a continuation, and the context has
	   already finished, then we should run the callback with an
	   immediate event, otherwise we can be stuck forever */
	if (new_ctx->state >= COMPOSITE_STATE_DONE && continuation) {
		tevent_add_timer(new_ctx->event_ctx, new_ctx, timeval_zero(), composite_trigger, new_ctx);
	}
}
Пример #10
0
_PUBLIC_ void composite_error(struct composite_context *ctx, NTSTATUS status)
{
	/* you are allowed to pass NT_STATUS_OK to composite_error(), in which
	   case it is equivalent to composite_done() */
	if (NT_STATUS_IS_OK(status)) {
		composite_done(ctx);
		return;
	}
	if (!ctx->used_wait && !ctx->async.fn) {
		tevent_add_timer(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx);
	}
	ctx->status = status;
	ctx->state = COMPOSITE_STATE_ERROR;
	if (ctx->async.fn != NULL) {
		ctx->async.fn(ctx);
	}
}
Пример #11
0
/*
  start the protocol going
*/
static int ctdb_tcp_connect_node(struct ctdb_node *node)
{
    struct ctdb_context *ctdb = node->ctdb;
    struct ctdb_tcp_node *tnode = talloc_get_type(
                                      node->private_data, struct ctdb_tcp_node);

    /* startup connection to the other server - will happen on
       next event loop */
    if (!ctdb_same_address(ctdb->address, &node->address)) {
        tnode->connect_te = tevent_add_timer(ctdb->ev, tnode,
                                             timeval_zero(),
                                             ctdb_tcp_node_connect,
                                             node);
    }

    return 0;
}
Пример #12
0
static void gensec_socket_trigger_read(struct tevent_context *ev, 
				       struct tevent_timer *te, 
				       struct timeval t, void *private_data)
{
	struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);

	gensec_socket->in_extra_read++;
	gensec_socket->recv_handler(gensec_socket->recv_private, TEVENT_FD_READ);
	gensec_socket->in_extra_read--;

	/* It may well be that, having run the recv handler, we still
	 * have even more data waiting for us! 
	 */
	if (gensec_socket->read_buffer.length > 0) {
		/* Schedule this funcion to run again */
		tevent_add_timer(gensec_socket->ev, gensec_socket, timeval_zero(), 
				gensec_socket_trigger_read, gensec_socket);
	}
}
Пример #13
0
/*
  complete an async reconnect
 */
static void reopen_connection_complete(struct composite_context *ctx)
{
	struct benchlock_state *state = (struct benchlock_state *)ctx->async.private_data;
	NTSTATUS status;
	struct smb_composite_connect *io = &state->reconnect;

	status = smb_composite_connect_recv(ctx, state->mem_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(state->te);
		state->te = event_add_timed(state->ev, state->mem_ctx, 
					    timeval_current_ofs(1,0), 
					    reopen_connection, state);
		return;
	}

	talloc_free(state->tree);
	state->tree = io->out.tree;

	/* do the reopen as a separate event */
	event_add_timed(state->ev, state->mem_ctx, timeval_zero(), reopen_file, state);
}
Пример #14
0
/*
  startup a copy of smbd as a child daemon
*/
static void s3fs_task_init(struct task_server *task)
{
	struct tevent_req *subreq;
	const char *smbd_path;
	const char *smbd_cmd[2] = { NULL, NULL };

	task_server_set_title(task, "task[s3fs_parent]");

	smbd_path = talloc_asprintf(task, "%s/smbd", dyn_SBINDIR);
	smbd_cmd[0] = smbd_path;

	/* the child should be able to call through nss_winbind */
	(void)winbind_on();
	/* start it as a child process */
	subreq = samba_runcmd_send(task, task->event_ctx, timeval_zero(), 1, 0,
				smbd_cmd,
				"--option=server role check:inhibit=yes",
				"--foreground",
				debug_get_output_is_stdout()?"--log-stdout":NULL,
				NULL);
	/* the parent should not be able to call through nss_winbind */
	if (!winbind_off()) {
		DEBUG(0,("Failed to re-disable recursive winbindd calls after forking smbd\n"));
		task_server_terminate(task, "Failed to re-disable recursive winbindd calls", true);
		return;
	}
	if (subreq == NULL) {
		DEBUG(0, ("Failed to start smbd as child daemon\n"));
		task_server_terminate(task, "Failed to startup s3fs smb task", true);
		return;
	}

	tevent_req_set_callback(subreq, file_server_smbd_done, task);

	DEBUG(5,("Started file server child smbd\n"));
}
Пример #15
0
/*
  test the TestSleep interface
*/
static bool test_sleep(struct torture_context *tctx,
		       struct dcerpc_pipe *p)
{
	int i;
#define ASYNC_COUNT 3
	struct tevent_req *req[ASYNC_COUNT];
	struct echo_TestSleep r[ASYNC_COUNT];
	bool done1[ASYNC_COUNT];
	bool done2[ASYNC_COUNT];
	struct timeval snd[ASYNC_COUNT];
	struct timeval rcv[ASYNC_COUNT];
	struct timeval diff[ASYNC_COUNT];
	int total_done = 0;
	struct dcerpc_binding_handle *b = p->binding_handle;
	enum dcerpc_transport_t transport;
	uint32_t assoc_group_id;
	struct dcerpc_pipe *p2 = NULL;
	NTSTATUS status;

	if (torture_setting_bool(tctx, "quick", false)) {
		torture_skip(tctx, "TestSleep disabled - use \"torture:quick=no\" to enable\n");
	}
	torture_comment(tctx, "Testing TestSleep - use \"torture:quick=yes\" to disable\n");

	transport	= dcerpc_binding_get_transport(p->binding);
	assoc_group_id	= dcerpc_binding_get_assoc_group_id(p->binding);

	torture_comment(tctx, "connect echo connection 2 with "
			"DCERPC_CONCURRENT_MULTIPLEX\n");
	status = torture_rpc_connection_transport(tctx, &p2,
						  &ndr_table_rpcecho,
						  transport,
						  assoc_group_id,
						  DCERPC_CONCURRENT_MULTIPLEX);
	torture_assert_ntstatus_ok(tctx, status, "opening echo connection 2");
	b = p2->binding_handle;

	for (i=0;i<ASYNC_COUNT;i++) {
		done1[i]	= false;
		done2[i]	= false;
		snd[i]		= timeval_current();
		rcv[i]		= timeval_zero();
		r[i].in.seconds = ASYNC_COUNT-i;
		req[i] = dcerpc_echo_TestSleep_r_send(tctx, tctx->ev, b, &r[i]);
		torture_assert(tctx, req[i], "Failed to send async sleep request\n");
		tevent_req_set_callback(req[i], test_sleep_done, &done1[i]);
	}

	while (total_done < ASYNC_COUNT) {
		torture_assert(tctx, tevent_loop_once(tctx->ev) == 0,
					   "Event context loop failed");
		for (i=0;i<ASYNC_COUNT;i++) {
			if (done2[i] == false && done1[i] == true) {
				int rounded_tdiff;
				total_done++;
				done2[i] = true;
				rcv[i]	= timeval_current();
				diff[i]	= timeval_until(&snd[i], &rcv[i]);
				rounded_tdiff = (int)(0.5 + diff[i].tv_sec + (1.0e-6*diff[i].tv_usec));
				torture_comment(tctx, "rounded_tdiff=%d\n", rounded_tdiff);
				torture_assert_ntstatus_ok(tctx,
					dcerpc_echo_TestSleep_r_recv(req[i], tctx),
					talloc_asprintf(tctx, "TestSleep(%d) failed", i));
				torture_assert(tctx, r[i].out.result == r[i].in.seconds,
					talloc_asprintf(tctx, "Failed - Asked to sleep for %u seconds (server replied with %u seconds and the reply takes only %u seconds)", 
						r[i].out.result, r[i].in.seconds, (unsigned int)diff[i].tv_sec));
				torture_assert(tctx, r[i].out.result <= rounded_tdiff, 
					talloc_asprintf(tctx, "Failed - Slept for %u seconds (but reply takes only %u.%06u seconds)", 
						r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec));
				if (r[i].out.result+1 == rounded_tdiff) {
					torture_comment(tctx, "Slept for %u seconds (but reply takes %u.%06u seconds - busy server?)\n", 
							r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
				} else if (r[i].out.result == rounded_tdiff) {
					torture_comment(tctx, "Slept for %u seconds (reply takes %u.%06u seconds - ok)\n", 
							r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
				} else {
					torture_fail(tctx, talloc_asprintf(tctx,
						     "(Failed) - Not async - Slept for %u seconds (but reply takes %u.%06u seconds)\n",
						     r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec));
				}
			}
		}
	}
	torture_comment(tctx, "\n");
	return true;
}
Пример #16
0
static void print_notify_send_messages_to_printer(struct messaging_context *msg_ctx,
						  const char *printer,
						  unsigned int timeout)
{
	char *buf;
	struct notify_queue *pq, *pq_next;
	size_t msg_count = 0, offset = 0;
	size_t num_pids = 0;
	size_t i;
	pid_t *pid_list = NULL;
	struct timeval end_time = timeval_zero();

	/* Count the space needed to send the messages. */
	for (pq = notify_queue_head; pq; pq = pq->next) {
		if (strequal(printer, pq->msg->printer)) {
			if (!flatten_message(pq)) {
				DEBUG(0,("print_notify_send_messages: Out of memory\n"));
				talloc_free_children(send_ctx);
				num_messages = 0;
				return;
			}
			offset += (pq->buflen + 4);
			msg_count++;
		}	
	}
	offset += 4; /* For count. */

	buf = (char *)TALLOC(send_ctx, offset);
	if (!buf) {
		DEBUG(0,("print_notify_send_messages: Out of memory\n"));
		talloc_free_children(send_ctx);
		num_messages = 0;
		return;
	}

	offset = 0;
	SIVAL(buf,offset,msg_count);
	offset += 4;
	for (pq = notify_queue_head; pq; pq = pq_next) {
		pq_next = pq->next;

		if (strequal(printer, pq->msg->printer)) {
			SIVAL(buf,offset,pq->buflen);
			offset += 4;
			memcpy(buf + offset, pq->buf, pq->buflen);
			offset += pq->buflen;

			/* Remove from list. */
			DLIST_REMOVE(notify_queue_head, pq);
		}
	}

	DEBUG(5, ("print_notify_send_messages_to_printer: sending %lu print notify message%s to printer %s\n", 
		  (unsigned long)msg_count, msg_count != 1 ? "s" : "", printer));

	/*
	 * Get the list of PID's to send to.
	 */

	if (!print_notify_pid_list(printer, send_ctx, &num_pids, &pid_list))
		return;

	if (timeout != 0) {
		end_time = timeval_current_ofs(timeout, 0);
	}

	for (i = 0; i < num_pids; i++) {
		messaging_send_buf(msg_ctx,
				   pid_to_procid(pid_list[i]),
				   MSG_PRINTER_NOTIFY2 | MSG_FLAG_LOWPRIORITY,
				   (uint8 *)buf, offset);

		if ((timeout != 0) && timeval_expired(&end_time)) {
			break;
		}
	}
}
Пример #17
0
/* These two routines could be changed to use a circular buffer of
 * some kind, or linked lists, or ... */
static NTSTATUS gensec_socket_recv(struct socket_context *sock, void *buf,
				   size_t wantlen, size_t *nread) 
{
	struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);

	if (!gensec_socket->wrap) {
		return socket_recv(gensec_socket->socket, buf, wantlen, nread);
	}

	gensec_socket->error = NT_STATUS_OK;

	if (gensec_socket->read_buffer.length == 0) {
		/* Process any data on the socket, into the read buffer. At
		 * this point, the socket is not available for read any
		 * longer */
		packet_recv(gensec_socket->packet);

		if (gensec_socket->eof) {
			*nread = 0;
			return NT_STATUS_OK;
		}
		
		if (!NT_STATUS_IS_OK(gensec_socket->error)) {
			return gensec_socket->error;
		}

		if (gensec_socket->read_buffer.length == 0) {
			/* Clearly we don't have the entire SASL packet yet,
			 * so it has not been written into the buffer */
			*nread = 0;
			return STATUS_MORE_ENTRIES;
		}
	}


	*nread = MIN(wantlen, gensec_socket->read_buffer.length);
	memcpy(buf, gensec_socket->read_buffer.data, *nread);

	if (gensec_socket->read_buffer.length > *nread) {
		memmove(gensec_socket->read_buffer.data, 
			gensec_socket->read_buffer.data + *nread, 
			gensec_socket->read_buffer.length - *nread);
	}

	gensec_socket->read_buffer.length -= *nread;
	gensec_socket->read_buffer.data = talloc_realloc(gensec_socket, 
							 gensec_socket->read_buffer.data, 
							 uint8_t, 
							 gensec_socket->read_buffer.length);

	if (gensec_socket->read_buffer.length && 
	    gensec_socket->in_extra_read == 0 && 
	    gensec_socket->recv_handler) {
		/* Manually call a read event, to get this moving
		 * again (as the socket should be dry, so the normal
		 * event handler won't trigger) */
		tevent_add_timer(gensec_socket->ev, gensec_socket, timeval_zero(), 
				gensec_socket_trigger_read, gensec_socket);
	}

	return NT_STATUS_OK;
}
Пример #18
0
/*
  main program
*/
int main(int argc, const char *argv[])
{
	struct ctdb_context *ctdb;

	struct poptOption popt_options[] = {
		POPT_AUTOHELP
		POPT_CTDB_CMDLINE
		POPT_TABLEEND
	};
	int opt;
	const char **extra_argv;
	int extra_argc = 0;
	poptContext pc;
	struct event_context *ev;
	struct ctdb_vnn_map *vnnmap=NULL;

	pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		default:
			fprintf(stderr, "Invalid option %s: %s\n", 
				poptBadOption(pc, 0), poptStrerror(opt));
			exit(1);
		}
	}

	/* setup the remaining options for the main program to use */
	extra_argv = poptGetArgs(pc);
	if (extra_argv) {
		extra_argv++;
		while (extra_argv[extra_argc]) extra_argc++;
	}

	ev = event_context_init(NULL);

	ctdb = ctdb_cmdline_client(ev, timeval_current_ofs(5, 0));
	if (ctdb == NULL) {
		exit(1);
	}

	/* attach to a specific database */
	ctdb_db = ctdb_attach(ctdb, timeval_current_ofs(5, 0), "test.tdb", false, 0);
	if (!ctdb_db) {
		printf("ctdb_attach failed - %s\n", ctdb_errstr(ctdb));
		exit(1);
	}

	printf("Waiting for cluster\n");
	while (1) {
		uint32_t recmode=1;
		ctdb_ctrl_getrecmode(ctdb, ctdb, timeval_zero(), CTDB_CURRENT_NODE, &recmode);
		if (recmode == 0) break;
		event_loop_once(ev);
	}


	if (ctdb_ctrl_getvnnmap(ctdb, timeval_zero(), CTDB_CURRENT_NODE, ctdb, &vnnmap) != 0) {
		printf("Unable to get vnnmap from local node\n");
		exit(1);
	}
	printf("Current Generation %d\n", (int)vnnmap->generation);

	fetch_lock_once(ctdb, ev, vnnmap->generation);

	return 0;
}
Пример #19
0
/*
  main program
*/
int main(int argc, const char *argv[])
{
	struct ctdb_context *ctdb;
	struct ctdb_db_context *ctdb_db;

	struct poptOption popt_options[] = {
		POPT_AUTOHELP
		POPT_CTDB_CMDLINE
		{ "num-records", 'r', POPT_ARG_INT, &num_records, 0, "num_records", "integer" },
		{ "base-rec", 'b', POPT_ARG_INT, &base_rec, 0, "base_rec", "integer" },
		POPT_TABLEEND
	};
	int opt;
	const char **extra_argv;
	int extra_argc = 0;
	poptContext pc;
	struct event_context *ev;

	pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		default:
			fprintf(stderr, "Invalid option %s: %s\n", 
				poptBadOption(pc, 0), poptStrerror(opt));
			exit(1);
		}
	}

	/* talloc_enable_leak_report_full(); */

	/* setup the remaining options for the main program to use */
	extra_argv = poptGetArgs(pc);
	if (extra_argv) {
		extra_argv++;
		while (extra_argv[extra_argc]) extra_argc++;
	}

	ev = event_context_init(NULL);

	ctdb = ctdb_cmdline_client(ev);

	/* attach to a specific database */
	ctdb_db = ctdb_attach(ctdb, "test.tdb", false, 0);
	if (!ctdb_db) {
		printf("ctdb_attach failed - %s\n", ctdb_errstr(ctdb));
		exit(1);
	}

	printf("Waiting for cluster\n");
	while (1) {
		uint32_t recmode=1;
		ctdb_ctrl_getrecmode(ctdb, ctdb, timeval_zero(), CTDB_CURRENT_NODE, &recmode);
		if (recmode == 0) break;
		event_loop_once(ev);
	}

	store_records(ctdb, ev);

	return 0;
}
Пример #20
0
static bool recalc_brl_timeout(struct smbd_server_connection *sconn)
{
	struct blocking_lock_record *blr;
	struct timeval next_timeout;
	int max_brl_timeout = lp_parm_int(-1, "brl", "recalctime", 5);

	TALLOC_FREE(sconn->smb1.locks.brl_timeout);

	next_timeout = timeval_zero();

	for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
		if (timeval_is_zero(&blr->expire_time)) {
			/*
			 * If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is
			 * a POSIX lock, so calculate a timeout of
			 * 10 seconds into the future.
			 */
                        if (blr->blocking_smblctx == 0xFFFFFFFFFFFFFFFFLL) {
				struct timeval psx_to = timeval_current_ofs(10, 0);
				next_timeout = timeval_brl_min(&next_timeout, &psx_to);
                        }

			continue;
		}

		next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time);
	}

	if (timeval_is_zero(&next_timeout)) {
		DEBUG(10, ("Next timeout = Infinite.\n"));
		return True;
	}

	/*
	 to account for unclean shutdowns by clients we need a
	 maximum timeout that we use for checking pending locks. If
	 we have any pending locks at all, then check if the pending
	 lock can continue at least every brl:recalctime seconds
	 (default 5 seconds).

	 This saves us needing to do a message_send_all() in the
	 SIGCHLD handler in the parent daemon. That
	 message_send_all() caused O(n^2) work to be done when IP
	 failovers happened in clustered Samba, which could make the
	 entire system unusable for many minutes.
	*/

	if (max_brl_timeout > 0) {
		struct timeval min_to = timeval_current_ofs(max_brl_timeout, 0);
		next_timeout = timeval_min(&next_timeout, &min_to);
	}

	if (DEBUGLVL(10)) {
		struct timeval cur, from_now;

		cur = timeval_current();
		from_now = timeval_until(&cur, &next_timeout);
		DEBUG(10, ("Next timeout = %d.%d seconds from now.\n",
		    (int)from_now.tv_sec, (int)from_now.tv_usec));
	}

	sconn->smb1.locks.brl_timeout = tevent_add_timer(sconn->ev_ctx,
							 NULL, next_timeout,
							 brl_timeout_fn, sconn);
	if (sconn->smb1.locks.brl_timeout == NULL) {
		return False;
	}

	return True;
}
Пример #21
0
/*
  test the TestSleep interface
*/
static bool test_sleep(struct torture_context *tctx,
						  struct dcerpc_pipe *p)
{
	int i;
	NTSTATUS status;
#define ASYNC_COUNT 3
	struct rpc_request *req[ASYNC_COUNT];
	struct echo_TestSleep r[ASYNC_COUNT];
	bool done[ASYNC_COUNT];
	struct timeval snd[ASYNC_COUNT];
	struct timeval rcv[ASYNC_COUNT];
	struct timeval diff[ASYNC_COUNT];
	struct tevent_context *ctx;
	int total_done = 0;

	if (torture_setting_bool(tctx, "quick", false)) {
		torture_skip(tctx, "TestSleep disabled - use \"torture:quick=no\" to enable\n");
	}
	torture_comment(tctx, "Testing TestSleep - use \"torture:quick=yes\" to disable\n");

	for (i=0;i<ASYNC_COUNT;i++) {
		done[i]		= false;
		snd[i]		= timeval_current();
		rcv[i]		= timeval_zero();
		r[i].in.seconds = ASYNC_COUNT-i;
		req[i] = dcerpc_echo_TestSleep_send(p, tctx, &r[i]);
		torture_assert(tctx, req[i], "Failed to send async sleep request\n");
	}

	ctx = dcerpc_event_context(p);
	while (total_done < ASYNC_COUNT) {
		torture_assert(tctx, event_loop_once(ctx) == 0, 
					   "Event context loop failed");
		for (i=0;i<ASYNC_COUNT;i++) {
			if (done[i] == false && req[i]->state == RPC_REQUEST_DONE) {
				int rounded_tdiff;
				total_done++;
				done[i] = true;
				rcv[i]	= timeval_current();
				diff[i]	= timeval_until(&snd[i], &rcv[i]);
				rounded_tdiff = (int)(0.5 + diff[i].tv_sec + (1.0e-6*diff[i].tv_usec));
				status	= dcerpc_ndr_request_recv(req[i]);
				torture_comment(tctx, "rounded_tdiff=%d\n", rounded_tdiff);
				torture_assert_ntstatus_ok(tctx, status, 
							talloc_asprintf(tctx, "TestSleep(%d) failed", i));
				torture_assert(tctx, r[i].out.result == r[i].in.seconds,
					talloc_asprintf(tctx, "Failed - Asked to sleep for %u seconds (server replied with %u seconds and the reply takes only %u seconds)", 
						r[i].out.result, r[i].in.seconds, (unsigned int)diff[i].tv_sec));
				torture_assert(tctx, r[i].out.result <= rounded_tdiff, 
					talloc_asprintf(tctx, "Failed - Slept for %u seconds (but reply takes only %u.%06u seconds)", 
						r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec));
				if (r[i].out.result+1 == rounded_tdiff) {
					torture_comment(tctx, "Slept for %u seconds (but reply takes %u.%06u seconds - busy server?)\n", 
							r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
				} else if (r[i].out.result == rounded_tdiff) {
					torture_comment(tctx, "Slept for %u seconds (reply takes %u.%06u seconds - ok)\n", 
							r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
				} else {
						torture_comment(tctx, "(Failed) - Not async - Slept for %u seconds (but reply takes %u.%06u seconds)", 
							r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
					/* TODO: let the test fail here, when we support async rpc on ncacn_np */
				}
			}
		}
	}
	torture_comment(tctx, "\n");
	return true;
}
Пример #22
0
/*
  call this when the socket becomes readable to kick off the whole
  stream parsing process
*/
_PUBLIC_ void packet_recv(struct packet_context *pc)
{
	size_t npending;
	NTSTATUS status;
	size_t nread = 0;
	DATA_BLOB blob;
	bool recv_retry = false;

	if (pc->processing) {
		TEVENT_FD_NOT_READABLE(pc->fde);
		pc->processing++;
		return;
	}

	if (pc->recv_disable) {
		pc->recv_need_enable = true;
		TEVENT_FD_NOT_READABLE(pc->fde);
		return;
	}

	if (pc->packet_size != 0 && pc->num_read >= pc->packet_size) {
		goto next_partial;
	}

	if (pc->packet_size != 0) {
		/* we've already worked out how long this next packet is, so skip the
		   socket_pending() call */
		npending = pc->packet_size - pc->num_read;
	} else if (pc->initial_read != 0) {
		npending = pc->initial_read - pc->num_read;
	} else {
		if (pc->sock) {
			status = socket_pending(pc->sock, &npending);
		} else {
			status = NT_STATUS_CONNECTION_DISCONNECTED;
		}
		if (!NT_STATUS_IS_OK(status)) {
			packet_error(pc, status);
			return;
		}
	}

	if (npending == 0) {
		packet_eof(pc);
		return;
	}

again:

	if (npending + pc->num_read < npending) {
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	if (npending + pc->num_read < pc->num_read) {
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	/* possibly expand the partial packet buffer */
	if (npending + pc->num_read > pc->partial.length) {
		if (!data_blob_realloc(pc, &pc->partial, npending+pc->num_read)) {
			packet_error(pc, NT_STATUS_NO_MEMORY);
			return;
		}
	}

	if (pc->partial.length < pc->num_read + npending) {
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	if ((uint8_t *)pc->partial.data + pc->num_read < (uint8_t *)pc->partial.data) {
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}
	if ((uint8_t *)pc->partial.data + pc->num_read + npending < (uint8_t *)pc->partial.data) {
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	status = socket_recv(pc->sock, pc->partial.data + pc->num_read, 
			     npending, &nread);

	if (NT_STATUS_IS_ERR(status)) {
		packet_error(pc, status);
		return;
	}
	if (recv_retry && NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
		nread = 0;
		status = NT_STATUS_OK;
	}
	if (!NT_STATUS_IS_OK(status)) {
		return;
	}

	if (nread == 0 && !recv_retry) {
		packet_eof(pc);
		return;
	}

	pc->num_read += nread;

	if (pc->unreliable_select && nread != 0) {
		recv_retry = true;
		status = socket_pending(pc->sock, &npending);
		if (!NT_STATUS_IS_OK(status)) {
			packet_error(pc, status);
			return;
		}
		if (npending != 0) {
			goto again;
		}
	}

next_partial:
	if (pc->partial.length != pc->num_read) {
		if (!data_blob_realloc(pc, &pc->partial, pc->num_read)) {
			packet_error(pc, NT_STATUS_NO_MEMORY);
			return;
		}
	}

	/* see if its a full request */
	blob = pc->partial;
	blob.length = pc->num_read;
	status = pc->full_request(pc->private_data, blob, &pc->packet_size);
	if (NT_STATUS_IS_ERR(status)) {
		packet_error(pc, status);
		return;
	}
	if (!NT_STATUS_IS_OK(status)) {
		return;
	}

	if (pc->packet_size > pc->num_read) {
		/* the caller made an error */
		DEBUG(0,("Invalid packet_size %lu greater than num_read %lu\n",
			 (long)pc->packet_size, (long)pc->num_read));
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	/* it is a full request - give it to the caller */
	blob = pc->partial;
	blob.length = pc->num_read;

	if (pc->packet_size < pc->num_read) {
		pc->partial = data_blob_talloc(pc, blob.data + pc->packet_size, 
					       pc->num_read - pc->packet_size);
		if (pc->partial.data == NULL) {
			packet_error(pc, NT_STATUS_NO_MEMORY);
			return;
		}
		/* Trunate the blob sent to the caller to only the packet length */
		if (!data_blob_realloc(pc, &blob, pc->packet_size)) {
			packet_error(pc, NT_STATUS_NO_MEMORY);
			return;
		}
	} else {
		pc->partial = data_blob(NULL, 0);
	}
	pc->num_read -= pc->packet_size;
	pc->packet_size = 0;
	
	if (pc->serialise) {
		pc->processing = 1;
	}

	pc->busy = true;

	status = pc->callback(pc->private_data, blob);

	pc->busy = false;

	if (pc->destructor_called) {
		talloc_free(pc);
		return;
	}

	if (pc->processing) {
		if (pc->processing > 1) {
			TEVENT_FD_READABLE(pc->fde);
		}
		pc->processing = 0;
	}

	if (!NT_STATUS_IS_OK(status)) {
		packet_error(pc, status);
		return;
	}

	/* Have we consumed the whole buffer yet? */
	if (pc->partial.length == 0) {
		return;
	}

	/* we got multiple packets in one tcp read */
	if (pc->ev == NULL) {
		goto next_partial;
	}

	blob = pc->partial;
	blob.length = pc->num_read;

	status = pc->full_request(pc->private_data, blob, &pc->packet_size);
	if (NT_STATUS_IS_ERR(status)) {
		packet_error(pc, status);
		return;
	}

	if (!NT_STATUS_IS_OK(status)) {
		return;
	}

	tevent_add_timer(pc->ev, pc, timeval_zero(), packet_next_event, pc);
}
/*
  main program
*/
int main(int argc, const char *argv[])
{
	struct ctdb_context *ctdb;
	struct ctdb_db_context *ctdb_db;
	struct tevent_context *ev;

	TDB_DATA key;

	struct poptOption popt_options[] = {
		POPT_AUTOHELP
		{ "record",      'r', POPT_ARG_STRING, &TESTKEY, 0, "record", "string" },
		POPT_TABLEEND
	};
	int opt;
	const char **extra_argv;
	int extra_argc = 0;
	poptContext pc;

	pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		default:
			fprintf(stderr, "Invalid option %s: %s\n", 
				poptBadOption(pc, 0), poptStrerror(opt));
			exit(1);
		}
	}

	/* setup the remaining options for the main program to use */
	extra_argv = poptGetArgs(pc);
	if (extra_argv) {
		extra_argv++;
		while (extra_argv[extra_argc]) extra_argc++;
	}

	ev = tevent_context_init(NULL);

	ctdb = ctdb_cmdline_client(ev, timeval_current_ofs(3, 0));
	if (ctdb == NULL) {
		printf("failed to connect to ctdb daemon.\n");
		exit(1);
	}

	key.dptr  = discard_const(TESTKEY);
	key.dsize = strlen(TESTKEY);

	/* attach to a specific database */
	ctdb_db = ctdb_attach(ctdb, timeval_current_ofs(3, 0), "test.tdb",
			      false, 0);
	if (!ctdb_db) {
		fprintf(stderr, "ctdb_attach failed - %s\n", ctdb_errstr(ctdb));
		exit(10);
	}

	printf("Waiting for cluster\n");
	while (1) {
		uint32_t recmode=1;
		ctdb_ctrl_getrecmode(ctdb, ctdb, timeval_zero(), CTDB_CURRENT_NODE, &recmode);
		if (recmode == 0) break;
		tevent_loop_once(ev);
	}

	fetch_readonly_once(ctdb, ctdb_db, key);

	return 0;
}
Пример #24
0
/*
  load our replication partners
*/
NTSTATUS wreplsrv_load_partners(struct wreplsrv_service *service)
{
	struct wreplsrv_partner *partner;
	struct ldb_result *res = NULL;
	int ret;
	TALLOC_CTX *tmp_ctx;
	int i;
	uint64_t new_seqnumber;

	new_seqnumber = wins_config_db_get_seqnumber(service->config.ldb);

	/* if it's not the first run and nothing changed we're done */
	if (service->config.seqnumber != 0 && service->config.seqnumber == new_seqnumber) {
		return NT_STATUS_OK;
	}

	tmp_ctx = talloc_new(service);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	service->config.seqnumber = new_seqnumber;

	/* find the record in the WINS database */
	ret = ldb_search(service->config.ldb, tmp_ctx, &res,
			 ldb_dn_new(tmp_ctx, service->config.ldb, "CN=PARTNERS"),
			 LDB_SCOPE_SUBTREE, NULL, "(objectClass=wreplPartner)");
	if (ret != LDB_SUCCESS) goto failed;

	/* first disable all existing partners */
	for (partner=service->partners; partner; partner = partner->next) {
		partner->type = WINSREPL_PARTNER_NONE;
	}

	for (i=0; i < res->count; i++) {
		const char *address;

		address	= ldb_msg_find_attr_as_string(res->msgs[i], "address", NULL);
		if (!address) {
			goto failed;
		}

		partner = wreplsrv_find_partner(service, address);
		if (partner) {
			if (partner->name != partner->address) {
				talloc_free(discard_const(partner->name));
			}
			partner->name = NULL;
			talloc_free(discard_const(partner->our_address));
			partner->our_address = NULL;

			/* force rescheduling of pulling */
			partner->pull.next_run = timeval_zero();
		} else {
			partner = talloc_zero(service, struct wreplsrv_partner);
			if (partner == NULL) goto failed;

			partner->service = service;
			partner->address = address;
			talloc_steal(partner, partner->address);

			DLIST_ADD_END(service->partners, partner, struct wreplsrv_partner *);
		}

		partner->name			= ldb_msg_find_attr_as_string(res->msgs[i], "name", partner->address);
		talloc_steal(partner, partner->name);
		partner->our_address		= ldb_msg_find_attr_as_string(res->msgs[i], "ourAddress", NULL);
		talloc_steal(partner, partner->our_address);

		partner->type			= ldb_msg_find_attr_as_uint(res->msgs[i], "type", WINSREPL_PARTNER_BOTH);
		partner->pull.interval		= ldb_msg_find_attr_as_uint(res->msgs[i], "pullInterval",
								    WINSREPL_DEFAULT_PULL_INTERVAL);
		partner->pull.retry_interval	= ldb_msg_find_attr_as_uint(res->msgs[i], "pullRetryInterval",
								    WINSREPL_DEFAULT_PULL_RETRY_INTERVAL);
		partner->push.change_count	= ldb_msg_find_attr_as_uint(res->msgs[i], "pushChangeCount",
								    WINSREPL_DEFAULT_PUSH_CHANGE_COUNT);
		partner->push.use_inform	= ldb_msg_find_attr_as_uint(res->msgs[i], "pushUseInform", true);

		DEBUG(3,("wreplsrv_load_partners: found partner: %s type: 0x%X\n",
			partner->address, partner->type));
	}

	DEBUG(2,("wreplsrv_load_partners: %u partners found: wins_config_db seqnumber %llu\n",
		res->count, (unsigned long long)service->config.seqnumber));

	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
failed:
	talloc_free(tmp_ctx);
	return NT_STATUS_FOOBAR;
}
Пример #25
0
/*
  serve up EchoData over the irpc system
*/
static NTSTATUS irpc_EchoData(struct irpc_message *irpc, struct echo_EchoData *r)
{
	irpc->defer_reply = true;
	event_add_timed(irpc->ev, irpc, timeval_zero(), deferred_echodata, irpc);
	return NT_STATUS_OK;
}
Пример #26
0
/*
  main program
*/
int main(int argc, const char *argv[])
{
	struct ctdb_context *ctdb;
	struct ctdb_db_context *ctdb_db;
	int unsafe_writes = 0;
	struct poptOption popt_options[] = {
		POPT_AUTOHELP
		POPT_CTDB_CMDLINE
		{ "timelimit", 't', POPT_ARG_INT, &timelimit, 0, "timelimit", "integer" },
		{ "delay", 'D', POPT_ARG_INT, &delay, 0, "delay (in seconds) between operations", "integer" },
		{ "verbose", 'v', POPT_ARG_NONE,  &verbose, 0, "switch on verbose mode", NULL },
		{ "unsafe-writes", 'u', POPT_ARG_NONE, &unsafe_writes, 0, "do not use tdb transactions when writing", NULL },
		POPT_TABLEEND
	};
	int opt;
	const char **extra_argv;
	int extra_argc = 0;
	poptContext pc;
	struct event_context *ev;

	printf("SUCCESS (transaction test disabled while transactions are being rewritten)\n");
	exit(0);

	if (verbose) {
		setbuf(stdout, (char *)NULL); /* don't buffer */
	} else {
		setlinebuf(stdout);
	}

	pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		default:
			fprintf(stderr, "Invalid option %s: %s\n", 
				poptBadOption(pc, 0), poptStrerror(opt));
			exit(1);
		}
	}

	/* setup the remaining options for the main program to use */
	extra_argv = poptGetArgs(pc);
	if (extra_argv) {
		extra_argv++;
		while (extra_argv[extra_argc]) extra_argc++;
	}

	ev = event_context_init(NULL);

	ctdb = ctdb_cmdline_client(ev);
	if (ctdb == NULL) {
		DEBUG(DEBUG_ERR, ("Could not attach to daemon\n"));
		return 1;
	}

	/* attach to a specific database */
	if (unsafe_writes == 1) {
		ctdb_db = ctdb_attach(ctdb, "transaction.tdb", true, TDB_NOSYNC);
	} else {
		ctdb_db = ctdb_attach(ctdb, "transaction.tdb", true, 0);
	}

	if (!ctdb_db) {
		DEBUG(DEBUG_ERR, ("ctdb_attach failed - %s\n", ctdb_errstr(ctdb)));
		exit(1);
	}

	DEBUG(DEBUG_ERR, ("Waiting for cluster\n"));
	while (1) {
		uint32_t recmode=1;
		ctdb_ctrl_getrecmode(ctdb, ctdb, timeval_zero(), CTDB_CURRENT_NODE, &recmode);
		if (recmode == 0) break;
		event_loop_once(ev);
	}

	pnn = ctdb_get_pnn(ctdb);
	printf("Starting test on node %u. running for %u seconds. sleep delay: %u seconds.\n", pnn, timelimit, delay);

	if (!verbose && (pnn == 0)) {
		event_add_timed(ev, ctdb, timeval_current_ofs(1, 0), each_second, ctdb);
	}

	test_store_records(ctdb, ev);

	if (verbose || (pnn == 0)) {
		if (success != true) {
			printf("The test FAILED\n");
			return 1;
		} else {
			printf("SUCCESS!\n");
		}
	}
	return 0;
}