summaryrefslogtreecommitdiff
path: root/source/com/c2kernel/persistency/RemoteMap.java
diff options
context:
space:
mode:
authorabranson <andrew.branson@cern.ch>2011-08-04 00:42:34 +0200
committerabranson <andrew.branson@cern.ch>2011-08-04 00:42:34 +0200
commit0ec8481c10cd8277d84c7c1a785483a0a739e5a0 (patch)
tree5f6e5d9ae75193e67e6f3b3dfa488960c5cde1d5 /source/com/c2kernel/persistency/RemoteMap.java
parent036cbdba66f804743c4c838ed598d6972c4b3e17 (diff)
More code cleanup:
Refactored Entity Proxy Subscription to handle generics better Rewrote RemoteMap to use TreeMap instead of the internal array for order. It now sorts its keys by number if they parse, else as strings. Removed a no-longer-in-progress outcome form class
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();
}