Atrinik Server  4.0
cache.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
57 #include <global.h>
58 #include <plugin.h>
59 
61 static cache_struct *cache = NULL;
63 static size_t num_cache = 0;
64 
68 static int cache_compare(const void *one, const void *two)
69 {
70  const cache_struct *one_cache = one;
71  const cache_struct *two_cache = two;
72 
73  if (one == NULL) {
74  return -1;
75  } else if (two == NULL) {
76  return 1;
77  }
78 
79  if (one_cache->key < two_cache->key) {
80  return -1;
81  } else if (one_cache->key > two_cache->key) {
82  return 1;
83  } else {
84  return 0;
85  }
86 }
87 
96 {
97  cache_struct bkey;
98 
99  /* Sanity. */
100  if (!cache || !num_cache || !key) {
101  return NULL;
102  }
103 
104  /* Attempt to find the cache entry. */
105  bkey.key = key;
106  return bsearch(&bkey, cache, num_cache, sizeof(cache_struct), cache_compare);
107 }
108 
121 int cache_add(const char *key, void *ptr, uint32_t flags)
122 {
123  size_t i, ii;
124  shstr *sh_key = add_string(key);
125 
126  /* Sanity. */
127  if (!ptr || cache_find(sh_key)) {
128  free_string_shared(sh_key);
129  return 0;
130  }
131 
132  /* Increase the array's size. */
133  cache = erealloc(cache, sizeof(cache_struct) * (num_cache + 1));
134 
135  /* Now, insert the cache into the correct spot in the array. */
136  for (i = 0; i < num_cache; i++) {
137  if (cache[i].key > sh_key) {
138  break;
139  }
140  }
141 
142  /* If this is not the special case of insertion at the last point, then
143  * shift everything. */
144  for (ii = num_cache; ii > i; ii--) {
145  cache[ii] = cache[ii - 1];
146  /* Increase the ID, as it's getting moved upwards. */
147  cache[ii].id++;
148  }
149 
150  /* Store the values. */
151  cache[i].key = sh_key;
152  cache[i].ptr = ptr;
153  cache[i].flags = flags;
154  cache[i].id = i;
155  num_cache++;
156 
157  return 1;
158 }
159 
167 int cache_remove(shstr *key)
168 {
169  cache_struct *entry = cache_find(key);
170  size_t i;
171 
172  if (!entry) {
173  return 0;
174  }
175 
176  /* The entry wants global events, so send one about it being removed. */
177  if (entry->flags & CACHE_FLAG_GEVENT) {
178  trigger_global_event(GEVENT_CACHE_REMOVED, entry->ptr, (uint32_t *) & entry->flags);
179  }
180 
181  /* Does it want to be freed automatically? */
182  if (entry->flags & CACHE_FLAG_AUTOFREE) {
183  efree(entry->ptr);
184  }
185 
186  free_string_shared(entry->key);
187 
188  /* Shift the entries. */
189  for (i = entry->id + 1; i < num_cache; i++) {
190  cache[i - 1] = cache[i];
191  /* Moving downwards, decrease ID. */
192  cache[i - 1].id--;
193  }
194 
195  /* Decrease the array's size. */
196  cache = erealloc(cache, sizeof(cache_struct) * (num_cache - 1));
197  num_cache--;
198 
199  return 1;
200 }
201 
206 {
207  /* Keep removing until there's nothing left. */
208  while (num_cache) {
209  if (!cache_remove(cache[0].key)) {
210  /* Shouldn't happen... */
211  LOG(BUG, "Failed to remove cache entry.");
212  return;
213  }
214  }
215 }
216 
222 void cache_remove_by_flags(uint32_t flags)
223 {
224  size_t i;
225 
226  /* Search for matching entries, and remove them. */
227  for (i = 0; i < num_cache; i++) {
228  if (!(cache[i].flags & flags)) {
229  continue;
230  }
231 
232  if (!cache_remove(cache[i].key)) {
233  /* Shouldn't happen... */
234  LOG(BUG, "Failed to remove cache entry.");
235  continue;
236  }
237 
238  i--;
239  }
240 }
static size_t num_cache
Definition: cache.c:63
static int cache_compare(const void *one, const void *two)
Definition: cache.c:68
void cache_remove_all(void)
Definition: cache.c:205
#define CACHE_FLAG_GEVENT
Definition: global.h:503
shstr * key
Definition: global.h:509
int cache_remove(shstr *key)
Definition: cache.c:167
static cache_struct * cache
Definition: cache.c:61
size_t id
Definition: global.h:518
cache_struct * cache_find(shstr *key)
Definition: cache.c:95
#define CACHE_FLAG_AUTOFREE
Definition: global.h:501
uint32_t flags
Definition: global.h:515
int cache_add(const char *key, void *ptr, uint32_t flags)
Definition: cache.c:121
void cache_remove_by_flags(uint32_t flags)
Definition: cache.c:222
#define GEVENT_CACHE_REMOVED
Definition: plugin.h:159
void * ptr
Definition: global.h:512
void trigger_global_event(int event_type, void *parm1, void *parm2)
Definition: plugins.c:455