aboutsummaryrefslogtreecommitdiffstats
path: root/src/anydb.h
blob: 64f86bdb9f69201dc128a4a917c52196036e2f91 (plain)
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
/*
 * Copyright (C) 2018 "IoT.bzh"
 * Author José Bollo <jose.bollo@iot.bzh>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once
/******************************************************************************/
/******************************************************************************/
/* HIGH LEVEL ABSTRACTION OF THE DATABASES                                    */
/******************************************************************************/
/******************************************************************************/

/**
 * An index is an integer
 */
typedef uint32_t anydb_idx_t;

/*
 * Definition of some predefined indexes
 */

/** The invalid index */
#define AnyIdx_Invalid	((anydb_idx_t)0xffffffffu)

/** The index for ANY */
#define AnyIdx_Any	((anydb_idx_t)0xfffffffeu)

/** The index for WIDE */
#define AnyIdx_Wide	((anydb_idx_t)0xfffffffdu)

/** The index for NONE */
#define AnyIdx_None	((anydb_idx_t)0xfffffffcu)

/** The maximum value for indexes */
#define AnyIdx_Max	((anydb_idx_t)0xfffffff7u)

/**
 * A key is a set of index
 */
struct anydb_key {
	/** client string id */
	anydb_idx_t client;

	/** session string id */
	anydb_idx_t session;

	/** user string id */
	anydb_idx_t user;

	/** permission string id */
	anydb_idx_t permission;
};
typedef struct anydb_key anydb_key_t;

/**
 * A rule is a set of 32 bits integers
 */
struct anydb_value
{
	/** value string id */
	anydb_idx_t value;

	/**  expiration */
	time_t expire;
};
typedef struct anydb_value anydb_value_t;

/**
 * Operation of the transaction
 */
enum anydb_transaction
{
	/**
	 * Operation: Start a cancelable transaction
	 */
	Anydb_Transaction_Start = 0,

	/**
	 * Operation: Terminate the started transaction and commit its changes
	 */
	Anydb_Transaction_Commit = 1,

	/**
	 * Operation: Terminate the started transaction and cancel its changes
	 */
	Anydb_Transaction_Cancel = 2
};
typedef enum anydb_transaction anydb_transaction_t;

/**
 * Actions to perform in response to anydb_applycb_t callbacks.
 */
enum anydb_action
{
	/** Continue to apply with the next element of the database */
	Anydb_Action_Continue = 0,

	/** Stop to apply */
	Anydb_Action_Stop = 1,

	/** Update the current element (implicitly, also continue) */
	Anydb_Action_Update = 2,

	/** Remove the current element (implicitly, also continue) */
	Anydb_Action_Remove = 4,

	/** Update the current element and stop to apply */
	Anydb_Action_Update_And_Stop = Anydb_Action_Update | Anydb_Action_Stop,

	/** Update the current element and continue to apply */
	Anydb_Action_Update_And_Continue = Anydb_Action_Update | Anydb_Action_Continue,

	/** Remove the current element and stop to apply */
	Anydb_Action_Remove_And_Stop = Anydb_Action_Remove | Anydb_Action_Stop,

	/** Remove the current element and continue to apply */
	Anydb_Action_Remove_And_Continue = Anydb_Action_Remove | Anydb_Action_Continue
};
typedef enum anydb_action anydb_action_t;

/**
 * Callback of apply method. This callback is called for any item of
 * the database and it tells through its return what the anydb has
 * to do: see anydb_action_t.
 * The 'closure' is the closure given by the caller of 'apply' method.
 * 'key' is the iterated key of the anydb. It can not be changed.
 * 'value' is the value stored in the database for the key.
 */
typedef anydb_action_t anydb_applycb_t(void *closure, const anydb_key_t *key, anydb_value_t *value);

/**
 * Interface to any database implementation
 */
struct anydb_itf
{
	/**
	 * Get the index of the 'name' in 'idx'. If the name is found
	 * then its index is returned. If the name is not found, the
	 * database backend has to create it if 'create' is not zero.
	 * 'clodb' is the database's closure.
	 * Returns 0 in case of success (*idx filled with the index)
	 * or return a negative error code in -errno like form.
	 */
	int (*index)(void *clodb, anydb_idx_t *idx, const char *name, bool create);

	/**
	 * Get the string for the index 'idx'. idx MUST be valid.
	 * 'clodb' is the database's closure.
	 */
	const char *(*string)(void *clodb, anydb_idx_t idx);

	/**
	 * Start, Commit or Cancel a cancellable transaction. The operation
	 * to perform is given by 'op'.
	 * 'clodb' is the database's closure.
	 * Returns 0 in case of success or return a negative error code
	 * in -errno like form.
	 */
	int (*transaction)(void *clodb, anydb_transaction_t atomic_op);

	/**
	 * Iterate over the database items and apply the operator 'oper'.
	 * The callback operator 'oper' is called with the given 'closure'
	 * and the key and value for the item. It can modify or delete the item.
	 * 'clodb' is the database's closure.
	 */
	void (*apply)(void *clodb, anydb_applycb_t *oper, void *closure);

	/**
	 * Add the item of 'key' and 'value'.
	 * 'clodb' is the database's closure.
	 * Returns 0 in case of success or return a negative error code
	 * in -errno like form.
	 */
	int (*add)(void *clodb, const anydb_key_t *key, const anydb_value_t *value);

	/**
	 * Garbage collection of unused items.
	 * 'clodb' is the database's closure.
	 */
	void (*gc)(void *clodb);

	/**
	 * Synchronize the database and its longterm support (file)
	 * 'clodb' is the database's closure.
	 * Returns 0 in case of success or return a negative error code
	 * in -errno like form.
	 */
	int (*sync)(void *clodb);

	/**
	 * Destroys the database
	 * 'clodb' is the database's closure.
	 */
	void (*destroy)(void *clodb);
};
typedef struct anydb_itf anydb_itf_t;

/**
 * The structure for abstracting backend databases
 */
struct anydb
{
	/** the closure */
	void *clodb;

	/** the implementation methods */
	anydb_itf_t itf;
};
typedef struct anydb anydb_t;

/**
 * Manage atomicity of modifications by enabling cancellation
 * @param db database to manage
 * @param oper operation to perform
 * @return 0 in case of success or a negative error code in -errno like form.
 */
extern
int
anydb_transaction(
	anydb_t *db,
	anydb_transaction_t oper
);

/**
 * Enumerate items of the database matching the given key
 * @param db database to enumerate
 * @param callback callback function receiving the item that matches the key
 * @param closure closure for the callback
 * @param key key to restrict enumeration can't be NULL
 */
extern
void
anydb_for_all(
	anydb_t *db,
	void (*callback)(
		void *closure,
		const data_key_t *key,
		const data_value_t *value),
	void *closure,
	const data_key_t *key
);

/**
 * Drop any rule that matches the key
 * @param db database to modify
 * @param key the key that select items to be dropped
 */
extern
void
anydb_drop(
	anydb_t *db,
	const data_key_t *key
);

/**
 * Set the rule described by key and value
 * @param db the database to set
 * @param key the key of the rule
 * @param value the value of the rule
 * @return 0 on success or a negative error code
 */
extern
int
anydb_set(
	anydb_t *db,
	const data_key_t *key,
	const data_value_t *value
);

/**
 * Test a rule and return its score and the value
 * @param db the database
 * @param key key to be matched by rules
 * @param value value found for the key, filled only if a key matched
 * @return 0 if no rule matched or a positive integer when the rule matched
 * The higher the integer is, the more accurate is the rule found.
 */
extern
unsigned
anydb_test(
	anydb_t *db,
	const data_key_t *key,
	data_value_t *value
);

/**
 * Drop any expired rule
 * @param db the database to clean
 */
extern
void
anydb_cleanup(
	anydb_t *db
);

/**
 * Is the database empty?
 * @param db the database to test
 * @return true if the database is empty or otherwise false
 */
extern
bool
anydb_is_empty(
	anydb_t *db
);

/**
 * Synchronize the database if needed
 * @param db the database to
 * @return 0 on success or a negative -errno like code
 */
extern
int
anydb_sync(
	anydb_t *db
);

/**
 * Destroy the database
 * @param db the database to destroy
 */
extern
void
anydb_destroy(
	anydb_t *db
);