1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 /* broken test - this added just to make it compile */
28
29 #include <kapp/main.h>
30 #include <kapp/args.h>
31 #include <kfs/directory.h>
32 #include <kfs/pagefile.h>
33 #include <kfs/file.h>
34 #include <kfs/mmap.h>
35 #include <kdb/btree.h>
36 #include <klib/token.h>
37 #include <klib/log.h>
38 #include <klib/out.h>
39 #include <klib/debug.h>
40 #include <klib/rc.h>
41 #include <sysalloc.h>
42
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46
47 #define USE_EXTERN_TEXT_CMP 0
48
49
50 typedef struct test_btree_stat test_btree_stat;
51 struct test_btree_stat
52 {
53 uint32_t type;
54 uint32_t first_seen;
55 uint32_t count;
56 };
57
58 static
test_btree_stat_report(const void * key,size_t key_size,KBTreeValue * val,void * ignore)59 void test_btree_stat_report ( const void *key, size_t key_size, KBTreeValue *val, void *ignore )
60 {
61 size_t bytes;
62 const test_btree_stat *stat;
63 rc_t rc = KBTreeValueAccessRead ( val, ( const void** ) & stat, & bytes );
64 if ( rc != 0 )
65 LOGERR ( klogInt, rc, "KBTreeValueAccessRead failed" );
66 else if ( bytes != sizeof * stat )
67 LOGMSG ( klogInt, "KBTreeValueAccessRead returned wrong size" );
68 else
69 {
70 printf ( "key: '%.*s'\n", ( int ) key_size, ( const char* ) key );
71 printf ( " type %u\n", stat -> type );
72 printf ( " first seen on line %u\n", stat -> first_seen );
73 printf ( " occurs %u times.\n\n", stat -> count );
74 }
75 }
76
77 #if USE_EXTERN_TEXT_CMP
78 static
bt_text_cmp(const void * a,size_t asize,const void * b,size_t bsize)79 int bt_text_cmp ( const void *a, size_t asize, const void *b, size_t bsize )
80 {
81 if ( asize < bsize )
82 return -1;
83 if ( asize > bsize )
84 return 1;
85 return memcmp ( a, b, asize );
86 }
87 #else
88 #define bt_text_cmp NULL
89 #endif
90
91 static
test_readonly1(const KDirectory * dir,const KFile * in)92 rc_t test_readonly1 ( const KDirectory *dir, const KFile *in )
93 {
94 const KFile *backing;
95 rc_t rc = KDirectoryOpenFileRead ( dir, & backing, "test-btree.out" );
96 if ( rc == 0 )
97 {
98 const KBTree *bt;
99 rc = KBTreeMakeRead ( & bt, backing, 256 * 1024 * 1024, bt_text_cmp );
100 if ( rc != 0 )
101 LOGERR ( klogInt, rc, "KBTreeMakeRead failed" );
102 else
103 {
104 rc = KBTreeForEach ( bt, false, test_btree_stat_report, NULL );
105 if ( rc != 0 )
106 LOGERR ( klogInt, rc, "KBTreeForEach failed" );
107
108 KBTreeRelease ( bt );
109 }
110
111 KFileRelease ( backing );
112 }
113 return rc;
114 }
115
116 static
test_readonly(const KDirectory * dir,const KFile * in)117 rc_t test_readonly ( const KDirectory *dir, const KFile *in )
118 {
119 rc_t rc;
120
121 rc = test_readonly1 ( dir, in );
122
123 return rc;
124 }
125
126 static
make_text_entry(KBTree * bt,const char * key,size_t key_size,int id,uint32_t lineno)127 rc_t make_text_entry ( KBTree *bt, const char *key, size_t key_size, int id, uint32_t lineno )
128 {
129 static int entry = 0;
130
131 KBTreeValue val;
132 bool was_inserted;
133 test_btree_stat *stat;
134 rc_t rc = KBTreeEntry ( bt, & val, & was_inserted, sizeof * stat, key, key_size );
135 ++ entry;
136 if ( rc != 0 )
137 {
138 LOGERR ( klogInt, rc, "KBTreeEntry failed" );
139 printf ( "failed on entry %d\n", entry );
140 fflush ( stdout );
141 }
142 else
143 {
144 size_t bytes;
145 rc = KBTreeValueAccessUpdate ( & val, ( void** ) & stat, & bytes );
146 if ( rc != 0 )
147 LOGERR ( klogInt, rc, "KBTreeValueAccessUpdate failed" );
148 else
149 {
150 if ( bytes != sizeof * stat )
151 rc = -1;
152 else if ( was_inserted )
153 {
154 stat -> type = id;
155 stat -> first_seen = lineno;
156 stat -> count = 1;
157 }
158 else
159 {
160 ++ stat -> count;
161 }
162 }
163
164 KBTreeValueWhack ( & val );
165 }
166 return rc;
167 }
168
169 static
test_update1(KDirectory * dir,const KFile * in,const char * path)170 rc_t test_update1 ( KDirectory *dir, const KFile *in, const char *path )
171 {
172 KFile *out;
173 rc_t rc = KDirectoryCreateFile ( dir, & out, true, 0666, kcmInit, "test-btree.out" );
174 if ( rc == 0 )
175 {
176 size_t pgsize = KPageConstSize ();
177 size_t key_max = ( pgsize > 1024 ) ? 255 : ( pgsize - 8 - 24 ) / 2;
178
179 KBTree *bt;
180 rc = KBTreeMakeUpdate ( & bt, out,
181 256 * 1024 * 1024, false, kbtOpaqueKey,
182 8, sizeof ( test_btree_stat ),
183 1, key_max,
184 sizeof ( test_btree_stat ), sizeof ( test_btree_stat ),
185 bt_text_cmp );
186 if ( rc != 0 )
187 LOGERR ( klogInt, rc, "KBTreeMakeUpdate failed" );
188 else
189 {
190 const KMMap *mm;
191 rc = KMMapMakeRead ( & mm, in );
192 if ( rc == 0 )
193 {
194 const void *addr;
195 rc = KMMapAddrRead ( mm, &addr );
196 if ( rc == 0 )
197 {
198 size_t size;
199 rc = KMMapSize ( mm, & size );
200 if ( rc == 0 )
201 {
202 char buffer [ 1024 ];
203
204 /* have a memory mapped input file, and it's text
205 ( er, at least that's the idea *. */
206 KToken t;
207 KTokenText ttxt;
208 KTokenSource src;
209 String sstr, pstr;
210
211 /* test also assumes ASCII - sorry */
212 StringInitCString ( & pstr, path );
213 StringInit ( & sstr, addr, size, ( uint32_t ) size );
214 KTokenTextInit ( & ttxt, & sstr, & pstr );
215 KTokenSourceInit ( & src, & ttxt );
216
217 /* okay, now parse the file */
218 while ( KTokenizerNext ( kDefaultTokenizer, & src, & t ) -> id != eEndOfInput )
219 {
220 switch ( t . id )
221 {
222 case eUntermString:
223 case eString:
224 case eUntermEscapedString:
225 case eEscapedString:
226 rc = KTokenToString ( & t, buffer, sizeof buffer, & size );
227 if ( rc != 0 )
228 rc = 0;
229 else
230 rc = make_text_entry ( bt, buffer, size, t . id, t . lineno );
231 break;
232
233 case eIdent:
234 case eName:
235 rc = make_text_entry ( bt, t . str . addr, t . str . size, t . id, t . lineno );
236 break;
237 }
238 }
239 }
240 }
241
242 KMMapRelease ( mm );
243 }
244
245 KBTreeRelease ( bt );
246 }
247
248 KFileRelease ( out );
249 }
250 return rc;
251 }
252
253 static
test_update(KDirectory * dir,const KFile * in,const char * path)254 rc_t test_update ( KDirectory *dir, const KFile *in, const char *path )
255 {
256 rc_t rc;
257
258 rc = test_update1 ( dir, in, path );
259
260 return rc;
261 }
262
KAppVersion(void)263 ver_t CC KAppVersion ( void )
264 {
265 return 0;
266 }
267
268
269 const char UsageDefaultName[] = "vdb-unlock";
270
UsageSummary(const char * progname)271 rc_t CC UsageSummary ( const char *progname )
272 {
273 return KOutMsg ( "\n"
274 "Usage:\n"
275 " %s [Options] <target>\n"
276 "\n"
277 "Summary:\n"
278 " test the btree.\n"
279 , progname
280 );
281 }
282
Usage(const Args * args)283 rc_t CC Usage ( const Args *args )
284 {
285 const char * progname = UsageDefaultName;
286 const char * fullpath = UsageDefaultName;
287 rc_t rc;
288
289 if (args == NULL)
290 rc = RC (rcApp, rcArgv, rcAccessing, rcSelf, rcNull);
291 else
292 rc = ArgsProgram (args, &fullpath, &progname);
293 if (rc)
294 progname = fullpath = UsageDefaultName;
295
296 UsageSummary (progname);
297
298 KOutMsg ("Options:\n");
299
300 HelpOptionsStandard ();
301
302 HelpVersion (fullpath, KAppVersion());
303
304 return rc;
305 }
KMain(int argc,char * argv[])306 rc_t CC KMain ( int argc, char *argv [] )
307 {
308 Args *args;
309 rc_t rc = ArgsMakeAndHandle ( & args, argc, argv, 0 );
310 if ( rc != 0 )
311 LogErr ( klogErr, rc, "failed to parse arguments" );
312 else
313 {
314 KDirectory *wd;
315
316 const char *path = "test-btree.c";
317 if ( argc == 2 )
318 path = argv [ 1 ];
319
320 rc = KDirectoryNativeDir ( & wd );
321 if ( rc == 0 )
322 {
323 const KFile *in;
324 rc = KDirectoryOpenFileRead ( wd, & in, path );
325 if ( rc == 0 )
326 {
327 rc = test_update ( wd, in, path );
328 if ( rc == 0 )
329 rc = test_readonly ( wd, in );
330
331 KFileRelease ( in );
332 }
333
334 KDirectoryRelease ( wd );
335 }
336 }
337 return rc;
338 }
339