public class MemcachedStorageService extends net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent implements StorageService
https://code.google.com/p/memcached/wiki/NewProgrammingTricks#Namespacing
This storage service supports arbitrary-length context names and keys despite the 250-byte limit on memcached keys. Keys whose length is greater than 250 bytes are hashed using the SHA-512 algorithm and hex encoded to produce a 128-character key that is stored in memcached. Collisions are avoided irrespective of hashing by using the memcached add operation on all create operations which guarantees that an entry is created if and only if a key of the same value does not already exist. Note that context names and keys are assumed to have single-byte encodings in UTF-8 (i.e. ASCII characters) such that key lengths are equal to their size in bytes. Hashed keys naturally meet this requirement.
An optional context key-tracking feature is available to support updateContextExpiration(String, Long)
.
Key tracking is disabled by default, but can be enabled by setting the enableContextKeyTracking
parameter in the MemcachedStorageService(net.spy.memcached.MemcachedClient, int, boolean)
constructor.
While there is modest performance impact for create and delete operations, the feature limits the number of keys
per context. With the default 1M memcached slab size, in the worst case 4180 keys are permitted per context.
In many if not most situations the value is easily double that. The limitation can be overcome by increasing the
slab size, which decreases overall cache memory consumption efficiency. When key tracking is disabled, there is no
limit on the number of keys per context other than overall cache capacity.
Limitations and requirements
deleteWithVersion(long, String, String)
and deleteWithVersion(long, Object)
will throw runtime errors under the ASCII protocol.Modifier and Type | Field and Description |
---|---|
protected static String |
CTX_KEY_BLACKLIST_SUFFIX
Key suffix for entry that contains a list of blacklisted (deleted) context keys.
|
private static String |
CTX_KEY_LIST_DELIMITER
Delimiter of items in the context key list.
|
protected static String |
CTX_KEY_LIST_SUFFIX
Key suffix for entry that contains a list of context keys.
|
private Logger |
logger
Logger instance.
|
private static int |
MAX_KEY_LENGTH
Maximum length in bytes of memcached keys.
|
private net.spy.memcached.MemcachedClient |
memcacheClient
Memcached client instance.
|
private int |
operationTimeout
Memcached asynchronous operation timeout in seconds.
|
private MemcachedStorageCapabilities |
storageCapabilities
Invariant storage capabilities.
|
private net.spy.memcached.transcoders.Transcoder<MemcachedStorageRecord> |
storageRecordTranscoder
Handles conversion of
MemcachedStorageRecord to bytes and vice versa. |
private net.spy.memcached.transcoders.Transcoder<String> |
stringTranscoder
Handles conversion of strings to bytes and vice versa.
|
private boolean |
trackContextKeys
Flag that controls context key tracking.
|
Constructor and Description |
---|
MemcachedStorageService(net.spy.memcached.MemcachedClient client,
int timeout)
Creates a new instance.
|
MemcachedStorageService(net.spy.memcached.MemcachedClient client,
int timeout,
boolean enableContextKeyTracking)
Creates a new instance with optional context key tracking.
|
Modifier and Type | Method and Description |
---|---|
boolean |
create(Object value) |
boolean |
create(String context,
String key,
Object value,
StorageSerializer serializer,
Long expiration) |
boolean |
create(String context,
String key,
String value,
Long expiration) |
protected String |
createNamespace(String context)
Creates a cache-wide unique namespace for the given context name.
|
boolean |
delete(Object value) |
boolean |
delete(String context,
String key) |
void |
deleteContext(String context) |
boolean |
deleteWithVersion(long version,
Object value) |
boolean |
deleteWithVersion(long version,
String context,
String key) |
protected void |
doDestroy() |
StorageCapabilities |
getCapabilities() |
private <T> T |
handleAsyncResult(net.spy.memcached.internal.OperationFuture<T> result)
Handle async result.
|
protected String |
lookupNamespace(String context)
Looks up the namespace for the given context name in the cache.
|
private String |
memcachedKey(String... parts)
Creates a memcached key from one or more parts.
|
Object |
read(Object value) |
StorageRecord |
read(String context,
String key) |
net.shibboleth.utilities.java.support.collection.Pair<Long,StorageRecord> |
read(String context,
String key,
long version) |
void |
reap(String context) |
void |
setCapabilities(MemcachedStorageCapabilities capabilities)
Sets the storage capabilities.
|
boolean |
update(Object value) |
boolean |
update(String context,
String key,
Object value,
StorageSerializer serializer,
Long expiration) |
boolean |
update(String context,
String key,
String value,
Long expiration) |
void |
updateContextExpiration(String context,
Long expiration) |
private boolean |
updateContextKeyList(String suffix,
String namespace,
String key)
Update context key list.
|
boolean |
updateExpiration(Object value) |
boolean |
updateExpiration(String context,
String key,
Long expiration) |
Long |
updateWithVersion(long version,
Object value) |
Long |
updateWithVersion(long version,
String context,
String key,
Object value,
StorageSerializer serializer,
Long expiration) |
Long |
updateWithVersion(long version,
String context,
String key,
String value,
Long expiration) |
setId
doInitialize, getId
destroy, initialize, isDestroyed, isInitialized
protected static final String CTX_KEY_LIST_SUFFIX
protected static final String CTX_KEY_BLACKLIST_SUFFIX
private static final String CTX_KEY_LIST_DELIMITER
private static final int MAX_KEY_LENGTH
private final Logger logger
private final net.spy.memcached.transcoders.Transcoder<MemcachedStorageRecord> storageRecordTranscoder
MemcachedStorageRecord
to bytes and vice versa.private final net.spy.memcached.transcoders.Transcoder<String> stringTranscoder
@Nonnull private MemcachedStorageCapabilities storageCapabilities
@Nonnull private final net.spy.memcached.MemcachedClient memcacheClient
@Positive private int operationTimeout
private boolean trackContextKeys
public MemcachedStorageService(@Nonnull net.spy.memcached.MemcachedClient client, @Positive int timeout)
client
- Memcached client object. The client MUST be configured to use the binary memcached protocol,
i.e. BinaryConnectionFactory
, in order for
deleteWithVersion(long, String, String)
and deleteWithVersion(long, Object)
to work correctly. The binary protocol is recommended for efficiency as well.timeout
- Memcached operation timeout in seconds.public MemcachedStorageService(@Nonnull net.spy.memcached.MemcachedClient client, @Positive int timeout, boolean enableContextKeyTracking)
client
- Memcached client object. The client MUST be configured to use the binary memcached protocol,
i.e. BinaryConnectionFactory
, in order for
deleteWithVersion(long, String, String)
and deleteWithVersion(long, Object)
to work correctly. The binary protocol is recommended for efficiency as well.timeout
- Memcached operation timeout in seconds.enableContextKeyTracking
- True to enable context key tracking, false otherwise. NOTE
this flag must be set to true
in order for
updateContextExpiration(String, Long)
to work. If that capability is
not needed, the flag should be set to false
for better
performance. The feature is disabled by default.@Nonnull public StorageCapabilities getCapabilities()
getCapabilities
in interface StorageService
public void setCapabilities(@Nonnull MemcachedStorageCapabilities capabilities)
MemcachedStorageCapabilities.valueSize
should be set equal to the chosen slab size.capabilities
- Memcached storage capabilities.public boolean create(@Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key, @Nonnull@NotEmpty String value, @Nullable@Positive Long expiration) throws IOException
create
in interface StorageService
IOException
public boolean create(@Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key, @Nonnull Object value, @Nonnull StorageSerializer serializer, @Nullable@Positive Long expiration) throws IOException
create
in interface StorageService
IOException
public boolean create(@Nonnull Object value) throws IOException
create
in interface StorageService
IOException
public StorageRecord read(@Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key) throws IOException
read
in interface StorageService
IOException
public Object read(@Nonnull Object value) throws IOException
read
in interface StorageService
IOException
public net.shibboleth.utilities.java.support.collection.Pair<Long,StorageRecord> read(@Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key, @Positive long version) throws IOException
read
in interface StorageService
IOException
public boolean update(@Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key, @Nonnull@NotEmpty String value, @Nullable@Positive Long expiration) throws IOException
update
in interface StorageService
IOException
public boolean update(@Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key, @Nonnull Object value, @Nonnull StorageSerializer serializer, @Nullable@Positive Long expiration) throws IOException
update
in interface StorageService
IOException
public boolean update(@Nonnull Object value) throws IOException
update
in interface StorageService
IOException
public Long updateWithVersion(@Positive long version, @Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key, @Nonnull@NotEmpty String value, @Nullable@Positive Long expiration) throws IOException, VersionMismatchException
updateWithVersion
in interface StorageService
IOException
VersionMismatchException
@Nullable public Long updateWithVersion(@Positive long version, @Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key, @Nonnull Object value, @Nonnull StorageSerializer serializer, @Nullable@Positive Long expiration) throws IOException, VersionMismatchException
updateWithVersion
in interface StorageService
IOException
VersionMismatchException
@Nullable public Long updateWithVersion(@Positive long version, @Nonnull Object value) throws IOException, VersionMismatchException
updateWithVersion
in interface StorageService
IOException
VersionMismatchException
public boolean updateExpiration(@Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key, @Nullable@Positive Long expiration) throws IOException
updateExpiration
in interface StorageService
IOException
public boolean updateExpiration(@Nonnull Object value) throws IOException
updateExpiration
in interface StorageService
IOException
public boolean delete(@Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key) throws IOException
delete
in interface StorageService
IOException
public boolean delete(@Nonnull Object value) throws IOException
delete
in interface StorageService
IOException
public boolean deleteWithVersion(@Positive long version, @Nonnull@NotEmpty String context, @Nonnull@NotEmpty String key) throws IOException, VersionMismatchException
deleteWithVersion
in interface StorageService
IOException
VersionMismatchException
public boolean deleteWithVersion(@Positive long version, @Nonnull Object value) throws IOException, VersionMismatchException
deleteWithVersion
in interface StorageService
IOException
VersionMismatchException
public void reap(@Nonnull@NotEmpty String context) throws IOException
reap
in interface StorageService
IOException
public void updateContextExpiration(@Nonnull@NotEmpty String context, @Nullable Long expiration) throws IOException
updateContextExpiration
in interface StorageService
IOException
public void deleteContext(@Nonnull@NotEmpty String context) throws IOException
deleteContext
in interface StorageService
IOException
protected void doDestroy()
doDestroy
in class net.shibboleth.utilities.java.support.component.AbstractInitializableComponent
protected String lookupNamespace(String context) throws IOException
context
- Context name.IOException
- On memcached operation errors.protected String createNamespace(String context) throws IOException
context
- Context name.IOException
- On memcached operation errors.private String memcachedKey(String... parts)
parts
- Key parts (i.e. namespace, local name)private <T> T handleAsyncResult(net.spy.memcached.internal.OperationFuture<T> result) throws IOException
T
- type of resultresult
- the resultIOException
- if an error occursprivate boolean updateContextKeyList(String suffix, String namespace, String key) throws IOException
suffix
- the suffixnamespace
- the namespacekey
- the storage keyIOException
- if an error occursCopyright © 1999–2020 Shibboleth Consortium. All rights reserved.