Memcached for Tcl
From BovineNet
Contents |
[edit] Purpose
Memcached is a pretty cool data caching service that can be used to greatly accelerate computations or operations that are repeated frequently, but do not often change. This technique is very commonly useful on websites, applications that perform expensive database queries, code compilation, or other complex calculations.
Although there is one standard Memcached server implementation, there are client libraries written by numerous authors for a variety of languages. I noticed that support for the Tcl language was noticeably missing, so I decided to try to remedy the situation.
[edit] Alternatives
In my research, I was able to find one implementation for the Tcl-based NaviServer however it was not intended for stand-alone use outside of NaviServer. Additionally, that implementation chose to completely re-implement the Memcached client code instead of relying on one of the well-established existing C libraries.
Also of interest is the Speed Tables project which is a completely independent protocol, client, and server, but has been designed specifically with Tcl users in mind. However, it may not be suitable if you need to have reads or updates done from languages other than Tcl.
[edit] Pre-requisites
I have developed this Tcl extension against Tcl version 8.5.2, though I would expect any recent version of Tcl to also work since its extension API is quite stable between versions.
This extension makes use of the libmemcached by Brian Aker, so you will need to download, compile, and install it first. This library is a robust and mature implementation that is in use by many other projects, so using it for the underlying communications is a very reasonable choice.
[edit] Installation
- Extract the tarball
- Run make to start the compilation.
There is not currently an "install" target, so you'll have to install the .so into whatever directory you use for Tcl extensions.
[edit] Sample code
Here's some sample code that uses my extension to store and retrieve a string value from a memcached server installed on localhost:
#!/usr/bin/tclsh load ./memcache[info sharedlibextension] memcache server add localhost 11211 memcache set moo "cows go moo" memcache get moo value puts "value=$value!\n";
[edit] API documentation
Here is the list of methods currently supported by this extension:
- server -- specify the hostname and port of the memcached server. Can be invoked multiple times to specify use of more than one memcached server.
- server add {hostname} {port}
- get -- retrieve the value assigned to key and store the result in dataVar, optionally retrieving the associated data length and flags into lengthVar and flagsVar respectively.
- get {key} {dataVar} {?lengthVar?} {?flagsVar?}
- add -- adds an object to the server, but only if the object does not already exist.
- add {key} {value} {?expires?} {?flags?}
- append -- places a segment of data at the end of the last piece of data stored.
- append {key} {value} {?expires?} {?flags?}
- set -- will write an object to the server. If an object already exists it will overwrite what is in the server. If the object does not exist it will be written.
- set {key} {value} {?expires?} {?flags?}
- replace -- replaces an object on the server, but only if it already exists, returning an error if it does not.
- replace {key} {value} {?expires?} {?flags?}
- delete -- delete a particular key. If an expiration is specified, then its deletion will be delayed until the specified time.
- delete {key} {?expires?}
- incr -- increment key by the specified value, and optionally return the new value in varname.
- incr {key} {value} {?varname?}
- decr -- decrement key by the specified value, and optionally return the new value in varname.
- decr {key} {value} {?varname?}
I have chosen to keep the methods to be nearly identical to those established by the NaviServer nsmemcache extension in order to simplify the transition for existing users. There are a couple of methods that I do not currently support (such as the "server delete" and "version" commands), and the "server add" method in this extension takes an additional argument to specify the port number.
[edit] TODO
This extension is very new so there are still a number of things I would like to improve in it:
- add an autoconf/configure script to improve the compilation process
- add a "make install" target
- add more extensive tests of all methods
- fix threadsafety to allow calling from a multi-threaded program