source: benchmark/io/http/filecache.cfa @ 849fb370

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 849fb370 was 0aec496, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

First attempt at webserver, no option support yet

  • Property mode set to 100644
File size: 4.0 KB
RevLine 
[0aec496]1#include "filecache.hfa"
2
3#include <assert.h>
4#include <string.h>
5
6#include <stdlib.hfa>
7
8#include <errno.h>
9#include <unistd.h>
10extern "C" {
11        #include <fcntl.h>
12        #include <ftw.h>
13}
14
15#include "options.hfa"
16
17static inline uint32_t murmur_32_scramble(uint32_t k) {
18    k *= 0xcc9e2d51;
19    k = (k << 15) | (k >> 17);
20    k *= 0x1b873593;
21    return k;
22}
23
24uint32_t murmur3_32(const uint8_t* key, size_t len, uint32_t seed)
25{
26        uint32_t h = seed;
27        uint32_t k;
28        /* Read in groups of 4. */
29        for (size_t i = len >> 2; i; i--) {
30                // Here is a source of differing results across endiannesses.
31                // A swap here has no effects on hash properties though.
32                memcpy(&k, key, sizeof(uint32_t));
33                key += sizeof(uint32_t);
34                h ^= murmur_32_scramble(k);
35                h = (h << 13) | (h >> 19);
36                h = h * 5 + 0xe6546b64;
37        }
38        /* Read the rest. */
39        k = 0;
40        for (size_t i = len & 3; i; i--) {
41                k <<= 8;
42                k |= key[i - 1];
43        }
44        // A swap is *not* necessary here because the preceding loop already
45        // places the low bytes in the low places according to whatever endianness
46        // we use. Swaps only apply when the memory is copied in a chunk.
47        h ^= murmur_32_scramble(k);
48        /* Finalize. */
49        h ^= len;
50        h ^= h >> 16;
51        h *= 0x85ebca6b;
52        h ^= h >> 13;
53        h *= 0xc2b2ae35;
54        h ^= h >> 16;
55        return h;
56}
57
58
59struct {
60        cache_line * entries;
61        size_t size;
62} file_cache;
63
64void ?{}( cache_line & this ) with( this ) {
65        file = 0p;
66        size = 0;
67        fd   = 0;
68}
69
70[int fd, size_t size] get_file( * const char file, size_t len ) {
71        uint32_t idx = murmur3_32( (const uint8_t *)file, len, options.hash_seed ) % file_cache.size;
72
73        for(int i = 0;; i++) {
74                assert( i < file_cache.size );
75                cache_line & entry = file_cache.entries[idx];
76                if( !entry.file ) return [-1, 0];
77                #if !defined(REJECT_CONFLICTS)
78                        if( strncmp(entry.file, file, len) != 0 ) {
79                                idx = (idx + 1) % file_cache.size;
80                                continue;
81                        }
82                #endif
83                return [entry.fd, entry.size];
84        }
85}
86
87int put_file( cache_line & entry ) {
88        uint32_t idx = murmur3_32( (const uint8_t *)entry.file, strlen(entry.file), options.hash_seed ) % file_cache.size;
89
90        int i = 0;
91        for(;file_cache.entries[idx].file; i++ ) {
92                assert( i < file_cache.size );
93                idx = (idx + 1) % file_cache.size;
94        }
95
96        file_cache.entries[idx] = entry;
97        return i > 0 ? 1 : 0;
98}
99
100// int ftw(const char *dirpath, int (*fn) (const char *fpath, const struct stat *sb, int typeflag), int nopenfd)
101void fill_cache( const char * path ) {
102        int ret;
103        size_t fcount = 0;
104        size_t fsize = 16;
105        cache_line * raw = 0p;
106        raw = alloc(raw, fsize, true);
107        // Step 1 get a dense array of all files
108        int walk(const char *fpath, const struct stat *sb, int typeflag) {
109                if(typeflag != FTW_F) return 0;
110
111                int idx = fcount;
112                fcount++;
113                if(fcount > fsize) {
114                        fsize *= 2;
115                        raw = alloc(raw, fsize, true);
116                }
117
118                raw[idx].file = strdup(fpath+2);
119                raw[idx].size = sb->st_size;
120                raw[idx].fd = open( fpath, options.open_flags );
121                if(raw[idx].fd < 0) {
122                        abort( "open file error: (%d) %s\n", (int)errno, strerror(errno) );
123                }
124                return 0;
125        }
126
127        ret = ftw(path, walk, 10);
128        if(ret < 0) {
129                abort( "ftw error: (%d) %s\n", (int)errno, strerror(errno) );
130        }
131
132        if(fcount == 0) {
133                abort("No file found in path %s\n", path);
134        }
135
136        // Step 2 create the cache
137        file_cache.size = options.file_cache_size > 0 ? options.file_cache_size : fsize;
138        if( file_cache.size < fcount ) {
139                abort("File Cache too small\n");
140        }
141
142        file_cache.entries = anew(fsize);
143
144        // Step 3 fill the cache
145        int conflicts = 0;
146        for(i; fcount) {
147                printf("Added file %s\n", raw[i].file);
148                conflicts += put_file( raw[i] );
149        }
150        printf("Filled cache from path \"%s\" with %zu files\n", path, fcount);
151        if( conflicts > 0 ) {
152                printf("Found %d conflicts (seed: %u)\n", conflicts, options.hash_seed);
153                #if defined(REJECT_CONFLICTS)
154                        abort("Conflicts found in the cache");
155                #endif
156        }
157
158        // Step 4 clean up
159        free( raw );
160}
161
162void close_cache() {
163        for(idx; file_cache.size) {
164                cache_line & entry = file_cache.entries[idx];
165                if( !entry.file ) continue;
166
167                int ret = close( entry.fd );
168                if(ret < 0) {
169                        abort( "close file error: (%d) %s\n", (int)errno, strerror(errno) );
170                }
171        }
172
173        delete( file_cache.entries );
174}
Note: See TracBrowser for help on using the repository browser.