You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

kvstorage.h 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /* Copyright (c) 2011, Vsevolod Stakhov
  2. * All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above copyright
  9. * notice, this list of conditions and the following disclaimer in the
  10. * documentation and/or other materials provided with the distribution.
  11. *
  12. * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
  13. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  14. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
  16. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  17. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  18. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  19. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  21. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. #ifndef KVSTORAGE_H_
  24. #define KVSTORAGE_H_
  25. #include "config.h"
  26. struct rspamd_kv_cache;
  27. struct rspamd_kv_backend;
  28. struct rspamd_kv_storage;
  29. struct rspamd_kv_expire;
  30. struct rspamd_kv_element;
  31. /* Locking definitions */
  32. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  33. #define RW_R_LOCK g_rw_lock_reader_lock
  34. #define RW_R_UNLOCK g_rw_lock_reader_unlock
  35. #define RW_W_LOCK g_rw_lock_writer_lock
  36. #define RW_W_UNLOCK g_rw_lock_writer_unlock
  37. #else
  38. #define RW_R_LOCK g_static_rw_lock_reader_lock
  39. #define RW_R_UNLOCK g_static_rw_lock_reader_unlock
  40. #define RW_W_LOCK g_static_rw_lock_writer_lock
  41. #define RW_W_UNLOCK g_static_rw_lock_writer_unlock
  42. #endif
  43. /* Callbacks for cache */
  44. typedef void (*cache_init)(struct rspamd_kv_cache *cache);
  45. typedef struct rspamd_kv_element * (*cache_insert)(struct rspamd_kv_cache *cache,
  46. gpointer key, guint keylen, gpointer value, gsize len);
  47. typedef gboolean (*cache_replace)(struct rspamd_kv_cache *cache, gpointer key,
  48. guint keylen,
  49. struct rspamd_kv_element *elt);
  50. typedef struct rspamd_kv_element * (*cache_lookup)(struct rspamd_kv_cache *cache,
  51. gpointer key, guint keylen);
  52. typedef struct rspamd_kv_element * (*cache_delete)(struct rspamd_kv_cache *cache,
  53. gpointer key, guint keylen);
  54. typedef void (*cache_steal)(struct rspamd_kv_cache *cache,
  55. struct rspamd_kv_element * elt);
  56. typedef void (*cache_destroy)(struct rspamd_kv_cache *cache);
  57. /* Callbacks for backend */
  58. typedef void (*backend_init)(struct rspamd_kv_backend *backend);
  59. typedef gboolean (*backend_insert)(struct rspamd_kv_backend *backend,
  60. gpointer key, guint keylen,
  61. struct rspamd_kv_element *elt);
  62. typedef gboolean (*backend_replace)(struct rspamd_kv_backend *backend,
  63. gpointer key, guint keylen,
  64. struct rspamd_kv_element *elt);
  65. typedef struct rspamd_kv_element * (*backend_lookup)(struct rspamd_kv_backend *
  66. backend, gpointer key,
  67. guint keylen);
  68. typedef void (*backend_delete)(struct rspamd_kv_backend *backend, gpointer key,
  69. guint keylen);
  70. typedef gboolean (*backend_sync)(struct rspamd_kv_backend *backend);
  71. typedef gboolean (*backend_incref)(struct rspamd_kv_backend *backend,
  72. gpointer key, guint keylen);
  73. typedef void (*backend_destroy)(struct rspamd_kv_backend *backend);
  74. /* Callbacks for expire */
  75. typedef void (*expire_init)(struct rspamd_kv_expire *expire);
  76. typedef void (*expire_insert)(struct rspamd_kv_expire *expire,
  77. struct rspamd_kv_element *elt);
  78. typedef void (*expire_delete)(struct rspamd_kv_expire *expire,
  79. struct rspamd_kv_element *elt);
  80. typedef gboolean (*expire_step)(struct rspamd_kv_expire *expire,
  81. struct rspamd_kv_storage *storage,
  82. time_t now, gboolean forced);
  83. typedef void (*expire_destroy)(struct rspamd_kv_expire *expire);
  84. /* Flags of element */
  85. enum rspamd_kv_flags {
  86. KV_ELT_ARRAY = 1 << 0,
  87. KV_ELT_PERSISTENT = 1 << 1,
  88. KV_ELT_DIRTY = 1 << 2,
  89. KV_ELT_OUSTED = 1 << 3,
  90. KV_ELT_NEED_FREE = 1 << 4,
  91. KV_ELT_INTEGER = 1 << 5,
  92. KV_ELT_NEED_INSERT = 1 << 6,
  93. KV_ELT_NEED_EXPIRE = 1 << 7
  94. };
  95. #define ELT_DATA(elt) (gchar *)(elt)->data + (elt)->keylen + 1
  96. #define ELT_LONG(elt) *((glong *)((elt)->data + (elt)->keylen + 1))
  97. #define ELT_KEY(elt) (gchar *)(elt)->data
  98. #define ELT_SIZE(elt) elt->size + sizeof(struct rspamd_kv_element) + \
  99. elt->keylen + 1
  100. /* Common structures description */
  101. struct rspamd_kv_element {
  102. time_t age; /*< age of element */
  103. guint32 expire; /*< expire of element */
  104. gint flags; /*< element flags */
  105. gsize size; /*< size of element */
  106. TAILQ_ENTRY (rspamd_kv_element) entry; /*< list entry */
  107. guint keylen; /*< length of key */
  108. gpointer p; /*< pointer to data */
  109. gchar data[1]; /*< expandable data */
  110. };
  111. struct rspamd_kv_cache {
  112. cache_init init_func; /*< this callback is called on kv storage initialization */
  113. cache_insert insert_func; /*< this callback is called when element is inserted */
  114. cache_replace replace_func; /*< this callback is called when element is replace */
  115. cache_lookup lookup_func; /*< this callback is used for lookup of element */
  116. cache_delete delete_func; /*< this callback is called when an element is deleted */
  117. cache_steal steal_func; /*< this callback is used to replace duplicates in cache */
  118. cache_destroy destroy_func; /*< this callback is used for destroying all elements inside cache */
  119. };
  120. struct rspamd_kv_backend {
  121. backend_init init_func; /*< this callback is called on kv storage initialization */
  122. backend_insert insert_func; /*< this callback is called when element is inserted */
  123. backend_replace replace_func; /*< this callback is called when element is replaced */
  124. backend_lookup lookup_func; /*< this callback is used for lookup of element */
  125. backend_delete delete_func; /*< this callback is called when an element is deleted */
  126. backend_sync sync_func; /*< this callback is called when backend need to be synced */
  127. backend_incref incref_func; /*< this callback is called when element must be ref'd */
  128. backend_destroy destroy_func; /*< this callback is used for destroying all elements inside backend */
  129. };
  130. struct rspamd_kv_expire {
  131. expire_init init_func; /*< this callback is called on kv storage initialization */
  132. expire_insert insert_func; /*< this callback is called when element is inserted */
  133. expire_step step_func; /*< this callback is used when cache is full */
  134. expire_delete delete_func; /*< this callback is called when an element is deleted */
  135. expire_destroy destroy_func; /*< this callback is used for destroying all elements inside expire */
  136. };
  137. /* Main kv storage structure */
  138. struct rspamd_kv_storage {
  139. struct rspamd_kv_cache *cache;
  140. struct rspamd_kv_backend *backend;
  141. struct rspamd_kv_expire *expire;
  142. gsize elts; /*< current elements count in a storage */
  143. gsize max_elts; /*< maximum number of elements in a storage */
  144. gsize memory; /*< memory eaten */
  145. gsize max_memory; /*< memory limit */
  146. gint id; /* char ID */
  147. gchar *name; /* numeric ID */
  148. gboolean no_overwrite; /* do not overwrite data with the same keys */
  149. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  150. GRWLock rwlock; /* rwlock in new glib */
  151. #else
  152. GStaticRWLock rwlock; /* rwlock for threaded access */
  153. #endif
  154. };
  155. /** Create new kv storage */
  156. struct rspamd_kv_storage * rspamd_kv_storage_new (gint id, const gchar *name,
  157. struct rspamd_kv_cache *cache, struct rspamd_kv_backend *backend,
  158. struct rspamd_kv_expire *expire,
  159. gsize max_elts, gsize max_memory, gboolean no_overwrite);
  160. /** Insert new element to the kv storage */
  161. gboolean rspamd_kv_storage_insert (struct rspamd_kv_storage *storage,
  162. gpointer key,
  163. guint keylen,
  164. gpointer data,
  165. gsize len,
  166. gint flags,
  167. guint expire);
  168. /** Insert element only in cache */
  169. gboolean rspamd_kv_storage_insert_cache (struct rspamd_kv_storage *storage,
  170. gpointer key,
  171. guint keylen,
  172. gpointer data,
  173. gsize len,
  174. gint flags,
  175. guint expire,
  176. struct rspamd_kv_element **pelt);
  177. /** Replace an element in the kv storage */
  178. gboolean rspamd_kv_storage_replace (struct rspamd_kv_storage *storage,
  179. gpointer key,
  180. guint keylen,
  181. struct rspamd_kv_element *elt);
  182. /** Increment value in kvstorage */
  183. gboolean rspamd_kv_storage_increment (struct rspamd_kv_storage *storage,
  184. gpointer key,
  185. guint keylen,
  186. glong *value);
  187. /** Lookup an element inside kv storage */
  188. struct rspamd_kv_element * rspamd_kv_storage_lookup (
  189. struct rspamd_kv_storage *storage,
  190. gpointer key,
  191. guint keylen,
  192. time_t now);
  193. /** Expire an element from kv storage */
  194. struct rspamd_kv_element * rspamd_kv_storage_delete (
  195. struct rspamd_kv_storage *storage,
  196. gpointer key,
  197. guint keylen);
  198. /** Destroy kv storage */
  199. void rspamd_kv_storage_destroy (struct rspamd_kv_storage *storage);
  200. /** Insert array */
  201. gboolean rspamd_kv_storage_insert_array (struct rspamd_kv_storage *storage,
  202. gpointer key,
  203. guint keylen,
  204. guint elt_size,
  205. gpointer data,
  206. gsize len,
  207. gint flags,
  208. guint expire);
  209. /** Set element inside array */
  210. gboolean rspamd_kv_storage_set_array (struct rspamd_kv_storage *storage,
  211. gpointer key,
  212. guint keylen,
  213. guint elt_num,
  214. gpointer data,
  215. gsize len,
  216. time_t now);
  217. /** Get element inside array */
  218. gboolean rspamd_kv_storage_get_array (struct rspamd_kv_storage *storage,
  219. gpointer key,
  220. guint keylen,
  221. guint elt_num,
  222. gpointer *data,
  223. gsize *len,
  224. time_t now);
  225. /* Hash table functions */
  226. guint kv_elt_hash_func (gconstpointer e);
  227. gboolean kv_elt_compare_func (gconstpointer e1, gconstpointer e2);
  228. /**
  229. * LRU expire
  230. */
  231. struct rspamd_kv_expire * rspamd_lru_expire_new (void);
  232. /**
  233. * Ordinary hash
  234. */
  235. struct rspamd_kv_cache * rspamd_kv_hash_new (void);
  236. /**
  237. * Radix tree
  238. */
  239. struct rspamd_kv_cache * rspamd_kv_radix_new (void);
  240. #ifdef WITH_JUDY
  241. /**
  242. * Judy tree
  243. */
  244. struct rspamd_kv_cache * rspamd_kv_judy_new (void);
  245. #endif
  246. #endif /* KVSTORAGE_H_ */