Check-in [48c63d9789]

Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
SHA1 Hash:48c63d97899cd20727a8c0fb6292b577b8c87507
Date: 2009-06-15 19:28:31
User: stephan
Comment:added compile-time option to disable inode names cache. Disabled by default because the cost is so high for many use cases. TODO: make it runtime-togglable.
Tags And Properties
Changes
hide diffs unified diffs patch

Changes to test.c

Old (61daa3241291461d) New (d17fef391a1d7930)
1 /* 1 /*
2 Test/demo app for libwhefs. 2 Test/demo app for libwhefs.
3 3
4 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/) 4 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/)
5 5
10 hidden lines
16 #include <assert.h> 16 #include <assert.h>
17 #include <unistd.h> /* sleep() */ 17 #include <unistd.h> /* sleep() */
18 #include "whefs.h" 18 #include "whefs.h"
19 #include "whefs_client_util.h" 19 #include "whefs_client_util.h"
20 20
> 21 #include "WHEFSApp.c"
> 22 #if 0
21 #if 1 23 #if 1
22 #define MARKER if(1) printf("MARKER: %s:%d:%s():\n",__FILE__,__LINE__,__func__); if(1) printf 24 #define MARKER if(1) printf("MARKER: %s:%d:%s():\n",__FILE__,__LINE__,__func__); if(1) printf
23 #else 25 #else
24 static void bogo_printf(char const * fmt, ...) {} 26 static void bogo_printf(char const * fmt, ...) {}
25 #define MARKER if(0) bogo_printf 27 #define MARKER if(0) bogo_printf
> 28 #endif
26 #endif 29 #endif
27 30
28 31
29 struct app_data { 32 struct app_data {
30 whefs_fs_options fsopts; 33 whefs_fs_options fsopts;
434 hidden lines
465 468
466 extern void whefs_inode_hash_cache_sort(whefs_fs * fs ); 469 extern void whefs_inode_hash_cache_sort(whefs_fs * fs );
467 int test_caching() 470 int test_caching()
468 { 471 {
469 MARKER("Caching tests...\n"); 472 MARKER("Caching tests...\n");
470 const bool toFile = true; /* using a file is many orders of magnitude slower than in-memory (300x on my box at home). */ | 473 const bool toFile = true; /* using a file is many orders of magnitude slower than in-memory (300x on my box at home, but only 10-20x on some very fast drives). */
471 whefs_fs * fs = 0; 474 whefs_fs * fs = 0;
472 char const * const defaultFile = "caching.whefs"; 475 char const * const defaultFile = "caching.whefs";
473 char const * fname = toFile 476 char const * fname = toFile
474 ? defaultFile 477 ? defaultFile
475 : ":memory:" 478 : ":memory:"
79 hidden lines
555 whefs_fs_finalize( fs ); 558 whefs_fs_finalize( fs );
556 MARKER("End caching tests.\n"); 559 MARKER("End caching tests.\n");
557 return 0; 560 return 0;
558 } 561 }
559 562
560 int main( int argc, char ** argv ) | 563
| 564 int main( int argc, char const ** argv )
561 { 565 {
562 whefs_setup_debug( stderr, (unsigned int)-1 ); | 566 WHEFSApp.usageText = "[flags]";
| 567 WHEFSApp.helpText =
| 568 "Basic test/sanity-check program for whefs."
| 569 ;
| 570 int rc = 0;
| 571 WHEFSApp_init( argc, argv, WHEFSApp_NoOpen, 0, 0 ); // ignore return.
| 572
| 573 //whefs_setup_debug_arg( stderr, "hcl" );
563 ThisApp.fsopts = whefs_fs_options_default; 574 ThisApp.fsopts = whefs_fs_options_default;
564 ThisApp.fsopts.inode_count = 16; 575 ThisApp.fsopts.inode_count = 16;
565 ThisApp.fsopts.block_count = 32; 576 ThisApp.fsopts.block_count = 32;
566 ThisApp.fsopts.filename_length = 32; 577 ThisApp.fsopts.filename_length = 32;
567 ThisApp.fsopts.block_size = 1024 * 2; 578 ThisApp.fsopts.block_size = 1024 * 2;
568 int rc = 0; | 579 if(!rc) rc = test_encodings();
569 //if(!rc) rc = test_encodings(); | 580 if(!rc) rc = test_hash();
570 //if(!rc) rc = test_hash(); |
571 if(!rc) rc = test_one(); 581 if(!rc) rc = test_one();
572 if(!rc) rc = test_ramfs(); 582 if(!rc) rc = test_ramfs();
573 if(!rc) rc = test_multiple_files(); 583 if(!rc) rc = test_multiple_files();
574 if(!rc) rc = test_truncate(); 584 if(!rc) rc = test_truncate();
575 if(!rc) rc = test_caching(); 585 if(!rc) rc = test_caching();
577 (0==rc) 587 (0==rc)
578 ? "You win :)" 588 ? "You win :)"
579 : "You lose :("); 589 : "You lose :(");
580 return rc; 590 return rc;
581 } 591 }

Changes to whefs_cache.c

Old (d2e886ce8d7ef365) New (f6904bced88a4acf)
1 /** 1 /**
2 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/ 2 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/
3 3
4 License: Public Domain 4 License: Public Domain
5 5
4 hidden lines
10 #include <stdlib.h> // free() 10 #include <stdlib.h> // free()
11 #include <string.h> // memset() 11 #include <string.h> // memset()
12 #include <assert.h> 12 #include <assert.h>
13 #include "whefs_cache.h" 13 #include "whefs_cache.h"
14 14
15 const whefs_string_db whefs_string_db_init = whefs_string_db_init_m; | 15 const whefs_string_cache whefs_string_cache_init = whefs_string_cache_init_m;
16 16
17 int whefs_string_db_cleanup( whefs_string_db * db ) | 17 int whefs_string_cache_cleanup( whefs_string_cache * db )
18 { 18 {
19 if( ! db ) return whefs_rc.ArgError; 19 if( ! db ) return whefs_rc.ArgError;
20 else 20 else
21 { 21 {
22 whio_blockdev_cleanup( &db->devBlock ); 22 whio_blockdev_cleanup( &db->devBlock );
23 if( db->devMem ) db->devMem->api->finalize( db->devMem ); 23 if( db->devMem ) db->devMem->api->finalize( db->devMem );
24 *db = whefs_string_db_init; | 24 *db = whefs_string_cache_init;
| 25 return whefs_rc.OK;
| 26 }
| 27
| 28 }
| 29
| 30 int whefs_string_cache_clear_contents( whefs_string_cache * db )
| 31 {
| 32 if( ! db ) return whefs_rc.ArgError;
| 33 else
| 34 {
| 35 if( db->devMem ) db->devMem->api->truncate( db->devMem, 0 );
25 return whefs_rc.OK; 36 return whefs_rc.OK;
26 } 37 }
27 38
28 } 39 }
29 int whefs_string_db_free( whefs_string_db * db ) | 40
| 41 int whefs_string_cache_free( whefs_string_cache * db )
30 { 42 {
31 const int rc = whefs_string_db_cleanup( db ); | 43 const int rc = whefs_string_cache_cleanup( db );
32 if( whefs_rc.OK == rc ) 44 if( whefs_rc.OK == rc )
33 { 45 {
34 free(db); 46 free(db);
35 } 47 }
36 return rc; 48 return rc;
37 } 49 }
38 50
39 int whefs_string_db_setup( whefs_string_db * db, whefs_id_type blockCount, whio_size_t blockSize ) | 51 int whefs_string_cache_setup( whefs_string_cache * db, whefs_id_type blockCount, whio_size_t blockSize )
40 { 52 {
41 if( ! db ) return whefs_rc.ArgError; 53 if( ! db ) return whefs_rc.ArgError;
42 whefs_string_db_cleanup( db ); | 54 whefs_string_cache_cleanup( db );
43 db->devMem = whio_dev_for_membuf( 0, 1.0 ); 55 db->devMem = whio_dev_for_membuf( 0, 1.0 );
> 56 static unsigned char wipebuf[WHEFS_MAX_FILENAME_LENGTH+1] = {'*'};
> 57 if( '*' == wipebuf[0] )
> 58 {
> 59 memset( wipebuf, 0, WHEFS_MAX_FILENAME_LENGTH+1 );
> 60 }
44 int rc = whio_blockdev_setup( &db->devBlock, db->devMem, 0U, 61 int rc = whio_blockdev_setup( &db->devBlock, db->devMem, 0U,
45 blockSize+1/*trailing null!*/, blockCount, 0 ); | 62 blockSize+1/*trailing null!*/, blockCount, wipebuf );
46 if( whefs_rc.OK != rc ) 63 if( whefs_rc.OK != rc )
47 { 64 {
48 whefs_string_db_cleanup(db); | 65 whefs_string_cache_cleanup(db);
49 } 66 }
50 return rc; 67 return rc;
51 } 68 }
52 69
53 whefs_string_db * whefs_string_db_create( whefs_id_type blockCount, whio_size_t blockSize ) | 70 whefs_string_cache * whefs_string_cache_create( whefs_id_type blockCount, whio_size_t blockSize )
54 { 71 {
55 whefs_string_db * db = (whefs_string_db*)malloc(sizeof(whefs_string_db)); | 72 whefs_string_cache * db = (whefs_string_cache*)malloc(sizeof(whefs_string_cache));
56 if( ! db ) return 0; 73 if( ! db ) return 0;
57 int rc = whefs_string_db_setup( db, blockCount, blockSize ); | 74 int rc = whefs_string_cache_setup( db, blockCount, blockSize );
58 if( whefs_rc.OK != rc ) 75 if( whefs_rc.OK != rc )
59 { 76 {
60 whefs_string_db_free(db); | 77 whefs_string_cache_free(db);
61 db = 0; 78 db = 0;
62 } 79 }
63 return db; 80 return db;
64 } 81 }
65 82
66 whio_size_t whefs_string_db_memcost( whefs_string_db const * db ) | 83 whio_size_t whefs_string_cache_memcost( whefs_string_cache const * db )
67 { 84 {
68 whio_size_t msize = (whio_size_t)-1; 85 whio_size_t msize = (whio_size_t)-1;
69 whio_dev_ioctl( db->devMem, whio_dev_ioctl_BUFFER_size, &msize ); 86 whio_dev_ioctl( db->devMem, whio_dev_ioctl_BUFFER_size, &msize );
70 if( (whio_size_t)-1 == msize ) 87 if( (whio_size_t)-1 == msize )
71 { 88 {
72 assert( 0 && "whio_dev_ioctl_GENERAL_size not behaving as documented!" ); 89 assert( 0 && "whio_dev_ioctl_GENERAL_size not behaving as documented!" );
73 return 0; 90 return 0;
74 } 91 }
75 msize += sizeof(whefs_string_db) | 92 msize += sizeof(whefs_string_cache)
76 + sizeof(*(db->devMem)) 93 + sizeof(*(db->devMem))
77 // we don't know the underlying internal costs of db->devMem, other than msize. 94 // we don't know the underlying internal costs of db->devMem, other than msize.
78 ; 95 ;
79 return msize; 96 return msize;
80 } 97 }
81 int whefs_string_db_set( whefs_string_db * db, whefs_id_type id, char const * str ) | 98
| 99 int whefs_string_cache_set( whefs_string_cache * db, whefs_id_type id, char const * str )
82 { 100 {
> 101 if(!WHEFS_CONFIG_ENABLE_STRINGS_CACHE)
> 102 {
> 103 return whefs_rc.OK;
> 104 }
83 if( ! whio_blockdev_in_range( db ? &db->devBlock : 0, id ) ) return whefs_rc.ArgError; 105 if( ! whio_blockdev_in_range( db ? &db->devBlock : 0, id ) ) return whefs_rc.ArgError;
84 size_t slen = (str && *str) ? strlen(str) : 0; 106 size_t slen = (str && *str) ? strlen(str) : 0;
85 if( db->devBlock.blocks.size <= slen ) return whefs_rc.RangeError; 107 if( db->devBlock.blocks.size <= slen ) return whefs_rc.RangeError;
86 enum { bufSize = WHEFS_MAX_FILENAME_LENGTH+1 }; 108 enum { bufSize = WHEFS_MAX_FILENAME_LENGTH+1 };
87 unsigned char buf[bufSize]; | 109 unsigned char buf[bufSize] = {0};
| 110 #if 1
| 111 whio_blockdev_wipe( &db->devBlock, id );
| 112 #endif
88 memcpy( buf, str, slen ); 113 memcpy( buf, str, slen );
89 memset( buf + slen, 0, db->devBlock.blocks.size - slen ); 114 memset( buf + slen, 0, db->devBlock.blocks.size - slen );
90 //WHEFS_DBG("writing %u bytes for name of inode #%"WHEFS_ID_TYPE_PFMT" as [%s]",slen,id+1,buf); 115 //WHEFS_DBG("writing %u bytes for name of inode #%"WHEFS_ID_TYPE_PFMT" as [%s]",slen,id+1,buf);
91 const int rc = whio_blockdev_write( &db->devBlock, id, buf ); 116 const int rc = whio_blockdev_write( &db->devBlock, id, buf );
92 #if 0 // truncate to a known maximum size if we've allocated above that. 117 #if 0 // truncate to a known maximum size if we've allocated above that.
10 hidden lines
103 } 128 }
104 #endif 129 #endif
105 return rc; 130 return rc;
106 } 131 }
107 132
108 char const * whefs_string_db_get( whefs_string_db const * db, whefs_id_type id ) | 133 char const * whefs_string_cache_get( whefs_string_cache const * db, whefs_id_type id )
109 { 134 {
> 135 if( ! WHEFS_CONFIG_ENABLE_STRINGS_CACHE ) return 0;
110 #if 0 136 #if 0
111 static char empty[2] = {0,0}; 137 static char empty[2] = {0,0};
112 #elseif 0 138 #elseif 0
113 static char const * empty = ""; 139 static char const * empty = "";
114 #else 140 #else
115 static char const * empty = 0; 141 static char const * empty = 0;
> 142 /**
> 143 Reminder to self: we need to be able to differentiate between
> 144 "found but empty" and "not yet loaded".
> 145 */
116 #endif 146 #endif
117 if( ! db ) return 0; 147 if( ! db ) return 0;
118 if( ! whio_blockdev_in_range( db ? &db->devBlock : 0, id ) ) return 0; 148 if( ! whio_blockdev_in_range( db ? &db->devBlock : 0, id ) ) return 0;
119 149
120 150
19 hidden lines
140 { 170 {
141 mem += off; 171 mem += off;
142 //WHEFS_DBG("id=%"WHEFS_ID_TYPE_PFMT", mem=%p [%s] [-1=%d]",id,(void const *)mem,(mem?(char const*)mem:"<empty>"), *(mem-1) ); 172 //WHEFS_DBG("id=%"WHEFS_ID_TYPE_PFMT", mem=%p [%s] [-1=%d]",id,(void const *)mem,(mem?(char const*)mem:"<empty>"), *(mem-1) );
143 assert( ('\0' == *(mem-1)) && "Logic or memory management error here!"); 173 assert( ('\0' == *(mem-1)) && "Logic or memory management error here!");
144 } 174 }
145 return (char const *)mem; | 175 return (mem && *mem) ? (char const *)mem : (char const *)0;
146 } 176 }
147 177
148 int whefs_inode_hash_cache_load( whefs_fs * fs ) 178 int whefs_inode_hash_cache_load( whefs_fs * fs )
149 { 179 {
150 #if 1 180 #if 1
8 hidden lines
159 { 189 {
160 fs->cache.hashes->maxAlloc = fs->options.inode_count; 190 fs->cache.hashes->maxAlloc = fs->options.inode_count;
161 } 191 }
162 192
163 whefs_hashid_list * li = fs->cache.hashes; 193 whefs_hashid_list * li = fs->cache.hashes;
164 whefs_hashid h = whefs_hashid_init; | 194 //whefs_hashid h = whefs_hashid_init;
165 whefs_string name = whefs_string_init; 195 whefs_string name = whefs_string_init;
166 enum { bufSize = WHEFS_MAX_FILENAME_LENGTH+1 }; 196 enum { bufSize = WHEFS_MAX_FILENAME_LENGTH+1 };
167 unsigned char buf[bufSize]; 197 unsigned char buf[bufSize];
168 memset( buf, 0, bufSize ); 198 memset( buf, 0, bufSize );
169 // ensure that whefs_inode_name_get() won't malloc(): 199 // ensure that whefs_inode_name_get() won't malloc():
170 name.string = (char *)buf; 200 name.string = (char *)buf;
171 name.alloced = bufSize; 201 name.alloced = bufSize;
172 int rc = 0; 202 int rc = 0;
173 whefs_id_type i; 203 whefs_id_type i;
174 size_t count = 0; | 204 //size_t count = 0;
175 for( i = fs->options.inode_count; i >=1 ; --i ) 205 for( i = fs->options.inode_count; i >=1 ; --i )
176 { 206 {
177 /** 207 /**
178 Maintenance reminder: 208 Maintenance reminder:
179 209
180 We do this loop in reverse order as an efficiency hack for 210 We do this loop in reverse order as an efficiency hack for
181 whefs_string_db. The trick is: the whefs_string_db's | 211 whefs_string_cache. The trick is: the whefs_string_cache's
182 internal buffer grows only as the number of used inodes 212 internal buffer grows only as the number of used inodes
183 does (it's size is a function of the highest used inode 213 does (it's size is a function of the highest used inode
184 ID). If we insert from low to high it may realloc many 214 ID). If we insert from low to high it may realloc many
185 times. If we insert from high to low, we're guaranteed to 215 times. If we insert from high to low, we're guaranteed to
186 need only one malloc/realloc on it. 216 need only one malloc/realloc on it.
7 hidden lines
194 } 224 }
195 } 225 }
196 #endif // WHEFS_FS_BITSET_CACHE_ENABLED 226 #endif // WHEFS_FS_BITSET_CACHE_ENABLED
197 rc = whefs_inode_name_get( fs, i, &name ); 227 rc = whefs_inode_name_get( fs, i, &name );
198 if( whefs_rc.OK != rc ) break; 228 if( whefs_rc.OK != rc ) break;
> 229 #if 0
> 230 // already done via whefs_inode_name_get().
199 if( !*name.string ) continue; 231 if( !*name.string ) continue;
200 ++count; 232 ++count;
201 h.id = i; 233 h.id = i;
202 h.hash = fs->cache.hashfunc( name.string ); 234 h.hash = fs->cache.hashfunc( name.string );
203 whefs_hashid_list_add( li, &h ); 235 whefs_hashid_list_add( li, &h );
> 236 #endif
204 } 237 }
205 assert( (name.string == (char *)buf) && "Internal memory management foo-foo." ); 238 assert( (name.string == (char *)buf) && "Internal memory management foo-foo." );
206 whefs_hashid_list_sort(li); 239 whefs_hashid_list_sort(li);
207 //WHEFS_DBG("loaded names caches with %u name(s).",count); 240 //WHEFS_DBG("loaded names caches with %u name(s).",count);
208 return rc; 241 return rc;
69 hidden lines
278 { 311 {
279 #if DISABLE_NAME_CACHE 312 #if DISABLE_NAME_CACHE
280 return whefs_rc.OK; 313 return whefs_rc.OK;
281 #endif 314 #endif
282 if( ! fs || !name || !*name ) return whefs_rc.ArgError; 315 if( ! fs || !name || !*name ) return whefs_rc.ArgError;
283 int rc = whefs_string_db_set( &fs->cache.strings, id-1, name ); | 316 int rc = whefs_string_cache_set( &fs->cache.strings, id-1, name );
284 if( whefs_rc.OK != rc ) return rc; 317 if( whefs_rc.OK != rc ) return rc;
285 if( ! fs->cache.hashes ) 318 if( ! fs->cache.hashes )
286 { 319 {
287 const whefs_id_type max = fs->options.inode_count; 320 const whefs_id_type max = fs->options.inode_count;
288 whefs_id_type dflt = 100/sizeof(whefs_hashid) /*for lack of a better default value.*/; 321 whefs_id_type dflt = 100/sizeof(whefs_hashid) /*for lack of a better default value.*/;
29 hidden lines
318 H.id = id; 351 H.id = id;
319 rc = whefs_hashid_list_add( fs->cache.hashes, &H ); 352 rc = whefs_hashid_list_add( fs->cache.hashes, &H );
320 if(0) WHEFS_DBG("Added to name cache: hash[%"WHEFS_HASHVAL_TYPE_PFMT"]=id[%"WHEFS_ID_TYPE_PFMT"], name=[%s], rc=%d", H.hash, H.id, name, rc ); 353 if(0) WHEFS_DBG("Added to name cache: hash[%"WHEFS_HASHVAL_TYPE_PFMT"]=id[%"WHEFS_ID_TYPE_PFMT"], name=[%s], rc=%d", H.hash, H.id, name, rc );
321 return whefs_rc.OK; 354 return whefs_rc.OK;
322 } 355 }

Changes to whefs_cache.h

Old (36c19eae72cfe99c) New (80626a8fe4189b1e)
1 #if !defined(WANDERINGHORSE_NET_WHEFS_CACHE_H_INCLUDED) 1 #if !defined(WANDERINGHORSE_NET_WHEFS_CACHE_H_INCLUDED)
2 #define WANDERINGHORSE_NET_WHEFS_CACHE_H_INCLUDED 1 2 #define WANDERINGHORSE_NET_WHEFS_CACHE_H_INCLUDED 1
3 /* 3 /*
4 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/ 4 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/
5 5
17 hidden lines
23 An internal type for caching strings via a whio_dev memory 23 An internal type for caching strings via a whio_dev memory
24 device. This optimizes the storage by using a contiguous 24 device. This optimizes the storage by using a contiguous
25 array for all strings. Unfortunately, each entry in the cache 25 array for all strings. Unfortunately, each entry in the cache
26 must have a set length, however. 26 must have a set length, however.
27 */ 27 */
28 struct whefs_string_db | 28 struct whefs_string_cache
29 { 29 {
30 /** 30 /**
31 Block device manager for writing strings. 31 Block device manager for writing strings.
32 */ 32 */
33 whio_blockdev devBlock; 33 whio_blockdev devBlock;
4 hidden lines
38 /** 38 /**
39 Internal buffer used for encoding/decoding. 39 Internal buffer used for encoding/decoding.
40 */ 40 */
41 //unsigned char buf[WHEFS_MAX_FILENAME_LENGTH+1]; 41 //unsigned char buf[WHEFS_MAX_FILENAME_LENGTH+1];
42 }; 42 };
43 typedef struct whefs_string_db whefs_string_db; | 43 typedef struct whefs_string_cache whefs_string_cache;
44 /** Empty initialization whefs_string_db object. */ | 44 /** Empty initialization whefs_string_cache object. */
45 #define whefs_string_db_init_m { \ | 45 #define whefs_string_cache_init_m { \
46 whio_blockdev_init_m/*devBlock*/, \ 46 whio_blockdev_init_m/*devBlock*/, \
47 0/*devMem*/ \ 47 0/*devMem*/ \
48 } 48 }
49 49
50 /** Empty initialization whefs_string_db object. */ | 50 /** Empty initialization whefs_string_cache object. */
51 extern const whefs_string_db whefs_string_db_init; | 51 extern const whefs_string_cache whefs_string_cache_init;
52 /** 52 /**
53 Calls whefs_string_db_cleanup() then frees db. | 53 Calls whefs_string_cache_cleanup() then frees db.
54 */ 54 */
55 int whefs_string_db_free( whefs_string_db * db ); | 55 int whefs_string_cache_free( whefs_string_cache * db );
56 /** 56 /**
57 Deallocates all resources associated with db, but does not free db 57 Deallocates all resources associated with db, but does not free db
58 itself. It can be re-used in another call to 58 itself. It can be re-used in another call to
59 whefs_string_db_setup() or freed using whefs_string_db_free(). | 59 whefs_string_cache_setup() or freed using whefs_string_cache_free().
| 60 */
| 61 int whefs_string_cache_cleanup( whefs_string_cache * db );
| 62
| 63 /**
| 64 Truncates the internal string table of db to 0 bytes, potentially freeing
| 65 up memory. db is still a valid/usable object after calling this.
60 */ 66 */
61 int whefs_string_db_cleanup( whefs_string_db * db ); | 67 int whefs_string_cache_clear_contents( whefs_string_cache * db );
| 68
62 /** 69 /**
63 Sets up db, which must be initialized memory (use 70 Sets up db, which must be initialized memory (use
64 whefs_string_db_init or whefs_string_db_init_m to initialize it). | 71 whefs_string_cache_init or whefs_string_cache_init_m to initialize it).
65 db will be able to hold a number (blockCount) of fixed-size blocks of 72 db will be able to hold a number (blockCount) of fixed-size blocks of
66 blockSize bytes each. 73 blockSize bytes each.
67 74
68 On success whefs_rc.OK is returned. 75 On success whefs_rc.OK is returned.
69 */ 76 */
70 int whefs_string_db_setup( whefs_string_db * db, whefs_id_type blockCount, whio_size_t blockSize ); | 77 int whefs_string_cache_setup( whefs_string_cache * db, whefs_id_type blockCount, whio_size_t blockSize );
71 78
72 /** 79 /**
73 Creates a new whefs_string_db with the given capacity. On error | 80 Creates a new whefs_string_cache with the given capacity. On error
74 returns 0, else a new object which must be eventually deleted by 81 returns 0, else a new object which must be eventually deleted by
75 passing it to whefs_string_db_free(). | 82 passing it to whefs_string_cache_free().
76 */ 83 */
77 whefs_string_db * whefs_string_db_create( whefs_id_type blockCount, whio_size_t blockSize ); | 84 whefs_string_cache * whefs_string_cache_create( whefs_id_type blockCount, whio_size_t blockSize );
78 /** 85 /**
79 Sets the given record to the given str value. str may be null or empty but 86 Sets the given record to the given str value. str may be null or empty but
80 may not be longer than db's block size. It is copied, and need not live 87 may not be longer than db's block size. It is copied, and need not live
81 longer than this call. 88 longer than this call.
82 89
83 Error cases: 90 Error cases:
84 91
85 whefs_rc.ArgError = !db or id is out of range for db. 92 whefs_rc.ArgError = !db or id is out of range for db.
86 93
87 whefs_rc.RangeError = str is longer than db's block size, as passed 94 whefs_rc.RangeError = str is longer than db's block size, as passed
88 to whefs_string_db_create() or whefs_string_db_setup(). | 95 to whefs_string_cache_create() or whefs_string_cache_setup().
89 96
90 whio_rc.AllocError = underying cache memory could not be allocated. 97 whio_rc.AllocError = underying cache memory could not be allocated.
91 98
92 In theory, another whio_rc error may be propagated, but i can't 99 In theory, another whio_rc error may be propagated, but i can't
93 think of a reason why it would other than an internal bug. 100 think of a reason why it would other than an internal bug.
95 This is an O(N) operation, where N is the length of db's blocks, but it involves 102 This is an O(N) operation, where N is the length of db's blocks, but it involves
96 only simple math, memcpy() and memset(), so it's pretty past. If 103 only simple math, memcpy() and memset(), so it's pretty past. If
97 the underlying cache must reallocate to grow then it also takes on 104 the underlying cache must reallocate to grow then it also takes on
98 the performance characteristics of realloc(). 105 the performance characteristics of realloc().
99 106
100 @see whefs_string_db_get() | 107 @see whefs_string_cache_get()
101 */ 108 */
102 int whefs_string_db_set( whefs_string_db * db, whefs_id_type id, char const * str ); | 109 int whefs_string_cache_set( whefs_string_cache * db, whefs_id_type id, char const * str );
103 110
104 /** 111 /**
105 Gets the string at the given block number. 112 Gets the string at the given block number.
106 113
107 On success (i.e. a cache entry was found) it returns a pointer to 114 On success (i.e. a cache entry was found) it returns a pointer to
108 the cached string bytes (null-terminated). They are owned by db and 115 the cached string bytes (null-terminated). They are owned by db and
109 may be reallocated or destroyed by any whefs_string_db_set() calls, | 116 may be reallocated or destroyed by any whefs_string_cache_set() calls,
110 so they should be copied if they are to be held long-term. 117 so they should be copied if they are to be held long-term.
111 118
112 This is an O(1) operation. 119 This is an O(1) operation.
113 120
114 This function returns 0 (NULL) if the name cannot be read (i.e. it 121 This function returns 0 (NULL) if the name cannot be read (i.e. it
115 has not be cached yet, or caching has been disabled), if the id is 122 has not be cached yet, or caching has been disabled), if the id is
116 out of bounds, or a few other theoretical but not likely cases. 123 out of bounds, or a few other theoretical but not likely cases.
117 124
118 @see whefs_string_db_set(). | 125 @see whefs_string_cache_set().
119 */ 126 */
120 char const * whefs_string_db_get( whefs_string_db const * db, whefs_id_type id ); | 127 char const * whefs_string_cache_get( whefs_string_cache const * db, whefs_id_type id );
121 /** 128 /**
122 Returns an approximate cost of the memory associated with db, which 129 Returns an approximate cost of the memory associated with db, which
123 must be a fully-setup object. The real cost is slightly higher than 130 must be a fully-setup object. The real cost is slightly higher than
124 the returned value, as there are internal details which this code 131 the returned value, as there are internal details which this code
125 does not have access to, so it cannot measure them. 132 does not have access to, so it cannot measure them.
126 */ 133 */
127 whio_size_t whefs_string_db_memcost( whefs_string_db const * db ); | 134 whio_size_t whefs_string_cache_memcost( whefs_string_cache const * db );
128 135
129 #ifdef __cplusplus 136 #ifdef __cplusplus
130 } /* extern "C" */ 137 } /* extern "C" */
131 #endif 138 #endif
132 139
133 140
134 #endif /* WANDERINGHORSE_NET_WHEFS_CACHE_H_INCLUDED */ 141 #endif /* WANDERINGHORSE_NET_WHEFS_CACHE_H_INCLUDED */

Changes to whefs_config.h

Old (42c26bf40dc62fb8) New (99dc3053631fc38e)
1 #if !defined(WANDERINGHORSE_NET_WHEFS_CONFIG_H_INCLUDED) 1 #if !defined(WANDERINGHORSE_NET_WHEFS_CONFIG_H_INCLUDED)
2 #define WANDERINGHORSE_NET_WHEFS_CONFIG_H_INCLUDED 2 #define WANDERINGHORSE_NET_WHEFS_CONFIG_H_INCLUDED
3 3
4 /* 4 /*
5 This file contains the compile-time-configurable parts of 5 This file contains the compile-time-configurable parts of
289 hidden lines
295 #if !defined(DOXYGEN) 295 #if !defined(DOXYGEN)
296 # define WHEFS_MACROIZE_SMALL_CHECKS 0 296 # define WHEFS_MACROIZE_SMALL_CHECKS 0
297 #else 297 #else
298 # define WHEFS_MACROIZE_SMALL_CHECKS 0 298 # define WHEFS_MACROIZE_SMALL_CHECKS 0
299 #endif 299 #endif
> 300
> 301 /**
> 302 If WHEFS_CONFIG_ENABLE_STRINGS_CACHE is 0 then the internal inode
> 303 name string caching mechanism is disabled. The cache costs a
> 304 significant amount of memory (proportional to the number of used
> 305 inodes multiplied by the maximum filename length), but can save i/o
> 306 when files are searched by name often or their names are fetched
> 307 more than once. Any performance gains are only noted in apps which
> 308 have an unusually high amount of lookups by name. When it is turned
> 309 on, the whole inode names table is read and the cache is
> 310 populated. If the client searches by name less times than there are
> 311 used inodes, the loading of the cache costs more than any relative
> 312 benefit. Thus it is disabled by default.
> 313
> 314 In fact, an app may (and is likely to) end up making more calls to
> 315 malloc() and free() with the cache turned off, but they are likely
> 316 to not hold as much memory open at one time compared to the cache.
> 317
> 318 FIXME: make this runtime-togglable.
> 319 */
> 320 #define WHEFS_CONFIG_ENABLE_STRINGS_CACHE 0
300 321
301 #ifdef __cplusplus 322 #ifdef __cplusplus
302 } /* extern "C" */ 323 } /* extern "C" */
303 #endif 324 #endif
304 325
305 326
306 #endif /* WANDERINGHORSE_NET_WHEFS_CONFIG_H_INCLUDED */ 327 #endif /* WANDERINGHORSE_NET_WHEFS_CONFIG_H_INCLUDED */

Changes to whefs_details.c

Old (8bde80f305ca6936) New (07b8a5d618bcbcae)
1 #if !defined(WANDERINGHORSE_NET_WHEFS_DETAILS_C_INCLUDED) 1 #if !defined(WANDERINGHORSE_NET_WHEFS_DETAILS_C_INCLUDED)
2 #define WANDERINGHORSE_NET_WHEFS_DETAILS_C_INCLUDED 1 2 #define WANDERINGHORSE_NET_WHEFS_DETAILS_C_INCLUDED 1
3 #if ! defined __STDC_FORMAT_MACROS 3 #if ! defined __STDC_FORMAT_MACROS
4 # define __STDC_FORMAT_MACROS 1 4 # define __STDC_FORMAT_MACROS 1
5 #endif 5 #endif
267 hidden lines
273 } threads; 273 } threads;
274 struct _caches 274 struct _caches
275 { 275 {
276 whefs_hashid_list * hashes; 276 whefs_hashid_list * hashes;
277 whefs_hashval_type (*hashfunc)( char const * vstr); 277 whefs_hashval_type (*hashfunc)( char const * vstr);
278 whefs_string_db strings; | 278 whefs_string_cache strings;
279 } cache; 279 } cache;
280 }; 280 };
281 281
282 /** Empty initialization object. */ 282 /** Empty initialization object. */
283 extern const whefs_fs whefs_fs_init; 283 extern const whefs_fs whefs_fs_init;
479 hidden lines
763 void whefs_inode_hash_cache_sort(whefs_fs * fs ); 763 void whefs_inode_hash_cache_sort(whefs_fs * fs );
764 764
765 int whefs_fs_cache_name( whefs_fs * fs, whefs_id_type id, char const * n ); 765 int whefs_fs_cache_name( whefs_fs * fs, whefs_id_type id, char const * n );
766 766
767 #endif /* WANDERINGHORSE_NET_WHEFS_DETAILS_C_INCLUDED */ 767 #endif /* WANDERINGHORSE_NET_WHEFS_DETAILS_C_INCLUDED */

Changes to whefs_fs.c

Old (82b4dbaece4de700) New (fc5d5b096ea49ee9)
1 /* 1 /*
2 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/) 2 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/)
3 3
4 License: Public Domain 4 License: Public Domain
5 5
19 hidden lines
25 #endif 25 #endif
26 26
27 #define WHEFS_LOAD_CACHES_ON_OPEN 1 /* make sure and test whefs-cp and friends if setting this to 0. */ 27 #define WHEFS_LOAD_CACHES_ON_OPEN 1 /* make sure and test whefs-cp and friends if setting this to 0. */
28 #if ! WHEFS_LOAD_CACHES_ON_OPEN 28 #if ! WHEFS_LOAD_CACHES_ON_OPEN
29 # warning "(0==WHEFS_LOAD_CACHES_ON_OPEN) is is known to cause bugs. Fix it!" 29 # warning "(0==WHEFS_LOAD_CACHES_ON_OPEN) is is known to cause bugs. Fix it!"
> 30 /*
> 31 Reminder to self: the problem here is one of "how do we distinguish empty names vs. not-cached names,"
> 32 and is complicated by the voodoo we use to store the strings inside whefs_fs::cache::strings.
> 33 */
30 #endif 34 #endif
> 35
31 #if WHIO_ENABLE_THREADS 36 #if WHIO_ENABLE_THREADS
32 /** 37 /**
33 WHEFS_FS_STRUCT_THREAD_INFO is the initializer for whefs_fs.threads. 38 WHEFS_FS_STRUCT_THREAD_INFO is the initializer for whefs_fs.threads.
34 */ 39 */
35 # define WHEFS_FS_STRUCT_THREAD_INFO {/*threads*/ \ 40 # define WHEFS_FS_STRUCT_THREAD_INFO {/*threads*/ \
7 hidden lines
43 /* whefs_fs::cache struct ... */ 48 /* whefs_fs::cache struct ... */
44 #define WHEFS_FS_STRUCT_CACHE \ 49 #define WHEFS_FS_STRUCT_CACHE \
45 {/*cache*/ \ 50 {/*cache*/ \
46 0/*hashes*/, \ 51 0/*hashes*/, \
47 whefs_hash_cstring/*hashfunc*/, \ 52 whefs_hash_cstring/*hashfunc*/, \
48 whefs_string_db_init_m/*strings*/ \ | 53 whefs_string_cache_init_m/*strings*/ \
49 } 54 }
50 /* whefs_fs::fences struct ... */ 55 /* whefs_fs::fences struct ... */
51 #define WHEFS_FS_STRUCT_FENCES \ 56 #define WHEFS_FS_STRUCT_FENCES \
52 { /* fences */ \ 57 { /* fences */ \
53 whio_blockdev_init_m /* s */, \ 58 whio_blockdev_init_m /* s */, \
228 hidden lines
282 whefs_hashid_list_alloc( &fs->cache.hashes, 0 );// reminder: we keep fs->cache.hashes itself until finalization. 287 whefs_hashid_list_alloc( &fs->cache.hashes, 0 );// reminder: we keep fs->cache.hashes itself until finalization.
283 } 288 }
284 if(1) 289 if(1)
285 { 290 {
286 WHEFS_DBG_CACHE("Emptying names string cache using approximately %"WHIO_SIZE_T_PFMT" bytes.", 291 WHEFS_DBG_CACHE("Emptying names string cache using approximately %"WHIO_SIZE_T_PFMT" bytes.",
287 whefs_string_db_memcost( &fs->cache.strings ) ); | 292 whefs_string_cache_memcost( &fs->cache.strings ) );
| 293 whefs_string_cache_clear_contents( &fs->cache.strings );
288 } 294 }
289 } 295 }
290 void whefs_fs_caches_clear( whefs_fs * restrict fs ) 296 void whefs_fs_caches_clear( whefs_fs * restrict fs )
291 { 297 {
292 whbits_free_bits( &fs->bits.i ); 298 whbits_free_bits( &fs->bits.i );
20 hidden lines
313 whefs_fs_caches_clear(fs); 319 whefs_fs_caches_clear(fs);
314 whefs_hashid_list_free( fs->cache.hashes ); 320 whefs_hashid_list_free( fs->cache.hashes );
315 whio_blockdev_cleanup ( &fs->fences.s ); 321 whio_blockdev_cleanup ( &fs->fences.s );
316 whio_blockdev_cleanup ( &fs->fences.i ); 322 whio_blockdev_cleanup ( &fs->fences.i );
317 //whio_blockdev_cleanup ( &fs->fences.b ); 323 //whio_blockdev_cleanup ( &fs->fences.b );
318 whefs_string_db_cleanup( &fs->cache.strings ); | 324 whefs_string_cache_cleanup( &fs->cache.strings );
319 if( fs->dev ) 325 if( fs->dev )
320 { 326 {
321 whefs_fs_flush(fs); 327 whefs_fs_flush(fs);
322 whefs_fs_unlock( fs, 0, SEEK_SET, 0 ); 328 whefs_fs_unlock( fs, 0, SEEK_SET, 0 );
323 if( fs->ownsDev ) fs->dev->api->finalize( fs->dev ); 329 if( fs->ownsDev ) fs->dev->api->finalize( fs->dev );
168 hidden lines
492 } 498 }
493 499
494 int whefs_inode_name_get( whefs_fs * restrict fs, whefs_id_type id, whefs_string * tgt ) 500 int whefs_inode_name_get( whefs_fs * restrict fs, whefs_id_type id, whefs_string * tgt )
495 { 501 {
496 if( ! tgt || ! whefs_inode_id_is_valid( fs, id ) ) return whefs_rc.ArgError; 502 if( ! tgt || ! whefs_inode_id_is_valid( fs, id ) ) return whefs_rc.ArgError;
497 if(1) do | 503 if( WHEFS_CONFIG_ENABLE_STRINGS_CACHE )
498 { 504 {
499 static uint32_t hitmiss[2] = {0,0}; 505 static uint32_t hitmiss[2] = {0,0};
500 char const * cached = whefs_string_db_get( &fs->cache.strings, id-1 ); | 506 char const * cached = whefs_string_cache_get( &fs->cache.strings, id-1 );
501 if( cached && *cached ) 507 if( cached && *cached )
502 { 508 {
503 /* reminder: *cached is ambiguous: it could be an unused inode slot or | 509 /* reminder: (!*cached) is ambiguous: it could be an unused inode slot or
504 an empty name. 510 an empty name.
505 */ 511 */
506 //WHEFS_DBG("Got cached name for inode #%"WHEFS_ID_TYPE_PFMT" [%s]",id,cached); 512 //WHEFS_DBG("Got cached name for inode #%"WHEFS_ID_TYPE_PFMT" [%s]",id,cached);
507 //WHEFS_DBG("[inode strings db: misses=%u Hits=%u][name=[%s]]",hitmiss[0],hitmiss[1],cached); 513 //WHEFS_DBG("[inode strings db: misses=%u Hits=%u][name=[%s]]",hitmiss[0],hitmiss[1],cached);
508 ++hitmiss[1]; 514 ++hitmiss[1];
509 return whefs_string_copy_cstring( tgt, cached ); 515 return whefs_string_copy_cstring( tgt, cached );
510 } 516 }
511 ++hitmiss[0]; 517 ++hitmiss[0];
512 } 518 }
513 while(false); <
514 519
515 // FIXME: check opened inodes first! | 520 // FIXME? check opened inodes first?
516 int rc = 0; 521 int rc = 0;
517 unsigned char buf[whefs_sizeof_encoded_inode_name]; 522 unsigned char buf[whefs_sizeof_encoded_inode_name];
518 memset( buf, 0, whefs_sizeof_encoded_inode_name ); 523 memset( buf, 0, whefs_sizeof_encoded_inode_name );
519 assert( (fs->fences.s.blocks.size == fs->sizes[WHEFS_SZ_INODE_NAME]) && "fs inode name size has not been set up properly!" ); 524 assert( (fs->fences.s.blocks.size == fs->sizes[WHEFS_SZ_INODE_NAME]) && "fs inode name size has not been set up properly!" );
520 assert(fs->sizes[WHEFS_SZ_INODE_NAME] && "fs has not been set up properly!"); 525 assert(fs->sizes[WHEFS_SZ_INODE_NAME] && "fs has not been set up properly!");
463 hidden lines
984 fs->sizes[WHEFS_SZ_BLOCK], 989 fs->sizes[WHEFS_SZ_BLOCK],
985 fs->options.block_count, 990 fs->options.block_count,
986 0 /* FIXME: we need a prototype, but need the encoding routines for that first. */ ); 991 0 /* FIXME: we need a prototype, but need the encoding routines for that first. */ );
987 #endif 992 #endif
988 993
989 rc = whefs_string_db_setup( &fs->cache.strings, fs->options.inode_count, fs->options.filename_length ); | 994 rc = whefs_string_cache_setup( &fs->cache.strings, fs->options.inode_count, fs->options.filename_length );
990 995
991 return rc; 996 return rc;
992 } 997 }
993 998
994 999
366 hidden lines
1361 X(whio_stream), 1366 X(whio_stream),
1362 X(whio_stream_api), 1367 X(whio_stream_api),
1363 #endif 1368 #endif
1364 X(whbits), 1369 X(whbits),
1365 X(whefs_string), 1370 X(whefs_string),
1366 X(whefs_string_db), | 1371 X(whefs_string_cache),
1367 X(whefs_inode), 1372 X(whefs_inode),
1368 X(whefs_block), 1373 X(whefs_block),
1369 X(whefs_hashid), 1374 X(whefs_hashid),
1370 X(whefs_hashid_list), 1375 X(whefs_hashid_list),
1371 {0,0} 1376 {0,0}
85 hidden lines
1457 if( whefs_rc.OK != rc ) break; 1462 if( whefs_rc.OK != rc ) break;
1458 } 1463 }
1459 whefs_fs_flush( fs ); 1464 whefs_fs_flush( fs );
1460 return rc; 1465 return rc;
1461 } 1466 }

Changes to whefs_inode.c

Old (3cb755439006314b) New (ff3760ef7b8e4b23)
1 /* 1 /*
2 Implementations for whefs_inode operations. 2 Implementations for whefs_inode operations.
3 3
4 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/) 4 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/)
5 5
96 hidden lines
102 fs->hints.unused_inode_start = ino->id; 102 fs->hints.unused_inode_start = ino->id;
103 } 103 }
104 } 104 }
105 } 105 }
106 106
> 107
107 int whefs_inode_name_set( whefs_fs * fs, whefs_id_type nid, char const * name ) 108 int whefs_inode_name_set( whefs_fs * fs, whefs_id_type nid, char const * name )
108 { 109 {
109 //if( !n || !n->id ) return whefs_rc.ArgError; 110 //if( !n || !n->id ) return whefs_rc.ArgError;
110 if( !whefs_inode_id_is_valid(fs,nid) ) 111 if( !whefs_inode_id_is_valid(fs,nid) )
111 { 112 {
112 return whefs_rc.ArgError; 113 return whefs_rc.ArgError;
113 } 114 }
114 int rc = 0; 115 int rc = 0;
> 116
> 117 /**
> 118 We have to see if we have an existing entry for the given inode ID, so
> 119 we can replace its hashvalue in the cache. If we don't do this we end
> 120 up with stale/useless entries in the cache.
> 121 */
115 whefs_inode * nop = 0; 122 whefs_inode * nop = 0;
116 whefs_hashid * H = 0; 123 whefs_hashid * H = 0;
117 char const * oldName; oldName = whefs_string_db_get( &fs->cache.strings, nid-1 ); | 124 char const * nameCheck = name;
| 125 enum { bufSize = WHEFS_MAX_FILENAME_LENGTH + 1 };
| 126 char buf[bufSize] = {0};
| 127 whefs_string ncheck = whefs_string_init;
| 128 ncheck.string = buf;
| 129 ncheck.alloced = bufSize;
| 130 if(1)
| 131 {
| 132 rc = whefs_inode_name_get( fs, nid, &ncheck );
| 133 assert( (ncheck.string == buf) && "illegal (re)alloc!");
| 134 if( whefs_rc.OK != rc ) return rc;
| 135 if( *buf && (0==strcmp(buf,name))) return whefs_rc.OK;
| 136 if( *buf ) nameCheck = ncheck.string;
| 137 }
118 #if 1 138 #if 1
119 whefs_id_type ndx = whefs_inode_hash_cache_search_ndx( fs, oldName ? oldName : name ); | 139 if( whefs_rc.OK == whefs_inode_search_opened( fs, nid, &nop ) )
| 140 { // FIXME: this is unfortunate. TODO: remove whefs_inode::name altogether.
| 141 whefs_string_copy_cstring( &nop->name, name );
| 142 }
| 143 #endif
| 144
| 145 WHEFS_DBG_CACHE("inode-name-set searching for [old=%s][new=%s][check=%s].",ncheck.string,name,nameCheck);
| 146 whefs_id_type ndx = whefs_inode_hash_cache_search_ndx( fs, nameCheck );
120 if( ndx != whefs_id_type_end ) 147 if( ndx != whefs_id_type_end )
121 { 148 {
> 149 WHEFS_DBG_CACHE("inode-name-set found an existing entry for [%s].",nameCheck);
122 H = &fs->cache.hashes->list[ndx]; 150 H = &fs->cache.hashes->list[ndx];
123 if( H->id != nid ) 151 if( H->id != nid )
124 { 152 {
125 WHEFS_DBG_ERR("Internal error: cache hash collision for name [%s]!",name); 153 WHEFS_DBG_ERR("Internal error: cache hash collision for name [%s]!",name);
126 return whefs_rc.InternalError; 154 return whefs_rc.InternalError;
127 } 155 }
128 if( whefs_rc.OK == whefs_inode_search_opened( fs, nid, &nop ) ) <
129 { // this is unfortunate. TODO: remove whefs_inode::name altogether. <
130 whefs_string_copy_cstring( &nop->name, name ); <
131 } <
132 } 156 }
133 #endif <
134 /** 157 /**
135 Maintenance reminders: 158 Maintenance reminders:
136 159
137 We write to disk before updating any opened inode because writing is 160 We write to disk before updating any opened inode because writing is
138 much more likely to fail then updating the opened inode is, since the latter 161 much more likely to fail then updating the opened inode is, since the latter
6 hidden lines
145 if( whefs_rc.OK != rc ) return rc; 168 if( whefs_rc.OK != rc ) return rc;
146 #if 1 169 #if 1
147 if( H ) 170 if( H )
148 { 171 {
149 H->hash = fs->cache.hashfunc(name); 172 H->hash = fs->cache.hashfunc(name);
150 fs->cache.hashes->isSorted = false; | 173 //fs->cache.hashes->isSorted = false;
151 if(1) WHEFS_DBG("Replacing hashcode for file [%s].",name); | 174 whefs_hashid_list_sort( fs->cache.hashes );
152 rc = whefs_string_copy_cstring( &nop->name, name ); | 175 WHEFS_DBG_CACHE("Replacing hashcode for file [%s].",name);
| 176 if( nop )
| 177 {
| 178 rc = whefs_string_copy_cstring( &nop->name, name );
| 179 }
153 } 180 }
154 if( whefs_rc.OK != rc ) return rc; 181 if( whefs_rc.OK != rc ) return rc;
155 whefs_string_db_set( &fs->cache.strings, nid-1, name ); | 182 whefs_string_cache_set( &fs->cache.strings, nid-1, name );
156 #endif 183 #endif
157 return rc; 184 return rc;
158 } 185 }
159 186
160 #if ! WHEFS_MACROIZE_SMALL_CHECKS 187 #if ! WHEFS_MACROIZE_SMALL_CHECKS
58 hidden lines
219 } 246 }
220 247
221 int whefs_inode_id_read( whefs_fs * fs, whefs_id_type nid, whefs_inode * tgt ) 248 int whefs_inode_id_read( whefs_fs * fs, whefs_id_type nid, whefs_inode * tgt )
222 { 249 {
223 if( !tgt || !whefs_inode_id_is_valid( fs, nid ) ) return whefs_rc.ArgError; 250 if( !tgt || !whefs_inode_id_is_valid( fs, nid ) ) return whefs_rc.ArgError;
224 if(1) | 251 if( WHEFS_CONFIG_ENABLE_STRINGS_CACHE )
225 { 252 {
226 whefs_inode * nop = 0; 253 whefs_inode * nop = 0;
227 int xc = whefs_inode_search_opened( fs, nid, &nop ); 254 int xc = whefs_inode_search_opened( fs, nid, &nop );
228 if( (whefs_rc.OK == xc) && nop ) 255 if( (whefs_rc.OK == xc) && nop )
229 { 256 {
423 hidden lines
653 } 680 }
654 } 681 }
655 #endif 682 #endif
656 683
657 whefs_string ns = whefs_string_init; 684 whefs_string ns = whefs_string_init;
658 int rc = 0; | 685 int rc = whefs_rc.OK;
659 bool expectExact = false; // when true, we stop with error if first guess isn't correct 686 bool expectExact = false; // when true, we stop with error if first guess isn't correct
660 const whefs_hashval_type nameHash = fs->cache.hashfunc( name ); 687 const whefs_hashval_type nameHash = fs->cache.hashfunc( name );
661 #if 1 688 #if 1
662 if( fs->cache.hashes && !fs->cache.hashes->isSorted ) 689 if( fs->cache.hashes && !fs->cache.hashes->isSorted )
663 { 690 {
7 hidden lines
671 i = 2; // 2 = first client-usable inode. 698 i = 2; // 2 = first client-usable inode.
672 } 699 }
673 else 700 else
674 { // we know directly what inode record to jump to now... 701 { // we know directly what inode record to jump to now...
675 expectExact = true; 702 expectExact = true;
676 if(0) WHEFS_DBG("Filename matched cached INDEX (%"WHEFS_ID_TYPE_PFMT") for hash code 0x%"WHEFS_HASHVAL_TYPE_PFMT" for name [%s]",i, nameHash,name); | 703 if(0) WHEFS_DBG_CACHE("Filename matched cached INDEX (%"WHEFS_ID_TYPE_PFMT") for hash code 0x%"WHEFS_HASHVAL_TYPE_PFMT" for name [%s]",i, nameHash,name);
677 whefs_hashid * H = &fs->cache.hashes->list[i]; 704 whefs_hashid * H = &fs->cache.hashes->list[i];
678 ++H->hits; 705 ++H->hits;
679 i = H->id; 706 i = H->id;
680 cname = whefs_string_db_get( &fs->cache.strings, i-1 ); | 707 if( WHEFS_CONFIG_ENABLE_STRINGS_CACHE )
681 if(0) WHEFS_DBG("Got cached ID (%"WHEFS_ID_TYPE_PFMT") for hash code 0x%"WHEFS_HASHVAL_TYPE_PFMT" for name [%s]/[%s] hit count=[%"PRIu32"]",i, nameHash,name,cname,H->hits); |
682 if( !cname ) |
683 { 708 {
684 WHEFS_DBG("Internal consistency/usage error: hash cache has inode entry #%"WHEFS_ID_TYPE_PFMT" cached for name [%s] but names db does not have an entry!", | 709 cname = whefs_string_cache_get( &fs->cache.strings, i-1 );
685 i, name ); | 710 if(0) WHEFS_DBG_CACHE("Got cached ID (%"WHEFS_ID_TYPE_PFMT") for hash code 0x%"WHEFS_HASHVAL_TYPE_PFMT" for name [%s]/[%s] hit count=[%"PRIu32"]",i, nameHash,name,cname,H->hits);
686 return whefs_rc.InternalError; | 711 if( !cname )
| 712 {
| 713 WHEFS_DBG_ERR("Internal consistency/usage error: hash cache has inode entry #%"WHEFS_ID_TYPE_PFMT" cached for name [%s] but names db does not have an entry!",
| 714 i, name );
| 715 return whefs_rc.InternalError;
| 716 }
| 717 //rc = whefs_rc.OK;
| 718 // FIXME: either remove whefs_inode::name (replaced with the name cache)
| 719 // or search for opened node here where id==H->id and use that name,
| 720 // if it's set. (The plan is to try to phase out inode.name first.).
687 } 721 }
688 rc = whefs_rc.OK; <
689 // FIXME: either remove whefs_inode::name (replaced with the name cache) <
690 // or search for opened node here where id==H->id and use that name, <
691 // if it's set. (The plan is to try to phase out inode.name first.). <
692 } 722 }
693 723
694 enum { bufSize = WHEFS_MAX_FILENAME_LENGTH+1 }; 724 enum { bufSize = WHEFS_MAX_FILENAME_LENGTH+1 };
695 unsigned char buf[bufSize] = {0}; 725 unsigned char buf[bufSize] = {0};
696 if( ! cname ) 726 if( ! cname )
113 hidden lines
810 x += whefs_sizeof_encoded_uint32; 840 x += whefs_sizeof_encoded_uint32;
811 rc = whefs_id_decode( x, &dest->first_block ); 841 rc = whefs_id_decode( x, &dest->first_block );
812 return rc; 842 return rc;
813 } 843 }
814 844

Changes to whefs_inode.h

Old (e03f2910a9761dd2) New (5d5be8cd2a102fc6)
1 #if !defined(WANDERINGHORSE_NET_WHEFS_INODE_H_INCLUDED) 1 #if !defined(WANDERINGHORSE_NET_WHEFS_INODE_H_INCLUDED)
2 #define WANDERINGHORSE_NET_WHEFS_INODE_H_INCLUDED 1 2 #define WANDERINGHORSE_NET_WHEFS_INODE_H_INCLUDED 1
3 /* 3 /*
4 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/ 4 Author: Stephan Beal (http://wanderinghorse.net/home/stephan/
5 5
453 hidden lines
459 459
460 /** 460 /**
461 Loads the name for the given inode id into the given target string 461 Loads the name for the given inode id into the given target string
462 (which may not be null). If tgt has memory allocated to it, it may 462 (which may not be null). If tgt has memory allocated to it, it may
463 be re-used (or realloc()'d) by this function, so the caller must 463 be re-used (or realloc()'d) by this function, so the caller must
464 copy it beforehand if it will be needed later. If the read-in | 464 copy it beforehand if the existing value will be needed later. If the read-in
465 string has a length of 0 and tgt->alloced is not 0 (i.e. tgt 465 string has a length of 0 and tgt->alloced is not 0 (i.e. tgt
466 already has content), then the string's memory is kept but is 466 already has content), then the string's memory is kept but is
467 zeroed out and tgt->length will be set to 0. 467 zeroed out and tgt->length will be set to 0.
468 468
469 Returns whefs_rc.OK on success. 469 Returns whefs_rc.OK on success.
> 470
> 471 If you want to ensure that no call to malloc() or realloc() is made
> 472 to expand tgt, yet still be assured of having enough memory available
> 473 to store the string, here's a trick:
> 474
> 475 @code
> 476 enum { bufSize = WHEFS_MAX_FILENAME_LENGTH + 1 };
> 477 char buf[bufSize] = {0};
> 478 whefs_string str = whefs_string_init;
> 479 str.string = buf;
> 480 str.alloced = bufSize;
> 481 int rc = whefs_inode_name_get( fs, id, &str );
> 482 assert( (str.string == buf) && "Illegal (re)alloc!" );
> 483 ...
> 484 @endcode
> 485
> 486 The internals of the lib won't allow an inode name longer than
> 487 fs->options.filename_length, which must be less than or equal to
> 488 WHEFS_MAX_FILENAME_LENGTH. We add one to the maximum buffer size in
> 489 the above code to accommodate the trailing null.
470 */ 490 */
471 int whefs_inode_name_get( whefs_fs * fs, whefs_id_type id, whefs_string * tgt ); 491 int whefs_inode_name_get( whefs_fs * fs, whefs_id_type id, whefs_string * tgt );
472 492
473 493
474 /** 494 /**
71 hidden lines
546 decoding fails then whefs_rc.ConsistencyError is returned. 566 decoding fails then whefs_rc.ConsistencyError is returned.
547 */ 567 */
548 int whefs_inode_decode( whefs_inode * dest, unsigned char const * src ); 568 int whefs_inode_decode( whefs_inode * dest, unsigned char const * src );
549 569
550 /** 570 /**
551 A functor for use with whefs_inode_foreach(). n is the current inode | 571 whefs_inode_foreach_f describes a functor for use with
| 572 whefs_inode_foreach(). n is the current inode being iterated
| 573 over. clientData is the client-determined argument passed to
| 574 whefs_inode_foreach().
552 */ 575 */
553 typedef int (*whefs_inode_foreach_f)( whefs_fs * fs, whefs_inode const * n, void * clientData ); 576 typedef int (*whefs_inode_foreach_f)( whefs_fs * fs, whefs_inode const * n, void * clientData );
554 /** 577 /**
555 | 578 whefs_inode_predicate_f describes a predicate functor for use with
| 579 whefs_inode_foreach(). n is the current inode being iterated
| 580 over. clientData is the client-determined argument passed to
| 581 whefs_inode_foreach().
556 */ 582 */
557 typedef bool (*whefs_inode_predicate_f)( whefs_fs * fs, whefs_inode const * n, void * clientData ); 583 typedef bool (*whefs_inode_predicate_f)( whefs_fs * fs, whefs_inode const * n, void * clientData );
558 584
559 /** 585 /**
560 Walks each inode in fs, starting at inode #2 (#1 is reserved for 586 Walks each inode in fs, starting at inode #2 (#1 is reserved for
561 internal use as the root node). For each node, where(node,whereData) is called. | 587 internal use as the root node). For each node, whereFunc(node,whereData) is called.
562 If it returns true then forEach(fs,n,forEachData) is called. If forEach() returns 588 If it returns true then forEach(fs,n,forEachData) is called. If forEach() returns
563 any value other than whefs_rc.OK then looping stops and that code is returned. 589 any value other than whefs_rc.OK then looping stops and that code is returned.
564 590
565 The where function may be null but forEach may not. If where is | 591 The whereFunc function may be null but forEach may not. If whereFunc is
566 null then it is treated as always returning true. The whereData and 592 null then it is treated as always returning true. The whereData and
567 forEachData pointers may be anything - they are passed as-is to the 593 forEachData pointers may be anything - they are passed as-is to the
568 where/forEach functions. | 594 whereFunc/forEach functions.
569 595
570 On success, whefs_rc.OK is returned. The other failure cases are: 596 On success, whefs_rc.OK is returned. The other failure cases are:
571 597
572 - fs or forEach are null: whefs_rc.ArgError 598 - fs or forEach are null: whefs_rc.ArgError
573 599
3 hidden lines
577 would grow exponentially as the number of opened inodes grew). Thus 603 would grow exponentially as the number of opened inodes grew). Thus
578 care must be taken with the nodes passed on to forEach, lest any 604 care must be taken with the nodes passed on to forEach, lest any
579 changes made to them get overwritten by the opened node when it 605 changes made to them get overwritten by the opened node when it
580 flushes. 606 flushes.
581 */ 607 */
582 int whefs_inode_foreach( whefs_fs * fs, whefs_inode_predicate_f where, void * whereData, whefs_inode_foreach_f forEach, void * forEachData ); | 608 int whefs_inode_foreach( whefs_fs * fs, whefs_inode_predicate_f whereFunc, void * whereData, whefs_inode_foreach_f forEach, void * forEachData );
583 609
584 #ifdef __cplusplus 610 #ifdef __cplusplus
585 } /* extern "C" */ 611 } /* extern "C" */
586 #endif 612 #endif
587 613
588 614
589 #endif /* WANDERINGHORSE_NET_WHEFS_INODE_H_INCLUDED */ 615 #endif /* WANDERINGHORSE_NET_WHEFS_INODE_H_INCLUDED */