Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / store / access / RAMAccessManager.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/RAMAccessManager.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/RAMAccessManager.java
new file mode 100644 (file)
index 0000000..fd5df9d
--- /dev/null
@@ -0,0 +1,1219 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.store.access.RAMAccessManager\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.store.access;\r
+\r
+import org.apache.derby.iapi.services.cache.Cacheable;\r
+import org.apache.derby.iapi.services.cache.CacheableFactory;\r
+import org.apache.derby.iapi.services.cache.CacheFactory;\r
+import org.apache.derby.iapi.services.cache.CacheManager;\r
+\r
+import org.apache.derby.iapi.services.context.ContextManager;\r
+import org.apache.derby.iapi.services.context.ContextService;\r
+import org.apache.derby.iapi.services.daemon.Serviceable;\r
+import org.apache.derby.iapi.services.locks.LockFactory;\r
+import org.apache.derby.iapi.services.monitor.ModuleControl;\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+import org.apache.derby.iapi.services.property.PropertySetCallback;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;\r
+import org.apache.derby.iapi.store.access.conglomerate.ConglomerateFactory;\r
+import org.apache.derby.iapi.store.access.conglomerate.MethodFactory;\r
+import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;\r
+import org.apache.derby.iapi.services.property.PropertyUtil;\r
+import org.apache.derby.iapi.store.access.AccessFactory;\r
+import org.apache.derby.iapi.services.property.PropertyFactory;\r
+\r
+import org.apache.derby.iapi.store.access.AccessFactoryGlobals;\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+import org.apache.derby.iapi.store.access.TransactionInfo;\r
+\r
+import org.apache.derby.iapi.store.raw.ContainerHandle;\r
+import org.apache.derby.iapi.store.raw.ContainerKey;\r
+import org.apache.derby.iapi.store.raw.LockingPolicy;\r
+import org.apache.derby.iapi.store.raw.RawStoreFactory;\r
+import org.apache.derby.iapi.store.raw.Transaction;\r
+\r
+import org.apache.derby.catalog.UUID;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.reference.Attribute;\r
+\r
+import java.util.Dictionary;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.Properties;\r
+\r
+import java.io.Serializable;\r
+\r
+\r
+public abstract class RAMAccessManager\r
+    implements AccessFactory, \r
+               CacheableFactory, \r
+               ModuleControl, \r
+               PropertySetCallback\r
+{\r
+    /**************************************************************************\r
+     * Fields of the class\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+    The raw store that this access manager uses.\r
+    **/\r
+    private RawStoreFactory rawstore;\r
+\r
+    /**\r
+    Hash table on primary implementation type.\r
+    **/\r
+    private Hashtable implhash;\r
+\r
+    /**\r
+    Hash table on primary format.\r
+    **/\r
+    private Hashtable formathash;\r
+\r
+       /**\r
+       Service properties.  These are supplied from ModuleControl.boot(),\r
+       and ultimately come from the service.properties file.\r
+       By convention, these properties are passed down to all modules\r
+       booted by this one.  If this module needs to pass specific instructions\r
+       to its sub-modules, it should create a new Properties object with\r
+       serviceProperties as its default (so that the rest of the modules\r
+       that are looking at it don't see the properties that this module\r
+       needs to add).\r
+       **/\r
+       private Properties serviceProperties;\r
+\r
+    /**\r
+     * Default locking policy for the entire system.\r
+     **/\r
+    LockingPolicy system_default_locking_policy;\r
+\r
+       /**     \r
+               The object providing the properties like behaviour\r
+               that is transactional.\r
+       */\r
+       private PropertyConglomerate xactProperties;\r
+       private PropertyFactory         pf;\r
+\r
+    protected LockingPolicy table_level_policy[];\r
+    protected LockingPolicy record_level_policy[];\r
+\r
+\r
+    /**\r
+     * A map of the implementation specific id to conglomerate object.\r
+     * <p>\r
+     * A map of the implementation specific id to conglomerate object.\r
+     * The id is encoded into the conglomerate number, and then used to\r
+     * pick the right implementation of the conglomerate.  It is then\r
+     * up to the conglomerate implementation to retrieve it's stored \r
+     * representation from disk.\r
+     *\r
+     * An internal mapping of the encoding of conglomerate identity in the\r
+     * conglomerate number to the actual conglomerate implementation.  Encoding\r
+     * this means that we can't dynamically add conglomerate implementations\r
+     * into the system, so when we want to do that this mapping will have to\r
+     * be more dynamic - but for now store knows exactly what implementations\r
+     * there are.\r
+     **/\r
+    protected ConglomerateFactory conglom_map[];\r
+\r
+    /**\r
+     * Cache of Conglomerate objects, keyed by conglom id.  Used to speed up\r
+     * subsquent open of conglomerates, first open will need to call the \r
+     * conglomerate to read and return it's description.\r
+     **/\r
+    private CacheManager    conglom_cache;\r
+\r
+    /**************************************************************************\r
+     * Constructors for This class:\r
+     **************************************************************************\r
+     */\r
+\r
+    public RAMAccessManager()\r
+    {\r
+        // Intialize the hash tables that hold the access methods that\r
+        // this access manager knows about.\r
+        implhash   = new Hashtable();\r
+        formathash = new Hashtable();\r
+    }\r
+\r
+    /**************************************************************************\r
+     * Private/Protected methods of This class:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Return the default locking policy for this access manager.\r
+     *\r
+        * @return the default locking policy for this accessmanager.\r
+     **/\r
+    protected LockingPolicy getDefaultLockingPolicy()\r
+    {\r
+        return(system_default_locking_policy);\r
+    }\r
+\r
+\r
+    RawStoreFactory getRawStore()\r
+    {\r
+        return rawstore;\r
+    }\r
+\r
+\r
+       PropertyConglomerate getTransactionalProperties()\r
+    {\r
+               return xactProperties;\r
+       }\r
+\r
+    private void boot_load_conglom_map()\r
+        throws StandardException\r
+    {\r
+        // System.out.println("before new code.");\r
+\r
+        conglom_map = new ConglomerateFactory[2];\r
+\r
+               // Find the appropriate factory for the desired implementation.\r
+               MethodFactory mfactory = findMethodFactoryByImpl("heap");\r
+\r
+               if (mfactory == null || !(mfactory instanceof ConglomerateFactory))\r
+        {\r
+                       throw StandardException.newException(\r
+                    SQLState.AM_NO_SUCH_CONGLOMERATE_TYPE, "heap");\r
+        }\r
+\r
+        conglom_map[ConglomerateFactory.HEAP_FACTORY_ID] = \r
+            (ConglomerateFactory) mfactory;\r
+\r
+               // Find the appropriate factory for the desired implementation.\r
+               mfactory = findMethodFactoryByImpl("BTREE");\r
+\r
+               if (mfactory == null || !(mfactory instanceof ConglomerateFactory))\r
+        {\r
+                       throw StandardException.newException(\r
+                    SQLState.AM_NO_SUCH_CONGLOMERATE_TYPE, "BTREE");\r
+        }\r
+        conglom_map[ConglomerateFactory.BTREE_FACTORY_ID] = \r
+            (ConglomerateFactory) mfactory;\r
+\r
+        // System.out.println("conglom_map[0] = " + conglom_map[0]);\r
+        // System.out.println("conglom_map[1] = " + conglom_map[1]);\r
+    }\r
+\r
+\r
+\r
+\r
+    /***************************************************************************\r
+    ** Abstract Methods of RAMAccessManager, interfaces that control locking\r
+    ** level of the system.\r
+    ****************************************************************************\r
+    */\r
+\r
+    /**\r
+     * Return the locking level of the system.\r
+     * <p>\r
+     * This routine controls the lowest level of locking enabled for all locks\r
+     * for all tables accessed through this accessmanager.  The concrete \r
+     * implementation may set this value always to table level locking for\r
+     * a client configuration, or it may set it to row level locking for a\r
+     * server configuration.\r
+     * <p>\r
+     * If TransactionController.MODE_RECORD is returned table may either be\r
+     * locked at table or row locking depending on the type of access expected\r
+     * (ie. level 3 will require table locking for heap scans.)\r
+     *\r
+        * @return TransactionController.MODE_TABLE if only table locking allowed,\r
+     *         else returns TransactionController.MODE_RECORD.\r
+     *\r
+     **/\r
+    abstract protected int getSystemLockLevel();\r
+\r
+    /**\r
+     * Query property system to get the System lock level.\r
+     * <p>\r
+     * This routine will be called during boot after access has booted far \r
+     * enough, to allow access to the property conglomerate.  This routine\r
+     * will call the property system and set the value to be returned by\r
+     * getSystemLockLevel().\r
+     * <p>\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    abstract protected void bootLookupSystemLockLevel(\r
+    TransactionController tc)\r
+               throws StandardException;\r
+\r
+    /**************************************************************************\r
+     * Routines to map to/from conglomid/containerid:\r
+     **************************************************************************\r
+     */\r
+    private long conglom_nextid = 0;\r
+\r
+    /**\r
+     * Return next conglomid to try to add the container with.\r
+     * <p>\r
+     * The conglomerate number has 2 parts.  The low 4 bits are used to \r
+     * encode the factory which "owns" the conglomerate.  The high 60 bits\r
+     * are used as a normal unique id mechanism.\r
+     * <p>\r
+     * So for example if the next id to assign is 0x54 the following will\r
+     * be the conglomid:\r
+     *     if a HEAP  (factory 0) - 0x540\r
+     *     if a BTREE (factory 1) - 0x541\r
+     *\r
+     * And the next id assigned will be:\r
+     *     if a HEAP  (factory 0) - 0x550\r
+     *     if a BTREE (factory 1) - 0x551\r
+     *\r
+     * @param factory_type factory id as gotten from getConglomerateFactoryId()\r
+     *\r
+        * @return The identifier to be used to open the conglomerate later.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    protected long getNextConglomId(int   factory_type)\r
+               throws StandardException\r
+    {\r
+        long    conglomid;\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            // current code depends on this range, if we ever need to expand the\r
+            // range we can claim bits from the high order of the long.\r
+\r
+            SanityManager.ASSERT(factory_type >= 0x00 && factory_type <= 0x0f);\r
+        }\r
+\r
+        synchronized (conglom_cache)\r
+        {\r
+            if (conglom_nextid == 0)\r
+            {\r
+                // shift out the factory id and then add 1.\r
+                conglom_nextid = (rawstore.getMaxContainerId() >> 4) + 1;\r
+            }\r
+\r
+            conglomid = conglom_nextid++;\r
+        }\r
+\r
+        // shift in the factory id and then return the conglomid.\r
+        \r
+        return((conglomid << 4) | factory_type);\r
+    }\r
+\r
+    /**\r
+     * Bump the conglomid.\r
+     * <p>\r
+     * For some reason we have found that the give conglomid already exists\r
+     * in the directory so just bump the next conglomid to greater than this\r
+     * one.  The algorithm to store and retrieve the last conglomid is not\r
+     * transactional as we don't want to pay the overhead for such an algorithm\r
+     * on every ddl statement - so it is possible to "lose" an update to the\r
+     * counter if we crash at an inopportune moment.  In general the upper\r
+     * level store code will just handle the error from addContainer which \r
+     * says there already exists a conglom with that id, update the next\r
+     * conglomid and then try again.\r
+     * <p>\r
+     *\r
+     * @param conglomid The conglomid which already exists.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    // currently not used, but this is one idea on how to handle \r
+    // non-transactional update of the nextid field, just handle the error\r
+    // if we try to create a conglom and find the container already exists.\r
+    /*\r
+    private void handleConglomidExists(\r
+    long   conglomid)\r
+               throws StandardException\r
+    {\r
+        synchronized (conglom_cache)\r
+        {\r
+            conglom_nextid = ((conglomid >> 4) + 1);\r
+        }\r
+    }\r
+    */\r
+\r
+    /**\r
+     * Given a conglomid, return the factory which "owns" it.\r
+     * <p>\r
+     * A simple lookup on the boot time built table which maps the low order\r
+     * 4 bits into which factory owns the conglomerate.\r
+     * <p>\r
+     *\r
+     * @param conglom_id The conglomerate id of the conglomerate to look up.\r
+     *\r
+        * @return The ConglomerateFactory which "owns" this conglomerate.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    private ConglomerateFactory getFactoryFromConglomId(\r
+    long    conglom_id)\r
+               throws StandardException\r
+    {\r
+        try\r
+        {\r
+            return(conglom_map[((int) (0x0f & conglom_id))]);\r
+        }\r
+        catch (java.lang.ArrayIndexOutOfBoundsException e)\r
+        {\r
+            // just in case language passes in a bad factory id.\r
+                       throw StandardException.newException(\r
+                SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST, \r
+                new Long(conglom_id));\r
+        }\r
+    }\r
+\r
+\r
+    /**************************************************************************\r
+     * Conglomerate Cache routines:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * ACCESSMANAGER CONGLOMERATE CACHE - \r
+     * <p>\r
+     * Every conglomerate in the system is described by an object which \r
+     * implements Conglomerate.  This object basically contains the parameters\r
+     * which describe the metadata about the conglomerate that store needs\r
+     * to know - like types of columns, number of keys, number of columns, ...\r
+     * <p>\r
+     * It is up to each conglomerate to maintain it's own description, and\r
+     * it's factory must be able to read this info from disk and return it\r
+     * from the ConglomerateFactory.readConglomerate() interface.\r
+     * <p>\r
+     * This cache simply maintains an in memory copy of these conglomerate\r
+     * objects, key'd by conglomerate id.  By caching, this avoids the cost\r
+     * of reading the conglomerate info from disk on each subsequent query\r
+     * which accesses the conglomerate.\r
+     * <p>\r
+     * The interfaces and internal routines which deal with this cache are:\r
+     * conglomCacheInit() - initializes the cache at boot time.\r
+     *\r
+     *\r
+     *\r
+     **/\r
+\r
+    /**\r
+     * Initialize the conglomerate cache.\r
+     * <p>\r
+     * Simply calls the cache manager to create the cache with some hard\r
+     * coded defaults for size.\r
+     * <p>\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    private void conglomCacheInit()\r
+        throws StandardException\r
+    {\r
+        // Get a cache factory to create the conglomerate cache.\r
+               CacheFactory cf = \r
+            (CacheFactory) Monitor.startSystemModule(\r
+                 org.apache.derby.iapi.reference.Module.CacheFactory);\r
+\r
+        // Now create the conglomerate cache.\r
+\r
+           conglom_cache =\r
+           cf.newCacheManager(\r
+               this, AccessFactoryGlobals.CFG_CONGLOMDIR_CACHE, 200, 300);\r
+\r
+    }\r
+\r
+    /**\r
+     * Find a conglomerate by conglomid in the cache.\r
+     * <p>\r
+     * Look for a conglomerate given a conglomid.  If in cache return it,\r
+     * otherwise fault in an entry by asking the owning factory to produce\r
+     * an entry.\r
+     * <p>\r
+     *\r
+        * @return The conglomerate object identified by "conglomid".\r
+     *\r
+     * @param conglomid The conglomerate id of the conglomerate to look up.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    /* package */ Conglomerate conglomCacheFind(\r
+    TransactionManager  xact_mgr,\r
+    long                conglomid)\r
+        throws StandardException\r
+    {\r
+        Conglomerate conglom       = null;\r
+        Long         conglomid_obj = new Long(conglomid);\r
+\r
+        synchronized (conglom_cache)\r
+        {\r
+            CacheableConglomerate cache_entry = \r
+                (CacheableConglomerate) conglom_cache.findCached(conglomid_obj);\r
+\r
+            if (cache_entry != null)\r
+            {\r
+                conglom = cache_entry.getConglom();\r
+                conglom_cache.release(cache_entry);\r
+\r
+                // SanityManager.DEBUG_PRINT("find", "find hit : " + conglomid);\r
+            }\r
+            else\r
+            {\r
+                // SanityManager.DEBUG_PRINT("find", "find miss: " + conglomid);\r
+\r
+                // If not in cache - ask the factory for it and insert it.\r
+\r
+                conglom = \r
+                    getFactoryFromConglomId(conglomid).readConglomerate(\r
+                        xact_mgr, new ContainerKey(0, conglomid));\r
+\r
+                if (conglom != null)\r
+                {\r
+                    // on cache miss, put the missing conglom in the cache.\r
+                    cache_entry = (CacheableConglomerate) \r
+                        this.conglom_cache.create(conglomid_obj, conglom);\r
+                    this.conglom_cache.release(cache_entry);\r
+                }\r
+            }\r
+        }\r
+\r
+        return(conglom);\r
+    }\r
+\r
+    /**\r
+     * Invalide the current Conglomerate Cache.\r
+     * <p>\r
+     * Abort of certain operations will invalidate the contents of the \r
+     * cache.  Longer term we could just invalidate those entries, but\r
+     * for now just invalidate the whole cache.\r
+     * <p>\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    /* package */ protected void conglomCacheInvalidate()\r
+        throws StandardException\r
+    {\r
+        synchronized (conglom_cache)\r
+        {\r
+            conglom_cache.ageOut();\r
+        }\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * Update a conglomerate directory entry.\r
+     * <p>\r
+     * Update the Conglom column of the Conglomerate Directory.  The \r
+     * Conglomerate with id "conglomid" is replaced by "new_conglom".\r
+     * <p>\r
+     *\r
+     * @param conglomid   The conglomid of conglomerate to replace.\r
+     * @param new_conglom The new Conglom to update the conglom column to.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    /* package */ void conglomCacheUpdateEntry(\r
+    long            conglomid, \r
+    Conglomerate    new_conglom) \r
+        throws StandardException\r
+    {\r
+        Long         conglomid_obj = new Long(conglomid);\r
+\r
+        synchronized (conglom_cache)\r
+        {\r
+            // remove the current entry\r
+            CacheableConglomerate conglom_entry = (CacheableConglomerate) \r
+                conglom_cache.findCached(conglomid_obj);\r
+\r
+            if (conglom_entry != null)\r
+                conglom_cache.remove(conglom_entry);\r
+\r
+            // insert the updated entry.\r
+            conglom_entry = (CacheableConglomerate) \r
+                conglom_cache.create(conglomid_obj, new_conglom);\r
+            conglom_cache.release(conglom_entry);\r
+        }\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * Add a newly created conglomerate to the cache.\r
+     * <p>\r
+     *\r
+     * @param conglomid   The conglomid of conglomerate to replace.\r
+     * @param conglom     The Conglom to add.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    /* package */ void conglomCacheAddEntry(\r
+    long            conglomid,\r
+    Conglomerate    conglom)\r
+        throws StandardException\r
+    {\r
+        synchronized (conglom_cache)\r
+        {\r
+            // insert the updated entry.\r
+            CacheableConglomerate conglom_entry = (CacheableConglomerate) \r
+                conglom_cache.create(new Long(conglomid), conglom);\r
+            conglom_cache.release(conglom_entry);\r
+        }\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * Remove an entry from the cache.\r
+     * <p>\r
+     *\r
+     * @param conglomid   The conglomid of conglomerate to replace.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    /* package */ void conglomCacheRemoveEntry(long conglomid)\r
+        throws StandardException\r
+    {\r
+        synchronized (conglom_cache)\r
+        {\r
+            CacheableConglomerate conglom_entry = (CacheableConglomerate) \r
+                conglom_cache.findCached(new Long(conglomid));\r
+\r
+            if (conglom_entry != null)\r
+                conglom_cache.remove(conglom_entry);\r
+        }\r
+\r
+        return;\r
+    }\r
+\r
+\r
+\r
+    /**************************************************************************\r
+     * Public Methods implementing AccessFactory Interface:\r
+     **************************************************************************\r
+     */\r
+\r
+       /**\r
+       Database creation finished.  Tell RawStore.\r
+       @exception StandardException standard Derby error policy\r
+       */\r
+       public void createFinished() throws StandardException\r
+       {\r
+               rawstore.createFinished();\r
+       }\r
+\r
+    /**\r
+    Find an access method that implements a format type.\r
+    @see AccessFactory#findMethodFactoryByFormat\r
+    **/\r
+    public MethodFactory findMethodFactoryByFormat(UUID format)\r
+    {\r
+        MethodFactory factory;\r
+        \r
+        // See if there's an access method that supports the desired\r
+        // format type as its primary format type.\r
+        factory = (MethodFactory) formathash.get(format);\r
+        if (factory != null)\r
+            return factory;\r
+\r
+        // No primary format.  See if one of the access methods\r
+        // supports it as a secondary format.\r
+        Enumeration e = formathash.elements();\r
+        while (e.hasMoreElements())\r
+        {\r
+            factory = (MethodFactory) e.nextElement();\r
+            if (factory.supportsFormat(format))\r
+                return factory;\r
+        }\r
+\r
+        // No such implementation.\r
+        return null;\r
+    }\r
+\r
+    /**\r
+    Find an access method that implements an implementation type.\r
+    @see AccessFactory#findMethodFactoryByImpl\r
+    **/\r
+    public MethodFactory findMethodFactoryByImpl(String impltype)\r
+        throws StandardException\r
+    {\r
+        // See if there's an access method that supports the desired\r
+        // implementation type as its primary implementation type.\r
+        MethodFactory factory = (MethodFactory) implhash.get(impltype);\r
+        if (factory != null)\r
+                               return factory;\r
+\r
+        // No primary implementation.  See if one of the access methods\r
+        // supports the implementation type as a secondary.\r
+        Enumeration e = implhash.elements();\r
+        while (e.hasMoreElements())\r
+        {\r
+            factory = (MethodFactory) e.nextElement();\r
+            if (factory.supportsImplementation(impltype))\r
+                return factory;\r
+        }\r
+               factory = null;\r
+\r
+               // try and load an implementation.  a new properties object needs\r
+               // to be created to hold the conglomerate type property, since\r
+               // that value is specific to the conglomerate we want to boot, not\r
+               // to the service as a whole\r
+               Properties conglomProperties = new Properties(serviceProperties);\r
+               conglomProperties.put(AccessFactoryGlobals.CONGLOM_PROP, impltype);\r
+\r
+               try {\r
+                       factory = \r
+               (MethodFactory) Monitor.bootServiceModule(\r
+                    false, this, MethodFactory.MODULE, \r
+                    impltype, conglomProperties);\r
+               } catch (StandardException se) {\r
+                       if (!se.getMessageId().equals(SQLState.SERVICE_MISSING_IMPLEMENTATION))\r
+                               throw se;\r
+               }\r
+\r
+               conglomProperties = null;\r
+\r
+               if (factory != null) {\r
+                       registerAccessMethod(factory);\r
+                       return factory;\r
+               }\r
+\r
+        // No such implementation.\r
+        return null;\r
+    }\r
+\r
+       public LockFactory getLockFactory() {\r
+               return rawstore.getLockFactory();\r
+       }\r
+\r
+\r
+    public TransactionController getTransaction(\r
+    ContextManager cm)\r
+        throws StandardException\r
+    {\r
+        return getAndNameTransaction(cm, AccessFactoryGlobals.USER_TRANS_NAME);\r
+    }\r
+\r
+    public TransactionController getAndNameTransaction(\r
+    ContextManager cm, String transName)\r
+        throws StandardException\r
+    {\r
+        if (cm == null)\r
+            return null;  // XXX (nat) should throw exception\r
+\r
+        // See if there's already a transaction context.\r
+        RAMTransactionContext rtc = (RAMTransactionContext)\r
+            cm.getContext(AccessFactoryGlobals.RAMXACT_CONTEXT_ID);\r
+\r
+        if (rtc == null)\r
+        {\r
+            // No transaction context.  Create or find a raw store transaction,\r
+            // make a context for it, and push the context.  Note this puts the\r
+            // raw store transaction context above the access context, which is\r
+            // required for error handling assumptions to be correct.\r
+            Transaction rawtran = rawstore.findUserTransaction(cm, transName);\r
+            RAMTransaction rt      = new RAMTransaction(this, rawtran, null);\r
+\r
+            rtc = \r
+                new RAMTransactionContext(\r
+                    cm, \r
+                    AccessFactoryGlobals.RAMXACT_CONTEXT_ID,\r
+                    rt, false /* abortAll */);\r
+\r
+                       TransactionController tc = rtc.getTransaction();\r
+\r
+                       if (xactProperties != null)\r
+            {\r
+                               rawtran.setup(tc);\r
+                               tc.commit();\r
+                       }\r
+\r
+            rawtran.setDefaultLockingPolicy(system_default_locking_policy);\r
+\r
+                       tc.commit();\r
+\r
+                       return tc;\r
+        }\r
+        return rtc.getTransaction();\r
+    }\r
+\r
+       /**\r
+     * Start a global transaction.\r
+     * <p>\r
+        * Get a transaction controller with which to manipulate data within\r
+        * the access manager.  Implicitly creates an access context.\r
+     * <p>\r
+     * Must only be called if no other transaction context exists in the\r
+     * current context manager.  If another transaction exists in the context\r
+     * an exception will be thrown.\r
+     * <p>\r
+     * The (format_id, global_id, branch_id) triplet is meant to come exactly\r
+     * from a javax.transaction.xa.Xid.  We don't use Xid so that the system\r
+     * can be delivered on a non-1.2 vm system and not require the javax classes\r
+     * in the path.  \r
+     *\r
+     * @param cm        The context manager for the current context.\r
+     * @param format_id the format id part of the Xid - ie. Xid.getFormatId().\r
+     * @param global_id the global transaction identifier part of XID - ie.\r
+     *                  Xid.getGlobalTransactionId().\r
+     * @param branch_id The branch qualifier of the Xid - ie. \r
+     *                  Xid.getBranchQaulifier()\r
+     *         \r
+        * @exception StandardException Standard exception policy.\r
+        * @see TransactionController\r
+        **/\r
+       public /* XATransactionController */ Object startXATransaction(\r
+    ContextManager  cm, \r
+    int             format_id,\r
+    byte[]          global_id,\r
+    byte[]          branch_id)\r
+               throws StandardException\r
+    {\r
+        RAMTransaction xa_tc = null;\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            SanityManager.ASSERT(global_id != null);\r
+            SanityManager.ASSERT(branch_id != null);\r
+        }\r
+\r
+        if (cm == null)\r
+            return null;  // XXX (nat) should throw exception\r
+\r
+        // See if there's already a transaction context.\r
+        RAMTransactionContext rtc = (RAMTransactionContext) \r
+            cm.getContext(AccessFactoryGlobals.RAMXACT_CONTEXT_ID);\r
+\r
+        if (rtc == null)\r
+        {\r
+            // No transaction context.  Create or find a raw store transaction,\r
+            // make a context for it, and push the context.  Note this puts the\r
+            // raw store transaction context above the access context, which is\r
+            // required for error handling assumptions to be correct.\r
+            Transaction rawtran = \r
+                rawstore.startGlobalTransaction(\r
+                    cm, format_id, global_id, branch_id);\r
+\r
+            xa_tc                    = new RAMTransaction(this, rawtran, null);\r
+\r
+            rtc = \r
+                new RAMTransactionContext(\r
+                    cm, \r
+                    AccessFactoryGlobals.RAMXACT_CONTEXT_ID,\r
+                    xa_tc, false /* abortAll */);\r
+\r
+            // RESOLVE - an XA transaction can only commit once so, if we\r
+            // acquire readlocks.\r
+\r
+                       if (xactProperties != null) \r
+            {\r
+                               rawtran.setup(xa_tc);\r
+\r
+                // HACK - special support has been added to the commitNoSync\r
+                // of a global xact, to allow committing of read only xact, \r
+                // which will allow subsequent activity on the xact keeping\r
+                // the same global transaction id.\r
+                xa_tc.commitNoSync(\r
+                    TransactionController.RELEASE_LOCKS |\r
+                    TransactionController.READONLY_TRANSACTION_INITIALIZATION);\r
+                       }\r
+\r
+            rawtran.setDefaultLockingPolicy(system_default_locking_policy);\r
+\r
+            // HACK - special support has been added to the commitNoSync\r
+            // of a global xact, to allow committing of read only xact, \r
+            // which will allow subsequent activity on the xact keeping\r
+            // the same global transaction id.\r
+            xa_tc.commitNoSync(\r
+                TransactionController.RELEASE_LOCKS |\r
+                TransactionController.READONLY_TRANSACTION_INITIALIZATION);\r
+        }\r
+        else\r
+        {\r
+            // throw an error.\r
+            if (SanityManager.DEBUG)\r
+                SanityManager.THROWASSERT(\r
+                    "RAMTransactionContext found on stack.");\r
+        }\r
+\r
+        return(xa_tc);\r
+    }\r
+\r
+\r
+    /**\r
+     * Return the XAResourceManager associated with this AccessFactory.\r
+     * <p>\r
+     * Returns an object which can be used to implement the "offline" \r
+     * 2 phase commit interaction between the accessfactory and outstanding\r
+     * transaction managers taking care of in-doubt transactions.\r
+     *\r
+     * @return The XAResourceManager associated with this accessfactory.\r
+     *\r
+     **/\r
+       public /* XAResourceManager */ Object getXAResourceManager()\r
+        throws StandardException\r
+    {\r
+        return(rawstore.getXAResourceManager());\r
+    }\r
+\r
+    public void registerAccessMethod(MethodFactory factory)\r
+    {\r
+        // Put the access method's primary implementation type in\r
+        // a hash table so we can find it quickly.\r
+        implhash.put(factory.primaryImplementationType(), factory);\r
+\r
+        // Put the access method's primary format in a hash table\r
+        // so we can find it quickly.\r
+        formathash.put(factory.primaryFormat(), factory);\r
+    }\r
+\r
+       public boolean isReadOnly()\r
+       {\r
+               return rawstore.isReadOnly();\r
+       }\r
+\r
+       private void addPropertySetNotification(PropertySetCallback who, TransactionController tc) {\r
+\r
+               pf.addPropertySetNotification(who);\r
+               \r
+               // set up the initial values by calling the validate and apply methods.\r
+               // the map methods are not called as they will have been called\r
+               // at runtime when the user set the property.\r
+               Dictionary d = new Hashtable();\r
+               try {\r
+                       xactProperties.getProperties(tc,d,false/*!stringsOnly*/,false/*!defaultsOnly*/);\r
+               } catch (StandardException se) {\r
+                       return;\r
+               }\r
+\r
+               boolean dbOnly = PropertyUtil.isDBOnly(d);\r
+\r
+               who.init(dbOnly, d);\r
+       }\r
+\r
+       public TransactionInfo[] getTransactionInfo()\r
+       {\r
+               return rawstore.getTransactionInfo();\r
+       }\r
+\r
+       public void freeze() throws StandardException\r
+       {\r
+               rawstore.freeze();\r
+       }\r
+\r
+       public void unfreeze() throws StandardException\r
+       {\r
+               rawstore.unfreeze();\r
+       }\r
+\r
+    public void backup(\r
+    String  backupDir, \r
+    boolean wait) \r
+        throws StandardException\r
+       {\r
+               rawstore.backup(backupDir, wait);\r
+       }\r
+\r
+\r
+    public void backupAndEnableLogArchiveMode(\r
+    String  backupDir, \r
+    boolean deleteOnlineArchivedLogFiles,\r
+    boolean wait)\r
+               throws StandardException \r
+       {\r
+               rawstore.backupAndEnableLogArchiveMode(backupDir, \r
+                                               deleteOnlineArchivedLogFiles, \r
+                                               wait);\r
+       }\r
+\r
+       public void disableLogArchiveMode(boolean deleteOnlineArchivedLogFiles)\r
+               throws StandardException\r
+       {\r
+               rawstore.disableLogArchiveMode(deleteOnlineArchivedLogFiles);\r
+       }\r
+\r
+\r
+\r
+       public void checkpoint() throws StandardException\r
+       {\r
+               rawstore.checkpoint();\r
+       }\r
+\r
+       public void waitForPostCommitToFinishWork()\r
+       {\r
+               rawstore.getDaemon().waitUntilQueueIsEmpty();\r
+       }\r
+\r
+    /**************************************************************************\r
+     * Public Methods implementing ModuleControl Interface:\r
+     **************************************************************************\r
+     */\r
+       public void boot(boolean create, Properties startParams)\r
+               throws StandardException\r
+       {\r
+               this.serviceProperties = startParams;\r
+\r
+        boot_load_conglom_map();\r
+\r
+        if (create)\r
+        {\r
+            // if we are creating the db, then just start the conglomid's at\r
+            // 1, and proceed from there.  If not create, we delay \r
+            // initialization of this until the first ddl which needs a new\r
+            // id.\r
+            conglom_nextid = 1;\r
+        }\r
+\r
+        // Access depends on a Raw Store implementations.  Load it.\r
+        //\r
+        rawstore = (RawStoreFactory) Monitor.bootServiceModule(\r
+            create, this, RawStoreFactory.MODULE, serviceProperties);\r
+\r
+               // Note: we also boot this module here since we may start Derby\r
+               // system from store access layer, as some of the unit test case,\r
+               // not from JDBC layer.(See\r
+               // /protocol/Database/Storage/Access/Interface/T_AccessFactory.java)\r
+               // If this module has already been booted by the JDBC layer, this will \r
+               // have no effect at all.\r
+               Monitor.bootServiceModule(\r
+            create, this, org.apache.derby.iapi.reference.Module.PropertyFactory, \r
+            startParams);\r
+\r
+        // Create the in-memory conglomerate directory\r
+\r
+        conglomCacheInit();\r
+\r
+        // Read in the conglomerate directory from the conglom conglom\r
+        // Create the conglom conglom from within a separate system xact\r
+        RAMTransaction tc =\r
+            (RAMTransaction) getAndNameTransaction(\r
+                ContextService.getFactory().getCurrentContextManager(),\r
+                AccessFactoryGlobals.USER_TRANS_NAME);\r
+\r
+        // looking up lock_mode is dependant on access booting, but\r
+        // some boot routines need lock_mode and\r
+        // system_default_locking_policy, so during boot do table level\r
+        // locking and then look up the "right" locking level.\r
+\r
+        int lock_mode = LockingPolicy.MODE_CONTAINER;\r
+\r
+        system_default_locking_policy =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                lock_mode,\r
+                TransactionController.ISOLATION_SERIALIZABLE, true);\r
+\r
+\r
+        // RESOLVE - code reduction - get rid of this table, and somehow\r
+        // combine it with the raw store one.\r
+\r
+        table_level_policy = new LockingPolicy[6];\r
+\r
+        table_level_policy[TransactionController.ISOLATION_NOLOCK] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_CONTAINER,\r
+                TransactionController.ISOLATION_NOLOCK, true);\r
+\r
+        table_level_policy[TransactionController.ISOLATION_READ_UNCOMMITTED] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_CONTAINER,\r
+                TransactionController.ISOLATION_READ_UNCOMMITTED, true);\r
+\r
+        table_level_policy[TransactionController.ISOLATION_READ_COMMITTED] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_CONTAINER,\r
+                TransactionController.ISOLATION_READ_COMMITTED, true);\r
+\r
+        table_level_policy[TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_CONTAINER,\r
+                TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK,\r
+                true);\r
+\r
+        table_level_policy[TransactionController.ISOLATION_REPEATABLE_READ] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_CONTAINER,\r
+                TransactionController.ISOLATION_REPEATABLE_READ, true);\r
+\r
+        table_level_policy[TransactionController.ISOLATION_SERIALIZABLE] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_CONTAINER,\r
+                TransactionController.ISOLATION_SERIALIZABLE, true);\r
+\r
+        record_level_policy = new LockingPolicy[6];\r
+\r
+        record_level_policy[TransactionController.ISOLATION_NOLOCK] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_RECORD,\r
+                TransactionController.ISOLATION_NOLOCK, true);\r
+\r
+        record_level_policy[TransactionController.ISOLATION_READ_UNCOMMITTED] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_RECORD,\r
+                TransactionController.ISOLATION_READ_UNCOMMITTED, true);\r
+\r
+        record_level_policy[TransactionController.ISOLATION_READ_COMMITTED] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_RECORD,\r
+                TransactionController.ISOLATION_READ_COMMITTED, true);\r
+\r
+        record_level_policy[TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_RECORD,\r
+                TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK,\r
+                true);\r
+\r
+        record_level_policy[TransactionController.ISOLATION_REPEATABLE_READ] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_RECORD,\r
+                TransactionController.ISOLATION_REPEATABLE_READ, true);\r
+\r
+        record_level_policy[TransactionController.ISOLATION_SERIALIZABLE] =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                LockingPolicy.MODE_RECORD,\r
+                TransactionController.ISOLATION_SERIALIZABLE, true);\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            for (int i = 0;\r
+                 i < TransactionController.ISOLATION_SERIALIZABLE;\r
+                 i++)\r
+            {\r
+                SanityManager.ASSERT(\r
+                    table_level_policy[i] != null,\r
+                    "table_level_policy[" + i + "] is null");\r
+                SanityManager.ASSERT(\r
+                    record_level_policy[i] != null,\r
+                    "record_level_policy[" + i + "] is null");\r
+            }\r
+        }\r
+\r
+        tc.commit();\r
+\r
+        // set up the property validation\r
+        pf = (PropertyFactory) \r
+            Monitor.findServiceModule(\r
+                this, org.apache.derby.iapi.reference.Module.PropertyFactory);\r
+\r
+        // set up the transaction properties.  On J9, over NFS, runing on a\r
+        // power PC coprossor, the directories were created fine, but create\r
+        // db would fail when trying to create this first file in seg0.\r
+        xactProperties = new PropertyConglomerate(tc, create, startParams, pf);\r
+\r
+        // see if there is any properties that raw store needs to know\r
+        // about\r
+        rawstore.getRawStoreProperties(tc);\r
+\r
+        // now that access and raw store are booted, do the property lookup\r
+        // which may do conglomerate access.\r
+        bootLookupSystemLockLevel(tc);\r
+\r
+        lock_mode =\r
+            (getSystemLockLevel() == TransactionController.MODE_TABLE ?\r
+                 LockingPolicy.MODE_CONTAINER : LockingPolicy.MODE_RECORD);\r
+\r
+        system_default_locking_policy =\r
+            tc.getRawStoreXact().newLockingPolicy(\r
+                lock_mode,\r
+                TransactionController.ISOLATION_SERIALIZABLE, true);\r
+\r
+        // set up the callbacl for the lock manager with initialization\r
+        addPropertySetNotification(getLockFactory(), tc);\r
+\r
+        // make sure user cannot change these properties\r
+        addPropertySetNotification(this,tc);\r
+\r
+        tc.commit();\r
+\r
+        tc.destroy();\r
+        tc = null;\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            // RESOLVE - (mikem) currently these constants need to be the\r
+            // same, but for modularity reasons there are 2 sets.  Probably\r
+            // should only be one set.  For now just make sure they are the\r
+            // same value.\r
+            SanityManager.ASSERT(\r
+                TransactionController.OPENMODE_USE_UPDATE_LOCKS ==\r
+                ContainerHandle.MODE_USE_UPDATE_LOCKS);\r
+            SanityManager.ASSERT(\r
+                TransactionController.OPENMODE_SECONDARY_LOCKED ==\r
+                ContainerHandle.MODE_SECONDARY_LOCKED);\r
+            SanityManager.ASSERT(\r
+                TransactionController.OPENMODE_BASEROW_INSERT_LOCKED ==\r
+                ContainerHandle.MODE_BASEROW_INSERT_LOCKED);\r
+            SanityManager.ASSERT(\r
+                TransactionController.OPENMODE_FORUPDATE ==\r
+                ContainerHandle.MODE_FORUPDATE);\r
+            SanityManager.ASSERT(\r
+                TransactionController.OPENMODE_FOR_LOCK_ONLY ==\r
+                ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY);\r
+        }\r
+       }\r
+\r
+    public void stop()\r
+    {\r
+    }\r
+\r
+    /* Methods of the PropertySetCallback interface */\r
+\r
+    // This interface is implemented to ensure the user cannot change the\r
+    // encryption provider or algorithm.\r
+\r
+       public void init(boolean dbOnly, Dictionary p)\r
+    {\r
+    }\r
+\r
+    public boolean validate(String key, Serializable value, Dictionary p)\r
+                throws StandardException\r
+    {\r
+        if (key.equals(Attribute.CRYPTO_ALGORITHM))\r
+        {\r
+            throw StandardException.newException(SQLState.ENCRYPTION_NOCHANGE_ALGORITHM);\r
+               }\r
+        if (key.equals(Attribute.CRYPTO_PROVIDER))\r
+        {\r
+            throw StandardException.newException(SQLState.ENCRYPTION_NOCHANGE_PROVIDER);\r
+               }\r
+        return true;\r
+    }\r
+\r
+    public Serviceable apply(String key, Serializable value, Dictionary p)\r
+                throws StandardException\r
+    {\r
+        return null;\r
+    }\r
+\r
+    public Serializable map(String key, Serializable value, Dictionary p)\r
+                throws StandardException\r
+    {\r
+        return null;\r
+    }\r
+\r
+    // ///////////////////////////////////////////////////////////////\r
+\r
+       /*\r
+       ** CacheableFactory interface\r
+       */\r
+\r
+       public Cacheable newCacheable(CacheManager cm) {\r
+               return new CacheableConglomerate();\r
+       }\r
+\r
+}\r