Permalink
Browse files

[Memcached] Break memcached code up into separate files. Add a setup.…

…winxed with basic build rules for memcached lib.
  • Loading branch information...
1 parent e3977b4 commit f3bb28ebdea3cc2aaebc021a1d65fc9552dd904b @Whiteknight committed Apr 14, 2012
Showing with 204 additions and 0 deletions.
  1. +4 −0 memcached/Includes.winxed
  2. +107 −0 memcached/Memcached.winxed
  3. +23 −0 memcached/ServerList.winxed
  4. +70 −0 setup.winxed
@@ -0,0 +1,4 @@
+$include "Rosella/Core.winxed";
+$include "Rosella/Net.winxed";
+
+// See http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt
View
@@ -0,0 +1,107 @@
+class ParrotStore.Memcached
+{
+ var serverlist;
+ var socketfactory;
+
+ function Memcached(var servers)
+ {
+ self.serverlist = new ParrotStore.Memcached.ServerList(servers);
+ self.socketfactory = Rosella.Net.tcp_socket_factory();
+ }
+
+ function get(string name)
+ {
+ var socket = self.__get_socket(name);
+ socket.puts("get " + name + "\r\n");
+ string status_line = socket.readline();
+ var parts = split(" ", status_line);
+ if (elements(parts) == 0) {
+ self.__cleanup_socket(socket);
+ return false, "";
+ }
+ string status = parts[0];
+ if (length(status) >= 3 && substr(status, 0, 3) == "END") {
+ self.__cleanup_socket(socket);
+ return false, "";
+ }
+ if (status == "VALUE")
+ string rename = parts[1];
+ int flags = int(parts[2]);
+ int bytes = int(parts[3]);
+ string content = socket.read(bytes);
+ self.__cleanup_socket(socket);
+ return true, content;
+ }
+
+ function autoget(string name, var f, int exptime = 0)
+ {
+ :(int have, string value) = self.get(name);
+ if (have)
+ return value;
+ value = f();
+ self.set(name, value, 0);
+ return value;
+ }
+
+ function set(string name, string value, int exptime = 0)
+ {
+ return self.__store("set", name, value, exptime);
+ }
+
+ function add(string name, string value, int exptime = 0)
+ {
+ return self.__store("add", name, value, exptime);
+ }
+
+ function replace(string name, string value, int exptime = 0)
+ {
+ return self.__store("replace", name, value, exptime);
+ }
+
+ function append(string name, string value, int exptime = 0)
+ {
+ return self.__store("append", name, value, exptime);
+ }
+
+ function prepend(string name, string value, int exptime = 0)
+ {
+ return self.__store("prepend", name, value, exptime);
+ }
+
+ function __store(string cmd, string name, value, int exptime)
+ {
+ var socket = self.__get_socket(name);
+ string header_msg = sprintf("%s %s %d %d %d\r\n", [cmd, name, 0, exptime, bytelength(value)]);
+ socket.puts(header_msg);
+ socket.puts(value);
+ socket.puts("\r\n");
+ string status_line = socket.readline();
+ self.__cleanup_socket(socket);
+ if (status_line == "STORED")
+ return true;
+ return false;
+ }
+
+ function delete(string name)
+ {
+ var socket = self.__get_socket(name);
+ socket.puts("delete " + name + "\r\n");
+ string status_line = socket.readline();
+ self.__cleanup_socket(socket);
+ if (status_line == "DELETED")
+ return true;
+ return false;
+ }
+
+ function __get_socket(string name)
+ {
+ string server = self.serverlist.select_server(name);
+ // TODO: Get the port number for the server url
+ return self.socketfactory.create(server, 11211);
+ }
+
+ function __cleanup_socket(var socket)
+ {
+ socket.close();
+ }
+}
@@ -0,0 +1,23 @@
+class ParrotStore.Memcached.ServerList
+{
+ var servers;
+ const int HASH_SEED = 1234;
+
+ function ServerList(var servers)
+ {
+ if (elements(servers) == 0)
+ Rosella.Error.error("Must provide at least one memcached server");
+ self.servers = servers;
+ }
+
+ function select_server(string key)
+ {
+ if (elements(self.servers) == 1)
+ return self.servers[0];
+ int sum = HASH_SEED;
+ for (int c in var(key))
+ sum = sum ^ c;
+ int num_servers = elements(self.servers);
+ return self.servers[sum % num_servers];
+ }
+}
View
@@ -0,0 +1,70 @@
+$include "Rosella/Core.winxed";
+$include "Rosella/Winxed.winxed";
+
+function setup_memcached(var parrotstore, var argv)
+{
+ parrotstore["winxed_winxed"]["parrotstore/memcached.winxed"] = [
+ "memcached/Includes.winxed",
+ "memcached/Memcached.winxed",
+ "memcached/ServerList.winxed"
+ ];
+ parrotstore["pir_winxed"]["parrotstore/memcached.pir"] = "parrotstore/memcached.winxed";
+ parrotstore["pbc_pir"]["parrotstore/memcached.pbc"] = "parrotstore/memcached.pir";
+}
+
+function setup_main(var parrotstore, string target, var argv)
+{
+ switch (target) {
+ case "memcached":
+ setup_memcached(parrotstore, argv);
+ break;
+ }
+}
+
+function main[main](var argv)
+{
+ int exit_code = 0;
+ string programname = argv.shift();
+ var parrotstore = __get_distutils_data();
+ try {
+ Rosella.Winxed.Distutils.winxed_setup();
+ string libtarget = argv.shift();
+ setup_main(parrotstore, libtarget, argv);
+ setup(argv, parrotstore);
+ } catch (e) {
+ say(e["message"]);
+ for (string bt in e.backtrace_strings())
+ say(bt);
+ exit_code = 1;
+ }
+ if (exit_code != 0)
+ exit(exit_code);
+}
+
+function __get_distutils_data()
+{
+ return {
+ "name" : 'ParrotStore',
+ "abstract" : 'Library for Parrot database, cache and persistance',
+ "authority" : 'http://github.com/Whiteknight',
+ "copyright_holder" : 'Andrew Whitworth',
+ "keywords" : ["memcached", "database", "persistance"],
+ "license_type" : 'Artistic License 2.0',
+ "license_uri" : 'http://www.perlfoundation.org/artistic_license_2_0',
+ "checkout_uri" : 'git://github.com/Whiteknight/ParrotStore.git',
+ "browser_uri" : 'git://github.com/Whiteknight/ParrotStore',
+ "project_uri" : 'git://github.com/Whiteknight/ParrotStore',
+ "pir_nqp-rx" : {},
+ "pir_winxed" : {},
+ "pbc_pbc" : {},
+ "pbc_pir" : {},
+ "pir_pir" : {},
+ "winxed_debug" : false,
+ "winxed_winxed" : {},
+ "inst_lib" : [],
+ "installable_pbc" : {},
+ "include_winxed" : {},
+ "manifest_includes" : ["README.md", "setup.winxed"]
+ };
+}
+

0 comments on commit f3bb28e

Please sign in to comment.