From 254ee6f47eebfc00462c10756a92066e82cc1a96 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Tue, 21 Jun 2011 15:46:02 +0200 Subject: Initial commit --- source/com/c2kernel/persistency/RemoteMap.java | 404 +++++++++++++++++++++++++ 1 file changed, 404 insertions(+) create mode 100755 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 new file mode 100755 index 0000000..ca9cbc4 --- /dev/null +++ b/source/com/c2kernel/persistency/RemoteMap.java @@ -0,0 +1,404 @@ +package com.c2kernel.persistency; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import com.c2kernel.common.ObjectNotFoundException; +import com.c2kernel.entity.C2KLocalObject; +import com.c2kernel.entity.proxy.*; +import com.c2kernel.entity.proxy.EntityProxyObserver; +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 $ + * + * 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; + + 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; + TransactionManager storage; + EntityProxyObserver listener; + EntityProxy source; + Object mLocker; // if this remote map will participate in a transaction + + public RemoteMap(int sysKey, String path, Object locker) { + mSysKey = sysKey; + mLocker = locker; + + // split the path into path/name + int lastSlash = path.lastIndexOf("/"); + mName = path.substring(lastSlash+1); + if (lastSlash>0) mPath = path.substring(0,lastSlash); + + // see if the name is also a suitable id + try { + 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 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; + } + } + + + // c2kLocalObject methods + public void setID(int id) { mID = id; } + + public int getID() { return mID; } + + public void setName(String name) { mName = name; } + + public String getName() { return mName; } + + /** + * Cannot be stored + */ + public String getClusterType() { + return null; + } + /** + * @see java.util.Map#clear() + */ + public synchronized void clear() { + keys = null; + } + + + + /** + * @see java.util.Map#containsKey(Object) + */ + public synchronized boolean containsKey(Object key) { + getKeys(); + for (int i = 0; i < keys.length; i++) { + if (key.equals(keys[i])) + return true; + } + return false; + } + + /** + * This must retrieve all the values until a match is made. + * Very expensive, but if you must, you must. + * @see java.util.Map#containsValue(Object) + */ + 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); + } + } + } + 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]; + 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]; + } + } + } catch (ClusterStorageException e) { + Logger.error(e); + } catch (ObjectNotFoundException e) { + Logger.error(e); + } + } + return null; + } + + /** + * @see java.util.Map#isEmpty() + */ + public synchronized boolean isEmpty() { + return getKeys().length==0; + } + + /** + * @see java.util.Map#keySet() + */ + public synchronized Set keySet() { + return new RemoteMap.RemoteSet(this, KEYS); + } + + /** + * Inserts the given object into the storage + * 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) { + try { + C2KLocalObject newValue = (C2KLocalObject)value; + synchronized(keyLock) { + storage.put(mSysKey, newValue, mLocker); + keys = null; values = null; + } + } 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)); + } + } + + /** + * @see java.util.Map#remove(Object) + */ + public synchronized Object remove(Object key) { + try { + synchronized(keyLock) { + storage.remove(mSysKey, mPath+mName+"/"+key, mLocker); + keys = null; values = null; + } + } catch (ClusterStorageException e) { + Logger.error(e); + } + return null; + } + + /** + * @see java.util.Map#size() + */ + public synchronized int size() { + return getKeys().length; + } + + /** + * @see java.util.Map#values() + */ + public synchronized Collection values() { + return new RemoteMap.RemoteSet(this, VALUES); + } + + /** + * Basic implementation of Set and Collection to bridge to the Iterator + * Disallows all writes. + */ + + private class RemoteSet extends AbstractSet { + RemoteMap mParent; + boolean mMode; + + public RemoteSet(RemoteMap parent, boolean mode) { + mParent = parent; + mMode = mode; + } + + // no modifications allowed + public boolean add(Object o) { + throw new UnsupportedOperationException(); + } + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + public void clear() { + throw new UnsupportedOperationException(); + } + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public Iterator iterator() { + return new RemoteIterator(mParent, mMode); + } + + public int size() { + return mParent.size(); + } + + } + /** + * 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) { + mParent = parent; + mMode = mode; + keyArr = mParent.getKeys(); + } + + public boolean hasNext() { + return (pos