db-jdo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From m..@apache.org
Subject svn commit: r171355 [3/31] - in /incubator/jdo/trunk/fostore20: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/fostore/ test/ test/conf/ test/fsuid2/ test/fsuid2/org/ test/fsuid2/org/apache/ test/fsuid2/org/apache/jdo/ test/fsuid2/org/apache/jdo/pc/ test/java/ test/java/org/ test/java/org/apache/ test/java/org/apache/jdo/ test/java/org/apache/jdo/impl/ test/java/org/apache/jdo/impl/fostore/ test/java/org/apache/jdo/pc/ test/java/org/apache/jdo/pc/appid/ test/java/org/apache/jdo/pc/empdept/ test/java/org/apache/jdo/pc/serializable/ test/java/org/apache/jdo/pc/xempdept/ test/java/org/apache/jdo/test/ test/java/org/apache/jdo/test/query/ test/java/org/apache/jdo/test/util/ test/jdo/ test/jdo/org/ test/jdo/org/apache/ test/jdo/org/apache/jdo/ test/jdo/org/apache/jdo/pc/ test/jdo/org/apache/jdo/pc/appid/ test/jdo/org/apache/jdo/pc/empdept/ test/jdo/org/apache/jdo/pc/serializable/ test/jdo/org/apache/jdo/pc/xempdept/
Date Sun, 22 May 2005 18:40:21 GMT
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CLID.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CLID.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CLID.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CLID.java Sun May 22 11:40:13 2005
@@ -0,0 +1,525 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import javax.jdo.spi.PersistenceCapable;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Represents a class id.  These are in no way visible to clients, but are an
+* integral part of an OID.  Each distinct CLID represents a different class.
+* In this sense, a 'different class' is one which is structurally distinct
+* from all others.  Two classes with (e.g.) different fields with the same
+* name will therefore be considered different and hence have different
+* CLID's (methods, however, are not considered by structural equivalence).
+* @see OID
+*
+* @author Dave Bristor
+*/
+// XXX TBD Remote: Allocate provisional CLID's per-PMF w/ remote store.
+class CLID {
+    private static final int PROVISIONAL_MASK = 0x01000000;
+
+    // Indicates if this CLID is provisional.
+    private final boolean provisional;
+
+    // The "value" of this CLID.
+    private final int id;
+
+    // Value used to create the next provisional CLID
+    private static int nextProvisional = 0;
+
+    // For synchronizing access to nextProvisional;
+    private static final Integer lock = new Integer(1);
+
+    // Hashcode uniquely identifying this CLID within this JVM.
+    private final int hashCode;
+
+    // Minimum value for a CLID that is created by code that is a client of
+    // this class.  See the knownCLID table below, and make sure that it has
+    // less than this many elements.
+    private static final int MIN_USER_CLID = 100;
+
+    /**
+    * We reserve the first 100 CLID's for internal use.  We have no purpose
+    * for them (yet) but this allows for future expansion.
+    */
+    public static final CLID firstCLID = new CLID(MIN_USER_CLID, false);
+
+    private static I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+    
+    private CLID(int id, boolean provisional) {
+        this.id = id;
+        this.provisional = provisional;
+        this.hashCode = new Integer(id).hashCode();
+    }
+
+    static CLID createProvisional() {
+        CLID rc = null;
+        synchronized(lock) {
+            nextProvisional++;
+            if (nextProvisional <= OID.MAX_CLID) {
+                rc = new CLID(nextProvisional, true);
+            }
+        }
+        if (null == rc) {
+            throw new FOStoreFatalInternalException(
+                CLID.class, "createProvisional", // NOI18N
+                msg.msg("ERR_OutOfProvisionalCLIDs", // NOI18N
+                        new Integer(OID.MAX_CLID)));
+        }
+        return rc;
+    }
+
+    static CLID create(int id, boolean provisional) {
+        if (id > OID.MAX_CLID) {
+            throw new FOStoreFatalInternalException(
+                CLID.class, "create", // NOI18N
+                msg.msg("ERR_InvalidRange", new Integer(id), // NOI18N
+                        new Integer(MIN_USER_CLID), new Integer(OID.MAX_CLID)));
+        }
+        return new CLID(id, provisional);
+    }
+
+    // These are to be able to get the class of an array of a type.  They're
+    // not private, in order to allow FOStoreTranscriber.ObjectTranscriber to
+    // share them.
+    static final OID oidArray[]         = new OID[0];
+    static final boolean booleanArray[] = new boolean[0];
+    static final char charArray[]       = new char[0];
+    static final byte byteArray[]       = new byte[0];
+    static final short shortArray[]     = new short[0];
+    static final int intArray[]         = new int[0];
+    static final long longArray[]       = new long[0];
+    static final float floatArray[]     = new float[0];
+    static final double doubleArray[]   = new double[0];
+    
+    static final Boolean BooleanArray[] = new Boolean[0];
+    static final Character CharacterArray[]       = new Character[0];
+    static final Byte ByteArray[]       = new Byte[0];
+    static final Short ShortArray[]     = new Short[0];
+    static final Integer IntegerArray[]         = new Integer[0];
+    static final Long LongArray[]       = new Long[0];
+    static final Float FloatArray[]     = new Float[0];
+    static final Double DoubleArray[]   = new Double[0];
+    
+    static final String StringArray[]   = new String[0];
+
+    //static final TreeMap TreeMapArray[] = new TreeMap[0];
+    static final BigDecimal BigDecimalArray[] = new BigDecimal[0];
+    static final BigInteger BigIntegerArray[] = new BigInteger[0];
+    static final BitSet BitSetArray[] = new BitSet[0];
+    static final Locale LocaleArray[] = new Locale[0];
+
+    static final java.util.Date utilDateArray[] = new java.util.Date[0];
+    static final org.apache.jdo.impl.sco.Date scoDateArray[] = new org.apache.jdo.impl.sco.Date[0];
+    static final java.sql.Date sqlDateArray[] = new java.sql.Date[0];
+    static final org.apache.jdo.impl.sco.SqlDate scoSqlDateArray[] = new org.apache.jdo.impl.sco.SqlDate[0];
+
+    static final java.util.ArrayList utilArrayListArray[] = new java.util.ArrayList[0];
+    static final org.apache.jdo.impl.sco.ArrayList scoArrayListArray[] = new org.apache.jdo.impl.sco.ArrayList[0];
+    static final java.util.Vector utilVectorArray[] = new java.util.Vector[0];
+    static final org.apache.jdo.impl.sco.Vector scoVectorArray[] = new org.apache.jdo.impl.sco.Vector[0];
+    static final java.util.HashSet utilHashSetArray[] = new java.util.HashSet[0];
+    static final org.apache.jdo.impl.sco.HashSet scoHashSetArray[] = new org.apache.jdo.impl.sco.HashSet[0];
+    static final java.util.TreeSet utilTreeSetArray[] = new java.util.TreeSet[0];
+    static final org.apache.jdo.impl.sco.TreeSet scoTreeSetArray[] = new org.apache.jdo.impl.sco.TreeSet[0];
+    static final java.util.LinkedList utilLinkedListArray[] = new java.util.LinkedList[0];
+    static final org.apache.jdo.impl.sco.LinkedList scoLinkedListArray[] = new org.apache.jdo.impl.sco.LinkedList[0];
+    static final java.util.HashMap utilHashMapArray[] = new java.util.HashMap[0];
+    static final org.apache.jdo.impl.sco.HashMap scoHashMapArray[] = new org.apache.jdo.impl.sco.HashMap[0];
+    static final java.util.Hashtable utilHashtableArray[] = new java.util.Hashtable[0];
+    static final org.apache.jdo.impl.sco.Hashtable scoHashtableArray[] = new org.apache.jdo.impl.sco.Hashtable[0];
+    static final java.util.TreeMap utilTreeMapArray[] = new java.util.TreeMap[0];
+    static final org.apache.jdo.impl.sco.TreeMap scoTreeMapArray[] = new org.apache.jdo.impl.sco.TreeMap[0];
+
+    // Table mapping instances of java.lang.Class to CLID.  Represents CLIDs
+    // that are compile-time known.
+    private static HashMap knownCLIDs = new HashMap();
+
+    // Table mapping CLIDs to instancs of java.lang.Class for those CLIDs that
+    // represent classes for which we have both a java.* class and an SCO
+    // class (such as Date).
+    private static HashMap scoCLIDs = new HashMap();
+
+    // For numbering knownCLID's
+    static int nextCLID = 1;
+
+    // The CLID's for some classes are considered to be well-known, and
+    // are given below.  We provide a special method for writing out the CLID
+    // of a known class.  The "null" CLID gets special treatment.
+    //
+    static final CLID nullCLID = new CLID(0, false);
+
+    // CLIDs for special, well-known kinds of objects.
+    static final CLID forOID = new CLID(nextCLID++,  false);
+    static final CLID forOIDArray = new CLID(nextCLID++,  false);
+
+    static {
+        // Used only for inserting into knownCLIDs, scoCLIDs tables.
+        CLID tmpCLID;
+
+        knownCLIDs.put(OID.class,       forOID);
+
+        // Primitives
+        knownCLIDs.put(boolean.class,   new CLID(nextCLID++,  false));
+        knownCLIDs.put(char.class,      new CLID(nextCLID++,  false));
+        knownCLIDs.put(byte.class,      new CLID(nextCLID++,  false));
+        knownCLIDs.put(short.class,     new CLID(nextCLID++,  false));
+        knownCLIDs.put(int.class,       new CLID(nextCLID++,  false));
+        knownCLIDs.put(long.class,      new CLID(nextCLID++,  false));
+        knownCLIDs.put(float.class,     new CLID(nextCLID++,  false));
+        knownCLIDs.put(double.class,    new CLID(nextCLID++,  false));
+
+        // Immutables
+        knownCLIDs.put(Boolean.class,   new CLID(nextCLID++, false));
+        knownCLIDs.put(Character.class, new CLID(nextCLID++, false));
+        knownCLIDs.put(Byte.class,      new CLID(nextCLID++, false));
+        knownCLIDs.put(Short.class,     new CLID(nextCLID++, false));
+        knownCLIDs.put(Integer.class,   new CLID(nextCLID++, false));
+        knownCLIDs.put(Long.class,      new CLID(nextCLID++, false));
+        knownCLIDs.put(Float.class,     new CLID(nextCLID++, false));
+        knownCLIDs.put(Double.class,    new CLID(nextCLID++, false));
+
+        // String
+        knownCLIDs.put(String.class,    new CLID(nextCLID++, false));
+
+        // Collections for which we don't have an SCO equivalent
+
+        // Maps for which we don't have an SCO equivalent
+
+        // Numbers
+        knownCLIDs.put(BigDecimal.class, new CLID(nextCLID++, false));
+        knownCLIDs.put(BigInteger.class, new CLID(nextCLID++, false));
+
+        // BitSet
+        knownCLIDs.put(BitSet.class,     new CLID(nextCLID++, false));
+
+        // Locale
+        knownCLIDs.put(Locale.class,     new CLID(nextCLID++, false));
+
+        // Note: util and SCO CLID's
+        // We use the same CLID for the util and SCO classes.  Consider the
+        // case in which application code creates a field of a util class for
+        // which JDORI has a corresponding SCO class (e.g. Date).  When the
+        // field value is fetched, FOStore instantiates an instance of the
+        // SCO class regardless.
+        //
+        // So, we use the same CLID for each util/SCO pair.  And we make an
+        // entry in scoCLIDs from the CLID to the SCO class.
+
+        // Simple SCO's and their non-SCO equivalents.
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(java.util.Date.class, tmpCLID);
+        knownCLIDs.put(org.apache.jdo.impl.sco.Date.class, tmpCLID);
+        scoCLIDs.put(tmpCLID, org.apache.jdo.impl.sco.Date.class);
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(java.sql.Date.class, tmpCLID);
+        knownCLIDs.put(org.apache.jdo.impl.sco.SqlDate.class, tmpCLID);
+        scoCLIDs.put(tmpCLID, org.apache.jdo.impl.sco.SqlDate.class);
+
+        // Collection SCO's and their non-SCO equivalents.
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(java.util.ArrayList.class, tmpCLID);
+        knownCLIDs.put(org.apache.jdo.impl.sco.ArrayList.class, tmpCLID);
+        scoCLIDs.put(tmpCLID, org.apache.jdo.impl.sco.ArrayList.class);
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(java.util.Vector.class, tmpCLID);
+        knownCLIDs.put(org.apache.jdo.impl.sco.Vector.class, tmpCLID);
+        scoCLIDs.put(tmpCLID, org.apache.jdo.impl.sco.Vector.class);
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(java.util.HashSet.class, tmpCLID);
+        knownCLIDs.put(org.apache.jdo.impl.sco.HashSet.class, tmpCLID);
+        scoCLIDs.put(tmpCLID, org.apache.jdo.impl.sco.HashSet.class);
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(java.util.TreeSet.class, tmpCLID);
+        knownCLIDs.put(org.apache.jdo.impl.sco.TreeSet.class, tmpCLID);
+        scoCLIDs.put(tmpCLID, org.apache.jdo.impl.sco.TreeSet.class);
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(java.util.LinkedList.class, tmpCLID);
+        knownCLIDs.put(org.apache.jdo.impl.sco.LinkedList.class, tmpCLID);
+        scoCLIDs.put(tmpCLID, org.apache.jdo.impl.sco.LinkedList.class);
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(java.util.HashMap.class, tmpCLID);
+        knownCLIDs.put(org.apache.jdo.impl.sco.HashMap.class, tmpCLID);
+        scoCLIDs.put(tmpCLID, org.apache.jdo.impl.sco.HashMap.class);
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(java.util.Hashtable.class, tmpCLID);
+        knownCLIDs.put(org.apache.jdo.impl.sco.Hashtable.class, tmpCLID);
+        scoCLIDs.put(tmpCLID, org.apache.jdo.impl.sco.Hashtable.class);
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(java.util.TreeMap.class, tmpCLID);
+        knownCLIDs.put(org.apache.jdo.impl.sco.TreeMap.class, tmpCLID);
+        scoCLIDs.put(tmpCLID, org.apache.jdo.impl.sco.TreeMap.class);
+
+        // Arrays for all of the above
+        knownCLIDs.put(oidArray.getClass(),     forOIDArray);
+        knownCLIDs.put(booleanArray.getClass(), new CLID(nextCLID++, false));
+        knownCLIDs.put(charArray.getClass(),    new CLID(nextCLID++, false));
+        knownCLIDs.put(byteArray.getClass(),    new CLID(nextCLID++, false));
+        knownCLIDs.put(shortArray.getClass(),   new CLID(nextCLID++, false));
+        knownCLIDs.put(intArray.getClass(),     new CLID(nextCLID++, false));
+        knownCLIDs.put(longArray.getClass(),    new CLID(nextCLID++, false));
+        knownCLIDs.put(floatArray.getClass(),   new CLID(nextCLID++, false));
+        knownCLIDs.put(doubleArray.getClass(),  new CLID(nextCLID++, false));
+        
+        knownCLIDs.put(BooleanArray.getClass(), new CLID(nextCLID++, false));
+        knownCLIDs.put(CharacterArray.getClass(),    new CLID(nextCLID++, false));
+        knownCLIDs.put(ByteArray.getClass(),    new CLID(nextCLID++, false));
+        knownCLIDs.put(ShortArray.getClass(),   new CLID(nextCLID++, false));
+        knownCLIDs.put(IntegerArray.getClass(),     new CLID(nextCLID++, false));
+        knownCLIDs.put(LongArray.getClass(),    new CLID(nextCLID++, false));
+        knownCLIDs.put(FloatArray.getClass(),   new CLID(nextCLID++, false));
+        knownCLIDs.put(DoubleArray.getClass(),  new CLID(nextCLID++, false));
+        
+        knownCLIDs.put(StringArray.getClass(),  new CLID(nextCLID++, false));
+
+        // Numbers
+        knownCLIDs.put(BigDecimalArray.getClass(), new CLID(nextCLID++, false));
+        knownCLIDs.put(BigIntegerArray.getClass(), new CLID(nextCLID++, false));
+
+        // BitSet
+        knownCLIDs.put(BitSetArray.getClass(),     new CLID(nextCLID++, false));
+
+        // Locale
+        knownCLIDs.put(LocaleArray.getClass(),     new CLID(nextCLID++, false));
+
+        // Arrays of simple SCO's and their non-SCO equivalents.
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(utilDateArray.getClass(), tmpCLID);
+        knownCLIDs.put(scoDateArray.getClass(), tmpCLID);
+        scoCLIDs.put(tmpCLID, scoDateArray.getClass());
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(sqlDateArray.getClass(), tmpCLID);
+        knownCLIDs.put(scoSqlDateArray.getClass(), tmpCLID);
+        scoCLIDs.put(tmpCLID, scoSqlDateArray.getClass());
+
+        // Arrays of collection SCO's and their non-SCO equivalents.
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(utilArrayListArray.getClass(), tmpCLID);
+        knownCLIDs.put(scoArrayListArray.getClass(), tmpCLID);
+        scoCLIDs.put(tmpCLID, scoArrayListArray.getClass());
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(utilVectorArray.getClass(), tmpCLID);
+        knownCLIDs.put(scoVectorArray.getClass(), tmpCLID);
+        scoCLIDs.put(tmpCLID, scoVectorArray.getClass());
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(utilHashSetArray.getClass(), tmpCLID);
+        knownCLIDs.put(scoHashSetArray.getClass(), tmpCLID);
+        scoCLIDs.put(tmpCLID, scoHashSetArray.getClass());
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(utilTreeSetArray.getClass(), tmpCLID);
+        knownCLIDs.put(scoTreeSetArray.getClass(), tmpCLID);
+        scoCLIDs.put(tmpCLID, scoTreeSetArray.getClass());
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(utilLinkedListArray.getClass(), tmpCLID);
+        knownCLIDs.put(scoLinkedListArray.getClass(), tmpCLID);
+        scoCLIDs.put(tmpCLID, scoLinkedListArray.getClass());
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(utilHashMapArray.getClass(), tmpCLID);
+        knownCLIDs.put(scoHashMapArray.getClass(), tmpCLID);
+        scoCLIDs.put(tmpCLID, scoHashMapArray.getClass());
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(utilHashtableArray.getClass(), tmpCLID);
+        knownCLIDs.put(scoHashtableArray.getClass(), tmpCLID);
+        scoCLIDs.put(tmpCLID, scoHashtableArray.getClass());
+
+        tmpCLID = new CLID(nextCLID++, false);
+        knownCLIDs.put(utilTreeMapArray.getClass(), tmpCLID);
+        knownCLIDs.put(scoTreeMapArray.getClass(), tmpCLID);
+        scoCLIDs.put(tmpCLID, scoTreeMapArray.getClass());
+    }
+
+
+    /**
+     * Indicate whether a Class is known, that is, has built-in support
+     * @return true if known, false otherwise
+     */
+    static boolean isKnown(Class cls) {
+        return getKnownCLID(cls) != null;
+    }
+
+    /**
+    * Get the CLID that corresponds to the given Class.  Return null if there
+    * is no such CLID.
+    */
+    static CLID getKnownCLID(Class cls) {
+        CLID rc = (CLID)knownCLIDs.get(cls);
+        if (null == rc) {
+            if (cls.isArray()) {
+                Class componentType = cls.getComponentType();
+                if (PersistenceCapable.class.isAssignableFrom(componentType)) {
+                    rc = CLID.forOIDArray;
+                }
+            }
+        }
+        return rc;
+    }
+
+    /**
+    * Writes the CLID for the given class, which *must* be a known class
+    */ 
+    static void writeForKnown(Class cls, DataOutput out)
+        throws IOException {
+
+        CLID clid = (CLID)knownCLIDs.get(cls);
+        if (null != clid) {
+            clid.write(out);
+        } else {
+            throw new FOStoreFatalInternalException(
+                CLID.class, "writeForKnown", // NOI18N
+                msg.msg("ERR_Unknown", cls.getName())); // NOI18N
+        }
+    }
+
+    /**
+    * Get the java.lang.Class that corresponds to the given CLID.
+    */
+    static Class getKnownType(CLID clid) {
+        Class rc = null;
+        
+        // If the CLID corresponds to a java.* class for which we have an SCO
+        // equivalent, return the SCO Class.  This test is separate because
+        // the knownCLIDs HashMap contains, for those cases, both the java.*
+        // class and the SCO class mapped to the *same* CLID.
+        rc = (Class)scoCLIDs.get(clid);
+        
+        if (null == rc) {
+            Set entries = knownCLIDs.entrySet();
+            for (Iterator i = entries.iterator(); i.hasNext();) {
+                Map.Entry entry = (Map.Entry)i.next();
+                CLID ci = (CLID)entry.getValue();
+                if (clid.equals(ci)) {
+                    rc = (Class)entry.getKey();
+                    break;
+                }
+            }
+        }
+        return rc;
+    }
+
+    /**
+     * Indicates whether the given CLID is provisional or not.  A 'provisonal'
+     * CLID is one that has been allocated within a JVM, but for which the
+     * corresponding class is not yet known to have a correspondence in the
+     * store itself.
+     * @return True if this CLID is provisonal, false otherwise.
+     */
+    boolean isProvisional() {
+        return provisional;
+    }
+
+    // hashCode and the public equals are required for HashMaps, such as the
+    // provisional CLID map.
+    public int hashCode() {
+        return hashCode;
+    }
+    
+    public boolean equals(Object other) {
+        boolean rc = false;
+        if (other instanceof CLID) {
+            CLID clid = (CLID)other;
+            rc = id == clid.id && provisional == clid.provisional;
+        }
+        return rc;
+    }
+
+    //
+    // Serialization.  Not java.io.Serialization serialization, just what we
+    // need for the store.
+    //
+    
+    void write(DataOutput out) throws IOException {
+        int writtenId = id;
+        if (provisional) {
+            writtenId |= PROVISIONAL_MASK;
+        }
+        out.writeInt(writtenId);
+    }
+
+    static CLID read(DataInput in) throws IOException {
+        int id = in.readInt();
+        boolean provisional = (id & PROVISIONAL_MASK) > 0;
+        if (provisional) {
+            id &= ~PROVISIONAL_MASK;
+        }
+
+        return new CLID(id, provisional);
+    }
+
+    /**
+    * Provides a new CLID whose id is one greater than this one's.
+    * @return A new CLID.  */
+    CLID next() {
+        return new CLID(id + 1, false);
+    }
+
+    /**
+    * Provides the id part of a CLID.
+    * @return The CLID's representation.
+    */
+    int getId() {
+        return id;
+    }
+
+    // For debugging
+    public String toString() {
+        StringBuffer rc = new StringBuffer("CLID: " + id); // NOI18N
+        if (provisional) {
+            rc.append(" (provisional)"); // NOI18N
+        }
+        return rc.toString();
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CharTranscriber.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CharTranscriber.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CharTranscriber.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CharTranscriber.java Sun May 22 11:40:13 2005
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+* Transcribes char values.
+*
+* @author Dave Bristor
+*/
+class CharTranscriber extends FOStoreTranscriber {
+    private static CharTranscriber instance = new CharTranscriber();
+
+    private CharTranscriber() {}
+
+    static CharTranscriber getInstance() {
+        return instance;
+    }
+    
+    void storeChar(char value, DataOutput out) throws IOException {
+        out.writeChar(value);
+    }
+
+    char fetchChar(DataInput in) throws IOException {
+        return in.readChar();
+    }
+
+    void skip(DataInput in) throws IOException { 
+        in.readChar(); 
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CommitHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CommitHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CommitHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CommitHandler.java Sun May 22 11:40:13 2005
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.IOException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Process Commit requests.
+*
+* @author Dave Bristor
+*/
+// This is server-side code.  It does not need to live in the client.
+class CommitHandler extends RequestHandler {
+    /** Indicates whether or not the request should be honored.
+    */
+    private boolean okToCommit = true;
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+    private CommitHandler(Reply reply, int length,
+                         FOStoreServerConnection con) {
+
+        super(reply, length, con);
+    }
+    
+    public static final HandlerFactory factory =
+        new HandlerFactory() {
+                public RequestHandler getHandler(Reply reply, int length,
+                                             FOStoreServerConnection con) {
+                return new CommitHandler(reply, length, con);
+            }};
+
+    /**
+     * An instance of this class is the means by which a commit actually
+     * happens.  We must do this in a finisher, and not in handleRequest,
+     * because the finishers for insert, etc. must run before we commit.
+     */
+    private class CommitFinisher implements RequestFinisher {
+        private final FOStoreServerConnection con;
+
+        CommitFinisher(FOStoreServerConnection con) {
+            this.con = con;
+        }
+
+        /**
+         * Really commit.
+         */
+        public void finish() {
+            if (logger.isDebugEnabled()) {
+                logger.debug("CommitFinisher.finish: " + okToCommit); // NOI18N
+            }
+            if (okToCommit) {
+                try {
+                    con.commit();
+                } catch (FOStoreDatabaseException ex) {
+                    throw new FOStoreFatalInternalException(
+                        this.getClass(), "finish", // NOI18N
+                        msg.msg("ERR_CommitFailed", ex)); // NOI18N
+                }
+            }
+        }
+    }
+
+    protected void setOkToCommit(boolean okToCommit) {
+        this.okToCommit = okToCommit;
+    }
+    
+    RequestFinisher handleRequest()
+        throws IOException, FOStoreDatabaseException {
+
+        FOStoreInput in = con.getInputFromClient();
+        boolean okToReleaseDatabase = in.readBoolean();
+
+        if (logger.isDebugEnabled()) logger.debug(
+            "CommitHandler.hR: ok=" + okToReleaseDatabase); // NOI18N
+
+        con.setOkToReleaseDatabase(okToReleaseDatabase);
+        reply.setStatus(Status.OK);
+
+        return new CommitFinisher(con);
+    }
+}
+
+
+
+
+
+

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CommitRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CommitRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CommitRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CommitRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+/**
+* Represents a request to cause previous insert, update, and so on
+* operations since the previous Commit or Rollback request to commit to
+* the datastore.
+*
+* @author Dave Bristor
+*/
+//
+// This is client-side code.  It does not need to live in the server.
+//
+class CommitRequest extends AbstractRequest {
+    /** Message in which this request is written
+     */
+    private final Message message;
+
+    /** If true, then after committing the database should be released.
+     */
+    private boolean okToReleaseDatabase = true;
+    
+    CommitRequest(Message m, FOStorePMF pmf) {
+        super(m, pmf);
+        this.message = m;
+    }
+
+    void setOkToReleaseDatabase(boolean ok) {
+        okToReleaseDatabase = ok;
+    }
+
+    //
+    // Methods from AbstractRequest
+    //
+
+    /**
+     * Provides the information required to fulfill a CommitRequest.
+     * The format of this request is (aside from the request header):
+     * 
+     * boolean: okToReleaseDatabase
+     */
+    protected void doRequestBody() throws IOException {
+        if (logger.isDebugEnabled()) 
+            logger.debug("CommitRequest.dRB: ok=" + // NOI18N
+                         okToReleaseDatabase);
+
+        out.writeBoolean(okToReleaseDatabase);
+    }
+
+    //
+    // Methods from Request
+    //
+
+    /**
+     * Handles reply data from a CommitReply.
+     */
+    public void handleReply(Status status, DataInput in, int length)
+        throws IOException {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("CommitRequest.hR " + status); // NOI18N
+        }
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CreateOIDHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CreateOIDHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CreateOIDHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CreateOIDHandler.java Sun May 22 11:40:13 2005
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import javax.jdo.JDOUserException;
+
+/**
+* Process CreateOIDRequests.  Causes allocation of a new OID in the datastore.
+*
+* @author Dave Bristor
+*/
+//
+// This is server-side code.  It does not need to live in the client.
+//
+class CreateOIDHandler extends RequestHandler {
+    private CreateOIDHandler(Reply reply, int length,
+                         FOStoreServerConnection con) {
+
+        super(reply, length, con);
+    }
+    
+    public static final HandlerFactory factory =
+        new HandlerFactory() {
+                public RequestHandler getHandler(Reply reply, int length,
+                                             FOStoreServerConnection con) {
+                return new CreateOIDHandler(reply, length, con);
+            }};
+
+    RequestFinisher handleRequest()
+        throws IOException, FOStoreDatabaseException {
+
+        FOStoreDatabase fodb = con.getDatabase();
+        DataInput in = con.getInputFromClient();
+        OID oid = OID.read(in);
+
+        CLID clid = oid.getCLID();
+        if (clid.isProvisional()) {
+            clid = fodb.getRealCLIDFromProvisional(clid);
+        }
+
+        DBInfo dbInfo = fodb.getDBInfo();
+        OID realOID;
+        if (oid.isProvisional()) {
+            realOID = dbInfo.newInstanceOID(clid);
+        } else {
+            realOID = oid;
+        }
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("CreateOIDHandler.hR: " + oid + " -> " + realOID); // NOI18N
+        }
+
+        if (oid.isProvisional()) {
+            fodb.mapProvisionalOIDToReal(oid, realOID);
+        }
+
+        reply.writeOID(realOID);
+        reply.setStatus(Status.OK);
+
+        return null;
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CreateOIDRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CreateOIDRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CreateOIDRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/CreateOIDRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.state.StateManagerInternal;
+
+
+/**
+ * Causes a datastore OID to be associated with a provisional OID.
+ *
+ * @author Dave Bristor
+ */
+//
+// This is client-side code.  It does not need to live in the server.
+//
+class CreateOIDRequest extends AbstractRequest {
+    private final OID oid;
+    private final PersistenceManagerInternal pm;
+
+    CreateOIDRequest(StateManagerInternal sm, Message m, FOStorePMF pmf,
+                     OID oid, PersistenceManagerInternal pm) {
+        super(sm, m, pmf);
+        
+        this.oid = oid;
+        this.pm = pm;
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("CreateOIDRequest: " + oid); // NOI18N
+        }
+    }
+
+    //
+    // Methods from AbstractRequest
+    //
+
+    protected void doRequestBody() throws IOException {
+        oid.write(out); 
+    }
+
+    //
+    // Methods from Request
+    //
+
+    public void handleReply(Status status, DataInput in, int length)
+    throws IOException {
+
+        OID realOID = OID.read(in);
+        oid.replaceProvisionalOIDWithReal(realOID, pmf, sm);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "CreateOIDRequest.hR: " + oid + " -> " + realOID); // NOI18N
+        }
+
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBClass.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBClass.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBClass.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBClass.java Sun May 22 11:40:13 2005
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.netbeans.mdr.persistence.Streamable;
+import org.netbeans.mdr.persistence.StorageException;
+import org.netbeans.mdr.persistence.StorageIOException;
+
+/**
+* Represents a class stored in the database.
+* <p>
+* This class is <code>public</code> so that it can be used as a
+* <code>Streamable</code> and stored in the database.
+*
+* @author Dave Bristor
+*/
+public class DBClass implements Streamable {
+    // These are not final, because we must implement Streamable to store
+    // DBClass instances in the btree, and later read them out.
+    
+    /** Fully qualified name of the class represented. */
+    private String name;
+
+    /** CLID corresponding to the class.  It might be provisional, until the
+     * finishing phase of request handling has run. */
+    private CLID clid;
+
+    /** FSUID corresponding to the class. */
+    private FOStoreSchemaUID fsuid;
+
+    /** Lists the class's PersistenceCapable superclasses, from the class to
+     * Object.  Null unless the class has PersistenceCapable superclasses. */
+    private ClassDetail supers[] = null;
+
+    /** The fields of the class.  Null unless the class has fields. */
+    private ClassDetail fields[] = null;
+
+    /** Indicates whether the CLIDs of any superclass or field were given as
+     * provisional. */
+    private transient boolean hasProvisionals = false;
+
+    /** Logger */
+    static final Log logger = LogFactory.getFactory().getInstance(
+        "org.apache.jdo.impl.fostore"); // NOI18N
+
+    /** A ClassDetail represents a single field or PC superclass of a class
+    * that is (or was at one time) stored in the databse.  When created, the
+    * given CLID might be provisional.  If so, it will be replaced with a
+    * real CLID during ActivateClassHandler's finish phase.
+    * @see ActivateClassHandler#handleRequest
+    */
+    class ClassDetail {
+        /** Name of the field or superclass. */
+        final String name;
+
+        /** CLID of the field or superclass.  Not final, because it may be
+         * provisional when the ClassDetail is created, and updated later
+         * during finishing. */
+        CLID clid;
+
+        /* FSUID of the field or superclass. */
+        final FOStoreSchemaUID fsuid;
+
+        ClassDetail(DataInput in) throws IOException {
+            name = in.readUTF();
+            clid = CLID.read(in);
+            fsuid = FOStoreSchemaUID.read(in);
+            if (logger.isDebugEnabled()) {
+                logger.debug(
+                    "DBClass: fieldName=" + name + ", " + clid); // NOI18N
+            }
+        }
+
+        void write(DataOutputStream dos) throws IOException {
+            dos.writeUTF(name);
+            clid.write(dos);
+            fsuid.write(dos);
+        }
+
+        /**
+         * If the current clid is provisional, replace it with a real one if
+         * possible.
+         */
+        void remap(FOStoreDatabase db) {
+            if (clid.isProvisional()) {
+                CLID rCLID = db.getRealCLIDFromProvisional(clid);
+                if (null != rCLID) {
+                    clid = rCLID;
+                    if (logger.isDebugEnabled()) {
+                        logger.debug(
+                            "ClassDetail.remap: " + clid + " -> " + // NOI18N
+                            rCLID);
+                    }
+                }
+            }
+        }        
+        
+        CLID getCLID() {
+            return clid;
+        }
+
+        void setCLID(CLID clid) {
+            this.clid = clid;
+        }
+
+        public String toString() {
+            return "'" + name + "' " + clid.toString(); // NOI18N
+        }
+    }
+    // end of class ClassDetail
+
+    /**
+     * Constructor
+     */
+    private DBClass(String name, CLID clid, FOStoreSchemaUID fsuid,
+                    DataInput in, FOStoreDatabase db) throws IOException{
+
+        this.name = name;
+        this.clid = clid;
+        this.fsuid = fsuid;
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("DBClass: " + name + ", " + clid // NOI18N
+                           + ", fsuid: " + fsuid); // NOI18N
+        }
+
+        int numSupers = in.readInt();
+        if (numSupers > 0) {
+            supers = new ClassDetail[numSupers];
+            getClassDetail(supers, in);
+        }
+
+        int numFields = in.readInt();
+        if (numFields > 0) {
+            fields = new ClassDetail[numFields];
+            getClassDetail(fields, in);
+        }
+    }
+
+    /**
+     * @see ActivateClassRequest#doRequestBody
+     */
+    static DBClass create(String name, CLID clid, FOStoreSchemaUID fsuid,
+                          DataInput in, FOStoreDatabase db)
+        throws IOException{
+
+        return new DBClass(name, clid, fsuid, in, db);
+    }
+
+    /**
+     * Gets the details for as many slots as are in the given array.
+     */
+    private void getClassDetail(ClassDetail details[], DataInput in)
+        throws IOException {
+
+        int length = details.length;
+        for (int i = 0; i < length; i++) {
+            ClassDetail detail = new ClassDetail(in);
+            details[i] = detail;
+            CLID detailCLID = detail.getCLID();
+            if (detailCLID.isProvisional()) {
+                hasProvisionals = true;
+            }
+        }
+    }
+
+
+    /**
+    * @return True if any of this DBClass's fields or superclasses has a CLID
+    * that is provisional.
+    */
+    // In that case, ActivateClassHandler should cause remapCLIDs to be
+    // invoked during finishing.
+    boolean hasProvisionals() {
+        return hasProvisionals;
+    }
+
+    /**
+    * Changes the CLID mapping of this DBClass's fields and PC superclasses
+    * in the database as from provisional to real as necessary.
+    * @param db Database in which to find the provisional-to-real mapping.
+    */
+    void remapCLIDs(FOStoreDatabase db) {
+        remapCLIDs(supers, db);
+        remapCLIDs(fields, db);
+    }
+
+    /**
+     * Changes provisional CLIDs to real CLIDs in the given ClassDetails.
+     */
+    private void remapCLIDs(ClassDetail details[], FOStoreDatabase db) {
+        if (null != details  && details.length > 0) {
+            int length = details.length;
+            for (int i = 0; i < length; i++) {
+                details[i].remap(db);
+            }
+        }
+    }
+
+    /**
+    * @return True if this DBClass has superclasses.
+    */
+    // In that case, ActivateClassHandler should cause setupSubclasses to be
+    // invoked during finishing.
+    boolean hasSuperclasses() {
+        return null != supers;
+    }
+
+    /**
+    * Sets up subclass relationships between this DBClass and its superclass
+    * DBClass instances.
+    */
+    // Invariants: all superclasses of this DBClass have already been
+    // processed, and this class *does* have superclasses.
+    void setupSubclasses(FOStoreDatabase db) throws FOStoreDatabaseException {
+        int length = supers.length;
+        for (int i = 0; i < length; i++) {
+            CLID superCLID = supers[i].getCLID();
+            if (logger.isDebugEnabled()) {
+                logger.debug("DBClass.setupSubclasses for " + clid + //NOI18N
+                    " superclass: " + superCLID); // NOI18N
+            }
+            OID subclassSetOID = DBInfo.getSubclassSetOID(superCLID);
+            SubclassSet ss = (SubclassSet)db.getIfExists(subclassSetOID);
+            if (null == ss) {
+                ss = SubclassSet.create(subclassSetOID, clid);
+            } else {
+                ss.add(clid);
+            }
+            db.put(subclassSetOID, ss);
+        }        
+    }
+
+    OID getOID() {
+        return DBInfo.getDBClassOID(clid);
+    }
+
+    CLID getCLID() {
+        return clid;
+    }
+
+    void setCLID(CLID clid) {
+        this.clid = clid;
+    }
+
+    String getName() {
+        return name;
+    }
+
+    FOStoreSchemaUID getFSUID() {
+        return fsuid;
+    }
+
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("DBClass '").append(name).append("' "); // NOI18N
+        sb.append(clid.toString());
+
+        if (null != supers) {
+            for (int i = 0; i < supers.length; i++) {
+                sb.append("\n    superclass " + supers[i].toString()); // NOI18N
+            }
+        }
+
+        if (null != fields) {
+            for (int i = 0; i < fields.length; i++) {
+                sb.append("\n    field " + fields[i].toString()); // NOI18N
+            }
+        }
+
+        sb.append("\n"); // NOI18N
+        return sb.toString();
+    }
+
+    //
+    // Implement Streamable
+    //
+
+    public DBClass() { }
+
+    /**
+    * Write this DBClass to the given stream.
+    */
+    public void write(OutputStream os) throws StorageException {
+        DataOutputStream dos = new DataOutputStream(os);
+
+        try {
+            dos.writeUTF(name);
+            clid.write(dos);
+            fsuid.write(dos);
+            
+            writeClassDetails(supers, dos);
+            writeClassDetails(fields, dos);
+        } catch (IOException ex) {
+            throw new StorageIOException(ex);
+        }
+    }
+
+    /**
+    * Write the given details of this DBClass to the given stream.
+    */
+    private void writeClassDetails(ClassDetail details[],
+                                   DataOutputStream dos) throws IOException {
+
+        if (null == details) {
+            dos.writeInt(0);
+        } else {
+            int length = details.length;
+            dos.writeInt(length);
+            for (int i = 0; i < length; i++) {
+                details[i].write(dos);
+            }
+        }
+    }
+
+    /**
+    * Initialize this DBClass from the given stream.
+    */
+    public void read(InputStream is) throws StorageException {
+        DataInputStream dis = new DataInputStream(is);
+        try {
+            this.name = dis.readUTF();
+            this.clid = CLID.read(dis);
+            this.fsuid = FOStoreSchemaUID.read(dis);
+            
+            int length = dis.readInt();
+            if (length > 0) {
+                supers = new ClassDetail[length];
+                readClassDetails(supers, dis);
+            }
+
+            length = dis.readInt();
+            if (length > 0) {
+                fields = new ClassDetail[length];
+                readClassDetails(fields, dis);
+            }
+        } catch (IOException ex) {
+            throw new StorageIOException(ex);
+        }
+    }
+
+    /**
+    * Read details from the given input stream.
+    */
+    private void readClassDetails(ClassDetail details[],
+                                  DataInputStream dis) throws IOException {
+        
+        int length = details.length;
+        for (int i = 0; i < length; i++) {
+            details[i] = new ClassDetail(dis);
+        }
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBExtent.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBExtent.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBExtent.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBExtent.java Sun May 22 11:40:13 2005
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import javax.jdo.JDOFatalInternalException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.util.I18NHelper;
+import org.netbeans.mdr.persistence.Streamable;
+import org.netbeans.mdr.persistence.StorageException;
+import org.netbeans.mdr.persistence.StorageIOException;
+
+/**
+* Represents a set of instances of a given class stored in the database.
+* <p>
+* This class is <code>public</code> so that it can be used as a
+* <code>Streamable</code> and stored in the database.
+*
+* @author Dave Bristor
+*/
+public class DBExtent implements Streamable {
+    
+    /** This DBExtent lives in a database.
+     */
+    private FOStoreDatabase fodb;
+    
+    /** Name of the class of instances in this extent.
+    */
+    private String name;
+
+    /* Along with name, determines equality of extent instances.
+    */
+    private FOStoreSchemaUID fsuid;
+
+    /** CLID of the class of the instances of this extent.
+    */
+    private CLID classCLID;
+
+    /** OID of this extent.  Cached so that we don't have to calculate each
+    * time we store the extent
+    */
+    private OID extentOID;
+
+    /** OIDs of instances of this extent.
+    */
+    private HashSet instances = new HashSet();
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+    /** Logger */
+    static final Log logger = LogFactory.getFactory().getInstance(
+        "org.apache.jdo.impl.fostore"); // NOI18N
+    
+    /**
+    * Create a new DBExtent
+    */
+    private DBExtent(FOStoreDatabase fodb, String name,
+                     FOStoreSchemaUID fsuid, CLID classCLID) {
+
+        this.fodb = fodb;
+        this.name = name;
+        this.fsuid = fsuid;
+        this.classCLID = classCLID;
+        this.extentOID = DBInfo.getExtentOID(classCLID);
+
+        if (logger.isDebugEnabled()) { dump("()"); } // NOI18N
+    }
+
+    /**
+    * Return a new DBExtent to the caller.
+    */
+    static DBExtent create(FOStoreDatabase fodb, String name,
+                           FOStoreSchemaUID fsuid, CLID classCLID) {
+        return new DBExtent(fodb, name, fsuid, classCLID);
+    }
+
+    /** @return true if the given name and FOStoreSchemaUID are equal to those
+     * in this DBExtent.
+     */
+    boolean isExtentFor(String n, FOStoreSchemaUID f) {
+        boolean rc = false;
+        if (null != n && null != f) {
+            rc = name.equals(n) && fsuid.equals(f);
+        }
+        return rc;
+    }        
+
+    String getName() {
+        return name;
+    }
+
+    OID getExtentOID() {
+        return extentOID;
+    }
+
+    CLID getExtentCLID() {
+        return extentOID.getCLID();
+    }
+
+    OID getDBClassOID() {
+        return DBInfo.getDBClassOID(classCLID);
+    }
+    
+    CLID getClassCLID() {
+        return classCLID;
+    }
+
+    synchronized void add(OID oid) {
+        if (instances.contains(oid)) {
+            throw new JDOFatalInternalException(
+                msg.msg("ERR_SecondInstance", oid, name)); // NOI18N
+        }
+        instances.add(oid);
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "DBExtent: added " + oid + ", size=" + size()); // NOI18N
+        }
+    }
+
+    synchronized void remove(OID oid) {
+        instances.remove(oid);
+    }
+
+    synchronized int size() {
+        return instances.size();
+    }
+    
+    Iterator iterator() {
+        return instances.iterator();
+    }
+
+    synchronized void store(FOStoreDatabase db)
+        throws FOStoreDatabaseException {
+
+        db.put(extentOID, this);
+
+        if (logger.isDebugEnabled()) { dump(" store"); } // NOI18N
+    }
+
+    //
+    // Implement Streamable
+    //
+
+    public DBExtent() { }
+
+    public void write(OutputStream os) throws StorageException {
+        DataOutputStream dos = new DataOutputStream(os);
+
+        try {
+            if (logger.isDebugEnabled()) { dump(" write"); } // NOI18N
+                
+            dos.writeUTF(name);
+            classCLID.write(dos);
+            fsuid.write(dos);
+
+            int numInstances = instances.size();
+            dos.writeInt(numInstances);
+            for (Iterator i = instances.iterator(); i.hasNext();) {
+                OID oid = (OID)i.next();
+                oid.write(dos);
+                if (logger.isDebugEnabled()) {
+                    logger.debug("DBExtent.write: wrote " + oid); // NOI18N
+                }
+            }
+        } catch (IOException ex) {
+            throw new StorageIOException(ex);
+        }
+    }
+
+    public void read(InputStream is) throws StorageException {
+        DataInputStream dis = new DataInputStream(is);
+        try {
+            name = dis.readUTF();
+            classCLID = CLID.read(dis);
+            fsuid = FOStoreSchemaUID.read(dis);
+
+            extentOID = DBInfo.getExtentOID(classCLID);
+
+            int numInstances = dis.readInt();
+            if (logger.isDebugEnabled()) {
+                logger.debug(
+                    "DBExtent.read: numInstances=" + numInstances); // NOI18N
+            }
+            instances = new HashSet(numInstances);
+            for (int i = 0; i < numInstances; i++) {
+                instances.add(OID.read(dis));
+            }
+            if (logger.isDebugEnabled()) { dump(".read"); } // NOI18N
+        } catch (IOException ex) {
+            throw new StorageIOException(ex);
+        }
+    }
+
+    private void dump(String where) {
+        logger.debug("DBExtent" + where + ": " + toString()); // NOI18N
+    }
+
+    public String toString() {
+        return name + " " + extentOID + " " + // NOI18N
+            Tester.toHex(extentOID.oid, 16) + 
+            ", numInstances=" + instances.size(); // NOI18N
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBInfo.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBInfo.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBInfo.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DBInfo.java Sun May 22 11:40:13 2005
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.util.I18NHelper;
+import org.netbeans.mdr.persistence.Streamable;
+import org.netbeans.mdr.persistence.StorageException;
+import org.netbeans.mdr.persistence.StorageIOException;
+
+/**
+* This class represents the information about the contents of the store
+* itself which must be durable across JVMs.
+* <p>
+* This class is <code>public</code> so that it can be used as a
+* <code>Streamable</code> and stored in the database.
+*
+* @author Dave Bristor
+*/
+// Streamable requires that the class be public.  I think!.
+// This class is server-side only, not needed in client.
+public class DBInfo implements Streamable {
+    // There is only ever one instance of DBInfo in a store.
+    //
+    // When a database is first created, we use the initial values here
+    // specified.  If the database is being brought up from an existing
+    // backing store, then the read method below will provide the correct
+    // values from the store.
+    //
+    private FOStoreDatabase fodb = null;
+
+    /**
+    * This is the OID of the DBInfo.
+    */
+    // See CLID.java: This relies on the facts that (a) CLID's less than 100
+    // are reserved, and (b) the primitive types are final and cannot be
+    // subclassed.
+    private static final OID dbInfoOID = new OID(0);
+    
+    // Next available CLID.
+    private CLID nextCLID = CLID.firstCLID;
+
+    // For the OID of the DBClass corresponding to a given CLID.
+    private static final int DBCLASS_UID = 0;
+
+    // For the OID of the OID's which are of DBClass instances that are
+    // subclasses of an OID's CLID's class.  Got that?  No?  Then see
+    // GetExtentHandler.java.
+    private static final int SUBCLASS_UID = 1;
+
+    // For the OID of the extent of instances of the class indicated by a
+    // CLID.
+    private static final int EXTENT_UID = 2;
+
+    // Reserve the first N UID's in each OID for future use.
+    //
+    // Note to maintainers: Make sure that this is greater than
+    // LAST_RESERVED_UID.
+    private static final int FIRST_CLASS_UID = 10;
+
+    // Indexed by CLID: the value in a given position is the value of the
+    // next available UID for that CLID.  That is, when we need a new
+    // datastore OID for a particular CLID, we use that CLID's id value as an
+    // index into this list, and extract the value there.  We use that value
+    // as the UID part of the OID being created.  And we update the list
+    // element by incrementing the value in the list by 1.
+    private ArrayList nextUIDs = new ArrayList(CLID.firstCLID.getId());
+
+    /** Set of extents that are currently modified and need to be stored when
+     * a transaction commits.
+     */
+    // XXX This relies on the fact that transactions are serialized.  Once
+    // that goes away, index a set of dirtyExtents HashSets by some kind of
+    // transaction id.
+    private HashSet dirtyExtents = new HashSet();
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+    /** Logger */
+    static final Log logger = LogFactory.getFactory().getInstance(
+        "org.apache.jdo.impl.fostore"); // NOI18N
+    
+    /**
+    * Create a new instance. 
+    * Use this constructor when creating an instance for a brand new
+    * database (as opposed to an existing database, in which we use the
+    * Streamable-required default constructor, below).
+    * @param fodb The FOStoreDatabase instance.
+    * @exception FOStoreFatalInternalException Thrown when there is an attempt
+    * to create a second DBInfo within a store.
+    */
+    DBInfo(FOStoreDatabase fodb) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("DBInfo: new for " + fodb); // NOI18N
+        }
+        this.fodb = fodb;
+        // Initialize nextUIDs for the reserved CLIDs.
+        int size = nextCLID.getId();
+        for (int i = 0; i < size; i++) {
+            // FIRST_CLASS_UID number of uid's are reserved per-CLID.
+            nextUIDs.add(i, new Long(FIRST_CLASS_UID));
+        }
+    }
+
+    void store() throws FOStoreDatabaseException {
+        fodb.put(dbInfoOID, this);
+    }
+
+    static DBInfo get(FOStoreDatabase db) throws FOStoreDatabaseException {
+        DBInfo rc = (DBInfo)db.getIfExists(dbInfoOID);
+        if (null == rc) {
+            rc = new DBInfo(db);
+            rc.fodb = db;
+            rc.store();
+        }
+        rc.fodb = db;
+        if (logger.isDebugEnabled()) {
+            logger.debug("DBInfo.get: " + rc); // NOI18N
+        }
+        return rc;
+    }
+
+    //
+    // The intent of the next 2 methods is to provide an OID which can be
+    // used to store information about the class represented by the CLID.
+    // ActivateClassHandler uses newClassOID to create an OID for storing
+    // class metadata, GetClassHandler uses getDBClassOID to get that OID.
+    //
+    
+    /**
+    * Provide a new OID to represent a class.  Use this when activating a
+    * class.
+    * @return An OID for a class just now known to this store.
+    */
+    OID newClassOID() {
+        // FIRST_CLASS_UID number of uid's are reserved per-CLID.
+        nextUIDs.add(nextCLID.getId(), new Long(FIRST_CLASS_UID));
+
+        OID rc = OID.create(nextCLID, DBCLASS_UID);
+
+        nextCLID = nextCLID.next();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "newClassOID: returning; nextCLID now=" + nextCLID); // NOI18N
+        }
+
+        return rc;
+    }
+
+    /**
+    * Provides the OID which represents the given CLID's class.
+    * @param clid The CLID for which the corresponding OID is needed.
+    * @return The OID of the CLID.
+    */
+    static OID getDBClassOID(CLID clid) {
+        return OID.create(clid, DBCLASS_UID);
+    }
+
+    /**
+    * Provides the OID which at which is stored the ArrayList of the CLIDs of
+    * of subclasses of the class corresponding to the CLID.
+    * @param clid The CLID for which the corresponding OID is needed.
+    * @return The OID of the ArrayList of CLIDs of the given CLID's
+    * subclasses.
+    */
+    static OID getSubclassSetOID(CLID clid) {
+        return OID.create(clid, SUBCLASS_UID);
+    }
+
+    /**
+    * Provides the OID which represents extent of instances of objects all of
+    * which have the given CLID.
+    * @param clid CLID of extent to return.
+    * @return OID of the extent of instances of CLID's class.
+    */
+    static OID getExtentOID(CLID clid) {
+        return OID.create(clid, EXTENT_UID);
+    }
+
+    /**
+    * @return Iterator of DBClass objects
+    */
+    Iterator getDBClasses() {
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "DBInfo.getDBClasses: first=" + CLID.firstCLID + // NOI18N
+                ", next=" + nextCLID); // NOI18N
+        }
+        return new DBClassIterator(CLID.firstCLID, nextCLID);
+    }
+
+    class DBClassIterator implements Iterator {
+        private int current;
+        private final int finish;
+        
+        DBClassIterator(CLID start, CLID finish) {
+            this.current = start.getId();
+            this.finish = finish.getId();
+        }
+        
+        public boolean hasNext() {
+            return current < finish;
+        }
+        
+        public Object next() {
+            Object rc = null;
+            try {
+                rc = fodb.get(getDBClassOID(CLID.create(current++, false)));
+            } catch (FOStoreDatabaseException ex) {
+            }
+            return rc;
+        }
+
+        public void remove() { }
+    }
+
+    //
+    // Dirty extent handling
+    //
+
+    /**
+     * Marks the given extent as dirty, so that it can later be stored.
+     */
+    boolean makeExtentDirty(DBExtent e) {
+        return dirtyExtents.add(e);
+    }
+
+    /**
+     * Stores all extents that have been marked dirty since the last time this
+     * method was invoked.
+     */
+    void storeDirtyExtents() throws FOStoreDatabaseException {
+        for (Iterator i = dirtyExtents.iterator(); i.hasNext();) {
+            DBExtent dbExtent = (DBExtent)i.next();
+            if (logger.isDebugEnabled()) {
+                logger.debug("FOSCI.commit:" + dbExtent); // NOI18N
+            }
+            dbExtent.store(fodb);
+        }
+        clearDirtyExtents();
+    }
+
+    /**
+     * Causes this DBInfo to forget about the dirty state of all extents
+     * marked as dirty since the last time storeDirtyExtents was invoked.
+     */    
+    void clearDirtyExtents() {
+        dirtyExtents.clear();
+    }
+
+    /**
+    * @return Iterator of DBExtent objects
+    */
+    Iterator getExtents() {
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "DBInfo.getExtents: first=" + CLID.firstCLID + // NOI18N
+                ", next=" + nextCLID); // NOI18N
+        }
+        return new ExtentIterator(CLID.firstCLID, nextCLID);
+    }
+
+    class ExtentIterator implements Iterator {
+        private int current;
+        private final int finish;
+        
+        ExtentIterator(CLID start, CLID finish) {
+            this.current = start.getId();
+            this.finish = finish.getId();
+        }
+        
+        public boolean hasNext() {
+            return current < finish;
+        }
+        
+        public Object next() {
+            Object rc = null;
+            try {
+                rc = fodb.get(getExtentOID(CLID.create(current++, false)));
+            } catch (FOStoreDatabaseException ex) {
+            }
+            return rc;
+        }
+
+        public void remove() { }
+    }
+        
+    /**
+    * Provide a new OID for the given CLID.  Use this when creating an
+    * instance in the store.  The OID will have its CLID part as per the
+    * given CLID, and its UID part one greater than the last-created
+    * newInstanceOID.
+    * @param clid CLID for which a new OID is needed.
+    * @return An OID for the CLID.
+    * @exception FOStoreFatalInternalException thrown if the CLID is invalid.
+    */
+    OID newInstanceOID(CLID clid) {
+        OID rc = null;
+        int clidIndex = clid.getId();
+
+        synchronized(nextUIDs) {
+            if (nextUIDs.size() > clidIndex) {
+
+                // Get the next-uid value, increment by one, store the new
+                // next-uid.  Make an OID to return.
+                Long UID = (Long)nextUIDs.get(clidIndex);
+                long uid = UID.longValue();
+                if (uid == OID.MAX_UID) {
+                    throw new FOStoreFatalInternalException(
+                        this.getClass(), "newInstance", // NOI18N
+                        msg.msg("ERR_OutOfUIDs", // NOI18N
+                                new Long(OID.MAX_UID)));
+                }
+                uid++;
+                UID = new Long(uid);
+                nextUIDs.set(clidIndex, UID);
+                
+                rc = OID.create(clid, uid);
+            } else {
+                throw new FOStoreFatalInternalException(
+                    this.getClass(), "newInstance", // NOI18N
+                    msg.msg("ERR_NoUIDsForCLID", clid)); // NOI18N
+            }
+        }
+        return rc;
+    }
+
+    /** Returns a human-readable description of this DBInfo.  If system
+     * property "dbinfo.shortname" is true, then the description includes the
+     * name of the database (e.g. 'foo'), otherwise it includes the complete
+     * pathname of the database (e.g. '/bleem/foo').
+     */
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("DBInfo '"); // NOI18N
+        String name = fodb.getName();
+        // Default is to provide full pathname of database; for testing the
+        // short name is more appropriate.
+        if (Boolean.getBoolean("dbinfo.shortname")) { // NOI18N
+            int pos = name.lastIndexOf(File.separatorChar);
+            if (pos > 0) {
+                name = name.substring(pos + 1);
+            }
+        }
+        sb.append(name).append("'\n");  // NOI18N
+            
+        sb.append("Next ").append(nextCLID.toString()).append("\n"); // NOI18N
+
+        for (Iterator i = getExtents(); i.hasNext();) {
+            DBExtent e = (DBExtent)i.next();
+            CLID clid = e.getClassCLID();
+            Long uid = (Long)nextUIDs.get(clid.getId());
+
+            sb.append(
+                "    class ").append(e.toString()).append(", "); // NOI18N
+            sb.append(
+                "next UID: ").append(uid.toString()).append(".\n"); // NOI18N
+        }
+
+        return sb.toString();
+    }
+
+    //
+    // Implement Streamable
+    //
+    
+    public DBInfo() {
+        this(null);
+    }
+    
+    public void write(OutputStream os) throws StorageException {
+        DataOutputStream dos = new DataOutputStream(os);
+
+        try {
+            nextCLID.write(dos);
+
+            int size = nextUIDs.size();
+            dos.writeInt(size);
+            for (int i = 0; i < size; i++) {
+                Long clid = (Long)nextUIDs.get(i);
+                dos.writeLong(clid.longValue());
+            }
+        } catch (IOException ex) {
+            throw new StorageIOException(ex);
+        }
+    }
+
+    public void read(InputStream is) throws StorageException {
+        DataInputStream dis = new DataInputStream(is);
+        try {
+            nextCLID = CLID.read(dis);
+            
+            int size = dis.readInt();
+            nextUIDs = new ArrayList(size);
+            for (int i = 0; i < size; i++) {
+                nextUIDs.add(i, new Long(dis.readLong()));
+            }
+        } catch (IOException ex) {
+            throw new StorageIOException(ex);
+        }
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DeleteHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DeleteHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DeleteHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DeleteHandler.java Sun May 22 11:40:13 2005
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Processes requests to delete objects from the datastore.
+*
+* @author Dave Bristor
+*/
+class DeleteHandler extends RequestHandler {
+
+    /** I18N Support */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+    private DeleteHandler(Reply reply, int length,
+                          FOStoreServerConnection con) {
+        super(reply, length, con);
+    }
+
+    public static HandlerFactory factory =
+        new HandlerFactory() {
+            public RequestHandler getHandler(Reply reply, int length,
+                                             FOStoreServerConnection con) {
+                return new DeleteHandler(reply, length, con);
+            }};
+
+
+    RequestFinisher handleRequest()
+        throws IOException, FOStoreDatabaseException {
+
+        if (logger.isDebugEnabled()) logger.debug("DeleteHandler.hR"); //NOI18N
+
+        DataInput in = con.getInputFromClient();
+        OID oid = OID.read(in);
+        boolean optimistic = in.readBoolean();
+
+        FOStoreDatabase fodb = con.getDatabase();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("DeleteHandler.hR: deleting " + oid + // NOI18N
+                           ", optimistic=" + optimistic); // NOI18N
+        }
+
+        if (logger.isTraceEnabled()) {
+            Block block = (Block)fodb.get(oid);
+            block.dump();
+        }
+
+        // Remove instance from database and from its Extent
+        boolean found = fodb.remove(oid);
+
+        if (found) {
+            DBInfo dbInfo = fodb.getDBInfo();
+            OID extentOID = dbInfo.getExtentOID(oid.getCLID());
+            DBExtent dbExtent = (DBExtent)fodb.get(extentOID);
+            dbExtent.remove(oid);
+            con.addExtent(dbExtent);
+            reply.setStatus(Status.OK);
+        } else {
+            // Instance to be deleted not in database.  If Tx is optimistic,
+            // it's a consistency failure; if datastore it's a bug.
+            if (optimistic) {
+                // XXX when delete verify is added, write the oid there also
+                oid.write(reply);
+                reply.setStatus(
+                    Status.OPTIMISTIC,
+                    msg.msg("EXC_DeleteVerifyFailed", oid)); // NOI18N
+            } else {
+
+                // Should not happen: datastore tx and instance not in store
+                if (logger.isDebugEnabled()) {
+                    logger.debug(
+                        "DeleteHandler.hR: " + oid + " not in db"); // NOI18N
+                }
+                reply.setStatus(
+                    Status.FATAL,
+                    msg.msg("ERR_DatastoreFailed", oid)); // NOI18N
+            }
+        }
+
+        return null;
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DeleteRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DeleteRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DeleteRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DeleteRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.Transaction;
+import javax.jdo.JDOHelper;
+
+import org.apache.jdo.state.StateManagerInternal;
+
+
+/**
+ * Represents a requests to remove a persistent object in the store.
+ *
+ * @author Dave Bristor
+ */
+//
+// This is client-side code.  It does not need to live in the server.
+//
+class DeleteRequest extends AbstractRequest {
+    /** OID of the instance being deleted. */
+    private final OID oid;
+
+    /** Optimistic/datastore state of current transaction. */
+    private final boolean optimistic;
+
+    DeleteRequest(StateManagerInternal sm, Message m, FOStorePMF pmf) {
+        super(sm, m, pmf);
+        this.oid = (OID)sm.getInternalObjectId();
+        PersistenceManager pm = sm.getPersistenceManager(); 
+        Transaction tx = pm.currentTransaction();
+        this.optimistic = tx.getOptimistic();
+    }
+
+    protected void doRequestBody() throws IOException {
+        //
+        // The format of this request is (aside from the request header):
+        //
+        // oid: OID
+        // optimistic: boolean
+        // numFields: int
+        // fieldValue: Object...
+        //
+
+        // XXX Need in optimistic Tx, verify w/ dirtyFields? ; see StoreManger#delete
+        if (logger.isDebugEnabled()) {
+            logger.debug("DeleteRequest.dRB: " + oid); // NOI18N
+        }
+        oid.write(out);
+        out.writeBoolean(optimistic);
+    }
+
+    //
+    // Methods from Request
+    //
+
+    /**
+     * @see Request#handleReply
+     */
+    public void handleReply(Status status, DataInput in, int length)
+        throws IOException {
+
+        //
+        // The format of this reply is
+        //
+        //  empty, that's right, no data needed.
+        //
+        if (logger.isDebugEnabled()) logger.debug("DeleteRequest.hR"); // NOI18N
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DoubleTranscriber.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DoubleTranscriber.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DoubleTranscriber.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DoubleTranscriber.java Sun May 22 11:40:13 2005
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+* Transcribes double values.
+*
+* @author Dave Bristor
+*/
+class DoubleTranscriber extends FOStoreTranscriber {
+    private static DoubleTranscriber instance = new DoubleTranscriber();
+
+    private DoubleTranscriber() {}
+
+    static DoubleTranscriber getInstance() {
+        return instance;
+    }
+    
+    void storeDouble(double value, DataOutput out) throws IOException {
+        out.writeDouble(value);
+    }
+
+    double fetchDouble(DataInput in) throws IOException {
+        return in.readDouble();
+    }
+
+    void skip(DataInput in) throws IOException { 
+        in.readDouble(); 
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DummyTranscriber.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DummyTranscriber.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DummyTranscriber.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DummyTranscriber.java Sun May 22 11:40:13 2005
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+* This Transcriber is used to skip managed non-persistent fields.
+* Any attempt to use it for fetching or storing a field will
+* result in FOStoreAbstractMethodException.
+*
+* @author Marina Vatkina
+*/
+class DummyTranscriber extends FOStoreTranscriber {
+    private static DummyTranscriber instance = new DummyTranscriber();
+
+    private DummyTranscriber() {}
+
+    static DummyTranscriber getInstance() {
+        return instance;
+    }
+    
+    void skip(DataInput in) throws IOException {}
+
+}
+



Mime
View raw message