package com.rubiconproject.oss.kv.backends; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Random; import com.rubiconproject.oss.kv.BaseManagedKeyValueStore; import com.rubiconproject.oss.kv.KeyValueStore; import com.rubiconproject.oss.kv.KeyValueStoreException; import com.rubiconproject.oss.kv.transcoder.Transcoder; public class ReadLoadBalancingKeyValueStore extends BaseManagedKeyValueStore implements KeyValueStore { public static final String IDENTIFIER = "readloadbalancing"; protected KeyValueStore master; protected List<KeyValueStore> readers; protected Random random = new Random(); public ReadLoadBalancingKeyValueStore() { this.readers = new ArrayList<KeyValueStore>(); } public ReadLoadBalancingKeyValueStore(KeyValueStore master) { this.readers = new ArrayList<KeyValueStore>(); this.master = master; } public ReadLoadBalancingKeyValueStore(KeyValueStore master, List<KeyValueStore> readers) { this.master = master; this.readers = readers; } public String getIdentifier() { return IDENTIFIER; } public void setMaster(KeyValueStore master) { this.master = master; } public void addReader(KeyValueStore reader) { readers.add(reader); } public void removeReader(KeyValueStore reader) { readers.remove(reader); } public boolean exists(String key) throws KeyValueStoreException, IOException { assertReadable(); boolean exists = false; try { exists = getReader().exists(key); } catch (Exception e) { exists = master.exists(key); } return exists; } public Object get(String key) throws KeyValueStoreException, IOException { assertReadable(); Object obj = null; try { obj = getReader().get(key); } catch (Exception e) { obj = master.get(key); } return obj; } public Object get(String key, Transcoder transcoder) throws KeyValueStoreException, IOException { assertReadable(); Object obj = null; try { obj = getReader().get(key, transcoder); } catch (Exception e) { obj = master.get(key, transcoder); } return obj; } public Map<String, Object> getBulk(String... keys) throws KeyValueStoreException, IOException { assertReadable(); Map<String, Object> results = null; try { results = getReader().getBulk(keys); } catch (Exception e) { results = master.getBulk(keys); } return results; } public Map<String, Object> getBulk(List<String> keys) throws KeyValueStoreException, IOException { assertReadable(); Map<String, Object> results = null; try { results = getReader().getBulk(keys); } catch (Exception e) { results = master.getBulk(keys); } return results; } public Map<String, Object> getBulk(List<String> keys, Transcoder transcoder) throws KeyValueStoreException, IOException { assertReadable(); Map<String, Object> results = null; try { results = getReader().getBulk(keys, transcoder); } catch (Exception e) { results = master.getBulk(keys, transcoder); } return results; } public void set(String key, Object value) throws KeyValueStoreException, IOException { assertWriteable(); master.set(key, value); } public void set(String key, Object value, Transcoder transcoder) throws KeyValueStoreException, IOException { assertWriteable(); master.set(key, value, transcoder); } public void delete(String key) throws KeyValueStoreException, IOException { assertWriteable(); master.delete(key); } protected KeyValueStore getReader() { if (readers == null) return master; int size = readers.size(); if (size == 0) return master; else { int index = random.nextInt(size); return readers.get(index); } } }