📄 jdbmspace.java
字号:
/* * Copyright (c) 2004 jPOS.org * * See terms of license at http://jpos.org/license.html * */package org.jpos.space;import java.io.IOException;import java.io.Serializable;import java.io.Externalizable;import java.io.ObjectInput;import java.io.ObjectOutput;import java.rmi.RemoteException;import java.util.Properties;import java.util.Iterator;import java.util.Map;import java.util.Arrays;import java.util.HashMap;import java.util.TimerTask;import java.util.ConcurrentModificationException;import jdbm.RecordManager;import jdbm.RecordManagerFactory;import jdbm.RecordManagerOptions;import jdbm.helper.FastIterator;import jdbm.htree.HTree;import jdbm.helper.Serializer;import jdbm.helper.DefaultSerializer;import jdbm.helper.FastIterator;import org.jpos.util.DefaultTimer;/** * JDBM based persistent space implementation * * @author Alejandro Revilla * @author Kris Leite * @version $Revision: 1.9 $ $Date: 2005/06/27 01:09:56 $ * @since 1.4.7 */public class JDBMSpace extends TimerTask implements Space { protected HTree htree; protected RecordManager recman; protected static Serializer refSerializer = new Ref (); protected static Map spaceRegistrar = new HashMap (); protected boolean autoCommit = true; protected String name; public static final long GCDELAY = 5*60*1000; /** * protected constructor. * @see getSpace() */ protected JDBMSpace (String name, String filename) { super(); this.name = name; try { Properties props = new Properties(); props.put (RecordManagerOptions.CACHE_SIZE, "512"); recman = RecordManagerFactory.createRecordManager (filename, props); long recid = recman.getNamedObject ("space"); if (recid != 0) { htree = HTree.load (recman, recid); } else { htree = HTree.createInstance (recman); recman.setNamedObject ("space", htree.getRecid()); } recman.commit (); } catch (IOException e) { throw new SpaceError (e); } DefaultTimer.getTimer().schedule (this, GCDELAY, GCDELAY); } /** * @return reference to default JDBMSpace */ public static final JDBMSpace getSpace () { return getSpace ("space"); } /** * creates a named JDBMSpace * (filename used for storage is the same as the given name) * @param name the Space name * @return reference to named JDBMSpace */ public static final JDBMSpace getSpace (String name) { return getSpace (name, name); } /** * creates a named JDBMSpace * @param name the Space name * @param filename the storage file name * @return reference to named JDBMSpace */ public synchronized static final JDBMSpace getSpace (String name, String filename) { JDBMSpace sp = (JDBMSpace) spaceRegistrar.get (name); if (sp == null) { sp = new JDBMSpace (name, filename); spaceRegistrar.put (name, sp); } return sp; } /** * Use with utmost care and at your own risk. * * If you are to perform several operations on the space you * should synchronize on the space, i.e: * <pre> * synchronized (sp) { * sp.setAutoCommit (false); * sp.out (..., ...) * sp.out (..., ...) * ... * ... * sp.inp (...); * sp.commit (); // or sp.rollback (); * sp.setAutoCommit (true); * } * </pre> * @param b true or false */ public void setAutoCommit (boolean b) { this.autoCommit = b; } /** * force commit * @see setAutoCommit(boolean) */ public void commit () { try { recman.commit (); this.notifyAll (); } catch (IOException e) { throw new SpaceError (e); } } /** * force rollback * @see setAutoCommit(boolean) */ public void rollback () { try { recman.rollback (); } catch (IOException e) { throw new SpaceError (e); } } /** * close this space - use with care */ public void close () { synchronized (JDBMSpace.class) { spaceRegistrar.remove (name); } synchronized (this) { try { recman.close (); recman = null; } catch (IOException e) { throw new SpaceError (e); } } } /** * Write a new entry into the Space * @param key Entry's key * @param value Object value */ public void out (Object key, Object value) { out (key, value, -1); } /** * Write a new entry into the Space * The entry will timeout after the specified period * @param key Entry's key * @param value Object value * @param timeout entry timeout in millis */ public void out (Object key, Object value, long timeout) { try { synchronized (this) { long recid = recman.insert (value); long expiration = timeout == -1 ? Long.MAX_VALUE : (System.currentTimeMillis() + timeout); Ref dataRef = new Ref (recid, expiration); long dataRefRecId = recman.insert (dataRef, refSerializer); Head head = (Head) htree.get (key); if (head == null) { head = new Head (); head.first = dataRefRecId; head.last = dataRefRecId; head.count = 1; } else { long previousLast = head.last; Ref lastRef = (Ref) recman.fetch (previousLast, refSerializer); lastRef.next = dataRefRecId; head.last = dataRefRecId; head.count++; recman.update (previousLast, lastRef, refSerializer); } htree.put (key, head); if (autoCommit) { recman.commit (); this.notifyAll (); } } } catch (IOException e) { throw new SpaceError (e); } } /** * Read probe reads an entry from the space if one exists, * return null otherwise. * @param key Entry's key * @return value or null */ public synchronized Object rdp (Object key) { try { if (key instanceof Template) return getObject ((Template) key, false); Object obj = null; Ref ref = getFirst (key, false); if (ref != null) obj = recman.fetch (ref.recid); if (autoCommit) recman.commit (); return obj; } catch (IOException e) { throw new SpaceError (e); } } /** * In probe takes an entry from the space if one exists, * return null otherwise. * @param key Entry's key * @return value or null */ public synchronized Object inp (Object key) { try { if (key instanceof Template) return getObject ((Template) key, true); Object obj = null; Ref ref = getFirst (key, true); if (ref != null) { obj = recman.fetch (ref.recid); recman.delete (ref.recid); } if (autoCommit) recman.commit (); return obj; } catch (IOException e) { throw new SpaceError (e); } } public synchronized Object in (Object key) { Object obj; while ((obj = inp (key)) == null) { try { this.wait (); } catch (InterruptedException e) { } } return obj; } /** * Take an entry from the space, waiting forever until one exists. * @param key Entry's key * @return value */ public synchronized Object in (Object key, long timeout) { Object obj; long now = System.currentTimeMillis(); long end = now + timeout; while ((obj = inp (key)) == null && ((now = System.currentTimeMillis()) < end)) { try { this.wait (end - now); } catch (InterruptedException e) { } } return obj; } /** * Read an entry from the space, waiting forever until one exists. * @param key Entry's key * @return value */ public synchronized Object rd (Object key) { Object obj; while ((obj = rdp (key)) == null) { try { this.wait (); } catch (InterruptedException e) { } } return obj; } /** * Read an entry from the space, waiting a limited amount of time * until one exists.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -