summaryrefslogtreecommitdiff
path: root/source/com/c2kernel/persistency/RemoteMap.java
diff options
context:
space:
mode:
Diffstat (limited to 'source/com/c2kernel/persistency/RemoteMap.java')
-rw-r--r--[-rwxr-xr-x]source/com/c2kernel/persistency/RemoteMap.java353
1 files changed, 161 insertions, 192 deletions
diff --git a/source/com/c2kernel/persistency/RemoteMap.java b/source/com/c2kernel/persistency/RemoteMap.java
index ca9cbc4..bc17e3f 100755..100644
--- a/source/com/c2kernel/persistency/RemoteMap.java
+++ b/source/com/c2kernel/persistency/RemoteMap.java
@@ -2,22 +2,23 @@ package com.c2kernel.persistency;
import java.util.AbstractSet;
import java.util.Collection;
+import java.util.Comparator;
import java.util.Iterator;
-import java.util.Map;
-import java.util.NoSuchElementException;
import java.util.Set;
+import java.util.TreeMap;
import com.c2kernel.common.ObjectNotFoundException;
import com.c2kernel.entity.C2KLocalObject;
-import com.c2kernel.entity.proxy.*;
+import com.c2kernel.entity.proxy.EntityProxy;
import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.MemberSubscription;
import com.c2kernel.lookup.EntityPath;
import com.c2kernel.process.Gateway;
import com.c2kernel.utils.Logger;
/**
* Maps a storage cluster onto a java.util.Map
- *
+ *
* @author Andrew Branson
* $Revision: 1.22 $
* $Date: 2006/03/03 13:52:21 $
@@ -25,24 +26,34 @@ import com.c2kernel.utils.Logger;
* Copyright (C) 2003 CERN - European Organization for Nuclear Research
* All rights reserved.
*/
-public class RemoteMap implements C2KLocalObject, Map {
-
- protected static final boolean KEYS = false;
- protected static final boolean VALUES = true;
+public class RemoteMap<V extends C2KLocalObject> extends TreeMap<String, V> implements C2KLocalObject {
private int mID=-1;
private String mName;
protected int mSysKey;
private String mPath = "";
- protected String[] keys = null;
- Object keyLock = new Object();
- protected C2KLocalObject[] values = null;
+ Object keyLock = null;
TransactionManager storage;
- EntityProxyObserver listener;
+ EntityProxyObserver<V> listener;
+ Comparator<String> comp;
EntityProxy source;
- Object mLocker; // if this remote map will participate in a transaction
-
+ Object mLocker; // if this remote map will participate in a transaction
+
public RemoteMap(int sysKey, String path, Object locker) {
+
+ super(new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ Integer i1 = null, i2 = null;
+ try {
+ i1 = Integer.valueOf(o1);
+ i2 = Integer.valueOf(o2);
+ return i1.compareTo(i2);
+ } catch (NumberFormatException ex) { }
+ return o1.compareTo(o2);
+ }
+ });
+
mSysKey = sysKey;
mLocker = locker;
@@ -56,138 +67,99 @@ public class RemoteMap implements C2KLocalObject, Map {
mID = Integer.parseInt(mName);
} catch (NumberFormatException e) {}
storage = Gateway.getStorage();
-
- listener = new EntityProxyObserver() {
- public void add(C2KLocalObject obj) {
- synchronized (keyLock) {
- if (keys == null) return;
- boolean found = false;
- for (int i=0; i<keys.length; i++) {
- if (keys[i].equals(obj.getName())) { //replaced
- values[i] = obj;
- found = true;
- break;
- }
- }
-
- if (found == false) { // new
- String[] newKeys = new String[keys.length+1];
- C2KLocalObject[] newValues = new C2KLocalObject[keys.length+1];
- System.arraycopy(keys, 0, newKeys, 0, keys.length);
- if (values!=null) System.arraycopy(values, 0, newValues, 0, keys.length);
- newKeys[newKeys.length-1] = obj.getName();
- newValues[newValues.length-1] = obj;
- keys = newKeys;
- values = newValues;
- }
- }
+
+ listener = new EntityProxyObserver<V>() {
+ @Override
+ public void add(V obj) {
+ synchronized (this) {
+ putLocal(obj.getName(), obj);
+ }
}
- public void remove(String id) {
- synchronized (keyLock) {
- if (keys == null) return;
- boolean found = false;
- for (int i=0; i<keys.length; i++) {
- if (keys[i].equals(id)) { //replaced
- String[] newKeys = new String[keys.length-1];
- C2KLocalObject[] newValues = new C2KLocalObject[keys.length-1];
- int pos = 0;
- for (int j=0; j<keys.length;j++) {
- if (i!=j) {
- newKeys[pos] = keys[j];
- newValues[pos++] = values[j];
- }
- }
- keys = newKeys;
- values = newValues;
- break;
- }
- }
+ @Override
+ public void remove(String id) {
+ synchronized (this) {
+ removeLocal(id);
}
}
+
+ @Override
+ public void control(String control, String msg) { }
};
try {
source = Gateway.getProxyManager().getProxy(new EntityPath(sysKey));
- source.subscribe(listener, path, false);
+ source.subscribe(new MemberSubscription<V>(listener, path, false));
} catch (Exception ex) {
Logger.error("Error subscribing to remote map. Changes will not be received");
Logger.error(ex);
}
}
-
- protected void loadKeys() throws ClusterStorageException {
- synchronized(keyLock) {
- keys = storage.getClusterContents(mSysKey, mPath+mName);
- values = new C2KLocalObject[keys.length];
+
+ protected void loadKeys() {
+ if (keyLock != null) return;
+ clear();
+ keyLock = new Object();
+ synchronized(this) {
+ String[] keys;
+ try {
+ keys = storage.getClusterContents(mSysKey, mPath+mName);
+ for (String key : keys) super.put(key, null);
+ } catch (ClusterStorageException e) {
+ Logger.error(e);
+ }
+
}
}
-
- protected String[] getKeys() {
- try {
- if (keys == null) loadKeys();
- } catch (ClusterStorageException e) {
- Logger.error(e);
- keys = new String[0];
- }
- return keys;
- }
-
+
public synchronized int getLastId() {
-
- synchronized (this) {
- int lastID = -1;
-
- String[] allIds = getKeys();
-
- for (int i = 0; i < allIds.length; i++) {
- try {
- int thisID = Integer.parseInt(allIds[i]);
- if (thisID > lastID) lastID = thisID;
- } catch (NumberFormatException e) {
- Logger.warning("RemoteMap.getLastID() - Cluster contained invalid id: "+allIds[i]);
- }
- }
- Logger.msg(7, "RemoteMap.getLastID() - last id in "+mPath+mName+" of "+mSysKey+" is "+lastID);
- return lastID;
- }
- }
-
+ loadKeys();
+ try {
+ return Integer.parseInt(lastKey());
+ } catch (NumberFormatException ex) {
+ return -1;
+ }
+ }
+
// c2kLocalObject methods
public void setID(int id) { mID = id; }
public int getID() { return mID; }
+ @Override
public void setName(String name) { mName = name; }
+ @Override
public String getName() { return mName; }
/**
* Cannot be stored
*/
+ @Override
public String getClusterType() {
return null;
}
/**
* @see java.util.Map#clear()
*/
+ @Override
public synchronized void clear() {
- keys = null;
+ synchronized (this) {
+ super.clear();
+ }
+ keyLock = null;
}
-
+
/**
* @see java.util.Map#containsKey(Object)
*/
+ @Override
public synchronized boolean containsKey(Object key) {
- getKeys();
- for (int i = 0; i < keys.length; i++) {
- if (key.equals(keys[i]))
- return true;
- }
- return false;
+ if (keyLock == null) loadKeys();
+ return super.containsKey(key);
}
/**
@@ -195,46 +167,40 @@ public class RemoteMap implements C2KLocalObject, Map {
* Very expensive, but if you must, you must.
* @see java.util.Map#containsValue(Object)
*/
+ @Override
public synchronized boolean containsValue(Object value) {
- getKeys();
- synchronized(keyLock) {
- if (values == null) values = new C2KLocalObject[keys.length];
- for (int i = 0; i < keys.length; i++) {
- try {
- if (values[i] == null) values[i] = storage.get(mSysKey, mPath+mName+"/"+keys[i], mLocker);
- if (value.equals(values[i])) return true;
- } catch (ClusterStorageException ex) {
- Logger.error(ex);
- } catch (ObjectNotFoundException e) {
- Logger.error(e);
- }
+ loadKeys();
+ synchronized(this) {
+ for (String key: keySet()) {
+ if (get(key).equals(value)) return true;
}
}
return false;
}
- /**
- * @see java.util.Map#entrySet()
- */
- public synchronized Set entrySet() {
- return new RemoteMap.RemoteSet(this, KEYS);
- }
/**
* @see java.util.Map#get(Object)
*/
- public synchronized Object get(Object key) {
- getKeys();
- synchronized(keyLock) {
- if (values == null) values = new C2KLocalObject[keys.length];
+ @Override
+ public synchronized V get(Object objKey) {
+ loadKeys();
+ String key;
+ if (objKey instanceof Integer)
+ key = ((Integer)objKey).toString();
+ else if (objKey instanceof String)
+ key = (String)objKey;
+ else
+ return null;
+
+ synchronized(this) {
try {
- for (int i = 0; i < keys.length; i++) {
- if (key.equals(keys[i])) {
- if (values[i] == null)
- values[i] = storage.get(mSysKey, mPath+mName+"/"+keys[i], mLocker);
- return values[i];
- }
+ V value = super.get(key);
+ if (value == null) {
+ value = (V)storage.get(mSysKey, mPath+mName+"/"+key, mLocker);
+ super.put(key, value);
}
+ return value;
} catch (ClusterStorageException e) {
Logger.error(e);
} catch (ObjectNotFoundException e) {
@@ -247,15 +213,19 @@ public class RemoteMap implements C2KLocalObject, Map {
/**
* @see java.util.Map#isEmpty()
*/
+ @Override
public synchronized boolean isEmpty() {
- return getKeys().length==0;
+ loadKeys();
+ return super.isEmpty();
}
/**
* @see java.util.Map#keySet()
*/
- public synchronized Set keySet() {
- return new RemoteMap.RemoteSet(this, KEYS);
+ @Override
+ public synchronized Set<String> keySet() {
+ loadKeys();
+ return super.keySet();
}
/**
@@ -263,60 +233,59 @@ public class RemoteMap implements C2KLocalObject, Map {
* the key is ignored - it can be fetched from the value.
* @see java.util.Map#put(Object, Object)
*/
- public synchronized Object put(Object key, Object value) {
+ @Override
+ public synchronized V put(String key, V value) {
try {
- C2KLocalObject newValue = (C2KLocalObject)value;
- synchronized(keyLock) {
- storage.put(mSysKey, newValue, mLocker);
- keys = null; values = null;
+ synchronized(this) {
+ storage.put(mSysKey, value, mLocker);
+ return putLocal(key, value);
}
} catch (ClusterStorageException e) {
Logger.error(e);
return null;
- } catch (ClassCastException e) {
- Logger.error("RemoteMap.put() - value was not a localobject, it was a "+value.getClass().getName());
- return null;
}
- return value;
}
-
- /**
- * @see java.util.Map#putAll(Map)
- */
- public synchronized void putAll(Map t) {
- for (Iterator iter = t.keySet().iterator(); iter.hasNext();) {
- Object key = iter.next();
- put(key, t.get(key));
- }
+
+ protected synchronized V putLocal(String key, V value) {
+ return super.put(key, value);
}
/**
* @see java.util.Map#remove(Object)
*/
- public synchronized Object remove(Object key) {
- try {
+ @Override
+ public synchronized V remove(Object key) {
+ loadKeys();
+ if (containsKey(key)) try {
synchronized(keyLock) {
storage.remove(mSysKey, mPath+mName+"/"+key, mLocker);
- keys = null; values = null;
- }
+ return super.remove(key);
+ }
} catch (ClusterStorageException e) {
Logger.error(e);
}
return null;
}
+
+ protected synchronized V removeLocal(Object key) {
+ return super.remove(key);
+ }
/**
* @see java.util.Map#size()
*/
+ @Override
public synchronized int size() {
- return getKeys().length;
+ loadKeys();
+ return super.size();
}
/**
* @see java.util.Map#values()
*/
- public synchronized Collection values() {
- return new RemoteMap.RemoteSet(this, VALUES);
+ @Override
+ public synchronized Collection<V> values() {
+ return new RemoteSet<V>(this);
}
/**
@@ -324,39 +293,45 @@ public class RemoteMap implements C2KLocalObject, Map {
* Disallows all writes.
*/
- private class RemoteSet extends AbstractSet {
- RemoteMap mParent;
- boolean mMode;
-
- public RemoteSet(RemoteMap parent, boolean mode) {
+ private class RemoteSet<E extends C2KLocalObject> extends AbstractSet<E> {
+ RemoteMap<E> mParent;
+
+ public RemoteSet(RemoteMap<E> parent) {
mParent = parent;
- mMode = mode;
}
- // no modifications allowed
- public boolean add(Object o) {
+ // no modifications allowed
+ @Override
+ public boolean add(E o) {
throw new UnsupportedOperationException();
}
- public boolean addAll(Collection c) {
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
- public void clear() {
+ @Override
+ public void clear() {
throw new UnsupportedOperationException();
}
- public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
- public boolean removeAll(Collection c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
- public boolean retainAll(Collection c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
- public Iterator iterator() {
- return new RemoteIterator(mParent, mMode);
+ @Override
+ public Iterator<E> iterator() {
+ return new RemoteIterator<E>(mParent);
}
+ @Override
public int size() {
return mParent.size();
}
@@ -366,32 +341,26 @@ public class RemoteMap implements C2KLocalObject, Map {
* Iterator view on RemoteMap data. Doesn't preload anything.
* REVISIT: Will go strange if the RemoteMap is modified. Detect this and throw ConcurrentMod ex
*/
- private class RemoteIterator implements Iterator {
- RemoteMap mParent;
- boolean mMode;
- String[] keyArr;
- int pos;
-
- public RemoteIterator(RemoteMap parent, boolean mode) {
+ private class RemoteIterator<C extends C2KLocalObject> implements Iterator<C> {
+ RemoteMap<C> mParent;
+ Iterator<String> iter;
+
+ public RemoteIterator(RemoteMap<C> parent) {
mParent = parent;
- mMode = mode;
- keyArr = mParent.getKeys();
+ iter = mParent.keySet().iterator();
}
+ @Override
public boolean hasNext() {
- return (pos<keyArr.length);
+ return iter.hasNext();
}
- public Object next() {
- if (pos == keyArr.length)
- throw new NoSuchElementException();
-
- if (mMode == KEYS)
- return keyArr[pos++];
- else
- return mParent.get(keyArr[pos++]);
+ @Override
+ public C next() {
+ return mParent.get(iter.next());
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}