From 0ec8481c10cd8277d84c7c1a785483a0a739e5a0 Mon Sep 17 00:00:00 2001 From: abranson Date: Thu, 4 Aug 2011 00:42:34 +0200 Subject: 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 --- source/com/c2kernel/persistency/RemoteMap.java | 353 +++++++++++-------------- 1 file changed, 161 insertions(+), 192 deletions(-) mode change 100755 => 100644 source/com/c2kernel/persistency/RemoteMap.java (limited to 'source/com/c2kernel/persistency/RemoteMap.java') diff --git a/source/com/c2kernel/persistency/RemoteMap.java b/source/com/c2kernel/persistency/RemoteMap.java old mode 100755 new mode 100644 index ca9cbc4..bc17e3f --- 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 extends TreeMap 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 listener; + Comparator 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() { + @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() { + @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(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 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 values() { + return new RemoteSet(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 extends AbstractSet { + RemoteMap mParent; + + public RemoteSet(RemoteMap 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 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 iterator() { + return new RemoteIterator(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 implements Iterator { + RemoteMap mParent; + Iterator iter; + + public RemoteIterator(RemoteMap parent) { mParent = parent; - mMode = mode; - keyArr = mParent.getKeys(); + iter = mParent.keySet().iterator(); } + @Override public boolean hasNext() { - return (pos