1 /*-
2  * Copyright (c) 2015 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Christos Zoulas.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: h_lfsr.c,v 1.2 2017/06/24 10:25:23 gson Exp $");
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <fcntl.h>
35 #include <err.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <db.h>
39 
40 #define MAXKEY 1000
41 #ifdef DEBUG
42 #define DPRINTF(...)          printf(__VA_ARGS__)
43 #else
44 #define DPRINTF(...)
45 #endif
46 
47 static uint16_t
next(uint16_t * cur)48 next(uint16_t *cur)
49 {
50         uint16_t lsb = *cur & 1;
51         *cur >>= 1;
52         *cur ^= (-lsb) & 0xB400u;
53           return *cur;
54 }
55 
56 int
main(int argc,char * argv[])57 main(int argc, char *argv[])
58 {
59           char buf[65536];
60           char kb[256];
61           DBT key, val;
62           DB *db;
63           HASHINFO hi;
64           uint8_t c;
65           uint16_t len;
66           uint32_t pagesize = atoi(argv[1]);
67 
68           memset(&hi, 0, sizeof(hi));
69           memset(buf, 'a', sizeof(buf));
70           hi.bsize = pagesize;
71           hi.nelem = 65536;
72           hi.ffactor = 128;
73 
74           key.data = kb;
75           val.data = buf;
76 
77           db = dbopen(NULL, O_CREAT|O_TRUNC|O_RDWR, 0, DB_HASH, &hi);
78           if (db == NULL)
79                     err(EXIT_FAILURE, "dbopen");
80 
81           len = 0xaec1;
82           for (size_t i = 0; i < MAXKEY; i++) {
83                     key.size = (len & 0xff) + 1;
84                     c = len >> 8;
85                     memset(kb, c, key.size);
86                     val.size = (next(&len) & 0xff) + 1;
87                     switch ((*db->put)(db, &key, &val, R_NOOVERWRITE)) {
88                     case 0:
89                               DPRINTF("put %zu %zu %#x\n",
90                                   key.size, val.size, c);
91                               break;
92                     case -1:
93                               err(EXIT_FAILURE, "put error %zu %zu %#x",
94                                   key.size, val.size, c);
95                     case 1:
96                               errx(EXIT_FAILURE, "put overwrite %zu %zu %#x",
97                                   key.size, val.size, c);
98                     default:
99                               abort();
100                     }
101           }
102 
103           len = 0xaec1;
104           for (size_t i = 0; i < MAXKEY; i++) {
105                     key.size = (len & 0xff) + 1;
106                     c = len >> 8;
107                     memset(kb, c, key.size);
108                     next(&len);
109                     switch ((*db->get)(db, &key, &val, 0)) {
110                     case 0:
111                               DPRINTF("get %zu %zu %#x\n",
112                                   key.size, val.size, c);
113                               break;
114                     case -1:
115                               err(EXIT_FAILURE, "get %zu %zu %#x",
116                                   key.size, val.size, c);
117                     case 1:
118                               errx(EXIT_FAILURE, "get not found %zu %zu %#x",
119                                   key.size, val.size, c);
120                     default:
121                               abort();
122                     }
123                     if (memcmp(key.data, kb, key.size) != 0)
124                               errx(EXIT_FAILURE, "get badkey %zu %zu %#x",
125                                   key.size, val.size, c);
126                     if (val.size != (len & 0xff) + 1U)
127                               errx(EXIT_FAILURE, "get badvallen %zu %zu %#x",
128                                   key.size, val.size, c);
129                     if (memcmp(val.data, buf, val.size) != 0)
130                               errx(EXIT_FAILURE, "get badval %zu %zu %#x",
131                                   key.size, val.size, c);
132           }
133 
134           len = 0xaec1;
135           for (size_t i = 0; i < MAXKEY; i++) {
136                     key.size = (len & 0xff) + 1;
137                     c = len >> 8;
138                     memset(kb, c, key.size);
139                     next(&len);
140                     switch ((*db->del)(db, &key, 0)) {
141                     case 0:
142                               DPRINTF("del %zu %zu %#x\n",
143                                   key.size, val.size, c);
144                               break;
145                     case -1:
146                               err(EXIT_FAILURE, "del %zu %zu %#x", key.size,
147                                   val.size, c);
148                     case 1:
149                               errx(EXIT_FAILURE, "del not found %zu %zu %#x",
150                                   key.size, val.size, c);
151                     default:
152                               abort();
153                     }
154           }
155 
156           len = 0xaec1;
157           for (size_t i = 0; i < MAXKEY; i++) {
158                     key.size = (len & 0xff) + 1;
159                     c = len >> 8;
160                     memset(kb, c, key.size);
161                     next(&len);
162                     switch ((*db->get)(db, &key, &val, 0)) {
163                     case 0:
164                               errx(EXIT_FAILURE, "get2 found %zu %zu %#x",
165                                   key.size, val.size, c);
166                               break;
167                     case -1:
168                               err(EXIT_FAILURE, "get2 %zu %zu %#x",
169                                   key.size, val.size, c);
170                     case 1:
171                               DPRINTF("get2 %zu %zu %#x\n",
172                                   key.size, val.size, c);
173                               break;
174                     default:
175                               abort();
176                     }
177           }
178           return 0;
179 }
180