r24733: Add support for storing DATA_BLOBs in gencache.tdb (including torturetest).
authorGünther Deschner <gd@samba.org>
Tue, 28 Aug 2007 12:40:01 +0000 (12:40 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:30:15 +0000 (12:30 -0500)
Mimir, please have a look. DATA_BLOBs will now just show up as "DATA_BLOB"
values with "net cache list".

Guenther
(This used to be commit b8ad546d041a2a8cc85c7db8eba4d2d3b97df1a8)

source3/lib/gencache.c
source3/torture/torture.c

index c58546da9c0948051d4b34fcaf9d68811973bc22..1ee720cdfdaa8f7161da4bb9aa4baff47ccbf35a 100644 (file)
@@ -28,6 +28,8 @@
 #define TIMEOUT_LEN 12
 #define CACHE_DATA_FMT "%12u/%s"
 #define READ_CACHE_DATA_FMT_TEMPLATE "%%12u/%%%us"
+#define BLOB_TYPE "DATA_BLOB"
+#define BLOB_TYPE_LEN 9
 
 static TDB_CONTEXT *cache;
 static BOOL cache_readonly;
@@ -243,6 +245,161 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout)
        return True;
 } 
 
+/**
+ * Get existing entry from the cache file.
+ *
+ * @param keystr string that represents a key of this entry
+ * @param blob DATA_BLOB that is filled with entry's blob
+ * @param expired pointer to a BOOL that indicates whether the entry is expired
+ *
+ * @retval true when entry is successfuly fetched
+ * @retval False for failure
+ **/
+
+BOOL gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, BOOL *expired)
+{
+       TDB_DATA databuf;
+       time_t t;
+       char *blob_type;
+       unsigned char *buf = NULL;
+       BOOL ret = False;
+       fstring valstr;
+       int buflen = 0, len = 0, blob_len = 0;
+       unsigned char *blob_buf = NULL;
+
+       /* fail completely if get null pointers passed */
+       SMB_ASSERT(keystr);
+
+       if (!gencache_init()) {
+               return False;
+       }
+
+       databuf = tdb_fetch_bystring(cache, keystr);
+       if (!databuf.dptr) {
+               DEBUG(10,("Cache entry with key = %s couldn't be found\n",
+                         keystr));
+               return False;
+       }
+
+       buf = (unsigned char *)databuf.dptr;
+       buflen = databuf.dsize;
+
+       len += tdb_unpack(buf+len, buflen-len, "fB",
+                         &valstr,
+                         &blob_len, &blob_buf);
+       if (len == -1) {
+               goto out;
+       }
+
+       t = strtol(valstr, &blob_type, 10);
+
+       if (strcmp(blob_type+1, BLOB_TYPE) != 0) {
+               goto out;
+       }
+
+       DEBUG(10,("Returning %s cache entry: key = %s, "
+                 "timeout = %s", t > time(NULL) ? "valid" :
+                 "expired", keystr, ctime(&t)));
+
+       if (t <= time(NULL)) {
+               /* We're expired */
+               if (expired) {
+                       *expired = True;
+               }
+       }
+
+       if (blob) {
+               *blob = data_blob(blob_buf, blob_len);
+               if (!blob->data) {
+                       goto out;
+               }
+       }
+
+       ret = True;
+ out:
+       SAFE_FREE(blob_buf);
+       SAFE_FREE(databuf.dptr);
+
+       return ret;
+}
+
+/**
+ * Set an entry in the cache file. If there's no such
+ * one, then add it.
+ *
+ * @param keystr string that represents a key of this entry
+ * @param blob DATA_BLOB value being cached
+ * @param timeout time when the value is expired
+ *
+ * @retval true when entry is successfuly stored
+ * @retval false on failure
+ **/
+
+BOOL gencache_set_data_blob(const char *keystr, DATA_BLOB *blob, time_t timeout)
+{
+       BOOL ret = False;
+       int tdb_ret;
+       TDB_DATA databuf;
+       char *valstr = NULL;
+       unsigned char *buf = NULL;
+       int len = 0, buflen = 0;
+
+       /* fail completely if get null pointers passed */
+       SMB_ASSERT(keystr && blob);
+
+       if (!gencache_init()) {
+               return False;
+       }
+
+       if (cache_readonly) {
+               return False;
+       }
+
+       asprintf(&valstr, "%12u/%s", (int)timeout, BLOB_TYPE);
+       if (!valstr) {
+               return False;
+       }
+
+ again:
+       len = 0;
+
+       len += tdb_pack(buf+len, buflen-len, "fB",
+                       valstr,
+                       blob->length, blob->data);
+
+       if (len == -1) {
+               goto out;
+       }
+
+       if (buflen < len) {
+               SAFE_FREE(buf);
+               buf = SMB_MALLOC_ARRAY(unsigned char, len);
+               if (!buf) {
+                       goto out;
+               }
+               buflen = len;
+               goto again;
+       }
+
+       databuf = make_tdb_data(buf, len);
+
+       DEBUG(10,("Adding cache entry with key = %s; "
+                 "blob size = %d and timeout = %s"
+                 "(%d seconds %s)\n", keystr, (int)databuf.dsize,
+                 ctime(&timeout), (int)(timeout - time(NULL)),
+                 timeout > time(NULL) ? "ahead" : "in the past"));
+
+       tdb_ret = tdb_store_bystring(cache, keystr, databuf, 0);
+       if (tdb_ret == 0) {
+               ret = True;
+       }
+
+ out:
+       SAFE_FREE(valstr);
+       SAFE_FREE(buf);
+
+       return ret;
+}
 
 /**
  * Iterate through all entries which key matches to specified pattern
index 4b6d98aea842b8fb1e1322b7d6997d947015d240..6d0fc546ab4acfb8abe118ece5ea0a5d99bf19bf 100644 (file)
@@ -4820,6 +4820,7 @@ static BOOL run_local_gencache(int dummy)
 {
        char *val;
        time_t tm;
+       DATA_BLOB blob;
 
        if (!gencache_init()) {
                d_printf("%s: gencache_init() failed\n", __location__);
@@ -4861,6 +4862,46 @@ static BOOL run_local_gencache(int dummy)
                return False;
        }
 
+       blob = data_blob_string_const("bar");
+       tm = time(NULL);
+
+       if (!gencache_set_data_blob("foo", &blob, tm)) {
+               d_printf("%s: gencache_set_data_blob() failed\n", __location__);
+               return False;
+       }
+
+       data_blob_free(&blob);
+
+       if (!gencache_get_data_blob("foo", &blob, NULL)) {
+               d_printf("%s: gencache_get_data_blob() failed\n", __location__);
+               return False;
+       }
+
+       if (strcmp((const char *)blob.data, "bar") != 0) {
+               d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
+                        __location__, (const char *)blob.data, "bar");
+               data_blob_free(&blob);
+               return False;
+       }
+
+       data_blob_free(&blob);
+
+       if (!gencache_del("foo")) {
+               d_printf("%s: gencache_del() failed\n", __location__);
+               return False;
+       }
+       if (gencache_del("foo")) {
+               d_printf("%s: second gencache_del() succeeded\n",
+                        __location__);
+               return False;
+       }
+
+       if (gencache_get_data_blob("foo", &blob, NULL)) {
+               d_printf("%s: gencache_get_data_blob() on deleted entry "
+                        "succeeded\n", __location__);
+               return False;
+       }
+
        if (!gencache_shutdown()) {
                d_printf("%s: gencache_shutdown() failed\n", __location__);
                return False;