diff --git a/bin/uce_fastcgi.debug.linux.bin b/bin/uce_fastcgi.debug.linux.bin index 5e5a9bb..b505e38 100755 Binary files a/bin/uce_fastcgi.debug.linux.bin and b/bin/uce_fastcgi.debug.linux.bin differ diff --git a/src/lib/functionlib.h b/src/lib/functionlib.h index 04f669b..218c3fc 100644 --- a/src/lib/functionlib.h +++ b/src/lib/functionlib.h @@ -128,6 +128,23 @@ u64 int_val(string s, u32 base = 10) return(strtoll(s.c_str(), 0, base)); } +string nibble(string& haystack, string delim) +{ + auto idx = haystack.find(delim); + if(idx == string::npos) + { + string result = haystack; + haystack = ""; + return(result); + } + else + { + string result = haystack.substr(0, idx); + haystack = haystack.substr(idx+delim.length()); + return(result); + } +} + string json_encode(DTree t) { string result = ""; diff --git a/src/lib/sys.h b/src/lib/sys.h index ca3b381..c93f7b2 100644 --- a/src/lib/sys.h +++ b/src/lib/sys.h @@ -291,12 +291,34 @@ string socket_read(u64 sockfd, u32 max_length = 1024*128, u32 timeout = 1) return(""); } +string memcache_escape_key(string key) +{ + string result; + for(auto c : key) + { + if(isspace(c)) + c = '_'; + result.append(1, c); + } + return(result); +} + +StringList memcache_escape_keys(StringList keys) +{ + StringList result; + for(auto s : keys) + { + result.push_back(memcache_escape_key(s)); + } + return(result); +} + u64 memcache_connect(string host = "127.0.0.1", short port = 11211) { return(socket_connect(host, port)); } -string memcache_get_raw(u64 connection, string command) +string memcache_command(u64 connection, string command) { socket_write(connection, command+"\r\n"); return(socket_read(connection)); // FIXME: do multi-chunk until END line is received! @@ -304,17 +326,52 @@ string memcache_get_raw(u64 connection, string command) bool memcache_set(u64 connection, string key, string value, u64 expires_in = 60*60) { - // to do: escape key string socket_write(connection, // set KEY META_DATA EXPIRY_TIME LENGTH_IN_BYTES - string("set ") + (key) + " 0 " + std::to_string(expires_in) + " " + std::to_string(value.length()) + "\r\n" + + string("set ") + memcache_escape_key(key) + " 0 " + std::to_string(expires_in) + " " + std::to_string(value.length()) + "\r\n" + value + "\r\n"); return("STORED" == trim(socket_read(connection))); } -string memcache_get(u64 connection, string key) +bool memcache_delete(u64 connection, string key) { - // to do: escape key string - auto res = memcache_get_raw(connection, string("get ")+key); - + socket_write(connection, + // set KEY META_DATA EXPIRY_TIME LENGTH_IN_BYTES + string("delete ") + memcache_escape_key(key) + "\r\n" + ); + return("DELETED" == trim(socket_read(connection))); +} + +string memcache_get(u64 connection, string key, string default_value = "") +{ + auto res = memcache_command(connection, string("get ")+memcache_escape_key(key)); + string t = nibble(res, " "); + if(t == "VALUE") + { + string key = nibble(res, " "); + string meta = nibble(res, " "); + u32 length = stoi(nibble(res, "\r\n")); + return(res.substr(0, length)); + } + return(default_value); +} + +StringMap memcache_get_multiple(u64 connection, StringList keys) +{ + StringMap result; + // to do: escape key string + auto res = memcache_command(connection, string("get ")+join(memcache_escape_keys(keys), " ")); + while(res.length() > 0) + { + string t = nibble(res, " "); + if(t == "VALUE") + { + string key = nibble(res, " "); + string meta = nibble(res, " "); + u32 length = stoi(nibble(res, "\r\n")); + result[key] = res.substr(0, length); + res = res.substr(length+2); + } + } + return(result); } diff --git a/test/memcached.uce b/test/memcached.uce index 9f8eb2c..f091dae 100644 --- a/test/memcached.uce +++ b/test/memcached.uce @@ -17,7 +17,7 @@ RENDER() auto sfd = memcache_connect(); - echo(memcache_get_raw(sfd, "stats")); + echo(memcache_command(sfd, "stats")); ?> @@ -26,7 +26,10 @@ RENDER()
memcache_set(sfd, "test_key", "test_value");
- echo(memcache_get_raw(sfd, "get test_key"));
+ memcache_set(sfd, "test_key2", "test_value2");
+ echo("raw:: "+memcache_command(sfd, "get test_key")+"\n");
+ echo("get:: "+memcache_get(sfd, "test_key")+"\n");
+ echo("multiple::\n"+var_dump(memcache_get_multiple(sfd, {"test_key", "test_key2"}))+"\n");
?>
diff --git a/todo.txt b/todo.txt
index d0f6344..55fb4fa 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,6 +1,5 @@
Library
=================================
-- memcached
- mysql
- sha1 / md5 / meow
- cache