7574b9541284e50db987a6868a8dc3351a6a3b1a
[OpenSRF.git] / src / libopensrf / osrf_cache.c
1 /*
2 Copyright (C) 2005  Georgia Public Library Service 
3 Bill Erickson <highfalutin@gmail.com>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 */
15
16 #include <opensrf/osrf_cache.h>
17
18 static struct memcached_st* _osrfCache = NULL;
19 static time_t _osrfCacheMaxSeconds = -1;
20 static char* _clean_key( const char* );
21
22 int osrfCacheInit( const char* serverStrings[], int size, time_t maxCacheSeconds ) {
23         memcached_server_st *server_pool;
24         memcached_return rc;
25
26         if( !(serverStrings && size > 0) ) return -1;
27         osrfCacheCleanup(); /* in case we've already been init-ed */
28
29         int i;
30         _osrfCache = memcached_create(NULL);
31         _osrfCacheMaxSeconds = maxCacheSeconds;
32
33         for( i = 0; i < size && serverStrings[i]; i++ ) {
34                 /* TODO: modify caller to pass a list of servers all at once */
35                 server_pool = memcached_servers_parse(serverStrings[i]);
36                 rc = memcached_server_push(_osrfCache, server_pool);
37                 if (rc != MEMCACHED_SUCCESS) {
38                         osrfLogError(OSRF_LOG_MARK,
39                                 "Failed to add memcached server: %s - %s",
40                                 serverStrings[i], memcached_strerror(_osrfCache, rc));
41                 }
42         }
43
44         return 0;
45 }
46
47 int osrfCachePutObject( const char* key, const jsonObject* obj, time_t seconds ) {
48         if( !(key && obj) ) return -1;
49         char* s = jsonObjectToJSON( obj );
50         osrfLogInternal( OSRF_LOG_MARK, "osrfCachePut(): Putting object (key=%s): %s", key, s);
51         osrfCachePutString(key, s, seconds);
52         free(s);
53         return 0;
54 }
55
56 char* _clean_key( const char* key ) {
57     char* clean_key = (char*)strdup(key);
58     char* d = clean_key;
59     char* s = clean_key;
60     do while(isspace(*s)) s++; while(*d++ = *s++);
61     return clean_key;
62 }
63
64 int osrfCachePutString( const char* key, const char* value, time_t seconds ) {
65         memcached_return rc;
66         if( !(key && value) ) return -1;
67         seconds = (seconds <= 0 || seconds > _osrfCacheMaxSeconds) ? _osrfCacheMaxSeconds : seconds;
68         osrfLogInternal( OSRF_LOG_MARK, "osrfCachePutString(): Putting string (key=%s): %s", key, value);
69
70         char* clean_key = _clean_key( key );
71
72         /* add or overwrite existing key:value pair */
73         rc = memcached_set(_osrfCache, clean_key, strlen(clean_key), value, strlen(value), seconds, 0);
74         if (rc != MEMCACHED_SUCCESS) {
75                 osrfLogError(OSRF_LOG_MARK, "Failed to cache key:value [%s]:[%s] - %s",
76                         key, value, memcached_strerror(_osrfCache, rc));
77         }
78
79         free(clean_key);
80         return 0;
81 }
82
83 jsonObject* osrfCacheGetObject( const char* key, ... ) {
84         size_t val_len;
85         uint32_t flags;
86         memcached_return rc;
87         jsonObject* obj = NULL;
88         if( key ) {
89                 VA_LIST_TO_STRING(key);
90                 char* clean_key = _clean_key( VA_BUF );
91                 const char* data = (const char*) memcached_get(_osrfCache, clean_key, strlen(clean_key), &val_len, &flags, &rc);
92                 free(clean_key);
93                 if (rc != MEMCACHED_SUCCESS) {
94                         osrfLogDebug(OSRF_LOG_MARK, "Failed to get key [%s] - %s",
95                                 VA_BUF, memcached_strerror(_osrfCache, rc));
96                 }
97                 if( data ) {
98                         osrfLogInternal( OSRF_LOG_MARK, "osrfCacheGetObject(): Returning object (key=%s): %s", VA_BUF, data);
99                         obj = jsonParse( data );
100                         return obj;
101                 }
102                 osrfLogDebug(OSRF_LOG_MARK, "No cache data exists with key %s", VA_BUF);
103         }
104         return NULL;
105 }
106
107 char* osrfCacheGetString( const char* key, ... ) {
108         size_t val_len;
109         uint32_t flags;
110         memcached_return rc;
111         if( key ) {
112                 VA_LIST_TO_STRING(key);
113                 char* clean_key = _clean_key( VA_BUF );
114                 char* data = (char*) memcached_get(_osrfCache, VA_BUF, strlen(VA_BUF), &val_len, &flags, &rc);
115                 free(clean_key);
116                 if (rc != MEMCACHED_SUCCESS) {
117                         osrfLogDebug(OSRF_LOG_MARK, "Failed to get key [%s] - %s",
118                                 VA_BUF, memcached_strerror(_osrfCache, rc));
119                 }
120                 osrfLogInternal( OSRF_LOG_MARK, "osrfCacheGetString(): Returning object (key=%s): %s", VA_BUF, data);
121                 if(!data) osrfLogDebug(OSRF_LOG_MARK, "No cache data exists with key %s", VA_BUF);
122                 return data;
123         }
124         return NULL;
125 }
126
127
128 int osrfCacheRemove( const char* key, ... ) {
129         memcached_return rc;
130         if( key ) {
131                 VA_LIST_TO_STRING(key);
132                 rc = memcached_delete(_osrfCache, VA_BUF, strlen(VA_BUF), 0 );
133                 if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED) {
134                         osrfLogDebug(OSRF_LOG_MARK, "Failed to delete key [%s] - %s",
135                                 VA_BUF, memcached_strerror(_osrfCache, rc));
136                 }
137                 return 0;
138         }
139         return -1;
140 }
141
142
143 int osrfCacheSetExpire( time_t seconds, const char* key, ... ) {
144         if( key ) {
145                 VA_LIST_TO_STRING(key);
146                 jsonObject* o = osrfCacheGetObject( VA_BUF );
147                 //osrfCacheRemove(VA_BUF);
148                 int rc = osrfCachePutObject( VA_BUF, o, seconds );
149                 jsonObjectFree(o);
150                 return rc;
151         }
152         return -1;
153 }
154
155 void osrfCacheCleanup() {
156         if(_osrfCache) {
157                 memcached_free(_osrfCache);
158         }
159 }
160
161