00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025
00026 #undef DBGC_CLASS
00027 #define DBGC_CLASS DBGC_TDB
00028
00029 #define TIMEOUT_LEN 12
00030 #define CACHE_DATA_FMT "%12u/%s"
00031 #define READ_CACHE_DATA_FMT_TEMPLATE "%%12u/%%%us"
00032
00033 static TDB_CONTEXT *cache;
00034 static BOOL cache_readonly;
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 BOOL gencache_init(void)
00053 {
00054 char* cache_fname = NULL;
00055
00056
00057 if (cache) return True;
00058
00059 cache_fname = lock_path("gencache.tdb");
00060
00061 DEBUG(5, ("Opening cache file at %s\n", cache_fname));
00062
00063 cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT,
00064 O_RDWR|O_CREAT, 0644);
00065
00066 if (!cache && (errno == EACCES)) {
00067 cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDONLY, 0644);
00068 if (cache) {
00069 cache_readonly = True;
00070 DEBUG(5, ("gencache_init: Opening cache file %s read-only.\n", cache_fname));
00071 }
00072 }
00073
00074 if (!cache) {
00075 DEBUG(5, ("Attempt to open gencache.tdb has failed.\n"));
00076 return False;
00077 }
00078 return True;
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 BOOL gencache_shutdown(void)
00090 {
00091 int ret;
00092
00093 if (!cache) return False;
00094 DEBUG(5, ("Closing cache file\n"));
00095 ret = tdb_close(cache);
00096 cache = NULL;
00097 cache_readonly = False;
00098 return ret != -1;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 BOOL gencache_set(const char *keystr, const char *value, time_t timeout)
00115 {
00116 int ret;
00117 TDB_DATA keybuf, databuf;
00118 char* valstr = NULL;
00119
00120
00121 SMB_ASSERT(keystr && value);
00122
00123 if (!gencache_init()) return False;
00124
00125 if (cache_readonly) {
00126 return False;
00127 }
00128
00129 asprintf(&valstr, CACHE_DATA_FMT, (int)timeout, value);
00130 if (!valstr)
00131 return False;
00132
00133 keybuf.dptr = CONST_DISCARD(char *, keystr);
00134 keybuf.dsize = strlen(keystr)+1;
00135 databuf.dptr = valstr;
00136 databuf.dsize = strlen(valstr)+1;
00137 DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout ="
00138 " %s (%d seconds %s)\n", keybuf.dptr, value,ctime(&timeout),
00139 (int)(timeout - time(NULL)),
00140 timeout > time(NULL) ? "ahead" : "in the past"));
00141
00142 ret = tdb_store(cache, keybuf, databuf, 0);
00143 SAFE_FREE(valstr);
00144
00145 return ret == 0;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 BOOL gencache_del(const char *keystr)
00158 {
00159 int ret;
00160 TDB_DATA keybuf;
00161
00162
00163 SMB_ASSERT(keystr);
00164
00165 if (!gencache_init()) return False;
00166
00167 if (cache_readonly) {
00168 return False;
00169 }
00170
00171 keybuf.dptr = CONST_DISCARD(char *, keystr);
00172 keybuf.dsize = strlen(keystr)+1;
00173 DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr));
00174 ret = tdb_delete(cache, keybuf);
00175
00176 return ret == 0;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout)
00194 {
00195 TDB_DATA keybuf, databuf;
00196 time_t t;
00197 char *endptr;
00198
00199
00200 SMB_ASSERT(keystr);
00201
00202 if (!gencache_init()) {
00203 return False;
00204 }
00205
00206 keybuf.dptr = CONST_DISCARD(char *, keystr);
00207 keybuf.dsize = strlen(keystr)+1;
00208 databuf = tdb_fetch(cache, keybuf);
00209
00210 if (databuf.dptr == NULL) {
00211 DEBUG(10, ("Cache entry with key = %s couldn't be found\n",
00212 keystr));
00213 return False;
00214 }
00215
00216 t = strtol(databuf.dptr, &endptr, 10);
00217
00218 if ((endptr == NULL) || (*endptr != '/')) {
00219 DEBUG(2, ("Invalid gencache data format: %s\n", databuf.dptr));
00220 SAFE_FREE(databuf.dptr);
00221 return False;
00222 }
00223
00224 DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
00225 "timeout = %s", t > time(NULL) ? "valid" :
00226 "expired", keystr, endptr+1, ctime(&t)));
00227
00228 if (t <= time(NULL)) {
00229
00230
00231 tdb_delete(cache, keybuf);
00232
00233 SAFE_FREE(databuf.dptr);
00234 return False;
00235 }
00236
00237 if (valstr) {
00238 *valstr = SMB_STRDUP(endptr+1);
00239 if (*valstr == NULL) {
00240 SAFE_FREE(databuf.dptr);
00241 DEBUG(0, ("strdup failed\n"));
00242 return False;
00243 }
00244 }
00245
00246 SAFE_FREE(databuf.dptr);
00247
00248 if (timeout) {
00249 *timeout = t;
00250 }
00251
00252 return True;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 void gencache_iterate(void (*fn)(const char* key, const char *value, time_t timeout, void* dptr),
00268 void* data, const char* keystr_pattern)
00269 {
00270 TDB_LIST_NODE *node, *first_node;
00271 TDB_DATA databuf;
00272 char *keystr = NULL, *valstr = NULL, *entry = NULL;
00273 time_t timeout = 0;
00274 int status;
00275 unsigned u;
00276
00277
00278 SMB_ASSERT(fn && keystr_pattern);
00279
00280 if (!gencache_init()) return;
00281
00282 DEBUG(5, ("Searching cache keys with pattern %s\n", keystr_pattern));
00283 node = tdb_search_keys(cache, keystr_pattern);
00284 first_node = node;
00285
00286 while (node) {
00287 char *fmt;
00288
00289
00290 keystr = SMB_STRNDUP(node->node_key.dptr, node->node_key.dsize);
00291 if (!keystr) {
00292 break;
00293 }
00294
00295
00296
00297
00298
00299 databuf = tdb_fetch(cache, node->node_key);
00300 if (!databuf.dptr || databuf.dsize <= TIMEOUT_LEN) {
00301 SAFE_FREE(databuf.dptr);
00302 SAFE_FREE(keystr);
00303 node = node->next;
00304 continue;
00305 }
00306 entry = SMB_STRNDUP(databuf.dptr, databuf.dsize);
00307 if (!entry) {
00308 SAFE_FREE(databuf.dptr);
00309 SAFE_FREE(keystr);
00310 break;
00311 }
00312
00313 SAFE_FREE(databuf.dptr);
00314
00315 valstr = (char *)SMB_MALLOC(databuf.dsize + 1 - TIMEOUT_LEN);
00316 if (!valstr) {
00317 SAFE_FREE(entry);
00318 SAFE_FREE(keystr);
00319 break;
00320 }
00321
00322 asprintf(&fmt, READ_CACHE_DATA_FMT_TEMPLATE, (unsigned int)databuf.dsize - TIMEOUT_LEN);
00323 if (!fmt) {
00324 SAFE_FREE(valstr);
00325 SAFE_FREE(entry);
00326 SAFE_FREE(keystr);
00327 break;
00328 }
00329 status = sscanf(entry, fmt, &u, valstr);
00330 SAFE_FREE(fmt);
00331
00332 if ( status != 2 ) {
00333 DEBUG(0,("gencache_iterate: invalid return from sscanf %d\n",status));
00334 }
00335 timeout = u;
00336
00337 DEBUG(10, ("Calling function with arguments (key = %s, value = %s, timeout = %s)\n",
00338 keystr, valstr, ctime(&timeout)));
00339 fn(keystr, valstr, timeout, data);
00340
00341 SAFE_FREE(valstr);
00342 SAFE_FREE(entry);
00343 SAFE_FREE(keystr);
00344 node = node->next;
00345 }
00346
00347 tdb_search_list_free(first_node);
00348 }
00349
00350
00351
00352
00353
00354 int gencache_lock_entry( const char *key )
00355 {
00356 if (!gencache_init())
00357 return -1;
00358
00359 return tdb_lock_bystring(cache, key);
00360 }
00361
00362
00363
00364
00365
00366 void gencache_unlock_entry( const char *key )
00367 {
00368 if (!gencache_init())
00369 return;
00370
00371 tdb_unlock_bystring(cache, key);
00372 return;
00373 }