コード例 #1
0
ファイル: testserver.c プロジェクト: balsdorf/MaxScale
/**
 * test1	Allocate a server and do lots of other things
 *
  */
static int
test1()
{
SERVER   *server;
int     result;
char    *status;

        /* Server tests */
        ss_dfprintf(stderr,
                    "testserver : creating server called MyServer"); 
        server = server_alloc("MyServer", "HTTPD", 9876);
        skygw_log_sync_all();

        //ss_info_dassert(NULL != service, "New server with valid protocol and port must not be null");
        //ss_info_dassert(0 != service_isvalid(service), "Service must be valid after creation");

        ss_dfprintf(stderr, "\t..done\nTest Parameter for Server.");
        ss_info_dassert(NULL == serverGetParameter(server, "name"), "Parameter should be null when not set");
        serverAddParameter(server, "name", "value");
        skygw_log_sync_all();
        ss_info_dassert(0 == strcmp("value", serverGetParameter(server, "name")), "Parameter should be returned correctly");
        ss_dfprintf(stderr, "\t..done\nTesting Unique Name for Server.");
        ss_info_dassert(NULL == server_find_by_unique_name("uniquename"), "Should not find non-existent unique name.");
        server_set_unique_name(server, "uniquename");
        skygw_log_sync_all();
        ss_info_dassert(server == server_find_by_unique_name("uniquename"), "Should find by unique name.");
        ss_dfprintf(stderr, "\t..done\nTesting Status Setting for Server.");
        status = server_status(server);
        skygw_log_sync_all();
        ss_info_dassert(0 == strcmp("Running", status), "Status of Server should be Running by default.");
        if (NULL != status) free(status);
        server_set_status(server, SERVER_MASTER);
        status = server_status(server);
        skygw_log_sync_all();
        ss_info_dassert(0 == strcmp("Master, Running", status), "Should find correct status.");
        server_clear_status(server, SERVER_MASTER);		
		free(status);
        status = server_status(server);
        skygw_log_sync_all();
        ss_info_dassert(0 == strcmp("Running", status), "Status of Server should be Running after master status cleared.");
        if (NULL != status) free(status);
        ss_dfprintf(stderr, "\t..done\nRun Prints for Server and all Servers.");
        printServer(server);
        printAllServers();
        skygw_log_sync_all();
        ss_dfprintf(stderr, "\t..done\nFreeing Server.");
        ss_info_dassert(0 != server_free(server), "Free should succeed");
        ss_dfprintf(stderr, "\t..done\n");
	return 0;
        
}
コード例 #2
0
int Message_Unit::process_timer_msg(uint32_t msg_id, Block_Buffer &buf, Time_Value &now) {
	if (data_pro_tick_ < Time_Value::gettimeofday()) {
		server_status();
	}


	switch (msg_id) {
	case SERVER_INNER_CLIENT_CLOSE: {
		int cid = 0, close_type = 0;
		int64_t value = 0;
		buf.read_int32(cid);
		buf.read_int32(close_type);
		buf.read_int64(value);
		monitor()->close_link_by_cid(cid, Link_Close(close_type, value));

		break;
	}
	default : {
		return CALL_CONTINUE;
		break;
	}
	}

	return CALL_RETURN;
}
コード例 #3
0
ファイル: server.c プロジェクト: littleyang/MaxScale
/**
 * List all servers in a tabular form to a DCB
 *
 */
void
dListServers(DCB *dcb)
{
SERVER	*ptr;
char	*stat;

	spinlock_acquire(&server_spin);
	ptr = allServers;
	if (ptr)
	{
		dcb_printf(dcb, "Servers.\n");
		dcb_printf(dcb, "-------------------+-----------------+-------+-------------+--------------------\n");
		dcb_printf(dcb, "%-18s | %-15s | Port  | Connections | %-20s\n",
			"Server", "Address", "Status");
		dcb_printf(dcb, "-------------------+-----------------+-------+-------------+--------------------\n");
	}
	while (ptr)
	{
		stat = server_status(ptr);
		dcb_printf(dcb, "%-18s | %-15s | %5d | %11d | %s\n",
				ptr->unique_name, ptr->name,
				ptr->port,
				ptr->stats.n_current, stat);
		free(stat);
		ptr = ptr->next;
	}
	if (allServers)
		dcb_printf(dcb, "-------------------+-----------------+-------+-------------+--------------------\n");
	spinlock_release(&server_spin);
}
コード例 #4
0
ファイル: server.c プロジェクト: littleyang/MaxScale
/**
 * Print all servers to a DCB
 *
 * Designed to be called within a debugger session in order
 * to display all active servers within the gateway
 */
void
dprintAllServers(DCB *dcb)
{
SERVER	*ptr;
char	*stat;

	spinlock_acquire(&server_spin);
	ptr = allServers;
	while (ptr)
	{
		dcb_printf(dcb, "Server %p (%s)\n", ptr, ptr->unique_name);
		dcb_printf(dcb, "\tServer:				%s\n",
								ptr->name);
		stat = server_status(ptr);
		dcb_printf(dcb, "\tStatus:               		%s\n",
									stat);
		free(stat);
		dcb_printf(dcb, "\tProtocol:			%s\n",
								ptr->protocol);
		dcb_printf(dcb, "\tPort:				%d\n",
								ptr->port);
		if (ptr->server_string)
			dcb_printf(dcb, "\tServer Version:\t\t\t%s\n",
							ptr->server_string);
		dcb_printf(dcb, "\tNode Id:			%d\n",
								ptr->node_id);
		dcb_printf(dcb, "\tMaster Id:			%d\n",
								ptr->master_id);
		if (ptr->slaves) {
			int i;
			dcb_printf(dcb, "\tSlave Ids:			");
			for (i = 0; ptr->slaves[i]; i++)
			{
				if (i == 0)
					dcb_printf(dcb, "%li", ptr->slaves[i]);
				else
					dcb_printf(dcb, ", %li ", ptr->slaves[i]);
			}
			dcb_printf(dcb, "\n");
		}
		dcb_printf(dcb, "\tRepl Depth:			%d\n",
							 ptr->depth);
		if (SERVER_IS_SLAVE(ptr) || SERVER_IS_RELAY_SERVER(ptr)) {
			if (ptr->rlag >= 0) {
				dcb_printf(dcb, "\tSlave delay:\t\t%d\n", ptr->rlag);
			}
		}
		if (ptr->node_ts > 0) {
			dcb_printf(dcb, "\tLast Repl Heartbeat:\t%lu\n", ptr->node_ts);
		}
		dcb_printf(dcb, "\tNumber of connections:		%d\n",
						ptr->stats.n_connections);
		dcb_printf(dcb, "\tCurrent no. of conns:		%d\n",
							ptr->stats.n_current);
                dcb_printf(dcb, "\tCurrent no. of operations:	%d\n",
						ptr->stats.n_current_ops);
                ptr = ptr->next;
	}
	spinlock_release(&server_spin);
}
コード例 #5
0
ファイル: webserver.c プロジェクト: art-spilgames/MaxScale
/**
 * Display a table row for a particular server. This is called via the
 * serverIterate call in send_servers.
 *
 * @param server	The server to print
 * @param dcb		The DCB to send the HTML to
 */
static void
server_row(SERVER *server, DCB *dcb)
{
	dcb_printf(dcb, "<TR><TD>%s</TD><TD>%s</TD><TD>%d</TD><TD>%s</TD><TD>%d</TD></TR>\n",
		server->unique_name, server->name, server->port,
		server_status(server), server->stats.n_current);
}
コード例 #6
0
ファイル: serverdialog.cpp プロジェクト: Tpimp/MissionControl
void ServerDialog::serverListening(QHostAddress address, int port)
{
    // update the server status string in the Status bar
    QString server_status("Server Running:");
    server_status.append(" @ " + address.toString());
    server_status.append(" on " + QString::number(port) );
    mStatusText->setText(server_status);

}
コード例 #7
0
ファイル: server.c プロジェクト: littleyang/MaxScale
/**
 * Print server details to a DCB
 *
 * Designed to be called within a debugger session in order
 * to display all active servers within the gateway
 */
void
dprintServer(DCB *dcb, SERVER *server)
{
char		*stat;
SERVER_PARAM	*param;

	dcb_printf(dcb, "Server %p (%s)\n", server, server->unique_name);
	dcb_printf(dcb, "\tServer:				%s\n", server->name);
	stat = server_status(server);
	dcb_printf(dcb, "\tStatus:               		%s\n", stat);
	free(stat);
	dcb_printf(dcb, "\tProtocol:			%s\n", server->protocol);
	dcb_printf(dcb, "\tPort:				%d\n", server->port);
	if (server->server_string)
		dcb_printf(dcb, "\tServer Version:\t\t\t%s\n", server->server_string);
	dcb_printf(dcb, "\tNode Id:			%d\n", server->node_id);
	dcb_printf(dcb, "\tMaster Id:			%d\n", server->master_id);
	if (server->slaves) {
		int i;
		dcb_printf(dcb, "\tSlave Ids:			");
		for (i = 0; server->slaves[i]; i++)
		{
			if (i == 0)
				dcb_printf(dcb, "%li", server->slaves[i]);
			else
				dcb_printf(dcb, ", %li ", server->slaves[i]);
		}
		dcb_printf(dcb, "\n");
	}
	dcb_printf(dcb, "\tRepl Depth:			%d\n", server->depth);
	if (SERVER_IS_SLAVE(server) || SERVER_IS_RELAY_SERVER(server)) {
		if (server->rlag >= 0) {
			dcb_printf(dcb, "\tSlave delay:\t\t%d\n", server->rlag);
		}
	}
	if (server->node_ts > 0) {
		struct tm result;
		char 	 buf[40];
		dcb_printf(dcb, "\tLast Repl Heartbeat:\t%s",
			asctime_r(localtime_r((time_t *)(&server->node_ts), &result), buf));
	}
	if ((param = server->parameters) != NULL)
	{
		dcb_printf(dcb, "\tServer Parameters:\n");
		while (param)
		{
			dcb_printf(dcb, "\t\t%-20s\t%s\n", param->name,
								param->value);
			param = param->next;
		}
	}
	dcb_printf(dcb, "\tNumber of connections:		%d\n",
						server->stats.n_connections);
	dcb_printf(dcb, "\tCurrent no. of conns:		%d\n",
						server->stats.n_current);
        dcb_printf(dcb, "\tCurrent no. of operations:	%d\n", server->stats.n_current_ops);
}
コード例 #8
0
ファイル: server.c プロジェクト: littleyang/MaxScale
/**
 * Provide a row to the result set that defines the set of servers
 *
 * @param set	The result set
 * @param data	The index of the row to send
 * @return The next row or NULL
 */
static RESULT_ROW *
serverRowCallback(RESULTSET *set, void *data)
{
int		*rowno = (int *)data;
int		i = 0;;
char		*stat, buf[20];
RESULT_ROW	*row;
SERVER		*ptr;

	spinlock_acquire(&server_spin);
	ptr = allServers;
	while (i < *rowno && ptr)
	{
		i++;
		ptr = ptr->next;
	}
	if (ptr == NULL)
	{
		spinlock_release(&server_spin);
		free(data);
		return NULL;
	}
	(*rowno)++;
	row = resultset_make_row(set);
	resultset_row_set(row, 0, ptr->unique_name);
	resultset_row_set(row, 1, ptr->name);
	sprintf(buf, "%d", ptr->port);
	resultset_row_set(row, 2, buf);
	sprintf(buf, "%d", ptr->stats.n_current);
	resultset_row_set(row, 3, buf);
	stat = server_status(ptr);
	resultset_row_set(row, 4, stat);
	free(stat);
	spinlock_release(&server_spin);
	return row;
}
コード例 #9
0
ファイル: gophernicus.c プロジェクト: unisx/gophernicus
/*
 * Main
 */
int main(int argc, char *argv[])
{
	struct stat file;
	state st;
	char self[64];
	char selector[BUFSIZE];
	char buf[BUFSIZE];
	char *dest;
	char *c;
#ifdef HAVE_SHMEM
	struct shmid_ds shm_ds;
	shm_state *shm;
	int shmid;
#endif

	/* Get the name of this binary */
	if ((c = strrchr(argv[0], '/'))) sstrlcpy(self, c + 1);
	else sstrlcpy(self, argv[0]);

	/* Initialize state */
#ifdef HAVE_LOCALES
	setlocale(LC_TIME, DATE_LOCALE);
#endif
	init_state(&st);
	srand(time(NULL) / (getpid() + getppid()));

	/* Handle command line arguments */
	parse_args(&st, argc, argv);

	/* Open syslog() */
	if (st.opt_syslog) openlog(self, LOG_PID, LOG_DAEMON);

	/* Make sure the computer is turned on */
#ifdef __HAIKU__
	if (is_computer_on() != TRUE)
		die(&st, ERR_ACCESS, "Please turn on the computer first");
#endif

	/* Refuse to run as root */
#ifdef HAVE_PASSWD
	if (st.opt_root && getuid() == 0)
		die(&st, ERR_ACCESS, "Refusing to run as root");
#endif

	/* Try to get shared memory */
#ifdef HAVE_SHMEM
	if ((shmid = shmget(SHM_KEY, sizeof(shm_state), IPC_CREAT | SHM_MODE)) == ERROR) {

		/* Getting memory failed -> delete the old allocation */
		shmctl(shmid, IPC_RMID, &shm_ds);
		shm = NULL;
	}
	else {
		/* Map shared memory */
		if ((shm = (shm_state *) shmat(shmid, (void *) 0, 0)) == (void *) ERROR)
			shm = NULL;

		/* Initialize mapped shared memory */
		if (shm && shm->start_time == 0) {
			shm->start_time = time(NULL);

			/* Keep server platform & description in shm */
			platform(&st);
			sstrlcpy(shm->server_platform, st.server_platform);
			sstrlcpy(shm->server_description, st.server_description);
		}
	}

	/* For debugging shared memory issues */
	if (!st.opt_shm) shm = NULL;

	/* Get server platform and description */
	if (shm) {
		sstrlcpy(st.server_platform, shm->server_platform);

		if (!*st.server_description)
			sstrlcpy(st.server_description, shm->server_description);
	}
	else
#endif
		platform(&st);

	/* Read selector */
	if (fgets(selector, sizeof(selector) - 1, stdin) == NULL)
		selector[0] = '\0';

	/* Remove trailing CRLF */
	chomp(selector);

	if (st.debug) syslog(LOG_INFO, "client sent us \"%s\"", selector);

	/* Handle hURL: redirect page */
	if (sstrncmp(selector, "URL:") == MATCH) {
		st.req_filetype = TYPE_HTML;
		sstrlcpy(st.req_selector, selector);
		url_redirect(&st);
		return OK;
	}

	/* Handle gopher+ root requests (UMN gopher client is seriously borken) */
	if (sstrncmp(selector, "\t$") == MATCH) {
		printf("+-1" CRLF);
		printf("+INFO: 1Main menu\t\t%s\t%i" CRLF,
			st.server_host,
			st.server_port);
		printf("+VIEWS:" CRLF " application/gopher+-menu: <512b>" CRLF);
		printf("." CRLF);

		if (st.debug) syslog(LOG_INFO, "got a request for gopher+ root menu");
		return OK;
	}

	/* Convert HTTP request to gopher (respond using headerless HTTP/0.9) */
	if (sstrncmp(selector, "GET ") == MATCH ||
	    sstrncmp(selector, "POST ") == MATCH ) {

		if ((c = strchr(selector, ' '))) sstrlcpy(selector, c + 1);
		if ((c = strchr(selector, ' '))) *c = '\0';

		st.req_protocol = PROTO_HTTP;

		if (st.debug) syslog(LOG_INFO, "got HTTP request for \"%s\"", selector);
	}

	/* Save default server_host & fetch session data (including new server_host) */
	sstrlcpy(st.server_host_default, st.server_host);
#ifdef HAVE_SHMEM
	if (shm) get_shm_session(&st, shm);
#endif

	/* Loop through the selector, fix it & separate query_string */
	dest = st.req_selector;
	if (selector[0] != '/') *dest++ = '/';

	for (c = selector; *c;) {

		/* Skip duplicate slashes and /./ */
		while (*c == '/' && *(c + 1) == '/') c++;
		if (*c == '/' && *(c + 1) == '.' && *(c + 2) == '/') c += 2;

		/* Start of a query string (either type 7 or HTTP-style)? */
		if (*c == '\t' || (st.opt_query && *c == '?')) {
			sstrlcpy(st.req_query_string, c + 1);
			if ((c = strchr(st.req_query_string, '\t'))) *c = '\0';
			break;
		}

		/* Start of virtual host hint? */
		if (*c == ';') {
			if (st.opt_vhost) sstrlcpy(st.server_host, c + 1);

			/* Skip vhost on selector */
			while (*c && *c != '\t') c++;
			continue;
		}

		/* Copy valid char */
		*dest++ = *c++;
	}
	*dest = '\0';

	/* Remove encodings from selector */
	strndecode(st.req_selector, st.req_selector, sizeof(st.req_selector));

	/* Deny requests for Slashdot and /../ hackers */
	if (strstr(st.req_selector, "/."))
		die(&st, ERR_ACCESS, "Refusing to serve out dotfiles");

	/* Handle /server-status requests */
#ifdef HAVE_SHMEM
	if (sstrncmp(st.req_selector, SERVER_STATUS) == MATCH) {
		if (shm) server_status(&st, shm, shmid);
		return OK;
	}
#endif

	/* Remove possible extra cruft from server_host */
	if ((c = strchr(st.server_host, '\t'))) *c = '\0';

	/* Guess request filetype so we can die() with style... */
	st.req_filetype = gopher_filetype(&st, st.req_selector, FALSE);

	/* Convert seletor to path & stat() */
	selector_to_path(&st);
	if (st.debug) syslog(LOG_INFO, "path to resource is \"%s\"", st.req_realpath);

	if (stat(st.req_realpath, &file) == ERROR) {

		/* Handle virtual /caps.txt requests */
		if (st.opt_caps && sstrncmp(st.req_selector, CAPS_TXT) == MATCH) {
#ifdef HAVE_SHMEM
			caps_txt(&st, shm);
#else
			caps_txt(&st, NULL);
#endif
			return OK;
		}

		/* Requested file not found - die() */
		die(&st, ERR_NOTFOUND, NULL);
	}

	/* Fetch request filesize from stat() */
	st.req_filesize = file.st_size;

	/* Everyone must have read access but no write access */
	if ((file.st_mode & S_IROTH) == 0)
		die(&st, ERR_ACCESS, "File or directory not world-readable");
	if ((file.st_mode & S_IWOTH) != 0)
		die(&st, ERR_ACCESS, "File or directory world-writeable");

	/* If stat said it was a dir then it's a menu */
	if ((file.st_mode & S_IFMT) == S_IFDIR) st.req_filetype = TYPE_MENU;

	/* Not a dir - let's guess the filetype again... */
	else if ((file.st_mode & S_IFMT) == S_IFREG)
		st.req_filetype = gopher_filetype(&st, st.req_realpath, st.opt_magic);

	/* Menu selectors must end with a slash */
	if (st.req_filetype == TYPE_MENU && strlast(st.req_selector) != '/')
		sstrlcat(st.req_selector, "/");

	/* Change directory to wherever the resource was */
	sstrlcpy(buf, st.req_realpath);

	if ((file.st_mode & S_IFMT) != S_IFDIR) c = dirname(buf);
	else c = buf;

	if (chdir(c) == ERROR) die(&st, ERR_ACCESS, NULL);

	/* Keep count of hits and data transfer */
#ifdef HAVE_SHMEM
	if (shm) {
		shm->hits++;
		shm->kbytes += st.req_filesize / 1024;

		/* Update user session */
		update_shm_session(&st, shm);
	}
#endif

	/* Log the request */
	if (st.opt_syslog) {
		syslog(LOG_INFO, "request for \"gopher://%s:%i/%c%s\" from %s",
			st.server_host,
			st.server_port,
			st.req_filetype,
			st.req_selector,
			st.req_remote_addr);
	}

	/* Check file type & act accordingly */
	switch (file.st_mode & S_IFMT) {
		case S_IFDIR:
			log_combined(&st, HTTP_OK);
			gopher_menu(&st);
			break;

		case S_IFREG:
			log_combined(&st, HTTP_OK);
			gopher_file(&st);
			break;

		default:
			die(&st, ERR_ACCESS, "Refusing to serve out special files");
	}

	/* Clean exit */
	return OK;
}
コード例 #10
0
ファイル: server.c プロジェクト: littleyang/MaxScale
/**
 * Print all servers in Json format to a DCB
 *
 * Designed to be called within a debugger session in order
 * to display all active servers within the gateway
 */
void
dprintAllServersJson(DCB *dcb)
{
SERVER	*ptr;
char	*stat;
int	len = 0;
int	el = 1;

	spinlock_acquire(&server_spin);
	ptr = allServers;
	while (ptr)
	{
		ptr = ptr->next;
		len++;
	}
	ptr = allServers;
	dcb_printf(dcb, "[\n");
	while (ptr)
	{
		dcb_printf(dcb, "  {\n  \"server\": \"%s\",\n",
								ptr->name);
		stat = server_status(ptr);
		dcb_printf(dcb, "    \"status\": \"%s\",\n",
									stat);
		free(stat);
		dcb_printf(dcb, "    \"protocol\": \"%s\",\n",
								ptr->protocol);
		dcb_printf(dcb, "    \"port\": \"%d\",\n",
								ptr->port);
		if (ptr->server_string)
			dcb_printf(dcb, "    \"version\": \"%s\",\n",
							ptr->server_string);
		dcb_printf(dcb, "    \"nodeId\": \"%d\",\n",
								ptr->node_id);
		dcb_printf(dcb, "    \"masterId\": \"%d\",\n",
								ptr->master_id);
		if (ptr->slaves) {
			int i;
			dcb_printf(dcb, "    \"slaveIds\": [ ");
			for (i = 0; ptr->slaves[i]; i++)
			{
				if (i == 0)
					dcb_printf(dcb, "%li", ptr->slaves[i]);
				else
					dcb_printf(dcb, ", %li ", ptr->slaves[i]);
			}
			dcb_printf(dcb, "],\n");
		}
		dcb_printf(dcb, "    \"replDepth\": \"%d\",\n",
							 ptr->depth);
		if (SERVER_IS_SLAVE(ptr) || SERVER_IS_RELAY_SERVER(ptr)) {
			if (ptr->rlag >= 0) {
				dcb_printf(dcb, "    \"slaveDelay\": \"%d\",\n", ptr->rlag);
			}
		}
		if (ptr->node_ts > 0) {
			dcb_printf(dcb, "    \"lastReplHeartbeat\": \"%lu\",\n", ptr->node_ts);
		}
		dcb_printf(dcb, "    \"totalConnections\": \"%d\",\n",
						ptr->stats.n_connections);
		dcb_printf(dcb, "    \"currentConnections\": \"%d\",\n",
							ptr->stats.n_current);
                dcb_printf(dcb, "    \"currentOps\": \"%d\"\n",
						ptr->stats.n_current_ops);
		if (el < len) {
			dcb_printf(dcb, "  },\n");
		}
		else {
			dcb_printf(dcb, "  }\n");
		}
                ptr = ptr->next;
		el++;
	}
	dcb_printf(dcb, "]\n");
	spinlock_release(&server_spin);
}
コード例 #11
0
ファイル: server.c プロジェクト: DBMSRmutl/MaxScale
/**
 * Print all servers to a DCB
 *
 * Designed to be called within a debugger session in order
 * to display all active servers within the gateway
 */
void
dprintAllServers(DCB *dcb)
{
    SERVER *server;
    char *stat;

    spinlock_acquire(&server_spin);
    server = allServers;
    while (server)
    {
        dcb_printf(dcb, "Server %p (%s)\n", server, server->unique_name);
        dcb_printf(dcb, "\tServer:                              %s\n",
                   server->name);
        stat = server_status(server);
        dcb_printf(dcb, "\tStatus:                              %s\n",
                   stat);
        free(stat);
        dcb_printf(dcb, "\tProtocol:                    %s\n",
                   server->protocol);
        dcb_printf(dcb, "\tPort:                                %d\n",
                   server->port);
        if (server->server_string)
            dcb_printf(dcb, "\tServer Version:\t\t\t%s\n",
                       server->server_string);
        dcb_printf(dcb, "\tNode Id:                     %d\n",
                   server->node_id);
        dcb_printf(dcb, "\tMaster Id:                   %d\n",
                   server->master_id);
        if (server->slaves)
        {
            int i;
            dcb_printf(dcb, "\tSlave Ids:                   ");
            for (i = 0; server->slaves[i]; i++)
            {
                if (i == 0)
                {
                    dcb_printf(dcb, "%li", server->slaves[i]);
                }
                else
                {
                    dcb_printf(dcb, ", %li ", server->slaves[i]);
                }
            }
            dcb_printf(dcb, "\n");
        }
        dcb_printf(dcb, "\tRepl Depth:                  %d\n",
                   server->depth);
        if (SERVER_IS_SLAVE(server) || SERVER_IS_RELAY_SERVER(server))
        {
            if (server->rlag >= 0)
            {
                dcb_printf(dcb, "\tSlave delay:\t\t%d\n", server->rlag);
            }
        }
        if (server->node_ts > 0)
        {
            dcb_printf(dcb, "\tLast Repl Heartbeat:\t%lu\n", server->node_ts);
        }
        dcb_printf(dcb, "\tNumber of connections:               %d\n",
                   server->stats.n_connections);
        dcb_printf(dcb, "\tCurrent no. of conns:                %d\n",
                   server->stats.n_current);
        dcb_printf(dcb, "\tCurrent no. of operations:   %d\n",
                   server->stats.n_current_ops);
        if (server->persistpoolmax)
        {
            dcb_printf(dcb, "\tPersistent pool size:            %d\n",
                       server->stats.n_persistent);
            dcb_printf(dcb, "\tPersistent measured pool size:   %d\n",
                       dcb_persistent_clean_count(server->persistent, false));
            dcb_printf(dcb, "\tPersistent max size achieved:    %d\n",
                       server->persistmax);
            dcb_printf(dcb, "\tPersistent pool size limit:      %d\n",
                       server->persistpoolmax);
            dcb_printf(dcb, "\tPersistent max time (secs):          %d\n",
                       server->persistmaxtime);
        }
        server = server->next;
    }
    spinlock_release(&server_spin);
}