1/*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source.  A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12/*
13 * Copyright (c) 2017 by Delphix. All rights reserved.
14 */
15
16/*
17 * The following is defined so the source can use
18 * lrand48() and srand48().
19 */
20#define	__EXTENSIONS__
21
22#include "../file_common.h"
23
24/*
25 * The following sample was derived from real-world data
26 * of a production Oracle database.
27 */
28static uint64_t size_distribution[] = {
29	0,
30	1499018,
31	352084,
32	1503485,
33	4206227,
34	5626657,
35	5387001,
36	3733756,
37	2233094,
38	874652,
39	238635,
40	81434,
41	33357,
42	13106,
43	2009,
44	1,
45	23660,
46};
47
48
49static uint64_t distribution_n;
50
51static uint8_t randbuf[BLOCKSZ];
52
53static void
54rwc_pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
55{
56	size_t nleft = nbytes;
57	ssize_t nwrite = 0;
58
59	nwrite = pwrite(fd, buf, nbytes, offset);
60	if (nwrite < 0) {
61		perror("pwrite");
62		exit(EXIT_FAILURE);
63	}
64
65	nleft -= nwrite;
66	if (nleft != 0) {
67		(void) fprintf(stderr, "warning: pwrite: "
68		    "wrote %zu out of %zu bytes\n",
69		    (nbytes - nleft), nbytes);
70	}
71}
72
73static void
74fillbuf(char *buf)
75{
76	uint64_t rv = lrand48() % distribution_n;
77	uint64_t sum = 0;
78
79	uint64_t i;
80	for (i = 0;
81	    i < sizeof (size_distribution) / sizeof (size_distribution[0]);
82	    i++) {
83		sum += size_distribution[i];
84		if (rv < sum)
85			break;
86	}
87
88	bcopy(randbuf, buf, BLOCKSZ);
89	if (i == 0)
90		bzero(buf, BLOCKSZ - 10);
91	else if (i < 16)
92		bzero(buf, BLOCKSZ - i * 512 + 256);
93	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
94	((uint32_t *)buf)[0] = lrand48();
95}
96
97static void
98exit_usage(void)
99{
100	(void) printf("usage: ");
101	(void) printf("randwritecomp <file> [-s] [nwrites]\n");
102	exit(EXIT_FAILURE);
103}
104
105static void
106sequential_writes(int fd, char *buf, uint64_t nblocks, int64_t n)
107{
108	for (int64_t i = 0; n == -1 || i < n; i++) {
109		fillbuf(buf);
110
111		static uint64_t j = 0;
112		if (j == 0)
113			j = lrand48() % nblocks;
114		rwc_pwrite(fd, buf, BLOCKSZ, j * BLOCKSZ);
115		j++;
116		if (j >= nblocks)
117			j = 0;
118	}
119}
120
121static void
122random_writes(int fd, char *buf, uint64_t nblocks, int64_t n)
123{
124	for (int64_t i = 0; n == -1 || i < n; i++) {
125		fillbuf(buf);
126		rwc_pwrite(fd, buf, BLOCKSZ, (lrand48() % nblocks) * BLOCKSZ);
127	}
128}
129
130int
131main(int argc, char *argv[])
132{
133	int fd, err;
134	char *filename = NULL;
135	char buf[BLOCKSZ];
136	struct stat ss;
137	uint64_t nblocks;
138	int64_t n = -1;
139	int sequential = 0;
140
141	if (argc < 2)
142		exit_usage();
143
144	argv++;
145	if (strcmp("-s", argv[0]) == 0) {
146		sequential = 1;
147		argv++;
148	}
149
150	if (argv[0] == NULL)
151		exit_usage();
152	else
153		filename = argv[0];
154
155	argv++;
156	if (argv[0] != NULL)
157		n = strtoull(argv[0], NULL, 0);
158
159	fd = open(filename, O_RDWR|O_CREAT, 0666);
160	err = fstat(fd, &ss);
161	if (err != 0) {
162		(void) fprintf(stderr,
163		    "error: fstat returned error code %d\n", err);
164		exit(EXIT_FAILURE);
165	}
166
167	nblocks = ss.st_size / BLOCKSZ;
168	if (nblocks == 0) {
169		(void) fprintf(stderr, "error: "
170		    "file is too small (min allowed size is %d bytes)\n",
171		    BLOCKSZ);
172		exit(EXIT_FAILURE);
173	}
174
175	srand48(getpid());
176	for (int i = 0; i < BLOCKSZ; i++)
177		randbuf[i] = lrand48();
178
179	distribution_n = 0;
180	for (uint64_t i = 0;
181	    i < sizeof (size_distribution) / sizeof (size_distribution[0]);
182	    i++) {
183		distribution_n += size_distribution[i];
184	}
185
186	if (sequential)
187		sequential_writes(fd, buf, nblocks, n);
188	else
189		random_writes(fd, buf, nblocks, n);
190
191	return (0);
192}
193