1 /* PersistentBidiHasthable.java -- Bidirectional persistent hash table.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu.classpath.tools.rmid;
40 import gnu.classpath.tools.common.Persistent;
41 import gnu.classpath.tools.rmid.ActivationSystemImpl;
42 import gnu.java.rmi.activation.BidiTable;
44 import java.io.BufferedInputStream;
45 import java.io.BufferedOutputStream;
47 import java.io.FileInputStream;
48 import java.io.FileOutputStream;
49 import java.io.IOException;
50 import java.io.InputStream;
51 import java.io.ObjectInputStream;
52 import java.io.ObjectOutputStream;
53 import java.util.Hashtable;
54 import java.util.Iterator;
56 import java.util.TimerTask;
59 * The persistent bidirectional hash table, maps both a to b and b to a. The
60 * changes are written to dist after SAVE_AT_MOST_AFTER time from the latest
61 * database change or at most after ALWAYS_UPDATE, if the database is updated
62 * very frequently. To ensure that no information is lost, the shutdown method
63 * must be called before exit.
65 * @author Audrius Meskauskas (audriusa@bioinformatics.org)
67 public class PersistentBidiHashTable extends BidiTable implements
70 class WriteToDiskTask extends TimerTask
83 * Replaces instances of ActivationSystemImpl into the currently active
84 * instance of the ActivationSystemImpl
86 class AdaptedReader extends ObjectInputStream
88 AdaptedReader(InputStream in) throws IOException
91 enableResolveObject(true);
94 protected Object resolveObject(Object obj) throws IOException
96 if (obj instanceof ActivationSystemImpl)
97 return ActivationSystemImpl.singleton2;
109 * The currently sheduled write to disk task, null if none.
111 WriteToDiskTask sheduled = null;
114 * The time, when the disk database was last updated.
119 * Create the unitialised instance that must be initalised when
120 * ActivationSystemImpl.singleton2 is assigned.
122 public PersistentBidiHashTable()
124 // Do not initalise the table fields - the initalise method must be
130 * Create a new persistent table that stores its information into the given
131 * file. The ActivationSystemImpl.singleton2 must be assigned.
134 * the file, where the table stores its information.
136 * if true, the existing file with this name will be erased and
137 * ignored. Otherwise, it will be assumed that the file contains the
138 * persistent table information.
140 public void init(File file, boolean coldStart)
145 if (database.exists())
149 k2v = new Hashtable();
150 v2k = new Hashtable();
155 FileInputStream fi = new FileInputStream(file);
156 BufferedInputStream b = new BufferedInputStream(fi);
157 ObjectInputStream oin = new AdaptedReader(b);
159 k2v = (Map) oin.readObject();
162 v2k = new Hashtable(k2v.size());
164 // Reguild v2k from k2v:
165 Iterator en = k2v.keySet().iterator();
170 v2k.put(k2v.get(key), key);
176 k2v = new Hashtable();
177 v2k = new Hashtable();
180 catch (Exception ioex)
182 InternalError ierr = new InternalError("Unable to intialize with file "
184 ierr.initCause(ioex);
190 * Write the database content to the disk.
192 public synchronized void writeContent()
196 FileOutputStream fou = new FileOutputStream(database);
197 BufferedOutputStream b = new BufferedOutputStream(fou);
198 ObjectOutputStream oout = new ObjectOutputStream(b);
199 oout.writeObject(k2v);
202 catch (Exception ioex)
204 InternalError ierr = new InternalError(
205 "Failed to write database to disk: "
207 ierr.initCause(ioex);
213 * Mark the modified database as modified. The database will be written after
214 * several seconds, unless another modification occurs.
216 public void markDirty()
218 if (System.currentTimeMillis() - lastUpdated > ALWAYS_UPDATE)
220 // Force storing to disk under intensive operation.
222 lastUpdated = System.currentTimeMillis();
223 if (sheduled != null)
231 // Otherwise coalesce the disk database copy update events.
232 if (sheduled != null)
234 sheduled = new WriteToDiskTask();
235 timer.schedule(sheduled, SAVE_AT_MOST_AFTER);
240 * Save the current database state to the disk before exit.
242 public void shutdown()
244 if (sheduled != null)
252 * Update the memory maps and mark as should be written to the disk.
254 public void put(Object key, Object value)
256 super.put(key, value);
261 * Update the memory maps and mark as should be written to the disk.
263 public void removeKey(Object key)
265 super.removeKey(key);