memcached
Portable Memcached client implementing the text (ASCII) protocol. This
library uses the sockets library and supports all backend Prolog
systems supported by that library: ECLiPSe, GNU Prolog, SICStus Prolog,
SWI-Prolog, Trealla Prolog, and XVM.
API documentation
Open the ../../apis/library_index.html#memcached link in a web browser.
Loading
To load this library, load the loader.lgt file:
| ?- logtalk_load(memcached(loader)).
Testing
To test this library predicates, load the tester.lgt file:
| ?- logtalk_load(memcached(tester)).
Note: Tests require a running Memcached server on localhost port
11211 (the default). To install and start Memcached:
On macOS:
$ brew install memcached
$ memcached -d
On Linux (Debian/Ubuntu):
$ sudo apt-get install memcached
$ sudo systemctl start memcached
On Linux (RHEL/Fedora):
$ sudo dnf install memcached
$ sudo systemctl start memcached
Protocol Version
This library implements the Memcached text (ASCII) protocol as documented in the official specification:
https://github.com/memcached/memcached/blob/master/doc/protocol.txt
The text protocol is the standard protocol supported by all Memcached
clients and servers. All commands use simple text lines terminated by
\r\n.
Features
Full storage command support:
set,add,replace,append,prepend,casRetrieval commands:
get,gets(with CAS token), multi-get,gat,gatsKey deletion with
deleteAtomic increment/decrement with
incr/decrItem expiration management with
touch,gat,gatsServer management:
flush_all,version,statsGraceful disconnect with
quitProper handling of all protocol response codes
Usage
Connecting to a Memcached server
Basic connection to localhost on the default port (11211):
?- memcached::connect(localhost, Connection).
Connection to a specific host and port:
?- memcached::connect('cache.example.com', 11211, Connection).
Storing data
Store a value unconditionally:
?- memcached::set(Connection, my_key, 'Hello, World!').
Store with flags and expiration time (in seconds):
?- memcached::set(Connection, my_key, 'Hello!', 0, 3600).
Store only if the key does not exist:
?- memcached::add(Connection, new_key, 'New value', 0, 60).
Store only if the key already exists:
?- memcached::replace(Connection, existing_key, 'Updated', 0, 60).
Append data to an existing value:
?- memcached::append(Connection, my_key, ' World!').
Prepend data to an existing value:
?- memcached::prepend(Connection, my_key, 'Hello ').
Retrieving data
Get a value by key:
?- memcached::get(Connection, my_key, Value).
Get a value with flags:
?- memcached::get(Connection, my_key, Value, Flags).
Get a value with CAS token (for optimistic locking):
?- memcached::gets(Connection, my_key, Value, CasUnique).
Get multiple keys at once:
?- memcached::mget(Connection, [key1, key2, key3], Items).
Check-and-Set (CAS)
CAS provides optimistic locking for cache updates:
?- memcached::gets(Connection, my_key, Value, CasUnique),
% ... process value ...
memcached::cas(Connection, my_key, 'New value', 0, 60, CasUnique).
If another client modifies the value between gets and cas, the
cas command will throw error(memcached_error(exists), _).
Deleting data
Delete an item by key:
?- memcached::delete(Connection, my_key).
Fails if the key does not exist.
Increment/Decrement
Atomically increment a numeric value:
?- memcached::set(Connection, counter, '100'),
memcached::incr(Connection, counter, 5, NewValue).
% NewValue = 105
Atomically decrement a numeric value:
?- memcached::decr(Connection, counter, 3, NewValue).
% NewValue = 102
Note: The item must already exist and contain a decimal representation of a 64-bit unsigned integer. Decrementing below 0 yields 0.
Touch and Get-and-Touch
Update expiration time without fetching:
?- memcached::touch(Connection, my_key, 3600).
Fetch and update expiration time in one operation:
?- memcached::gat(Connection, my_key, 3600, Value).
Fetch with CAS and update expiration:
?- memcached::gats(Connection, my_key, 3600, Value, CasUnique).
Server management
Invalidate all items:
?- memcached::flush_all(Connection).
Invalidate all items after a delay (in seconds):
?- memcached::flush_all(Connection, 30).
Get server version:
?- memcached::version(Connection, Version).
Get server statistics:
?- memcached::stats(Connection, Stats).
Get specific statistics:
?- memcached::stats(Connection, items, Stats).
Disconnecting
?- memcached::disconnect(Connection).
API Summary
Connection management
connect(+Host, +Port, -Connection)- Connect to serverconnect(+Host, -Connection)- Connect to server on default portdisconnect(+Connection)- Disconnect from server
Storage commands
set(+Connection, +Key, +Value, +Flags, +ExpTime)- Store unconditionallyset(+Connection, +Key, +Value)- Store with default flags and no expirationadd(+Connection, +Key, +Value, +Flags, +ExpTime)- Store only if newreplace(+Connection, +Key, +Value, +Flags, +ExpTime)- Store only if existsappend(+Connection, +Key, +Value)- Append to existing valueprepend(+Connection, +Key, +Value)- Prepend to existing valuecas(+Connection, +Key, +Value, +Flags, +ExpTime, +CasUnique)- Check-and-set
Retrieval commands
get(+Connection, +Key, -Value)- Get valueget(+Connection, +Key, -Value, -Flags)- Get value and flagsgets(+Connection, +Key, -Value, -CasUnique)- Get with CAS tokengets(+Connection, +Key, -Value, -Flags, -CasUnique)- Get with flags and CASmget(+Connection, +Keys, -Items)- Multi-get
Deletion
delete(+Connection, +Key)- Delete item
Increment/Decrement
incr(+Connection, +Key, +Amount, -NewValue)- Incrementdecr(+Connection, +Key, +Amount, -NewValue)- Decrement
Touch
touch(+Connection, +Key, +ExpTime)- Update expirationgat(+Connection, +Key, +ExpTime, -Value)- Get and touchgats(+Connection, +Key, +ExpTime, -Value, -CasUnique)- Get-and-touch with CAS
Server commands
flush_all(+Connection)- Invalidate all itemsflush_all(+Connection, +Delay)- Invalidate all items after delayversion(+Connection, -Version)- Get server versionstats(+Connection, -Stats)- Get general statisticsstats(+Connection, +Argument, -Stats)- Get specific statistics
Error Handling
Most predicates throw error(memcached_error(Reason), Context) on
failure. Common error reasons:
connection_failed- Could not establish TCP connectionnot_stored- Storage condition not met (e.g.addon existing key)exists- CAS conflict (item was modified by another client)not_found- CAS on non-existent keyserver_error(Message)- Server returned an error
Retrieval predicates (get, gets, gat, gats) fail (rather
than throw) when the requested key is not found. The delete,
incr, decr, and touch predicates also fail when the key is
not found.
Key Format
Keys are atoms up to 250 characters
Keys must not contain control characters or whitespace
Keys are case-sensitive
Expiration Times
0means the item never expires (may still be evicted by LRU)Values up to 2592000 (30 days) are treated as relative seconds
Values over 2592000 are treated as absolute Unix timestamps
Negative values cause immediate expiration