/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.oneandone.idev.johanna.store.redis; import java.util.HashSet; import java.util.Set; import java.util.logging.Level; import org.oneandone.idev.johanna.store.AbstractSession; import org.oneandone.idev.johanna.store.PlainValue; import org.oneandone.idev.johanna.store.Value; import org.oneandone.idev.johanna.store.id.Identifier; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; public class RedisBackedSession extends AbstractSession { public final static String REDIS_PREFIX= "s:"; private final static String REDIS_KEY_PREFIX= "v:"; private final static String REDIS_META_KEY= "ttl"; private JedisPool pool; protected String key() { return REDIS_PREFIX + this.getId(); } private Jedis jedis() { return this.pool.getResource(); } @Override public void putValue(String k, String v) { Jedis j= this.jedis(); try { j.hset(this.key().getBytes(), this.marshal(k).getBytes(), this.fromEncoded(v).asIntern()); } finally { this.pool.returnResource(j); } } @Override public String getValue(String k) { Jedis j= this.jedis(); try { byte[] bytes= j.hget(this.key().getBytes(), this.marshal(k).getBytes()); return this.fromIntern(bytes).asEncoded(); } finally { this.pool.returnResource(j); } } @Override public boolean removeValue(String k) { Jedis j= this.jedis(); try { return (1 == j.hdel(this.key(), this.marshal(k))); } finally { this.pool.returnResource(j); } } @Override public boolean hasValue(String k) { Jedis j= this.jedis(); try { return j.hexists(this.key(), this.marshal(k)); } finally { this.pool.returnResource(j); } } @Override public Set<String> keys() { Set<String> out, set; Jedis j= this.jedis(); try { set= j.hkeys(this.key()); } finally { this.pool.returnResource(j); } out= new HashSet(set.size()); for (String s : set) { if (REDIS_META_KEY.equals(s)) continue; out.add(this.unmarshal(s)); } return out; } @Override protected void terminate() { LOG.log(Level.INFO, "Terminating session {0}", this.getId()); Jedis j= this.jedis(); try { j.del(this.key()); } finally { this.pool.returnResource(j); } } public RedisBackedSession(Identifier id, JedisPool pool) { this(id, AbstractSession.DEFAULT_TTL, pool); } public RedisBackedSession(Identifier id, int ttl, JedisPool pool) { super(id, ttl); this.pool= pool; } @Override public long payloadBytesUsed() { return 0; } public void register() { this.touch(); } protected final void touch(Jedis j) { j.hset(this.key(), REDIS_META_KEY, Integer.toString(this.getTTL())); j.expire(this.key(), this.getTTL()); } @Override protected final void touch() { Jedis j= this.jedis(); try { this.touch(j); } finally { this.pool.returnResource(j); } } @Override public void expire() { this.terminate(); } @Override public boolean hasExpired() { Jedis j= this.jedis(); try { return !j.hexists(this.key(), REDIS_META_KEY); } finally { this.pool.returnResource(j); } } private String marshal(String k) { return REDIS_KEY_PREFIX + k; } private String unmarshal(String s) { if (!s.startsWith(REDIS_KEY_PREFIX)) { LOG.log(Level.WARNING, "Invalid key name: \"{0}\"", s); throw new IllegalArgumentException("Invalid key name, expected start with prefix."); } return s.substring(2); } public Value valueFromString(String value) { return new PlainValue(value); } public Value valueFromIntern(byte[] bytes) { return new PlainValue(bytes); } }