KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > store > access > RAMAccessManager


1 /*
2
3    Derby - Class org.apache.derby.impl.store.access.RAMAccessManager
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.store.access;
23
24 import org.apache.derby.iapi.services.cache.Cacheable;
25 import org.apache.derby.iapi.services.cache.CacheableFactory;
26 import org.apache.derby.iapi.services.cache.CacheFactory;
27 import org.apache.derby.iapi.services.cache.CacheManager;
28
29 import org.apache.derby.iapi.services.context.ContextManager;
30 import org.apache.derby.iapi.services.context.ContextService;
31 import org.apache.derby.iapi.services.daemon.Serviceable;
32 import org.apache.derby.iapi.services.locks.LockFactory;
33 import org.apache.derby.iapi.services.monitor.ModuleControl;
34 import org.apache.derby.iapi.services.monitor.Monitor;
35 import org.apache.derby.iapi.services.property.PropertySetCallback;
36
37 import org.apache.derby.iapi.services.sanity.SanityManager;
38 import org.apache.derby.iapi.services.io.FormatIdUtil;
39
40 import org.apache.derby.iapi.error.StandardException;
41
42 import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;
43 import org.apache.derby.iapi.store.access.conglomerate.ConglomerateFactory;
44 import org.apache.derby.iapi.store.access.conglomerate.MethodFactory;
45 import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;
46 import org.apache.derby.iapi.services.property.PropertyUtil;
47 import org.apache.derby.iapi.store.access.AccessFactory;
48 import org.apache.derby.iapi.services.property.PropertyFactory;
49
50 import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
51 import org.apache.derby.iapi.store.access.TransactionController;
52 import org.apache.derby.iapi.store.access.TransactionInfo;
53
54 import org.apache.derby.iapi.store.raw.ContainerHandle;
55 import org.apache.derby.iapi.store.raw.ContainerKey;
56 import org.apache.derby.iapi.store.raw.LockingPolicy;
57 import org.apache.derby.iapi.store.raw.RawStoreFactory;
58 import org.apache.derby.iapi.store.raw.Transaction;
59
60 import org.apache.derby.catalog.UUID;
61
62 import org.apache.derby.iapi.services.io.FormatableHashtable;
63 import org.apache.derby.iapi.reference.SQLState;
64 import org.apache.derby.iapi.reference.Attribute;
65
66 import java.util.Dictionary JavaDoc;
67 import java.util.Enumeration JavaDoc;
68 import java.util.Hashtable JavaDoc;
69 import java.util.Properties JavaDoc;
70
71 import java.io.File JavaDoc;
72 import java.io.Serializable JavaDoc;
73
74
75 public abstract class RAMAccessManager
76     implements AccessFactory,
77                CacheableFactory,
78                ModuleControl,
79                PropertySetCallback
80 {
81     /**************************************************************************
82      * Fields of the class
83      **************************************************************************
84      */

85
86     /**
87     The raw store that this access manager uses.
88     **/

89     private RawStoreFactory rawstore;
90
91     /**
92     Hash table on primary implementation type.
93     **/

94     private Hashtable implhash;
95
96     /**
97     Hash table on primary format.
98     **/

99     private Hashtable formathash;
100
101     /**
102     Service properties. These are supplied from ModuleControl.boot(),
103     and ultimately come from the service.properties file.
104     By convention, these properties are passed down to all modules
105     booted by this one. If this module needs to pass specific instructions
106     to its sub-modules, it should create a new Properties object with
107     serviceProperties as its default (so that the rest of the modules
108     that are looking at it don't see the properties that this module
109     needs to add).
110     **/

111     private Properties JavaDoc serviceProperties;
112
113     /**
114      * Default locking policy for the entire system.
115      **/

116     LockingPolicy system_default_locking_policy;
117
118     /**
119         The object providing the properties like behaviour
120         that is transactional.
121     */

122     private PropertyConglomerate xactProperties;
123     private PropertyFactory pf;
124
125     protected LockingPolicy table_level_policy[];
126     protected LockingPolicy record_level_policy[];
127
128
129     /**
130      * A map of the implementation specific id to conglomerate object.
131      * <p>
132      * A map of the implementation specific id to conglomerate object.
133      * The id is encoded into the conglomerate number, and then used to
134      * pick the right implementation of the conglomerate. It is then
135      * up to the conglomerate implementation to retrieve it's stored
136      * representation from disk.
137      *
138      * An internal mapping of the encoding of conglomerate identity in the
139      * conglomerate number to the actual conglomerate implementation. Encoding
140      * this means that we can't dynamically add conglomerate implementations
141      * into the system, so when we want to do that this mapping will have to
142      * be more dynamic - but for now store knows exactly what implementations
143      * there are.
144      **/

145     protected ConglomerateFactory conglom_map[];
146
147     /**
148      * Cache of Conglomerate objects, keyed by conglom id. Used to speed up
149      * subsquent open of conglomerates, first open will need to call the
150      * conglomerate to read and return it's description.
151      **/

152     private CacheManager conglom_cache;
153
154     /**************************************************************************
155      * Constructors for This class:
156      **************************************************************************
157      */

158
159     public RAMAccessManager()
160     {
161         // Intialize the hash tables that hold the access methods that
162
// this access manager knows about.
163
implhash = new Hashtable();
164         formathash = new Hashtable();
165     }
166
167     /**************************************************************************
168      * Private/Protected methods of This class:
169      **************************************************************************
170      */

171
172     /**
173      * Return the default locking policy for this access manager.
174      *
175      * @return the default locking policy for this accessmanager.
176      **/

177     protected LockingPolicy getDefaultLockingPolicy()
178     {
179         return(system_default_locking_policy);
180     }
181
182
183     RawStoreFactory getRawStore()
184     {
185         return rawstore;
186     }
187
188
189     PropertyConglomerate getTransactionalProperties()
190     {
191         return xactProperties;
192     }
193
194     private void boot_load_conglom_map()
195         throws StandardException
196     {
197         // System.out.println("before new code.");
198

199         conglom_map = new ConglomerateFactory[2];
200
201         // Find the appropriate factory for the desired implementation.
202
MethodFactory mfactory = findMethodFactoryByImpl("heap");
203
204         if (mfactory == null || !(mfactory instanceof ConglomerateFactory))
205         {
206             throw StandardException.newException(
207                     SQLState.AM_NO_SUCH_CONGLOMERATE_TYPE, "heap");
208         }
209
210         conglom_map[ConglomerateFactory.HEAP_FACTORY_ID] =
211             (ConglomerateFactory) mfactory;
212
213         // Find the appropriate factory for the desired implementation.
214
mfactory = findMethodFactoryByImpl("BTREE");
215
216         if (mfactory == null || !(mfactory instanceof ConglomerateFactory))
217         {
218             throw StandardException.newException(
219                     SQLState.AM_NO_SUCH_CONGLOMERATE_TYPE, "BTREE");
220         }
221         conglom_map[ConglomerateFactory.BTREE_FACTORY_ID] =
222             (ConglomerateFactory) mfactory;
223
224         // System.out.println("conglom_map[0] = " + conglom_map[0]);
225
// System.out.println("conglom_map[1] = " + conglom_map[1]);
226
}
227
228
229
230
231     /***************************************************************************
232     ** Abstract Methods of RAMAccessManager, interfaces that control locking
233     ** level of the system.
234     ****************************************************************************
235     */

236
237     /**
238      * Return the locking level of the system.
239      * <p>
240      * This routine controls the lowest level of locking enabled for all locks
241      * for all tables accessed through this accessmanager. The concrete
242      * implementation may set this value always to table level locking for
243      * a client configuration, or it may set it to row level locking for a
244      * server configuration.
245      * <p>
246      * If TransactionController.MODE_RECORD is returned table may either be
247      * locked at table or row locking depending on the type of access expected
248      * (ie. level 3 will require table locking for heap scans.)
249      *
250      * @return TransactionController.MODE_TABLE if only table locking allowed,
251      * else returns TransactionController.MODE_RECORD.
252      *
253      **/

254     abstract protected int getSystemLockLevel();
255
256     /**
257      * Query property system to get the System lock level.
258      * <p>
259      * This routine will be called during boot after access has booted far
260      * enough, to allow access to the property conglomerate. This routine
261      * will call the property system and set the value to be returned by
262      * getSystemLockLevel().
263      * <p>
264      *
265      * @exception StandardException Standard exception policy.
266      **/

267     abstract protected void bootLookupSystemLockLevel(
268     TransactionController tc)
269         throws StandardException;
270
271     /**************************************************************************
272      * Routines to map to/from conglomid/containerid:
273      **************************************************************************
274      */

275     private long conglom_nextid = 0;
276
277     /**
278      * Return next conglomid to try to add the container with.
279      * <p>
280      * The conglomerate number has 2 parts. The low 4 bits are used to
281      * encode the factory which "owns" the conglomerate. The high 60 bits
282      * are used as a normal unique id mechanism.
283      * <p>
284      * So for example if the next id to assign is 0x54 the following will
285      * be the conglomid:
286      * if a HEAP (factory 0) - 0x540
287      * if a BTREE (factory 1) - 0x541
288      *
289      * And the next id assigned will be:
290      * if a HEAP (factory 0) - 0x550
291      * if a BTREE (factory 1) - 0x551
292      *
293      * @param factory_type factory id as gotten from getConglomerateFactoryId()
294      *
295      * @return The identifier to be used to open the conglomerate later.
296      *
297      * @exception StandardException Standard exception policy.
298      **/

299     protected long getNextConglomId(int factory_type)
300         throws StandardException
301     {
302         long conglomid;
303
304         if (SanityManager.DEBUG)
305         {
306             // current code depends on this range, if we ever need to expand the
307
// range we can claim bits from the high order of the long.
308

309             SanityManager.ASSERT(factory_type >= 0x00 && factory_type <= 0x0f);
310         }
311
312         synchronized (conglom_cache)
313         {
314             if (conglom_nextid == 0)
315             {
316                 // shift out the factory id and then add 1.
317
conglom_nextid = (rawstore.getMaxContainerId() >> 4) + 1;
318             }
319
320             conglomid = conglom_nextid++;
321         }
322
323         // shift in the factory id and then return the conglomid.
324

325         return((conglomid << 4) | factory_type);
326     }
327
328     /**
329      * Bump the conglomid.
330      * <p>
331      * For some reason we have found that the give conglomid already exists
332      * in the directory so just bump the next conglomid to greater than this
333      * one. The algorithm to store and retrieve the last conglomid is not
334      * transactional as we don't want to pay the overhead for such an algorithm
335      * on every ddl statement - so it is possible to "lose" an update to the
336      * counter if we crash at an inopportune moment. In general the upper
337      * level store code will just handle the error from addContainer which
338      * says there already exists a conglom with that id, update the next
339      * conglomid and then try again.
340      * <p>
341      *
342      * @param conglomid The conglomid which already exists.
343      *
344      * @exception StandardException Standard exception policy.
345      **/

346     // currently not used, but this is one idea on how to handle
347
// non-transactional update of the nextid field, just handle the error
348
// if we try to create a conglom and find the container already exists.
349
/*
350     private void handleConglomidExists(
351     long conglomid)
352         throws StandardException
353     {
354         synchronized (conglom_cache)
355         {
356             conglom_nextid = ((conglomid >> 4) + 1);
357         }
358     }
359     */

360
361     /**
362      * Given a conglomid, return the factory which "owns" it.
363      * <p>
364      * A simple lookup on the boot time built table which maps the low order
365      * 4 bits into which factory owns the conglomerate.
366      * <p>
367      *
368      * @param conglom_id The conglomerate id of the conglomerate to look up.
369      *
370      * @return The ConglomerateFactory which "owns" this conglomerate.
371      *
372      * @exception StandardException Standard exception policy.
373      **/

374     private ConglomerateFactory getFactoryFromConglomId(
375     long conglom_id)
376         throws StandardException
377     {
378         try
379         {
380             return(conglom_map[((int) (0x0f & conglom_id))]);
381         }
382         catch (java.lang.ArrayIndexOutOfBoundsException JavaDoc e)
383         {
384             // just in case language passes in a bad factory id.
385
throw StandardException.newException(
386                 SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST,
387                 new Long JavaDoc(conglom_id));
388         }
389     }
390
391
392     /**************************************************************************
393      * Conglomerate Cache routines:
394      **************************************************************************
395      */

396
397     /**
398      * ACCESSMANAGER CONGLOMERATE CACHE -
399      * <p>
400      * Every conglomerate in the system is described by an object which
401      * implements Conglomerate. This object basically contains the parameters
402      * which describe the metadata about the conglomerate that store needs
403      * to know - like types of columns, number of keys, number of columns, ...
404      * <p>
405      * It is up to each conglomerate to maintain it's own description, and
406      * it's factory must be able to read this info from disk and return it
407      * from the ConglomerateFactory.readConglomerate() interface.
408      * <p>
409      * This cache simply maintains an in memory copy of these conglomerate
410      * objects, key'd by conglomerate id. By caching, this avoids the cost
411      * of reading the conglomerate info from disk on each subsequent query
412      * which accesses the conglomerate.
413      * <p>
414      * The interfaces and internal routines which deal with this cache are:
415      * conglomCacheInit() - initializes the cache at boot time.
416      *
417      *
418      *
419      **/

420
421     /**
422      * Initialize the conglomerate cache.
423      * <p>
424      * Simply calls the cache manager to create the cache with some hard
425      * coded defaults for size.
426      * <p>
427      * @exception StandardException Standard exception policy.
428      **/

429     private void conglomCacheInit()
430         throws StandardException
431     {
432         // Get a cache factory to create the conglomerate cache.
433
CacheFactory cf =
434             (CacheFactory) Monitor.startSystemModule(
435                  org.apache.derby.iapi.reference.Module.CacheFactory);
436
437         // Now create the conglomerate cache.
438

439         conglom_cache =
440            cf.newCacheManager(
441                this, AccessFactoryGlobals.CFG_CONGLOMDIR_CACHE, 200, 300);
442
443     }
444
445     /**
446      * Find a conglomerate by conglomid in the cache.
447      * <p>
448      * Look for a conglomerate given a conglomid. If in cache return it,
449      * otherwise fault in an entry by asking the owning factory to produce
450      * an entry.
451      * <p>
452      *
453      * @return The conglomerate object identified by "conglomid".
454      *
455      * @param conglomid The conglomerate id of the conglomerate to look up.
456      *
457      * @exception StandardException Standard exception policy.
458      **/

459     /* package */ Conglomerate conglomCacheFind(
460     TransactionManager xact_mgr,
461     long conglomid)
462         throws StandardException
463     {
464         Conglomerate conglom = null;
465         Long JavaDoc conglomid_obj = new Long JavaDoc(conglomid);
466
467         synchronized (conglom_cache)
468         {
469             CacheableConglomerate cache_entry =
470                 (CacheableConglomerate) conglom_cache.findCached(conglomid_obj);
471
472             if (cache_entry != null)
473             {
474                 conglom = cache_entry.getConglom();
475                 conglom_cache.release(cache_entry);
476
477                 // SanityManager.DEBUG_PRINT("find", "find hit : " + conglomid);
478
}
479             else
480             {
481                 // SanityManager.DEBUG_PRINT("find", "find miss: " + conglomid);
482

483                 // If not in cache - ask the factory for it and insert it.
484

485                 conglom =
486                     getFactoryFromConglomId(conglomid).readConglomerate(
487                         xact_mgr, new ContainerKey(0, conglomid));
488
489                 if (conglom != null)
490                 {
491                     // on cache miss, put the missing conglom in the cache.
492
cache_entry = (CacheableConglomerate)
493                         this.conglom_cache.create(conglomid_obj, conglom);
494                     this.conglom_cache.release(cache_entry);
495                 }
496             }
497         }
498
499         return(conglom);
500     }
501
502     /**
503      * Invalide the current Conglomerate Cache.
504      * <p>
505      * Abort of certain operations will invalidate the contents of the
506      * cache. Longer term we could just invalidate those entries, but
507      * for now just invalidate the whole cache.
508      * <p>
509      *
510      * @exception StandardException Standard exception policy.
511      **/

512     /* package */ protected void conglomCacheInvalidate()
513         throws StandardException
514     {
515         synchronized (conglom_cache)
516         {
517             conglom_cache.ageOut();
518         }
519
520         return;
521     }
522
523     /**
524      * Update a conglomerate directory entry.
525      * <p>
526      * Update the Conglom column of the Conglomerate Directory. The
527      * Conglomerate with id "conglomid" is replaced by "new_conglom".
528      * <p>
529      *
530      * @param conglomid The conglomid of conglomerate to replace.
531      * @param new_conglom The new Conglom to update the conglom column to.
532      *
533      * @exception StandardException Standard exception policy.
534      **/

535     /* package */ void conglomCacheUpdateEntry(
536     long conglomid,
537     Conglomerate new_conglom)
538         throws StandardException
539     {
540         Long JavaDoc conglomid_obj = new Long JavaDoc(conglomid);
541
542         synchronized (conglom_cache)
543         {
544             // remove the current entry
545
CacheableConglomerate conglom_entry = (CacheableConglomerate)
546                 conglom_cache.findCached(conglomid_obj);
547
548             if (conglom_entry != null)
549                 conglom_cache.remove(conglom_entry);
550
551             // insert the updated entry.
552
conglom_entry = (CacheableConglomerate)
553                 conglom_cache.create(conglomid_obj, new_conglom);
554             conglom_cache.release(conglom_entry);
555         }
556
557         return;
558     }
559
560     /**
561      * Add a newly created conglomerate to the cache.
562      * <p>
563      *
564      * @param conglomid The conglomid of conglomerate to replace.
565      * @param conglom The Conglom to add.
566      *
567      * @exception StandardException Standard exception policy.
568      **/

569     /* package */ void conglomCacheAddEntry(
570     long conglomid,
571     Conglomerate conglom)
572         throws StandardException
573     {
574         synchronized (conglom_cache)
575         {
576             // insert the updated entry.
577
CacheableConglomerate conglom_entry = (CacheableConglomerate)
578                 conglom_cache.create(new Long JavaDoc(conglomid), conglom);
579             conglom_cache.release(conglom_entry);
580         }
581
582         return;
583     }
584
585     /**
586      * Remove an entry from the cache.
587      * <p>
588      *
589      * @param conglomid The conglomid of conglomerate to replace.
590      *
591      * @exception StandardException Standard exception policy.
592      **/

593     /* package */ void conglomCacheRemoveEntry(long conglomid)
594         throws StandardException
595     {
596         synchronized (conglom_cache)
597         {
598             CacheableConglomerate conglom_entry = (CacheableConglomerate)
599                 conglom_cache.findCached(new Long JavaDoc(conglomid));
600
601             if (conglom_entry != null)
602                 conglom_cache.remove(conglom_entry);
603         }
604
605         return;
606     }
607
608
609
610     /**************************************************************************
611      * Public Methods implementing AccessFactory Interface:
612      **************************************************************************
613      */

614
615     /**
616     Database creation finished. Tell RawStore.
617     @exception StandardException cloudscape standard error policy
618     */

619     public void createFinished() throws StandardException
620     {
621         rawstore.createFinished();
622     }
623
624     /**
625     Find an access method that implements a format type.
626     @see AccessFactory#findMethodFactoryByFormat
627     **/

628     public MethodFactory findMethodFactoryByFormat(UUID format)
629     {
630         MethodFactory factory;
631         
632         // See if there's an access method that supports the desired
633
// format type as its primary format type.
634
factory = (MethodFactory) formathash.get(format);
635         if (factory != null)
636             return factory;
637
638         // No primary format. See if one of the access methods
639
// supports it as a secondary format.
640
Enumeration JavaDoc e = formathash.elements();
641         while (e.hasMoreElements())
642         {
643             factory = (MethodFactory) e.nextElement();
644             if (factory.supportsFormat(format))
645                 return factory;
646         }
647
648         // No such implementation.
649
return null;
650     }
651
652     /**
653     Find an access method that implements an implementation type.
654     @see AccessFactory#findMethodFactoryByImpl
655     **/

656     public MethodFactory findMethodFactoryByImpl(String JavaDoc impltype)
657         throws StandardException
658     {
659         // See if there's an access method that supports the desired
660
// implementation type as its primary implementation type.
661
MethodFactory factory = (MethodFactory) implhash.get(impltype);
662         if (factory != null)
663                 return factory;
664
665         // No primary implementation. See if one of the access methods
666
// supports the implementation type as a secondary.
667
Enumeration JavaDoc e = implhash.elements();
668         while (e.hasMoreElements())
669         {
670             factory = (MethodFactory) e.nextElement();
671             if (factory.supportsImplementation(impltype))
672                 return factory;
673         }
674         factory = null;
675
676         // try and load an implementation. a new properties object needs
677
// to be created to hold the conglomerate type property, since
678
// that value is specific to the conglomerate we want to boot, not
679
// to the service as a whole
680
Properties JavaDoc conglomProperties = new Properties JavaDoc(serviceProperties);
681         conglomProperties.put(AccessFactoryGlobals.CONGLOM_PROP, impltype);
682
683         try {
684             factory =
685                (MethodFactory) Monitor.bootServiceModule(
686                     false, this, MethodFactory.MODULE,
687                     impltype, conglomProperties);
688         } catch (StandardException se) {
689             if (!se.getMessageId().equals(SQLState.SERVICE_MISSING_IMPLEMENTATION))
690                 throw se;
691         }
692
693         conglomProperties = null;
694
695         if (factory != null) {
696             registerAccessMethod(factory);
697             return factory;
698         }
699
700         // No such implementation.
701
return null;
702     }
703
704     public LockFactory getLockFactory() {
705         return rawstore.getLockFactory();
706     }
707
708
709     public TransactionController getTransaction(
710     ContextManager cm)
711         throws StandardException
712     {
713         return getAndNameTransaction(cm, AccessFactoryGlobals.USER_TRANS_NAME);
714     }
715
716     public TransactionController getAndNameTransaction(
717     ContextManager cm, String JavaDoc transName)
718         throws StandardException
719     {
720         if (cm == null)
721             return null; // XXX (nat) should throw exception
722

723         // See if there's already a transaction context.
724
RAMTransactionContext rtc = (RAMTransactionContext)
725             cm.getContext(AccessFactoryGlobals.RAMXACT_CONTEXT_ID);
726
727         if (rtc == null)
728         {
729             // No transaction context. Create or find a raw store transaction,
730
// make a context for it, and push the context. Note this puts the
731
// raw store transaction context above the access context, which is
732
// required for error handling assumptions to be correct.
733
Transaction rawtran = rawstore.findUserTransaction(cm, transName);
734             RAMTransaction rt = new RAMTransaction(this, rawtran, null);
735
736             rtc =
737                 new RAMTransactionContext(
738                     cm,
739                     AccessFactoryGlobals.RAMXACT_CONTEXT_ID,
740                     rt, false /* abortAll */);
741
742             TransactionController tc = rtc.getTransaction();
743
744             if (xactProperties != null)
745             {
746                 rawtran.setup(tc);
747                 tc.commit();
748             }
749
750             rawtran.setDefaultLockingPolicy(system_default_locking_policy);
751
752             tc.commit();
753
754             return tc;
755         }
756         return rtc.getTransaction();
757     }
758
759     /**
760      * Start a global transaction.
761      * <p>
762      * Get a transaction controller with which to manipulate data within
763      * the access manager. Implicitly creates an access context.
764      * <p>
765      * Must only be called if no other transaction context exists in the
766      * current context manager. If another transaction exists in the context
767      * an exception will be thrown.
768      * <p>
769      * The (format_id, global_id, branch_id) triplet is meant to come exactly
770      * from a javax.transaction.xa.Xid. We don't use Xid so that the system
771      * can be delivered on a non-1.2 vm system and not require the javax classes
772      * in the path.
773      *
774      * @param cm The context manager for the current context.
775      * @param format_id the format id part of the Xid - ie. Xid.getFormatId().
776      * @param global_id the global transaction identifier part of XID - ie.
777      * Xid.getGlobalTransactionId().
778      * @param branch_id The branch qualifier of the Xid - ie.
779      * Xid.getBranchQaulifier()
780      *
781      * @exception StandardException Standard exception policy.
782      * @see TransactionController
783      **/

784     public /* XATransactionController */ Object JavaDoc startXATransaction(
785     ContextManager cm,
786     int format_id,
787     byte[] global_id,
788     byte[] branch_id)
789         throws StandardException
790     {
791         RAMTransaction xa_tc = null;
792
793         if (SanityManager.DEBUG)
794         {
795             SanityManager.ASSERT(global_id != null);
796             SanityManager.ASSERT(branch_id != null);
797         }
798
799         if (cm == null)
800             return null; // XXX (nat) should throw exception
801

802         // See if there's already a transaction context.
803
RAMTransactionContext rtc = (RAMTransactionContext)
804             cm.getContext(AccessFactoryGlobals.RAMXACT_CONTEXT_ID);
805
806         if (rtc == null)
807         {
808             // No transaction context. Create or find a raw store transaction,
809
// make a context for it, and push the context. Note this puts the
810
// raw store transaction context above the access context, which is
811
// required for error handling assumptions to be correct.
812
Transaction rawtran =
813                 rawstore.startGlobalTransaction(
814                     cm, format_id, global_id, branch_id);
815
816             xa_tc = new RAMTransaction(this, rawtran, null);
817
818             rtc =
819                 new RAMTransactionContext(
820                     cm,
821                     AccessFactoryGlobals.RAMXACT_CONTEXT_ID,
822                     xa_tc, false /* abortAll */);
823
824             // RESOLVE - an XA transaction can only commit once so, if we
825
// acquire readlocks.
826

827             if (xactProperties != null)
828             {
829                 rawtran.setup(xa_tc);
830
831                 // HACK - special support has been added to the commitNoSync
832
// of a global xact, to allow committing of read only xact,
833
// which will allow subsequent activity on the xact keeping
834
// the same global transaction id.
835
xa_tc.commitNoSync(
836                     TransactionController.RELEASE_LOCKS |
837                     TransactionController.READONLY_TRANSACTION_INITIALIZATION);
838             }
839
840             rawtran.setDefaultLockingPolicy(system_default_locking_policy);
841
842             // HACK - special support has been added to the commitNoSync
843
// of a global xact, to allow committing of read only xact,
844
// which will allow subsequent activity on the xact keeping
845
// the same global transaction id.
846
xa_tc.commitNoSync(
847                 TransactionController.RELEASE_LOCKS |
848                 TransactionController.READONLY_TRANSACTION_INITIALIZATION);
849         }
850         else
851         {
852             // throw an error.
853
if (SanityManager.DEBUG)
854                 SanityManager.THROWASSERT(
855                     "RAMTransactionContext found on stack.");
856         }
857
858         return(xa_tc);
859     }
860
861
862     /**
863      * Return the XAResourceManager associated with this AccessFactory.
864      * <p>
865      * Returns an object which can be used to implement the "offline"
866      * 2 phase commit interaction between the accessfactory and outstanding
867      * transaction managers taking care of in-doubt transactions.
868      *
869      * @return The XAResourceManager associated with this accessfactory.
870      *
871      **/

872     public /* XAResourceManager */ Object JavaDoc getXAResourceManager()
873         throws StandardException
874     {
875         return(rawstore.getXAResourceManager());
876     }
877
878     public void registerAccessMethod(MethodFactory factory)
879     {
880         // Put the access method's primary implementation type in
881
// a hash table so we can find it quickly.
882
implhash.put(factory.primaryImplementationType(), factory);
883
884         // Put the access method's primary format in a hash table
885
// so we can find it quickly.
886
formathash.put(factory.primaryFormat(), factory);
887     }
888
889     public boolean isReadOnly()
890     {
891         return rawstore.isReadOnly();
892     }
893
894     private void addPropertySetNotification(PropertySetCallback who, TransactionController tc) {
895
896         pf.addPropertySetNotification(who);
897         
898         // set up the initial values by calling the validate and apply methods.
899
// the map methods are not called as they will have been called
900
// at runtime when the user set the property.
901
Dictionary JavaDoc d = new Hashtable();
902         try {
903             xactProperties.getProperties(tc,d,false/*!stringsOnly*/,false/*!defaultsOnly*/);
904         } catch (StandardException se) {
905             return;
906         }
907
908         boolean dbOnly = PropertyUtil.isDBOnly(d);
909
910         who.init(dbOnly, d);
911     }
912
913     public TransactionInfo[] getTransactionInfo()
914     {
915         return rawstore.getTransactionInfo();
916     }
917
918     public void freeze() throws StandardException
919     {
920         rawstore.freeze();
921     }
922
923     public void unfreeze() throws StandardException
924     {
925         rawstore.unfreeze();
926     }
927
928     public void backup(
929     String JavaDoc backupDir,
930     boolean wait)
931         throws StandardException
932     {
933         rawstore.backup(backupDir, wait);
934     }
935
936
937     public void backupAndEnableLogArchiveMode(
938     String JavaDoc backupDir,
939     boolean deleteOnlineArchivedLogFiles,
940     boolean wait)
941         throws StandardException
942     {
943         rawstore.backupAndEnableLogArchiveMode(backupDir,
944                                                deleteOnlineArchivedLogFiles,
945                                                wait);
946     }
947
948     public void disableLogArchiveMode(boolean deleteOnlineArchivedLogFiles)
949         throws StandardException
950     {
951         rawstore.disableLogArchiveMode(deleteOnlineArchivedLogFiles);
952     }
953
954
955
956     public void checkpoint() throws StandardException
957     {
958         rawstore.checkpoint();
959     }
960
961     public void waitForPostCommitToFinishWork()
962     {
963         rawstore.getDaemon().waitUntilQueueIsEmpty();
964     }
965
966     /**************************************************************************
967      * Public Methods implementing ModuleControl Interface:
968      **************************************************************************
969      */

970     public void boot(boolean create, Properties JavaDoc startParams)
971         throws StandardException
972     {
973         this.serviceProperties = startParams;
974
975         boot_load_conglom_map();
976
977         if (create)
978         {
979             // if we are creating the db, then just start the conglomid's at
980
// 1, and proceed from there. If not create, we delay
981
// initialization of this until the first ddl which needs a new
982
// id.
983
conglom_nextid = 1;
984         }
985
986         // Access depends on a Raw Store implementations. Load it.
987
//
988
rawstore = (RawStoreFactory) Monitor.bootServiceModule(
989             create, this, RawStoreFactory.MODULE, serviceProperties);
990
991         // Note: we also boot this module here since we may start cloudscape
992
// system from store access layer, as some of the unit test case,
993
// not from JDBC layer.(See
994
// /protocol/Database/Storage/Access/Interface/T_AccessFactory.java)
995
// If this module has already been booted by the JDBC layer, this will
996
// have no effect at all.
997
Monitor.bootServiceModule(
998             create, this, org.apache.derby.iapi.reference.Module.PropertyFactory,
999             startParams);
1000
1001        // Create the in-memory conglomerate directory
1002

1003        conglomCacheInit();
1004
1005        // Read in the conglomerate directory from the conglom conglom
1006
// Create the conglom conglom from within a separate system xact
1007
RAMTransaction tc =
1008            (RAMTransaction) getAndNameTransaction(
1009                ContextService.getFactory().getCurrentContextManager(),
1010                AccessFactoryGlobals.USER_TRANS_NAME);
1011
1012        // looking up lock_mode is dependant on access booting, but
1013
// some boot routines need lock_mode and
1014
// system_default_locking_policy, so during boot do table level
1015
// locking and then look up the "right" locking level.
1016

1017        int lock_mode = LockingPolicy.MODE_CONTAINER;
1018
1019        system_default_locking_policy =
1020            tc.getRawStoreXact().newLockingPolicy(
1021                lock_mode,
1022                TransactionController.ISOLATION_SERIALIZABLE, true);
1023
1024
1025        // RESOLVE - code reduction - get rid of this table, and somehow
1026
// combine it with the raw store one.
1027

1028        table_level_policy = new LockingPolicy[6];
1029
1030        table_level_policy[TransactionController.ISOLATION_NOLOCK] =
1031            tc.getRawStoreXact().newLockingPolicy(
1032                LockingPolicy.MODE_CONTAINER,
1033                TransactionController.ISOLATION_NOLOCK, true);
1034
1035        table_level_policy[TransactionController.ISOLATION_READ_UNCOMMITTED] =
1036            tc.getRawStoreXact().newLockingPolicy(
1037                LockingPolicy.MODE_CONTAINER,
1038                TransactionController.ISOLATION_READ_UNCOMMITTED, true);
1039
1040        table_level_policy[TransactionController.ISOLATION_READ_COMMITTED] =
1041            tc.getRawStoreXact().newLockingPolicy(
1042                LockingPolicy.MODE_CONTAINER,
1043                TransactionController.ISOLATION_READ_COMMITTED, true);
1044
1045        table_level_policy[TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK] =
1046            tc.getRawStoreXact().newLockingPolicy(
1047                LockingPolicy.MODE_CONTAINER,
1048                TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK,
1049                true);
1050
1051        table_level_policy[TransactionController.ISOLATION_REPEATABLE_READ] =
1052            tc.getRawStoreXact().newLockingPolicy(
1053                LockingPolicy.MODE_CONTAINER,
1054                TransactionController.ISOLATION_REPEATABLE_READ, true);
1055
1056        table_level_policy[TransactionController.ISOLATION_SERIALIZABLE] =
1057            tc.getRawStoreXact().newLockingPolicy(
1058                LockingPolicy.MODE_CONTAINER,
1059                TransactionController.ISOLATION_SERIALIZABLE, true);
1060
1061        record_level_policy = new LockingPolicy[6];
1062
1063        record_level_policy[TransactionController.ISOLATION_NOLOCK] =
1064            tc.getRawStoreXact().newLockingPolicy(
1065                LockingPolicy.MODE_RECORD,
1066                TransactionController.ISOLATION_NOLOCK, true);
1067
1068        record_level_policy[TransactionController.ISOLATION_READ_UNCOMMITTED] =
1069            tc.getRawStoreXact().newLockingPolicy(
1070                LockingPolicy.MODE_RECORD,
1071                TransactionController.ISOLATION_READ_UNCOMMITTED, true);
1072
1073        record_level_policy[TransactionController.ISOLATION_READ_COMMITTED] =
1074            tc.getRawStoreXact().newLockingPolicy(
1075                LockingPolicy.MODE_RECORD,
1076                TransactionController.ISOLATION_READ_COMMITTED, true);
1077
1078        record_level_policy[TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK] =
1079            tc.getRawStoreXact().newLockingPolicy(
1080                LockingPolicy.MODE_RECORD,
1081                TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK,
1082                true);
1083
1084        record_level_policy[TransactionController.ISOLATION_REPEATABLE_READ] =
1085            tc.getRawStoreXact().newLockingPolicy(
1086                LockingPolicy.MODE_RECORD,
1087                TransactionController.ISOLATION_REPEATABLE_READ, true);
1088
1089        record_level_policy[TransactionController.ISOLATION_SERIALIZABLE] =
1090            tc.getRawStoreXact().newLockingPolicy(
1091                LockingPolicy.MODE_RECORD,
1092                TransactionController.ISOLATION_SERIALIZABLE, true);
1093
1094        if (SanityManager.DEBUG)
1095        {
1096            for (int i = 0;
1097                 i < TransactionController.ISOLATION_SERIALIZABLE;
1098                 i++)
1099            {
1100                SanityManager.ASSERT(
1101                    table_level_policy[i] != null,
1102                    "table_level_policy[" + i + "] is null");
1103                SanityManager.ASSERT(
1104                    record_level_policy[i] != null,
1105                    "record_level_policy[" + i + "] is null");
1106            }
1107        }
1108
1109        tc.commit();
1110
1111        // set up the property validation
1112
pf = (PropertyFactory)
1113            Monitor.findServiceModule(
1114                this, org.apache.derby.iapi.reference.Module.PropertyFactory);
1115
1116        // set up the transaction properties. On J9, over NFS, runing on a
1117
// power PC coprossor, the directories were created fine, but create
1118
// db would fail when trying to create this first file in seg0.
1119
xactProperties = new PropertyConglomerate(tc, create, startParams, pf);
1120
1121        // see if there is any properties that raw store needs to know
1122
// about
1123
rawstore.getRawStoreProperties(tc);
1124
1125        // now that access and raw store are booted, do the property lookup
1126
// which may do conglomerate access.
1127
bootLookupSystemLockLevel(tc);
1128
1129        lock_mode =
1130            (getSystemLockLevel() == TransactionController.MODE_TABLE ?
1131                 LockingPolicy.MODE_CONTAINER : LockingPolicy.MODE_RECORD);
1132
1133        system_default_locking_policy =
1134            tc.getRawStoreXact().newLockingPolicy(
1135                lock_mode,
1136                TransactionController.ISOLATION_SERIALIZABLE, true);
1137
1138        // set up the callbacl for the lock manager with initialization
1139
addPropertySetNotification(getLockFactory(), tc);
1140
1141        // make sure user cannot change these properties
1142
addPropertySetNotification(this,tc);
1143
1144        tc.commit();
1145
1146        tc.destroy();
1147        tc = null;
1148
1149        if (SanityManager.DEBUG)
1150        {
1151            // RESOLVE - (mikem) currently these constants need to be the
1152
// same, but for modularity reasons there are 2 sets. Probably
1153
// should only be one set. For now just make sure they are the
1154
// same value.
1155
SanityManager.ASSERT(
1156                TransactionController.OPENMODE_USE_UPDATE_LOCKS ==
1157                ContainerHandle.MODE_USE_UPDATE_LOCKS);
1158            SanityManager.ASSERT(
1159                TransactionController.OPENMODE_SECONDARY_LOCKED ==
1160                ContainerHandle.MODE_SECONDARY_LOCKED);
1161            SanityManager.ASSERT(
1162                TransactionController.OPENMODE_BASEROW_INSERT_LOCKED ==
1163                ContainerHandle.MODE_BASEROW_INSERT_LOCKED);
1164            SanityManager.ASSERT(
1165                TransactionController.OPENMODE_FORUPDATE ==
1166                ContainerHandle.MODE_FORUPDATE);
1167            SanityManager.ASSERT(
1168                TransactionController.OPENMODE_FOR_LOCK_ONLY ==
1169                ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY);
1170        }
1171    }
1172
1173    public void stop()
1174    {
1175    }
1176
1177    /* Methods of the PropertySetCallback interface */
1178
1179    // This interface is implemented to ensure the user cannot change the
1180
// encryption provider or algorithm.
1181

1182    public void init(boolean dbOnly, Dictionary JavaDoc p)
1183    {
1184    }
1185
1186    public boolean validate(String JavaDoc key, Serializable JavaDoc value, Dictionary JavaDoc p)
1187         throws StandardException
1188    {
1189        if (key.equals(Attribute.CRYPTO_ALGORITHM))
1190        {
1191            throw StandardException.newException(SQLState.ENCRYPTION_NOCHANGE_ALGORITHM);
1192        }
1193        if (key.equals(Attribute.CRYPTO_PROVIDER))
1194        {
1195            throw StandardException.newException(SQLState.ENCRYPTION_NOCHANGE_PROVIDER);
1196        }
1197        return true;
1198    }
1199
1200    public Serviceable apply(String JavaDoc key, Serializable JavaDoc value, Dictionary JavaDoc p)
1201         throws StandardException
1202    {
1203        return null;
1204    }
1205
1206    public Serializable JavaDoc map(String JavaDoc key, Serializable JavaDoc value, Dictionary JavaDoc p)
1207         throws StandardException
1208    {
1209        return null;
1210    }
1211
1212    // ///////////////////////////////////////////////////////////////
1213

1214    /*
1215    ** CacheableFactory interface
1216    */

1217
1218    public Cacheable newCacheable(CacheManager cm) {
1219        return new CacheableConglomerate();
1220    }
1221
1222}
1223
Popular Tags