Repository navigation
Expand file tree
/
Copy pathdiskhash.h
More file actions
175 lines (158 loc) · 5.74 KB
/
Copy pathdiskhash.h
File metadata and controls
175 lines (158 loc) · 5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#ifndef DISKHASH_H_INCLUDE_GUARD__
#define DISKHASH_H_INCLUDE_GUARD__
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* key_maxlen is the maximum key length not including the terminator NUL, i.e.,
* diskhash will check that for every key you insert `strlen(key) <
* opts.key_maxlen`.
*
* Internally, space is allocated on 8-Byte aligned boundaries, so numbers such
* as 7, 15, 23, 31, ... (i.e., multiples of 8 minus 1 for NUL) are good
* choices for key_maxlen.
*
* object_datalen is the number of Bytes that your data elements occupy.
*/
typedef struct HashTableOpts {
size_t key_maxlen;
size_t object_datalen;
} HashTableOpts;
typedef struct HashTable {
int fd_;
const char* fname_;
void* data_;
size_t datasize_;
int flags_;
} HashTable;
/** Zero-valued options
*/
HashTableOpts dht_zero_opts(void);
/** Open a hash table file
*
* fpath is the file path
* flags are passed to call to open() and the user should read the documentation therein
*
* Values returned from dht_open must be freed with dht_free.
*
* Examples:
*
* Read-write:
*
* HashTableOpts opts;
* opts.key_maxlen = 15;
* opts.object_datalen = 8;
* char* err;
* HashTable* ht = dht_open("hashtable.dht", opts, O_RDWR|O_CREAT, &err);
*
* Read-only:
*
* char* err;
* HashTable* ht = dht_open("hashtable.dht", opts, O_RDONLY, &err);
*
* When opening an existing disk table, you can pass `{ 0, 0 }` (the return
* value of `dht_zero_opts()`) as the options, in which case the values will be
* taken from the table on disk. If you do pass values > 0, they are checked
* against the values on disk and it is an error if there is a mismatch
* (passing zero to one of the option fields and not the other is supported:
* only the non-zero field is checked).
*
* The last argument is an error output argument. If it is set to a non-NULL
* value, then the memory must be released with free(). Passing NULL is valid
* (and no error message will be produced). An error return with *err == NULL
* will mean an out-of-memory error (when dht fails to allocate memory, it does
* not try to allocate memory for an error message).
*/
HashTable* dht_open(const char* fpath, HashTableOpts opts, int flags, char**);
/** Load table into memory
*
* Return:
* 0 : success
*
* 1 : impossible operation: nothing has been done. Attempting to load a
* previously loaded table or a read/write table is impossible.
*
* 2 : error: the HashTable has been freed and must not be used.
*/
int dht_load_to_memory(HashTable*, char**);
/** Lookup a value by key
*
* If the hash table was opened in read-write mode, then the memory returned
* can be written to (the hash table itself does not inspect the values in any
* way). Writing to a read-only hashtable will probably trigger a segmentation
* fault.
*
* If the object is not found, returns NULL.
*
* Thread safety: multiple concurrent reads are perfectly safe. No guarantees
* are given whenever writing is performed. Similarly, if you write to the
* output of this function (the ht_data field), no guarantees are given.
*/
void* dht_lookup(const HashTable*, const char* key);
/** Insert a value.
*
* The hashtable must be opened in read write mode.
*
* If a value with the given key is already present in the table, then no
* action is performed and 0 is returned. If you want to overwrite that value,
* you can use `dht_lookup` and write to its output.
*
* This operation is typically O(1) amortized. However, if table is at capacity
* when dht_insert is called, then it must be grown which can be a
* time-consuming operation as all the values are copied to the newly allocated
* memory block (see dht_reserve).
*
* Errors can occur if table expansion is needed and memory cannot be
* allocated.
*
* Returns 1 if the value was inserted.
* 0 if the key was already present in the table. The hash table was
* not modified.
* -EINVAL : key is too long
* -EACCES : attempted to insert into a read-only table.
* -ENOMEM : dht_reserve failed.
*
* The last argument is an error output argument. If it is set to a non-NULL
* value, then the memory must be released with free(). Passing NULL is valid
* (and no error message will be produced). An error return with *err == NULL
* will mean an out-of-memory error (when dht fails to allocate memory, it does
* not try to allocate memory for an error message).
*/
int dht_insert(HashTable*, const char* key, const void* data, char** err);
/** Preallocate memory for the table.
*
* Calling this function if the number of elements is known apriori can improve
* performance. Additionally, if capacity exists, then dht_insert never fails.
*
* This function returns the actual capacity allocated (which may be more than
* requested, but never less). Calling dht_reserve asking for _less_ capacity
* than is currently used is a no-op.
*
* If capacity cannot be allocated, this function returns 0 (but no changes to
* the hash table are made).
*
* This function can be used to query the current capacity by passing the value
* 1 as the desired capacity.
*
* The last argument is an error output argument. If it is set to a non-NULL
* value, then the memory must be released with free(). Passing NULL is valid
* (and no error message will be produced).
*
* Attempting to call this function on a read-only table will fail (return
* value: -EACCES).
*/
size_t dht_reserve(HashTable*, size_t capacity, char** err);
/**
* Return the number of elements
*/
size_t dht_size(const HashTable*);
/** Free the hashtable and sync to disk.
*/
void dht_free(HashTable*);
/** For debug use only */
void show_ht(const HashTable*);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* DISKHASH_H_INCLUDE_GUARD__*/