xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.lib/in.dhcpd/tests/test_dstore.c (revision 1914:8a8c5f225b1b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*1914Scasper  * Common Development and Distribution License (the "License").
6*1914Scasper  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*1914Scasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*1914Scasper  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <stdio.h>
29*1914Scasper #include <stdio_ext.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <unistd.h>
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/time.h>
340Sstevel@tonic-gate #include <fcntl.h>
350Sstevel@tonic-gate #include <sys/fcntl.h>
360Sstevel@tonic-gate #include <errno.h>
370Sstevel@tonic-gate #include <string.h>
380Sstevel@tonic-gate #include <limits.h>
390Sstevel@tonic-gate #include <sys/socket.h>
400Sstevel@tonic-gate #include <net/if.h>
410Sstevel@tonic-gate #include <netinet/in.h>
420Sstevel@tonic-gate #include <arpa/inet.h>
430Sstevel@tonic-gate #include <thread.h>
440Sstevel@tonic-gate #include <tnf/probe.h>
450Sstevel@tonic-gate 
460Sstevel@tonic-gate #include <netinet/dhcp.h>
470Sstevel@tonic-gate #include <locale.h>
480Sstevel@tonic-gate #include <signal.h>
490Sstevel@tonic-gate #include <tnf/probe.h>
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #include <dhcp_svc_confopt.h>
520Sstevel@tonic-gate #include <dhcp_svc_private.h>
530Sstevel@tonic-gate #include <dhcp_impl.h>
540Sstevel@tonic-gate 
550Sstevel@tonic-gate #ifdef	DEBUG
560Sstevel@tonic-gate #include <mtmalloc.h>
570Sstevel@tonic-gate #endif				/* DEBUG */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate /*
600Sstevel@tonic-gate  * Global variables.
610Sstevel@tonic-gate  */
620Sstevel@tonic-gate int		verbose = 0;
630Sstevel@tonic-gate thread_t	*tp;
640Sstevel@tonic-gate cond_t		never;
650Sstevel@tonic-gate volatile time_t *timp;
660Sstevel@tonic-gate volatile int    tms;
670Sstevel@tonic-gate char		*fl;
680Sstevel@tonic-gate mutex_t		mtx;
690Sstevel@tonic-gate mutex_t		thread_mtx;
700Sstevel@tonic-gate volatile ulong_t ops_outstanding;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate static volatile ulong_t tops, otops;
730Sstevel@tonic-gate static volatile ulong_t minops[6];
740Sstevel@tonic-gate static volatile time_t mintim[6];
750Sstevel@tonic-gate static volatile int minind;
760Sstevel@tonic-gate long		sample_time = 10L;
770Sstevel@tonic-gate long		nsamples = 2;
780Sstevel@tonic-gate 
790Sstevel@tonic-gate static volatile time_t start, ostart;
800Sstevel@tonic-gate volatile time_t ustart;
810Sstevel@tonic-gate volatile int    time_to_go;
820Sstevel@tonic-gate volatile int    spawn_helper;
830Sstevel@tonic-gate char		b[1024 * 1024];
840Sstevel@tonic-gate volatile double slp;
850Sstevel@tonic-gate volatile int    worktype;
860Sstevel@tonic-gate thread_t	sigthread;
870Sstevel@tonic-gate volatile int    old, new, unstarted;
880Sstevel@tonic-gate volatile uint_t	threads;
890Sstevel@tonic-gate volatile unsigned int douwork = 0;
900Sstevel@tonic-gate volatile int    dofsync = 0;
910Sstevel@tonic-gate volatile int    domalloc = 0;
920Sstevel@tonic-gate volatile int    dofork = 0;
930Sstevel@tonic-gate thread_t	opnthread;
940Sstevel@tonic-gate volatile int	doopen = 0;
950Sstevel@tonic-gate 
960Sstevel@tonic-gate dsvc_datastore_t datastore;	/* Datastore for container access */
970Sstevel@tonic-gate 
980Sstevel@tonic-gate #define	MAXTABLE	1024
990Sstevel@tonic-gate int		ntable;
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate dn_rec_list_t  *thread_dncp[MAXTABLE];
1020Sstevel@tonic-gate dsvc_handle_t   dh[MAXTABLE];	/* data handle */
1030Sstevel@tonic-gate struct in_addr  net[MAXTABLE];
1040Sstevel@tonic-gate uint_t		nrecords[MAXTABLE];
1050Sstevel@tonic-gate char		*network;
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate typedef struct work {
1080Sstevel@tonic-gate 	boolean_t	isthreaded;
1090Sstevel@tonic-gate 	int		thread;
1100Sstevel@tonic-gate 	cond_t		cv;
1110Sstevel@tonic-gate 	mutex_t		mtx;
1120Sstevel@tonic-gate 	dn_rec_t	*dnp;
1130Sstevel@tonic-gate }work_t;
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate void
free_work_t(work_t * wptr)1160Sstevel@tonic-gate free_work_t(work_t *wptr) {
1170Sstevel@tonic-gate 	free(wptr->dnp);
1180Sstevel@tonic-gate 	free(wptr);
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate /*
1210Sstevel@tonic-gate  * Simulated binary datastore work
1220Sstevel@tonic-gate  */
1230Sstevel@tonic-gate /* ARGSUSED */
1240Sstevel@tonic-gate static void    *
uwork(void * argp)1250Sstevel@tonic-gate uwork(void *argp)
1260Sstevel@tonic-gate {
1270Sstevel@tonic-gate 	int		i;
1280Sstevel@tonic-gate 	int		err;
1290Sstevel@tonic-gate 	int		fd;
1300Sstevel@tonic-gate 	long		block;
1310Sstevel@tonic-gate 	work_t		*wptr = argp;
1320Sstevel@tonic-gate 	char		*ptr;
1330Sstevel@tonic-gate 	size_t		size = ((random() & (domalloc - 1)) + 0x200) &
1340Sstevel@tonic-gate 				~(0x200 - 1);
1350Sstevel@tonic-gate 	int		wtype;
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	if (domalloc)
1380Sstevel@tonic-gate 		ptr = malloc(size);
1390Sstevel@tonic-gate 	else
1400Sstevel@tonic-gate 		ptr = b;
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	if (wptr->isthreaded) {
1430Sstevel@tonic-gate 		(void) mutex_lock(&wptr->mtx);
1440Sstevel@tonic-gate 	}
1450Sstevel@tonic-gate 	i = wptr->thread;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	TNF_PROBE_1(uwork, "work", "uwork%debug 'in function work'",
1480Sstevel@tonic-gate 		    tnf_long, size, size);
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	wtype = worktype == 0 ? random() & 0x7 : worktype;
1510Sstevel@tonic-gate 	block = (random() & (douwork - 1)) + (tms / 0x200) + 1;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	/* prewrite legal records */
1540Sstevel@tonic-gate 	if (timp[i] == NULL && ustart == 0) {
1550Sstevel@tonic-gate 		ustart = time(NULL);
1560Sstevel@tonic-gate 		wtype = 4;
1570Sstevel@tonic-gate 		block = (tms / 0x200) + 1;
1580Sstevel@tonic-gate 		size = sizeof (b);
1590Sstevel@tonic-gate 		ptr = b;
1600Sstevel@tonic-gate 	}
1610Sstevel@tonic-gate 	timp[i] = time(NULL);
1620Sstevel@tonic-gate 	fd = open(fl, O_RDWR);
1630Sstevel@tonic-gate 	(void) write(fd, (char *)timp, tms);
1640Sstevel@tonic-gate 	(void) close(fd);
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	if (wtype == 4) {
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 		TNF_PROBE_2(uwork_write, "work",
1690Sstevel@tonic-gate 			    "uwork_write%debug 'in function work'",
1700Sstevel@tonic-gate 			    tnf_long, block, block,
1710Sstevel@tonic-gate 			    tnf_long, size, size);
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 		fd = open(fl, O_RDWR);
1740Sstevel@tonic-gate 		(void) lseek(fd, block * 0x200, 0L);
1750Sstevel@tonic-gate 		err = write(fd, ptr, size);
1760Sstevel@tonic-gate 		(void) close(fd);
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 		TNF_PROBE_1(uwork_write_end, "work",
1790Sstevel@tonic-gate 			    "uwork_write_end%debug 'in function work'",
1800Sstevel@tonic-gate 			    tnf_long, err, err);
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	} else if (wtype == 3 && dofsync) {
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 		TNF_PROBE_0(uwork_fsync, "work",
1850Sstevel@tonic-gate 			    "uwork_fsync%debug 'in function work'");
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 		fd = open(fl, O_RDWR);
1880Sstevel@tonic-gate 		err = fsync(fd);
1890Sstevel@tonic-gate 		(void) close(fd);
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 		TNF_PROBE_1(uwork_fsync_end, "work",
1920Sstevel@tonic-gate 			    "uwork_fsync_end%debug 'in function work'",
1930Sstevel@tonic-gate 			    tnf_long, err, err);
1940Sstevel@tonic-gate 	} else {
1950Sstevel@tonic-gate 		TNF_PROBE_2(uwork_read, "work",
1960Sstevel@tonic-gate 			    "uwork_read%debug 'in function work'",
1970Sstevel@tonic-gate 			    tnf_long, block, block,
1980Sstevel@tonic-gate 			    tnf_long, size, size);
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 		fd = open(fl, O_RDWR);
2010Sstevel@tonic-gate 		(void) lseek(fd, block * 0x200, 0L);
2020Sstevel@tonic-gate 		err = read(fd, ptr, size);
2030Sstevel@tonic-gate 		(void) close(fd);
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 		TNF_PROBE_1(uwork_read_end, "work",
2060Sstevel@tonic-gate 			    "uwork_read_end%debug 'in function work'",
2070Sstevel@tonic-gate 			    tnf_long, err, err);
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	}
2100Sstevel@tonic-gate 	if (domalloc && ptr != b)
2110Sstevel@tonic-gate 		free(ptr);
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	if (wptr->isthreaded) {
2140Sstevel@tonic-gate 		(void) mutex_unlock(&wptr->mtx);
2150Sstevel@tonic-gate 		cond_signal(&wptr->cv);
2160Sstevel@tonic-gate 		TNF_PROBE_0(work_end, "work", "");
2170Sstevel@tonic-gate 		thr_exit(NULL);
2180Sstevel@tonic-gate 	}
2190Sstevel@tonic-gate 	TNF_PROBE_0(uwork_end, "work", "");
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 	return ((void *) NULL);
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate /*
2250Sstevel@tonic-gate  * Simulated datastore work
2260Sstevel@tonic-gate  */
2270Sstevel@tonic-gate static void    *
work(void * argp)2280Sstevel@tonic-gate work(void *argp)
2290Sstevel@tonic-gate {
2300Sstevel@tonic-gate 	int		i, j;
2310Sstevel@tonic-gate 	dn_rec_t	*dnp;
2320Sstevel@tonic-gate 	int		err;
2330Sstevel@tonic-gate 	work_t		*wptr = argp;
2340Sstevel@tonic-gate 	uchar_t		cid_len;
2350Sstevel@tonic-gate 	char		*ptr;
2360Sstevel@tonic-gate 	uint32_t	query;
2370Sstevel@tonic-gate 	dn_rec_t	dn, ndn;
2380Sstevel@tonic-gate 	dn_rec_list_t	*dncp = NULL;
2390Sstevel@tonic-gate 	uint_t		crecords, irecords;
2400Sstevel@tonic-gate 	int		wtype;
2410Sstevel@tonic-gate 	int		firsttime = 0;
2420Sstevel@tonic-gate 	int		op;
2430Sstevel@tonic-gate 	size_t		size = ((random() & (domalloc - 1)) + 0x100) &
2440Sstevel@tonic-gate 			~(0x1000 - 1);
2450Sstevel@tonic-gate 	int		table;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	if (domalloc)
2480Sstevel@tonic-gate 		ptr = malloc(size);
2490Sstevel@tonic-gate 	else
2500Sstevel@tonic-gate 		ptr = b;
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	irecords = (random() & 0xff) + 1;
2530Sstevel@tonic-gate 	if (irecords == 12) {
2540Sstevel@tonic-gate 		irecords = (uint_t)-1;
2550Sstevel@tonic-gate 	}
2560Sstevel@tonic-gate 	if (wptr->isthreaded) {
2570Sstevel@tonic-gate 		(void) mutex_lock(&wptr->mtx);
2580Sstevel@tonic-gate 	}
2590Sstevel@tonic-gate 	i = wptr->thread;
2600Sstevel@tonic-gate 	dnp = wptr->dnp;
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 	table = i % ntable;
2630Sstevel@tonic-gate 	dn = *dnp;
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	cid_len = 7;
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	if (worktype == 0) {
2680Sstevel@tonic-gate 		wtype = random() & 0x7;
2690Sstevel@tonic-gate 		if (wtype == 4)
2700Sstevel@tonic-gate 			wtype--;
2710Sstevel@tonic-gate 	} else
2720Sstevel@tonic-gate 		wtype = worktype;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	/* preload a legal record */
2750Sstevel@tonic-gate 	if (timp[i] == NULL) {
2760Sstevel@tonic-gate 		wtype = 3;
2770Sstevel@tonic-gate 		firsttime = 1;
2780Sstevel@tonic-gate 		irecords = threads * 2;
2790Sstevel@tonic-gate 		(void) mutex_lock(&thread_mtx);
2800Sstevel@tonic-gate 		if ((dncp = thread_dncp[table]) != NULL) {
2810Sstevel@tonic-gate 			thread_dncp[table] = dncp->dnl_next;
2820Sstevel@tonic-gate 			*dnp = *(dncp->dnl_rec);
2830Sstevel@tonic-gate 			dncp->dnl_next = NULL;
2840Sstevel@tonic-gate 			wtype = -1;
2850Sstevel@tonic-gate 			(void) mutex_unlock(&thread_mtx);
2860Sstevel@tonic-gate 		}
2870Sstevel@tonic-gate 	}
2880Sstevel@tonic-gate 	TNF_PROBE_2(work, "work", "work%debug 'in function work'",
2890Sstevel@tonic-gate 		    tnf_ulong, worktype, wtype,
2900Sstevel@tonic-gate 		    tnf_ulong, irecords, irecords);
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	timp[i] = time(NULL);
2930Sstevel@tonic-gate 	crecords = 0;
2940Sstevel@tonic-gate 	DSVC_QINIT(query);
2950Sstevel@tonic-gate 	switch (wtype) {
2960Sstevel@tonic-gate 	case -1:
2970Sstevel@tonic-gate 		break;
2980Sstevel@tonic-gate 	case 1:
2990Sstevel@tonic-gate 		switch (random() & 0x7) {
3000Sstevel@tonic-gate 		case 1:
3010Sstevel@tonic-gate 			for (j = 0; j < cid_len; j++)
3020Sstevel@tonic-gate 				dn.dn_cid[j] = random() & 0xff;
3030Sstevel@tonic-gate 			break;
3040Sstevel@tonic-gate 		case 2:
3050Sstevel@tonic-gate 			for (j = 0; j < cid_len; j++)
3060Sstevel@tonic-gate 				dn.dn_cid[j] = '\0';
3070Sstevel@tonic-gate 			dn.dn_cid_len = 1;
3080Sstevel@tonic-gate 			break;
3090Sstevel@tonic-gate 		}
3100Sstevel@tonic-gate 		DSVC_QEQ(query, DN_QCID);
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 		/* LINTED */
3130Sstevel@tonic-gate 		TNF_PROBE_2(work_cid, "work work_cid",
3140Sstevel@tonic-gate 			    "work_cid%debug 'in function work'",
3150Sstevel@tonic-gate 			    tnf_ulong, cid, *(ulong_t *)&dn.dn_cid,
3160Sstevel@tonic-gate 			    tnf_ulong, cid_len, dn.dn_cid_len);
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 		err = lookup_dd(dh[table], B_TRUE, query, -1,
3190Sstevel@tonic-gate 			    (const void *)&dn, (void **)&dncp, &crecords);
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 		TNF_PROBE_2(work_cid_end, "work work_cid",
3220Sstevel@tonic-gate 			    "work_cid_end%debug 'in function work'",
3230Sstevel@tonic-gate 			    tnf_ulong, err, err,
3240Sstevel@tonic-gate 			    tnf_ulong, crecords, crecords);
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 		if (crecords > 0 && dncp)
3270Sstevel@tonic-gate 			*dnp = *(dncp->dnl_rec);
3280Sstevel@tonic-gate 		break;
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	case 2:
3310Sstevel@tonic-gate 		switch (random() & 0x7) {
3320Sstevel@tonic-gate 		case 1:
3330Sstevel@tonic-gate 			dn.dn_cip.s_addr = random();
3340Sstevel@tonic-gate 			break;
3350Sstevel@tonic-gate 		case 2:
3360Sstevel@tonic-gate 			dn.dn_cip.s_addr = net[table].s_addr |
3370Sstevel@tonic-gate 				(random() & (nrecords[table] - 1));
3380Sstevel@tonic-gate 			break;
3390Sstevel@tonic-gate 		}
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 		DSVC_QEQ(query, DN_QCIP);
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 		TNF_PROBE_1(work_cip, "work work_cip",
3440Sstevel@tonic-gate 			    "work_cip%debug 'in function work'",
3450Sstevel@tonic-gate 			    tnf_ulong, cip, dn.dn_cip.s_addr);
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 		err = lookup_dd(dh[table], B_TRUE, query, -1,
3480Sstevel@tonic-gate 			    (const void *)&dn, (void **)&dncp, &crecords);
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 		TNF_PROBE_2(work_cip_end, "work work_cip",
3510Sstevel@tonic-gate 			    "work_cip_end%debug 'in function work'",
3520Sstevel@tonic-gate 			    tnf_ulong, err, err,
3530Sstevel@tonic-gate 			    tnf_ulong, crecords, crecords);
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 		if (crecords > 0 && dncp)
3560Sstevel@tonic-gate 			*dnp = *(dncp->dnl_rec);
3570Sstevel@tonic-gate 		break;
3580Sstevel@tonic-gate 	case 3:
3590Sstevel@tonic-gate 		op = random() & 0x7;
3600Sstevel@tonic-gate 		if (firsttime)
3610Sstevel@tonic-gate 			op = 2;
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 		switch (op) {
3640Sstevel@tonic-gate 		case 1:
3650Sstevel@tonic-gate 			DSVC_QNEQ(query, DN_QLEASE);
3660Sstevel@tonic-gate 			dn.dn_lease = 0;
3670Sstevel@tonic-gate 			break;
3680Sstevel@tonic-gate 		case 2:
3690Sstevel@tonic-gate 			DSVC_QEQ(query, DN_QCID);
3700Sstevel@tonic-gate 			for (j = 0; j < cid_len; j++)
3710Sstevel@tonic-gate 				dn.dn_cid[j] = '\0';
3720Sstevel@tonic-gate 			dn.dn_cid_len = 1;
3730Sstevel@tonic-gate 			break;
3740Sstevel@tonic-gate 		}
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 		TNF_PROBE_2(work_read, "work work_read",
3770Sstevel@tonic-gate 			    "work_read%debug 'in function work'",
3780Sstevel@tonic-gate 			    tnf_ulong, query, query,
3790Sstevel@tonic-gate 			    tnf_ulong, cid_len, dn.dn_cid_len);
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 		err = lookup_dd(dh[table], B_TRUE, query, irecords,
3820Sstevel@tonic-gate 			    (const void *)&dn, (void **)&dncp, &crecords);
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 		TNF_PROBE_2(work_read_end, "work work_read",
3850Sstevel@tonic-gate 			    "work_read_end%debug 'in function work'",
3860Sstevel@tonic-gate 			    tnf_ulong, err, err,
3870Sstevel@tonic-gate 			    tnf_ulong, crecords, crecords);
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 		if (crecords > 0 && dncp) {
3900Sstevel@tonic-gate 			*dnp = *(dncp->dnl_rec);
3910Sstevel@tonic-gate 			if (firsttime) {
3920Sstevel@tonic-gate 				thread_dncp[table] = dncp->dnl_next;
3930Sstevel@tonic-gate 				dncp->dnl_next = NULL;
3940Sstevel@tonic-gate 				mutex_unlock(&thread_mtx);
3950Sstevel@tonic-gate 			}
3960Sstevel@tonic-gate 		}
3970Sstevel@tonic-gate 		break;
3980Sstevel@tonic-gate 	case 4:
3990Sstevel@tonic-gate 		op = dnp->dn_lease & 0x3;
4000Sstevel@tonic-gate 		switch (op) {
4010Sstevel@tonic-gate 		case 0:
4020Sstevel@tonic-gate 			/* write record w/ cid */
4030Sstevel@tonic-gate 			ndn = *dnp;
4040Sstevel@tonic-gate 			ndn.dn_lease = (htonl(time(NULL)) & ~0x3) + 1;
4050Sstevel@tonic-gate 			ndn.dn_cid_len = 14;
4060Sstevel@tonic-gate 			for (j = 0; j < ndn.dn_cid_len; j++)
4070Sstevel@tonic-gate 				ndn.dn_cid[j] = random() & 0xff;
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 			/* LINTED */
4100Sstevel@tonic-gate 			TNF_PROBE_2(work1_modify, "work work1_modify",
4110Sstevel@tonic-gate 				    "work1_modify%debug 'in function work'",
4120Sstevel@tonic-gate 				    tnf_ulong, cid, *(ulong_t *)&ndn.dn_cid,
4130Sstevel@tonic-gate 				    tnf_ulong, cid_len, ndn.dn_cid_len);
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 			err = modify_dd_entry(dh[table], dnp, &ndn);
4160Sstevel@tonic-gate 			if (err != DSVC_SUCCESS && verbose) {
4170Sstevel@tonic-gate 				fprintf(stderr, "work: %d %d error %d\n",
4180Sstevel@tonic-gate 					wtype, op, err);
4190Sstevel@tonic-gate 			}
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 			TNF_PROBE_1(work1_modify_end, "work work1_modify_end",
4220Sstevel@tonic-gate 				    "work1_modify_end%debug 'in function work'",
4230Sstevel@tonic-gate 				    tnf_ulong, err, err);
4240Sstevel@tonic-gate 			*dnp = ndn;
4250Sstevel@tonic-gate 			break;
4260Sstevel@tonic-gate 		case 1:
4270Sstevel@tonic-gate 			/* re-read record w/ cid */
4280Sstevel@tonic-gate 			DSVC_QEQ(query, DN_QCID);
4290Sstevel@tonic-gate 			TNF_PROBE_2(work_read1, "work work_read1",
4300Sstevel@tonic-gate 				    "work_read1%debug 'in function work'",
4310Sstevel@tonic-gate 				    tnf_ulong, query, query,
4320Sstevel@tonic-gate 				    tnf_ulong, cid_len, dn.dn_cid_len);
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate 			err = lookup_dd(dh[table], B_TRUE, query, - 1,
4350Sstevel@tonic-gate 					(const void *)dnp, (void **)&dncp,
4360Sstevel@tonic-gate 					&crecords);
4370Sstevel@tonic-gate 			TNF_PROBE_2(work_read1_end, "work work_read1",
4380Sstevel@tonic-gate 				    "work_read1_end%debug 'in function work'",
4390Sstevel@tonic-gate 				    tnf_ulong, err, err,
4400Sstevel@tonic-gate 				    tnf_ulong, crecords, crecords);
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 			if ((err != DSVC_SUCCESS || crecords < 1) && verbose) {
4430Sstevel@tonic-gate 				fprintf(stderr, "work: %d %d error %d %d\n",
4440Sstevel@tonic-gate 					wtype, op, err, crecords);
4450Sstevel@tonic-gate 			}
4460Sstevel@tonic-gate 			dnp->dn_lease++;
4470Sstevel@tonic-gate 			break;
4480Sstevel@tonic-gate 		case 2:
4490Sstevel@tonic-gate 			/* write free record */
4500Sstevel@tonic-gate 			dnp->dn_lease--;
4510Sstevel@tonic-gate 			ndn = *dnp;
4520Sstevel@tonic-gate 			DSVC_QEQ(query, DN_QCID);
4530Sstevel@tonic-gate 			for (j = 0; j < cid_len; j++)
4540Sstevel@tonic-gate 				ndn.dn_cid[j] = '\0';
4550Sstevel@tonic-gate 			ndn.dn_cid_len = 1;
4560Sstevel@tonic-gate 			ndn.dn_lease = 0;
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 			TNF_PROBE_2(work_modify2, "work work_modify2",
4590Sstevel@tonic-gate 				    "work_modify2%debug 'in function work'",
4600Sstevel@tonic-gate 				    tnf_ulong, cid, *(ulong_t *)&ndn.dn_cid,
4610Sstevel@tonic-gate 				    tnf_ulong, cid_len, ndn.dn_cid_len);
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 			err = modify_dd_entry(dh[table], dnp, &ndn);
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 			TNF_PROBE_1(work_modify2_end, "work work_modify2_end",
4660Sstevel@tonic-gate 			    "work_modify2_end%debug 'in function work'",
4670Sstevel@tonic-gate 				    tnf_ulong, err, err);
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 			if (err != DSVC_SUCCESS && verbose) {
4700Sstevel@tonic-gate 				fprintf(stderr, "work: %d %d error %d\n",
4710Sstevel@tonic-gate 					wtype, op, err);
4720Sstevel@tonic-gate 			}
4730Sstevel@tonic-gate 			*dnp = ndn;
4740Sstevel@tonic-gate 			break;
4750Sstevel@tonic-gate 		}
4760Sstevel@tonic-gate 		break;
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	default:
4800Sstevel@tonic-gate 		ndn = *dnp;
4810Sstevel@tonic-gate 		ndn.dn_cid_len = cid_len;
4820Sstevel@tonic-gate 		switch (random() & 0x1) {
4830Sstevel@tonic-gate 		case 0:
4840Sstevel@tonic-gate 			for (j = 0; j < cid_len; j++)
4850Sstevel@tonic-gate 				ndn.dn_cid[j] = random() & 0xff;
4860Sstevel@tonic-gate 			break;
4870Sstevel@tonic-gate 		case 1:
4880Sstevel@tonic-gate 			for (j = 0; j < cid_len; j++)
4890Sstevel@tonic-gate 				ndn.dn_cid[j] = '\0';
4900Sstevel@tonic-gate 			ndn.dn_cid_len = 1;
4910Sstevel@tonic-gate 			break;
4920Sstevel@tonic-gate 		}
4930Sstevel@tonic-gate 		ndn.dn_lease = htonl(time(NULL));
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 		/* LINTED */
4960Sstevel@tonic-gate 		TNF_PROBE_2(work_modify, "work work_modify",
4970Sstevel@tonic-gate 			    "work_modify%debug 'in function work'",
4980Sstevel@tonic-gate 			    tnf_ulong, cid, *(ulong_t *)&ndn.dn_cid,
4990Sstevel@tonic-gate 			    tnf_ulong, cid_len, ndn.dn_cid_len);
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 		err = modify_dd_entry(dh[table], dnp, &ndn);
5020Sstevel@tonic-gate 		if (err != DSVC_SUCCESS && err != DSVC_COLLISION) {
5030Sstevel@tonic-gate 			if (verbose)
5040Sstevel@tonic-gate 				fprintf(stderr, "modify: error %d\n", err);
5050Sstevel@tonic-gate 		}
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 		TNF_PROBE_1(work_modify_end, "work work_modify_end",
5080Sstevel@tonic-gate 			    "work_modify_end%debug 'in function work'",
5090Sstevel@tonic-gate 			    tnf_ulong, err, err);
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 		*dnp = ndn;
5120Sstevel@tonic-gate 		break;
5130Sstevel@tonic-gate 	}
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	if (domalloc)
5160Sstevel@tonic-gate 		free(ptr);
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	if (wptr->isthreaded) {
5190Sstevel@tonic-gate 		(void) mutex_unlock(&wptr->mtx);
5200Sstevel@tonic-gate 		cond_signal(&wptr->cv);
5210Sstevel@tonic-gate 		TNF_PROBE_2(work_end, "work", "work_end%debug 'in function "
5220Sstevel@tonic-gate 				"work'", tnf_ulong, err, err,
5230Sstevel@tonic-gate 				tnf_ulong, crecords, crecords);
5240Sstevel@tonic-gate 		thr_exit(NULL);
5250Sstevel@tonic-gate 	}
5260Sstevel@tonic-gate 	if (dncp)
5270Sstevel@tonic-gate 		free_dd_list(dh[table], dncp);
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	TNF_PROBE_2(work_end, "work", "work_end%debug 'in function work'",
5300Sstevel@tonic-gate 		    tnf_ulong, err, err,
5310Sstevel@tonic-gate 		    tnf_ulong, crecords, crecords);
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	return ((void *) NULL);
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate /*
5370Sstevel@tonic-gate  * Worker thread.
5380Sstevel@tonic-gate  */
5390Sstevel@tonic-gate static void    *
dowork(void * argp)5400Sstevel@tonic-gate dowork(void *argp)
5410Sstevel@tonic-gate {
5420Sstevel@tonic-gate 	int		i = (int)argp;
5430Sstevel@tonic-gate 	timestruc_t	to;
5440Sstevel@tonic-gate 	work_t		*wptr;
5450Sstevel@tonic-gate 	dn_rec_t 	dn;
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	(void) memset((char *)&dn, '\0', sizeof (dn));
5480Sstevel@tonic-gate 	(void) mutex_lock(&mtx);
5490Sstevel@tonic-gate 	for (; time_to_go == 0; ) {
5500Sstevel@tonic-gate 		TNF_PROBE_1(dowork, "dowork",
5510Sstevel@tonic-gate 			    "dowork%debug 'in function dowork'",
5520Sstevel@tonic-gate 			    tnf_long, thread_number, i);
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 		to.tv_sec = time(NULL) + random() & 0x3;
5550Sstevel@tonic-gate 		to.tv_nsec = 0;
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 		if (slp > 0.0) {
5580Sstevel@tonic-gate 			to.tv_sec = time(NULL) + slp;
5590Sstevel@tonic-gate 			to.tv_nsec = (slp - (double)((int)slp)) * 1000000000.0;
5600Sstevel@tonic-gate 		} else if (slp < 0.0) {
5610Sstevel@tonic-gate 			to.tv_sec = time(NULL) + abs((int)slp);
5620Sstevel@tonic-gate 			to.tv_nsec = (slp + abs((double)((int)slp))) *
5630Sstevel@tonic-gate 				1000000000.0;
5640Sstevel@tonic-gate 		}
5650Sstevel@tonic-gate 		/* give up processor */
5660Sstevel@tonic-gate 		if (slp != 0.0) {
5670Sstevel@tonic-gate 			(void) mutex_unlock(&mtx);
5680Sstevel@tonic-gate 			(void) cond_timedwait(&never, &mtx, &to);
5690Sstevel@tonic-gate 		}
5700Sstevel@tonic-gate 		ops_outstanding++;
5710Sstevel@tonic-gate 		(void) mutex_unlock(&mtx);
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 		if (spawn_helper) {
5740Sstevel@tonic-gate 			wptr = (work_t *)malloc(sizeof (work_t));
5750Sstevel@tonic-gate 			wptr->thread = i * 2;
5760Sstevel@tonic-gate 			wptr->isthreaded = B_TRUE;
5770Sstevel@tonic-gate 			(void) cond_init(&wptr->cv, USYNC_THREAD, NULL);
5780Sstevel@tonic-gate 			(void) mutex_init(&wptr->mtx, USYNC_THREAD, NULL);
5790Sstevel@tonic-gate 			(void) mutex_lock(&wptr->mtx);
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 			/* fire up helper thread */
5820Sstevel@tonic-gate 			if (thr_create(NULL, 0, douwork ? uwork : work,
5830Sstevel@tonic-gate 					(void *)wptr, 0, &tp[i * 2]) != 0)
5840Sstevel@tonic-gate 				fprintf(stderr, "can't spawn lthread %d\n", i);
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 			/* wait for completion */
5870Sstevel@tonic-gate 			(void) cond_wait(&wptr->cv, &wptr->mtx);
5880Sstevel@tonic-gate 			(void) mutex_unlock(&wptr->mtx);
5890Sstevel@tonic-gate 			(void) thr_join(tp[i * 2], NULL, NULL);
5900Sstevel@tonic-gate 			free_work_t(wptr);
5910Sstevel@tonic-gate 		} else {
5920Sstevel@tonic-gate 			wptr = (work_t *)malloc(sizeof (work_t));
5930Sstevel@tonic-gate 			wptr->isthreaded = B_FALSE;
5940Sstevel@tonic-gate 			wptr->thread = i;
5950Sstevel@tonic-gate 			wptr->dnp = &dn;
5960Sstevel@tonic-gate 			if (douwork) {
5970Sstevel@tonic-gate 				(void) uwork((void *)wptr);
5980Sstevel@tonic-gate 			} else {
5990Sstevel@tonic-gate 				(void) work((void *)wptr);
6000Sstevel@tonic-gate 			}
6010Sstevel@tonic-gate 			free_work_t(wptr);
6020Sstevel@tonic-gate 		}
6030Sstevel@tonic-gate 		(void) mutex_lock(&mtx);
6040Sstevel@tonic-gate 		tops++;
6050Sstevel@tonic-gate 		ops_outstanding--;
6060Sstevel@tonic-gate 		TNF_PROBE_0(dowork_end, "dowork", "");
6070Sstevel@tonic-gate 	}
6080Sstevel@tonic-gate 	(void) mutex_unlock(&mtx);
6090Sstevel@tonic-gate 	thr_exit(NULL);
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 	return ((void *) NULL);
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate /*
6150Sstevel@tonic-gate  * Signal handler routine. All signals handled by calling thread.
6160Sstevel@tonic-gate  */
6170Sstevel@tonic-gate /* ARGSUSED */
6180Sstevel@tonic-gate static void    *
sig_handle(void * arg)6190Sstevel@tonic-gate sig_handle(void *arg)
6200Sstevel@tonic-gate {
6210Sstevel@tonic-gate 	int		i;
6220Sstevel@tonic-gate 	int		sig;
6230Sstevel@tonic-gate 	sigset_t	set;
6240Sstevel@tonic-gate 	timespec_t	ts;
6250Sstevel@tonic-gate 	siginfo_t	si;
6260Sstevel@tonic-gate 	int		go;
6270Sstevel@tonic-gate 	int		oldi;
6280Sstevel@tonic-gate 	ulong_t		minavg;
6290Sstevel@tonic-gate 	time_t		minstime;
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	(void) sigfillset(&set); /* catch all signals */
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	ts.tv_sec = sample_time;
6340Sstevel@tonic-gate 	ts.tv_nsec = 0L;
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	for (;;) {
6370Sstevel@tonic-gate 		(void) mutex_lock(&mtx);
6380Sstevel@tonic-gate 		go = time_to_go;
6390Sstevel@tonic-gate 		(void) mutex_unlock(&mtx);
6400Sstevel@tonic-gate 		if (go)
6410Sstevel@tonic-gate 			break;
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate 		switch (sig = sigtimedwait(&set, &si, &ts)) {
6440Sstevel@tonic-gate 		case -1:
6450Sstevel@tonic-gate 		case SIGHUP:
6460Sstevel@tonic-gate 			old = time(NULL);
6470Sstevel@tonic-gate 			oldi = new = unstarted = 0;
6480Sstevel@tonic-gate 			for (i = 0; i < threads; i++) {
6490Sstevel@tonic-gate 				if (timp[i] == NULL)
6500Sstevel@tonic-gate 					unstarted++;
6510Sstevel@tonic-gate 				if (timp[i] && timp[i] < old) {
6520Sstevel@tonic-gate 					old = timp[i];
6530Sstevel@tonic-gate 					oldi = i;
6540Sstevel@tonic-gate 				}
6550Sstevel@tonic-gate 				if (timp[i] && timp[i] > new)
6560Sstevel@tonic-gate 					new = timp[i];
6570Sstevel@tonic-gate 			}
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate 			if (start == 0) {
6600Sstevel@tonic-gate 				/* toss initial sample */
6610Sstevel@tonic-gate 				ostart = start = time(NULL);
6620Sstevel@tonic-gate 				(void) mutex_lock(&mtx);
6630Sstevel@tonic-gate 				otops = tops = 0;
6640Sstevel@tonic-gate 				(void) mutex_unlock(&mtx);
6650Sstevel@tonic-gate 				minind = 0;
6660Sstevel@tonic-gate 			} else {
6670Sstevel@tonic-gate 				minops[minind] = tops - otops;
6680Sstevel@tonic-gate 				mintim[minind] = ostart;
6690Sstevel@tonic-gate 				otops = tops;
6700Sstevel@tonic-gate 				ostart = time(NULL);
6710Sstevel@tonic-gate 				minind = minind + 1 > nsamples - 1 ? 0 :
6720Sstevel@tonic-gate 				    minind + 1;
6730Sstevel@tonic-gate 				minstime = 0;
6740Sstevel@tonic-gate 				minavg = 0;
6750Sstevel@tonic-gate 				for (i = 0; i < nsamples; i++) {
6760Sstevel@tonic-gate 					if (mintim[i])
6770Sstevel@tonic-gate 						minavg += minops[i];
6780Sstevel@tonic-gate 					if (minstime == 0)
6790Sstevel@tonic-gate 						minstime = mintim[i];
6800Sstevel@tonic-gate 					else if (mintim[i] &&
6810Sstevel@tonic-gate 					    mintim[i] < minstime)
6820Sstevel@tonic-gate 						minstime = mintim[i];
6830Sstevel@tonic-gate 				}
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 				fprintf(stderr, "%9.9d: Totops %d Curr %d "\
6860Sstevel@tonic-gate 				    "Persec %4.2f (%4.2f) Oldest %d (%d) "\
6870Sstevel@tonic-gate 				    "Gap %d Unstarted %d\n",
6880Sstevel@tonic-gate 					time(NULL),
6890Sstevel@tonic-gate 					tops,
6900Sstevel@tonic-gate 					ops_outstanding,
6910Sstevel@tonic-gate 					(double)tops / (double)(time(NULL)
6920Sstevel@tonic-gate 						- start),
6930Sstevel@tonic-gate 					(double)minavg / (double)(time(NULL)
6940Sstevel@tonic-gate 						- minstime),
6950Sstevel@tonic-gate 					time(NULL) - old,
6960Sstevel@tonic-gate 					oldi,
6970Sstevel@tonic-gate 					new - old,
6980Sstevel@tonic-gate 					unstarted);
6990Sstevel@tonic-gate 			}
7000Sstevel@tonic-gate 			break;
7010Sstevel@tonic-gate 		default:
7020Sstevel@tonic-gate 			(void) mutex_lock(&mtx);
7030Sstevel@tonic-gate 			time_to_go++;
7040Sstevel@tonic-gate 			(void) mutex_unlock(&mtx);
7050Sstevel@tonic-gate 			break;
7060Sstevel@tonic-gate 		}
7070Sstevel@tonic-gate 	}
7080Sstevel@tonic-gate 	thr_exit(NULL);
7090Sstevel@tonic-gate 	return ((void *) sig);	/* NOTREACHED */
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate int	fd[0x10000];
7130Sstevel@tonic-gate /*
7140Sstevel@tonic-gate  * open handler routine.
7150Sstevel@tonic-gate  */
7160Sstevel@tonic-gate /* ARGSUSED */
7170Sstevel@tonic-gate static void    *
open_handle(void * arg)7180Sstevel@tonic-gate open_handle(void *arg)
7190Sstevel@tonic-gate {
7200Sstevel@tonic-gate 	int	i;
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 	for (;;) {
7230Sstevel@tonic-gate 		for (i = 0; i < doopen; i++)
7240Sstevel@tonic-gate 			fd[i] = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
7250Sstevel@tonic-gate 		for (i = 0; i < doopen; i++)
7260Sstevel@tonic-gate 			if (fd[i] >= 0)
7270Sstevel@tonic-gate 				(void) close(fd[i]);
7280Sstevel@tonic-gate 	}
7290Sstevel@tonic-gate 	return ((void *) NULL);	/* NOTREACHED */
7300Sstevel@tonic-gate }
7310Sstevel@tonic-gate /*
7320Sstevel@tonic-gate  * test_dstore network[,network] worktype[,worktype] <thr_create flags>
7330Sstevel@tonic-gate  *	 <spawn_helper> <nlwp> <nthread> <file> <sleeptype>
7340Sstevel@tonic-gate  *
7350Sstevel@tonic-gate  * network - list of network containers, comma-separated
7360Sstevel@tonic-gate  * worktypes:
7370Sstevel@tonic-gate  *	0 - random
7380Sstevel@tonic-gate  *	1 - cid reads
7390Sstevel@tonic-gate  *	2 - cip reads
7400Sstevel@tonic-gate  *	3 - whole db reads
7410Sstevel@tonic-gate  *	4 - write read write (simulate simple test)
7420Sstevel@tonic-gate  *	5 - modify writes
7430Sstevel@tonic-gate  * sleeptypes:
7440Sstevel@tonic-gate  * 	N == * condwait N sec.nsec period
7450Sstevel@tonic-gate  * 	-N == condwait a random 1-N sec.nsec period
7460Sstevel@tonic-gate  */
main(int c,char ** v)7470Sstevel@tonic-gate main(int c, char **v)
7480Sstevel@tonic-gate {
7490Sstevel@tonic-gate 	int		i;
7500Sstevel@tonic-gate 	timespec_t	to;
7510Sstevel@tonic-gate 	uint_t		flags;
7520Sstevel@tonic-gate 	int		err;
7530Sstevel@tonic-gate 	sigset_t	set;
7540Sstevel@tonic-gate 	dhcp_confopt_t *dsp = NULL;
7550Sstevel@tonic-gate 	uint32_t	query;
7560Sstevel@tonic-gate 	dn_rec_t	dn;
7570Sstevel@tonic-gate 	dn_rec_list_t  *dncp = NULL;
7580Sstevel@tonic-gate 	struct rlimit   rl;
7590Sstevel@tonic-gate 	char		*np;
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate #ifdef	DEBUG
7620Sstevel@tonic-gate 	mallocctl(MTDEBUGPATTERN, 1);
7630Sstevel@tonic-gate 	mallocctl(MTINITBUFFER, 1);
7640Sstevel@tonic-gate #endif				/* DEBUG */
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 	srandom(time(NULL));
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 	if (dofork)
7690Sstevel@tonic-gate 		if (fork() != 0)
7700Sstevel@tonic-gate 			exit(0);
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 	if ((err = getrlimit(RLIMIT_NOFILE, &rl)) < 0) {
7730Sstevel@tonic-gate 		(void) fprintf(stderr, "Cannot get open file limit: %s\n",
7740Sstevel@tonic-gate 				strerror(errno));
7750Sstevel@tonic-gate 	}
7760Sstevel@tonic-gate 	/* handle cases where limit is infinity */
7770Sstevel@tonic-gate 	if (rl.rlim_cur == RLIM_INFINITY) {
7780Sstevel@tonic-gate 		rl.rlim_cur = (rl.rlim_max == RLIM_INFINITY) ?
7790Sstevel@tonic-gate 			OPEN_MAX : rl.rlim_max;
7800Sstevel@tonic-gate 	}
7810Sstevel@tonic-gate 	/* set NOFILE to unlimited */
7820Sstevel@tonic-gate 	rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
7830Sstevel@tonic-gate 	if ((err = setrlimit(RLIMIT_NOFILE, &rl)) < 0) {
7840Sstevel@tonic-gate 		(void) fprintf(stderr, "Cannot set open file limit: %s\n",
7850Sstevel@tonic-gate 				strerror(errno));
7860Sstevel@tonic-gate 	}
787*1914Scasper 	(void) enable_extended_FILE_stdio(-1, -1);
788*1914Scasper 
7890Sstevel@tonic-gate 	if (c == 1) {
7900Sstevel@tonic-gate 		(void) fprintf(stderr,
7910Sstevel@tonic-gate 				"/*\n"\
7920Sstevel@tonic-gate 				" * test_dstore network[,network] worktype[,"\
7930Sstevel@tonic-gate 					"worktype] <thr_create flags>\n"\
7940Sstevel@tonic-gate 				" *	 <spawn_helper> <nlwp> <nthread> "\
7950Sstevel@tonic-gate 					"<file> <sleeptype>\n"\
7960Sstevel@tonic-gate 				" *\n"\
7970Sstevel@tonic-gate 				" * network - list of network containers, "\
7980Sstevel@tonic-gate 					"comma-separated\n"\
7990Sstevel@tonic-gate 				" * worktypes:\n"\
8000Sstevel@tonic-gate 				" *	0 - random\n"\
8010Sstevel@tonic-gate 				" *	1 - cid reads\n"\
8020Sstevel@tonic-gate 				" *	2 - cip reads\n"\
8030Sstevel@tonic-gate 				" *	3 - whole db reads\n"\
8040Sstevel@tonic-gate 				" *	4 - write read write (simulate simple"\
8050Sstevel@tonic-gate 					" test)\n"\
8060Sstevel@tonic-gate 				" *	5 - modify writes\n"\
8070Sstevel@tonic-gate 				" * sleeptypes:\n"\
8080Sstevel@tonic-gate 				" * 	N == * condwait N sec.nsec period\n"\
8090Sstevel@tonic-gate 				" * 	-N == condwait a random 1-N sec.nsec "\
8100Sstevel@tonic-gate 					"period\n"\
8110Sstevel@tonic-gate 				" */\n");
8120Sstevel@tonic-gate 		return (0);
8130Sstevel@tonic-gate 	}
8140Sstevel@tonic-gate 	network = v[1];
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 	worktype = strtoul(v[2], 0L, 0L);
8170Sstevel@tonic-gate 	flags = strtoul(v[3], 0L, 0L);
8180Sstevel@tonic-gate 	spawn_helper = strtoul(v[4], 0L, 0L);
8190Sstevel@tonic-gate 	if (strtoul(v[5], 0L, 0L) > 0)
8200Sstevel@tonic-gate 		(void) thr_setconcurrency(strtoul(v[5], 0L, 0L));
8210Sstevel@tonic-gate 	threads = strtoul(v[6], 0L, 0L);
8220Sstevel@tonic-gate 	fl = v[7];
8230Sstevel@tonic-gate 	if (c > 8)
8240Sstevel@tonic-gate 		slp = atof(v[8]);
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	if (douwork == 0) {
8270Sstevel@tonic-gate 		/* Load current datastore. */
8280Sstevel@tonic-gate 		(void) read_dsvc_conf(&dsp);
8290Sstevel@tonic-gate 		if ((i = confopt_to_datastore(dsp, &datastore))
8300Sstevel@tonic-gate 			!= DSVC_SUCCESS) {
8310Sstevel@tonic-gate 			(void) fprintf(stderr, "Invalid datastore: %s\n",
8320Sstevel@tonic-gate 					dhcpsvc_errmsg(i));
8330Sstevel@tonic-gate 			return (EINVAL);
8340Sstevel@tonic-gate 		}
8350Sstevel@tonic-gate 		for (i = 0, np = strtok(network, ","); np; i++,
8360Sstevel@tonic-gate 			np = strtok(NULL, ",")) {
8370Sstevel@tonic-gate 			net[i].s_addr = inet_addr(np);
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate 			err = open_dd(&dh[i], &datastore, DSVC_DHCPNETWORK, np,
8400Sstevel@tonic-gate 					DSVC_READ | DSVC_WRITE);
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate 			if (err != DSVC_SUCCESS) {
8430Sstevel@tonic-gate 				(void) fprintf(stderr, "Invalid network: "\
8440Sstevel@tonic-gate 						"%s %s\n", np,
8450Sstevel@tonic-gate 						dhcpsvc_errmsg(err));
8460Sstevel@tonic-gate 				return (err);
8470Sstevel@tonic-gate 			}
8480Sstevel@tonic-gate 			/*
8490Sstevel@tonic-gate 			 * XXXX: bug: currently can't get the count as
8500Sstevel@tonic-gate 			 * advertised
8510Sstevel@tonic-gate 			 */
8520Sstevel@tonic-gate 			(void) memset(&dn, '\0', sizeof (dn));
8530Sstevel@tonic-gate 			DSVC_QINIT(query);
8540Sstevel@tonic-gate 			err = lookup_dd(dh[i], B_FALSE, query, -1,
8550Sstevel@tonic-gate 				(const void *) &dn, (void **) &dncp,
8560Sstevel@tonic-gate 				&nrecords[i]);
8570Sstevel@tonic-gate 			if (dncp)
8580Sstevel@tonic-gate 				free_dd_list(dh[i], dncp);
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 			if (err != DSVC_SUCCESS) {
8610Sstevel@tonic-gate 				(void) fprintf(stderr, "Bad nrecords: %s "
8620Sstevel@tonic-gate 					"[%d]\n", dhcpsvc_errmsg(err),
8630Sstevel@tonic-gate 					nrecords[i]);
8640Sstevel@tonic-gate 				return (err);
8650Sstevel@tonic-gate 			}
8660Sstevel@tonic-gate 		}
8670Sstevel@tonic-gate 		ntable = i;
8680Sstevel@tonic-gate 	}
8690Sstevel@tonic-gate 	TNF_PROBE_2(main, "main",
8700Sstevel@tonic-gate 		    "main%debug 'in function main'",
8710Sstevel@tonic-gate 		    tnf_ulong, threads, threads,
8720Sstevel@tonic-gate 		    tnf_ulong, nrecords, nrecords[i]);
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 	(void) sigfillset(&set);
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate 	(void) sigdelset(&set, SIGABRT);	/* allow for user abort */
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 	(void) thr_sigsetmask(SIG_SETMASK, &set, NULL);
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 	tms = threads * sizeof (thread_t);
8810Sstevel@tonic-gate 	if (spawn_helper)
8820Sstevel@tonic-gate 		tms *= 2;
8830Sstevel@tonic-gate 	tp = malloc(tms);
8840Sstevel@tonic-gate 	tms = (threads * sizeof (time_t) + 0x200) & ~(0x200 - 1);
8850Sstevel@tonic-gate 	if (spawn_helper)
8860Sstevel@tonic-gate 		tms *= 2;
8870Sstevel@tonic-gate 	timp = malloc(tms);
8880Sstevel@tonic-gate 	(void) memset((char *)timp, NULL, tms);
8890Sstevel@tonic-gate 
8900Sstevel@tonic-gate 	(void) mutex_init(&mtx, USYNC_THREAD, 0);
8910Sstevel@tonic-gate 
8920Sstevel@tonic-gate 	/*
8930Sstevel@tonic-gate 	 * Create signal handling thread. XXXX: due to threads library
8940Sstevel@tonic-gate 	 * limitations, this must currently be directly called in the main
8950Sstevel@tonic-gate 	 * program thread.
8960Sstevel@tonic-gate 	 */
8970Sstevel@tonic-gate 	if ((err = thr_create(NULL, 0, sig_handle, NULL,
8980Sstevel@tonic-gate 				THR_NEW_LWP | THR_DAEMON | THR_BOUND |
8990Sstevel@tonic-gate 				THR_DETACHED, &sigthread)) != 0) {
9000Sstevel@tonic-gate 		(void) fprintf(stderr,
9010Sstevel@tonic-gate 		gettext("Cannot start signal handling thread, error: %d\n"),
9020Sstevel@tonic-gate 			err);
9030Sstevel@tonic-gate 		return (err);
9040Sstevel@tonic-gate 	}
9050Sstevel@tonic-gate 	for (i = 0; i < threads; i++)
9060Sstevel@tonic-gate 		/* fire up monitor thread */
9070Sstevel@tonic-gate 		if (thr_create(NULL, 0, dowork, (void *) i,
9080Sstevel@tonic-gate 			flags, &tp[i]) != 0)
9090Sstevel@tonic-gate 			fprintf(stderr, "can't spawn thread %d\n", i);
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate 	/*
9120Sstevel@tonic-gate 	 * Create open handling thread.
9130Sstevel@tonic-gate 	 */
9140Sstevel@tonic-gate 	if (doopen && (err = thr_create(NULL, 0, open_handle, NULL,
9150Sstevel@tonic-gate 			THR_NEW_LWP | THR_DAEMON | THR_BOUND | THR_DETACHED,
9160Sstevel@tonic-gate 			&opnthread)) != 0) {
9170Sstevel@tonic-gate 		(void) fprintf(stderr,
9180Sstevel@tonic-gate 		gettext("Cannot start open handling thread, error: %d\n"),
9190Sstevel@tonic-gate 			err);
9200Sstevel@tonic-gate 		return (err);
9210Sstevel@tonic-gate 	}
9220Sstevel@tonic-gate 
9230Sstevel@tonic-gate 	(void) mutex_lock(&mtx);
9240Sstevel@tonic-gate 	for (; time_to_go == 0; ) {
9250Sstevel@tonic-gate 		to.tv_sec = time(NULL) + 10;
9260Sstevel@tonic-gate 		to.tv_nsec = 0L;
9270Sstevel@tonic-gate 		(void) cond_timedwait(&never, &mtx, &to);
9280Sstevel@tonic-gate 		(void) mutex_unlock(&mtx);
9290Sstevel@tonic-gate 	}
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 	/*
9320Sstevel@tonic-gate 	 * Attempt to join threads.
9330Sstevel@tonic-gate 	 */
9340Sstevel@tonic-gate 	for (i = 0; i < threads; i++)
9350Sstevel@tonic-gate 		(void) thr_join(tp[i], NULL, NULL);
9360Sstevel@tonic-gate 
9370Sstevel@tonic-gate 	(void) sleep(5);
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 	TNF_PROBE_0(main_end, "main", "");
9400Sstevel@tonic-gate 
9410Sstevel@tonic-gate 	return (0);
9420Sstevel@tonic-gate }
943