Start work on record caching - does not work!
[yaz-moved-to-github.git] / src / zoom-record-cache.c
index e90ef02..17c4ac5 100644 (file)
@@ -1,11 +1,14 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2010 Index Data
+ * Copyright (C) Index Data
  * See the file LICENSE for details.
  */
 /**
  * \file zoom-record-cache.c
  * \brief Implements ZOOM record caching
  */
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 #include <assert.h>
 #include <string.h>
@@ -13,6 +16,7 @@
 #include "zoom-p.h"
 
 #include <yaz/diagbib1.h>
+#include <yaz/record_render.h>
 #include <yaz/shptr.h>
 
 #if SHPTR
@@ -45,16 +49,6 @@ struct ZOOM_record_cache_p {
     ZOOM_record_cache next;
 };
 
-
-static int strcmp_null(const char *v1, const char *v2)
-{
-    if (!v1 && !v2)
-        return 0;
-    if (!v1 || !v2)
-        return -1;
-    return strcmp(v1, v2);
-}
-
 static size_t record_hash(int pos)
 {
     if (pos < 0)
@@ -62,23 +56,25 @@ static size_t record_hash(int pos)
     return pos % RECORD_HASH_SIZE;
 }
 
-void ZOOM_record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr, 
-                           int pos,
-                           const char *syntax, const char *elementSetName,
-                           const char *schema,
-                           Z_SRW_diagnostic *diag)
+static ZOOM_record record_cache_add(ZOOM_resultset r,
+                                    Z_NamePlusRecord *npr,
+                                    int pos,
+                                    const char *syntax,
+                                    const char *elementSetName,
+                                    const char *schema,
+                                    Z_SRW_diagnostic *diag)
 {
     ZOOM_record_cache rc = 0;
-    
+
     ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
     ZOOM_connection_put_event(r->connection, event);
 
     for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
     {
-        if (pos == rc->pos 
-            && strcmp_null(r->schema, rc->schema) == 0
-            && strcmp_null(elementSetName,rc->elementSetName) == 0
-            && strcmp_null(syntax, rc->syntax) == 0)
+        if (pos == rc->pos
+            && yaz_strcmp_null(schema, rc->schema) == 0
+            && yaz_strcmp_null(elementSetName,rc->elementSetName) == 0
+            && yaz_strcmp_null(syntax, rc->syntax) == 0)
             break;
     }
     if (!rc)
@@ -92,15 +88,17 @@ void ZOOM_record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
         rc->rec.wrbuf = 0;
 #endif
         rc->elementSetName = odr_strdup_null(r->odr, elementSetName);
-        
+
         rc->syntax = odr_strdup_null(r->odr, syntax);
-        
-        rc->schema = odr_strdup_null(r->odr, r->schema);
+
+        rc->schema = odr_strdup_null(r->odr, schema);
 
         rc->pos = pos;
         rc->next = r->record_hash[record_hash(pos)];
         r->record_hash[record_hash(pos)] = rc;
+
     }
+
     rc->rec.npr = npr;
     rc->rec.schema = odr_strdup_null(r->odr, schema);
     rc->rec.diag_set = 0;
@@ -117,30 +115,114 @@ void ZOOM_record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
                 *cp = '\0';
             rc->rec.diag_uri = odr_strdup(r->odr, diag->uri);
         }
-        rc->rec.diag_message = odr_strdup_null(r->odr, diag->message);            
+        rc->rec.diag_message = odr_strdup_null(r->odr, diag->message);
         rc->rec.diag_details = odr_strdup_null(r->odr, diag->details);
     }
+    return &rc->rec;
 }
 
+void ZOOM_record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
+                           int pos,
+                           const char *syntax, const char *elementSetName,
+                           const char *schema,
+                           Z_SRW_diagnostic *diag)
+{
+    record_cache_add(r, npr, pos, syntax, elementSetName, schema, diag);
+#if HAVE_LIBMEMCACHED_MEMCACHED_H
+    if (r->connection->mc_st &&
+        !diag && npr->which == Z_NamePlusRecord_databaseRecord &&
+        npr->u.databaseRecord->which == Z_External_octet)
+    {
+        WRBUF k = wrbuf_alloc();
+        uint32_t flags = 0;
+        memcached_return_t rc;
+        time_t expiration = 36000;
+
+        wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
+        wrbuf_printf(k, ";%d;%s;%s;%s", pos,
+                     syntax ? syntax : "",
+                     elementSetName ? elementSetName : "",
+                     schema ? schema : "");
+        rc = memcached_set(r->connection->mc_st,
+                           wrbuf_buf(k),wrbuf_len(k),
+                           npr->u.databaseRecord->u.octet_aligned->buf,
+                           npr->u.databaseRecord->u.octet_aligned->len,
+                           expiration, flags);
+
+        yaz_log(YLOG_LOG, "Store record key=%s rc=%u %s",
+                wrbuf_cstr(k), (unsigned) rc,
+                memcached_last_error_message(r->connection->mc_st));
+        wrbuf_destroy(k);
+    }
+#endif
+}
+
+
 ZOOM_record ZOOM_record_cache_lookup(ZOOM_resultset r, int pos,
                                      const char *syntax,
-                                     const char *elementSetName)
+                                     const char *elementSetName,
+                                     const char *schema)
 {
     ZOOM_record_cache rc;
-    
+
     for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
     {
         if (pos == rc->pos)
         {
-            if (strcmp_null(r->schema, rc->schema))
+            if (yaz_strcmp_null(schema, rc->schema))
                 continue;
-            if (strcmp_null(elementSetName,rc->elementSetName))
+            if (yaz_strcmp_null(elementSetName,rc->elementSetName))
                 continue;
-            if (strcmp_null(syntax, rc->syntax))
+            if (yaz_strcmp_null(syntax, rc->syntax))
                 continue;
             return &rc->rec;
         }
     }
+#if HAVE_LIBMEMCACHED_MEMCACHED_H
+    if (r->connection && r->connection->mc_st)
+    {
+        WRBUF k = wrbuf_alloc();
+        size_t v_len;
+        char *v;
+        uint32_t flags;
+        memcached_return_t rc;
+
+        wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
+        wrbuf_printf(k, ";%d;%s;%s;%s", pos,
+                     syntax ? syntax : "",
+                     elementSetName ? elementSetName : "",
+                     schema ? schema : "");
+
+        v = memcached_get(r->connection->mc_st, wrbuf_buf(k), wrbuf_len(k),
+                          &v_len, &flags, &rc);
+        wrbuf_destroy(k);
+        if (v)
+        {
+            yaz_log(YLOG_LOG, "Building record from memcached!! syntax=%s",
+                syntax);
+            Z_NamePlusRecord *npr = (Z_NamePlusRecord *)
+                odr_malloc(r->odr, sizeof(Z_NamePlusRecord));
+            npr->databaseName = 0;
+            npr->which = Z_NamePlusRecord_databaseRecord;
+            npr->u.databaseRecord = (Z_External *)
+                odr_malloc(r->odr, sizeof(Z_External));
+            npr->u.databaseRecord->descriptor = 0;
+            npr->u.databaseRecord->direct_reference =
+                syntax ?
+                yaz_string_to_oid_odr(yaz_oid_std(), CLASS_RECSYN,
+                                      syntax, r->odr) : 0;
+            npr->u.databaseRecord->indirect_reference = 0;
+            npr->u.databaseRecord->which = Z_External_octet;
+            npr->u.databaseRecord->u.octet_aligned =
+                odr_create_Odr_oct(r->odr, v, v_len);
+            free(v);
+
+            if (v)
+                return record_cache_add(r, npr, pos, syntax, elementSetName,
+                                        schema, 0);
+        }
+    }
+#endif
     return 0;
 }
 
@@ -156,7 +238,7 @@ ZOOM_API(ZOOM_record)
     if (!z_NamePlusRecord(odr_enc, &srec->npr, 0, 0))
         return 0;
     buf = odr_getbuf(odr_enc, &size, 0);
-    
+
     nrec = (ZOOM_record) xmalloc(sizeof(*nrec));
     nrec->odr = odr_createmem(ODR_DECODE);
 #if SHPTR
@@ -166,7 +248,7 @@ ZOOM_API(ZOOM_record)
 #endif
     odr_setbuf(nrec->odr, buf, size, 0);
     z_NamePlusRecord(nrec->odr, &nrec->npr, 0, 0);
-    
+
     nrec->schema = odr_strdup_null(nrec->odr, srec->schema);
     nrec->diag_uri = odr_strdup_null(nrec->odr, srec->diag_uri);
     nrec->diag_message = odr_strdup_null(nrec->odr, srec->diag_message);
@@ -213,10 +295,10 @@ ZOOM_API(const char *)
     ZOOM_record_get(ZOOM_record rec, const char *type_spec, int *len)
 {
     WRBUF wrbuf;
-    
+
     if (len)
         *len = 0; /* default return */
-        
+
     if (!rec || !rec->npr)
         return 0;
 
@@ -232,7 +314,7 @@ ZOOM_API(const char *)
         rec->wrbuf = wrbuf_alloc();
     wrbuf = rec->wrbuf;
 #endif
-    return ZOOM_npr_format(rec->npr, rec->schema, wrbuf, type_spec, len);
+    return yaz_record_render(rec->npr, rec->schema, wrbuf, type_spec, len);
 }
 
 ZOOM_API(int)
@@ -240,7 +322,7 @@ ZOOM_API(int)
                       const char **addinfo, const char **diagset)
 {
     Z_NamePlusRecord *npr;
-    
+
     if (!rec)
         return 0;
 
@@ -265,7 +347,7 @@ ZOOM_API(int)
         {
             Z_DefaultDiagFormat *ddf = diag_rec->u.defaultFormat;
             oid_class oclass;
-    
+
             error = *ddf->condition;
             switch (ddf->which)
             {