KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > core > storage > wizardStore > WizardStore


1 // You can redistribute this software and/or modify it under the terms of
2
// the Ozone Core License version 1 published by ozone-db.org.
3
//
4
// The original code and portions created by SMB are
5
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
6
//
7
// $Id: WizardStore.java,v 1.6 2004/01/26 00:57:30 wieslawf Exp $
8

9 package org.ozoneDB.core.storage.wizardStore;
10
11 import java.io.*;
12
13 import org.ozoneDB.DxLib.*;
14 import org.ozoneDB.*;
15 import org.ozoneDB.io.stream.ResolvingObjectInputStream;
16 import org.ozoneDB.core.*;
17 import org.ozoneDB.core.storage.wizardStore.*;
18 import org.ozoneDB.core.storage.wizardStore.WizardCluster;
19 import org.ozoneDB.core.storage.wizardStore.ClusterStore;
20 import org.ozoneDB.core.storage.wizardStore.IDTable;
21 import org.ozoneDB.core.storage.wizardStore.IDTableChange;
22 import org.ozoneDB.core.storage.wizardStore.NameTableChange;
23 import org.ozoneDB.core.storage.wizardStore.WizardObjectContainer;
24 import org.ozoneDB.core.storage.ClusterID;
25 import org.ozoneDB.core.storage.StorageObjectContainer;
26 import org.ozoneDB.util.LogWriter;
27
28
29 /**
30  * @author <a HREF="http://www.softwarebuero.de/">SMB</a>
31  * @author <a HREF="http://www.medium.net/">Medium.net</a>
32  * @version $Revision: 1.6 $Date: 2004/01/26 00:57:30 $
33  */

34 public final class WizardStore
35         extends ServerComponent
36         implements StoreManager {
37
38     protected final static String JavaDoc ID_TABLE_NAME = "idTable.wizard";
39
40     protected final static String JavaDoc NAME_TABLE_NAME = "nameTable.wizard";
41
42     protected final static String JavaDoc COMMIT_FLAG_NAME = "commitflag.wizard";
43
44     /**
45      * Maps ObjectIDs to ClusterIDs
46      */

47     protected DxMap idTable;
48
49     /**
50      * Maps names to ObjectIDs
51      */

52     protected DxMap nameTable;
53
54     protected ClusterStore clusterStore;
55
56     /**
57      The garbage collector. It should be notified in the event
58      <UL>
59      <LI>that a formerly unnamed object receives a name.</LI>
60      <LI>that an object is freshly created</LI>
61      </LI>
62      */

63     protected GarbageCollector garbageCollector;
64
65     public WizardStore(Env env) {
66         super(env);
67     }
68
69
70     public synchronized void init(Env _env) {
71         env = _env;
72
73         int idTableBufferSize = env.config.intProperty(Setup.WS_TABLE_BUFF_SIZE, -1);
74         int idTableCacheSize = env.config.intProperty(Setup.WS_TABLE_CACHE_SIZE, -1);
75         int[] idTableSubtableSize = env.config.intArrayProperty(Setup.WS_TABLE_SUBTABLE_SIZE, new int[]{-1});
76
77         idTable = new IDTable(env.getDatabaseDir() + "ostab" + File.separator + "tab", idTableBufferSize, idTableCacheSize, idTableSubtableSize);
78         // idTable = new DxHashMap (10000);
79
nameTable = new DxHashMap(100);
80
81         clusterStore = new ClusterStore(_env);
82
83         this.garbageCollector = env.getGarbageCollector();
84     }
85
86
87     public synchronized void startup() throws Exception JavaDoc {
88         env.logWriter.newEntry(this, "startup...", LogWriter.INFO);
89         clusterStore.startup();
90
91         env.logWriter.newEntry(this, "checking for pending shadow clusters...", LogWriter.INFO);
92
93         boolean isCleanShutdown = isCleanShutdown() && clusterStore.isCleanShutdown();
94
95         boolean isSuccessfullyStarted = false;
96
97         if (isCleanShutdown) {
98             ObjectInputStream nameTableIn = null;
99             ObjectInputStream idTableIn = null;
100             try {
101                 // restore nameTable
102
nameTableIn = new ResolvingObjectInputStream(new FileInputStream(env.getDatabaseDir() + NAME_TABLE_NAME));
103                 int count = nameTableIn.readInt();
104                 for (int i = 0; i < count; i++) {
105                     nameTable.addForKey(nameTableIn.readObject(), nameTableIn.readObject());
106                 }
107                 nameTableIn.close();
108
109                 // restore idTable
110
if (!(idTable instanceof DxDiskHashMap)) {
111                     idTableIn = new ResolvingObjectInputStream(new FileInputStream(env.getDatabaseDir() + ID_TABLE_NAME));
112                     count = idTableIn.readInt();
113                     for (int i = 0; i < count; i++) {
114                         idTable.addForKey(idTableIn.readObject(), idTableIn.readObject());
115                     }
116                     idTableIn.close();
117                 } else {
118                     ((DxDiskHashMap) idTable).re_use();
119                     ((DxDiskHashMap) idTable).setReusable(true);
120                 }
121
122                 isSuccessfullyStarted = true;
123             } catch (FileNotFoundException fe) {
124                 env.logWriter.newEntry(this, " " + fe.toString(), LogWriter.INFO);
125             } catch (Exception JavaDoc e) {
126                 env.logWriter.newEntry(this, " error while starting up... ", LogWriter.INFO);
127                 env.logWriter.newEntry(this, " exception: ", e, LogWriter.DEBUG);
128             } finally {
129                 if (nameTableIn != null) {
130                     nameTableIn.close();
131                 }
132                 if (idTableIn != null) {
133                     idTableIn.close();
134                 }
135             }
136         }
137
138         if (!isCleanShutdown || !isSuccessfullyStarted) {
139             env.logWriter.newEntry(this, " recovering...", LogWriter.INFO);
140             recover();
141         }
142
143         env.logWriter.newEntry(this, " " + idTable.count() + " IDs, " + nameTable.count() + " name(s))",
144                                LogWriter.INFO);
145     }
146
147
148     public synchronized void shutdown() throws Exception JavaDoc {
149         env.logWriter.newEntry(this, "shutdown...", LogWriter.INFO);
150         clusterStore.shutdown();
151
152         commitNameTable();
153
154         commitIDTable();
155         if (idTable instanceof DxDiskHashMap) {
156             ((DxDiskHashMap) idTable).printStatistics();
157             ((DxDiskHashMap) idTable).close();
158         }
159     }
160
161
162     public void save() throws Exception JavaDoc {
163     }
164
165
166     public DxIterator objectIDIterator() {
167         return idTable.iterator();
168     }
169
170
171     protected void commitNameTable() throws IOException {
172         env.logWriter.newEntry(this, "commitNameTable...", LogWriter.DEBUG3);
173
174         String JavaDoc filename = env.getDatabaseDir() + NAME_TABLE_NAME;
175         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename));
176         try {
177             out.writeInt(nameTable.count());
178             DxIterator it = nameTable.iterator();
179             while (it.next() != null) {
180                 out.writeObject(it.object());
181                 out.writeObject(it.key());
182             }
183         } catch (Exception JavaDoc e) {
184             new File(filename).delete();
185         } finally {
186             out.close();
187         }
188     }
189
190
191     protected void commitIDTable() throws IOException {
192         env.logWriter.newEntry(this, "commitIDTable...", LogWriter.DEBUG3);
193
194         if (!(idTable instanceof DxDiskHashMap)) {
195             String JavaDoc filename = env.getDatabaseDir() + ID_TABLE_NAME;
196             ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename));
197
198             try {
199                 out.writeInt(idTable.count());
200                 DxIterator it = idTable.iterator();
201                 while (it.next() != null) {
202                     out.writeObject(it.object());
203                     out.writeObject(it.key());
204                 }
205             } catch (Exception JavaDoc e) {
206                 new File(filename).delete();
207             } finally {
208                 out.close();
209             }
210         } else {
211             ((IDTable) idTable).setReusable(false);
212             ((IDTable) idTable).writeDirtyTables();
213             ((IDTable) idTable).setReusable(true);
214         }
215     }
216
217
218     /**
219      * Fill idTable and nameTable from the information that are stored in the
220      * clusters directly.
221      *
222      * @throws java.lang.Exception If a cluster cannot be read.
223      */

224     protected synchronized void recover() throws Exception JavaDoc {
225         env.logWriter.newEntry(this, " cleaning ID table...", LogWriter.INFO);
226         ((DxDiskHashMap) idTable).cleanFiles();
227         (idTable).clear();
228
229         env.logWriter.newEntry(this, " cleaning name table...", LogWriter.INFO);
230         nameTable.clear();
231
232         DxSet cids = clusterStore.recoverClusterIDs();
233         
234         int totalNumClusters = cids.count();
235         int processedNumClusters = 0;
236
237         DxIterator it = cids.iterator();
238         while (it.next() != null) {
239             ClusterID cid = (ClusterID) it.object();
240
241             org.ozoneDB.core.storage.Cluster cluster = null;
242             boolean exceptionWhileLoading = false;
243
244             env.logWriter.newEntry(this, " cluster: " + cid + " (" + ++processedNumClusters + " of " + totalNumClusters + ")", LogWriter.INFO);
245             try {
246                 cluster = clusterStore.restoreCluster(cid);
247                 env.logWriter.newEntry(this, " " + cluster.containers().count() + " containers", LogWriter.INFO);
248             } catch (Exception JavaDoc e) {
249                 env.logWriter.newEntry(this, "exception while loading cluster: " + cid + " (" + e + ")", LogWriter.WARN);
250                 env.logWriter.newEntry(this, "", e, LogWriter.DEBUG);
251                 exceptionWhileLoading = true;
252             }
253
254             if (exceptionWhileLoading || cluster.containers().isEmpty()) {
255                 if (exceptionWhileLoading) {
256                     env.logWriter.newEntry(this, " cluster is unable to read - should be deleted!", LogWriter.INFO);
257                 } else {
258                     env.logWriter.newEntry(this, " cluster is empty - should be deleted!", LogWriter.INFO);
259                 }
260                 if (cluster != null) {
261                     env.logWriter.newEntry(this, " try to delete cluster...", LogWriter.INFO);
262                     cluster.delete();
263                 }
264             } else {
265                 // fill in idTable and nameTable
266
DxIterator it2 = cluster.containers().iterator();
267                 StorageObjectContainer container;
268                 while ((container = (StorageObjectContainer) it2.next()) != null) {
269                     if (env.logWriter.hasTarget(LogWriter.DEBUG)) {
270                         if (container.id().value()==1) {
271                             env.logWriter.newEntry(this, "Adding container "+container+".", LogWriter.DEBUG);
272                         }
273                     }
274                     if (idTable.addForKey(cluster.clusterID(), container.id()) == false) {
275                         throw new IllegalStateException JavaDoc("Unable to add container "+container+" to ID table because cluster ID "+idTable.elementForKey(container.id())+" is already registered for container ID "+container.id()+".");
276                     }
277                     if (container.name() != null) {
278                         env.logWriter.newEntry(this, " adding name: " + container.name(), LogWriter.INFO);
279                         if (nameTable.addForKey(container.id(), container.name()) == false) {
280                             throw new IllegalStateException JavaDoc("Unable to add name to name table: " + container.name());
281                         }
282                     }
283                 }
284             }
285             clusterStore.unloadCluster(cid, false);
286         }
287         commitIDTable();
288         commitNameTable();
289     }
290
291
292     public synchronized ObjectContainer newContainerAndLock(Transaction ta, OzoneCompatible target, ObjectID objID,
293                                                                   Permissions permissions, int lockLevel) throws Exception JavaDoc {
294
295
296         StorageObjectContainer container = new WizardObjectContainer(objID);
297
298         if (target != null) {
299             container.setTarget(target);
300         }
301
302         clusterStore.registerContainerAndLock(container, permissions, ta, lockLevel);
303
304         boolean alright = false;
305
306         try {
307
308             garbageCollector.notifyNewObjectContainer(container);
309
310             WizardTransaction wizardTa = (WizardTransaction) ta;
311             ClusterID cid = container.getCluster().clusterID();
312             ObjectID oid = container.id();
313
314             if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
315                 env.logWriter.newEntry(this, "newContainer(): cid=" + cid + ",oid=" + oid + ".", LogWriter.DEBUG3);
316             }
317
318             wizardTa.idTable.addForKey(cid, oid);
319             wizardTa.idTableChanges_push(new IDTableChange(oid, cid, IDTableChange.STATE_ADDED));
320
321             alright = true;
322
323             return container;
324         } finally {
325             if (!alright) {
326                 container.getCluster().lock().release(ta);
327                 container.unpin();
328             }
329         }
330     }
331
332
333     // public synchronized void deleteContainer (Transaction ta, ObjectContainer _container)
334
// throws Exception {
335
// if (env.logWriter.hasTarget (LogWriter.DEBUG3))
336
// env.logWriter.newEntry (this, "deleteContainer()", LogWriter.DEBUG3);
337
//
338
// WizardObjectContainer container = (WizardObjectContainer)_container;
339
// taData.idTableChanges.push (new IDTableChange (oid, cid, IDTableChange.STATE_ADDED));
340

341
342     public void updateLockLevel(Transaction _ta, ObjectContainer _container) throws IOException {
343         if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
344             env.logWriter.newEntry(this, "updateLockLevel()", LogWriter.DEBUG3);
345         }
346
347         if (_container instanceof WizardObjectContainer) {
348             StorageObjectContainer container = (StorageObjectContainer) _container;
349             container.getCluster().updateLockLevel(_ta);
350
351             WizardTransaction wizardTa = (WizardTransaction) _ta;
352             wizardTa.idTable.addForKey(container.getCluster().clusterID(), container.id());
353         }
354     }
355
356
357     /**
358      * Returns the ObjectContainer for the given ObjectID or null if there is
359      * no such container.<p>
360      If an ObjectContainer is returned, it is pinned once.
361      Thus, the caller has to ensure that the ObjectContainer is unpinned as soon as it is not needed anymore.
362      *
363      * @param ta the Transaction for within the container is requested or null.
364      *
365      * Impl. Note: For performance reasons this is the only method of this Store
366      * that is not synchronized. This will not cause problems because the only
367      * field that is updated inside the method (currentContainer) does not need
368      * to be stable while this method is running.
369      */

370     public ObjectContainer containerForID(Transaction ta, ObjectID id) throws ObjectNotFoundException, IOException, ClassNotFoundException JavaDoc {
371
372         StorageObjectContainer container = null;
373         WizardTransaction wizardTa = (WizardTransaction) ta;
374
375         // search the LRU cluster to speed things up; since this is not
376
// synchronized, checking and accessing currentCluster must be done in
377
// one line to avoid other thread to change the variable in between
378
// container = (currentCluster != null && currentCluster.lock != null) ? currentCluster.containerForID (id) : null;
379
// if (container != null) {
380
// // System.out.print ("+");
381
// return container.isDeleted() ? null : container;
382
// }
383

384         ClusterID cid = null;
385
386         // search members of current ta first
387
if (ta != null) {
388             DxMap taDataIDTable = wizardTa.idTable;
389             cid = (ClusterID) taDataIDTable.elementForKey(id);
390
391             if (cid == null && wizardTa.lrucid != null) {
392                 org.ozoneDB.core.storage.Cluster lru = clusterStore.loadCluster(wizardTa.lrucid, true);
393
394                 if (lru != null) {
395                     try {
396                         container = lru.lock() != null ? lru.containerForID(id) : null;
397                         if (container != null) {
398                             // System.out.print ("+");
399
if (container.isDeleted()) {
400                                 return null;
401                             } else {
402                                 container.pin();
403                                 return container;
404                             }
405                         }
406                     } finally {
407                         if (lru instanceof WizardCluster) {
408                             ((WizardCluster)lru).unpin();
409                         }
410                     }
411                 }
412             }
413         }
414
415         // search global table ONLY if ta doesn't contain the container
416
if (cid == null) {
417             cid = (ClusterID) idTable.elementForKey(id);
418         }
419
420 // env.logWriter.newEntry( this, "containerForID(): id="+id+",cid="+cid+".", LogWriter.DEBUG3 );
421

422         if (cid == null) {
423             return null;
424         } else {
425             // System.out.println ("-");
426
org.ozoneDB.core.storage.Cluster cluster = clusterStore.loadCluster(cid, true);
427
428             if (cluster == null) {
429                 throw new ObjectNotFoundException("No object registered for ID: " + id);
430             }
431
432             try {
433                 if (wizardTa != null) {
434                     wizardTa.lrucid = cid;
435                 }
436
437                 try {
438                     container = cluster.containerForID(id);
439
440                     if (container.isDeleted()) {
441                         return null;
442                     } else {
443                         container.pin();
444                         return container;
445                     }
446                 } catch (NullPointerException JavaDoc e) {
447                     env.logWriter.newEntry(this, "NullPointerException during " + cluster + ".containerForID(" + id + "). We were able to load a cluster for that ID but the cluster did not contain the container. This is an inconsistent view.", e, LogWriter.ERROR);
448                     throw e;
449                 }
450
451             } finally {
452                 if (cluster instanceof WizardCluster) {
453                     ((WizardCluster)cluster).unpin();
454                 }
455             }
456         }
457     }
458
459     public DxSet objectNames(Transaction ta) {
460         env.logWriter.newEntry(this, "Returning objectnames", LogWriter.DEBUG);
461
462         return nameTable.keySet();
463     }
464
465     public synchronized ObjectContainer containerForName(Transaction ta, String JavaDoc name) throws Exception JavaDoc {
466         if (name == null) {
467             return null;
468         }
469
470         WizardTransaction wizardTa = (WizardTransaction) ta;
471
472         if (ta == null || wizardTa.nameTable == null) {
473             ObjectID oid = (ObjectID) nameTable.elementForKey(name);
474             return oid != null ? containerForID(ta, oid) : null;
475         }
476
477         if (ta != null) {
478             ObjectID oid = (ObjectID) wizardTa.nameTable.elementForKey(name);
479             return oid != null ? containerForID(ta, oid) : null;
480         }
481         return null;
482     }
483
484
485     public synchronized void nameContainer(Transaction ta, ObjectContainer container, String JavaDoc name)
486             throws PermissionDeniedException {
487
488         if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
489             env.logWriter.newEntry(this, "nameContainer(), nameTable=" + nameTable + ".", LogWriter.DEBUG3);
490         }
491
492         WizardTransaction wizardTa = (WizardTransaction) ta;
493         if (wizardTa.nameTable == null) {
494             Object JavaDoc o = null;
495             try {
496                 java.lang.reflect.Method JavaDoc method = nameTable.getClass().getDeclaredMethod("clone", null);
497                 if (env.logWriter.hasTarget(LogWriter.DEBUG)) {
498                     env.logWriter.newEntry(this, "nameContainer(), nameTable=" + nameTable + ", nameTable.getClass().getDeclaredMethod(\"clone\",null)=" + method + ".", LogWriter.DEBUG);
499                 }
500                 o = method.invoke(nameTable, null);
501             } catch (Exception JavaDoc e) {
502                 env.logWriter.newEntry(this, "nameContainer(): caught: ", e, LogWriter.INFO);
503             }
504
505             if (o == null) {
506                 o = nameTable.clone();
507             }
508
509
510             wizardTa.nameTable = (DxMap) o;
511         }
512
513         String JavaDoc oldName = container.name();
514         if (oldName != null) {
515             wizardTa.nameTable.removeForKey(oldName);
516             wizardTa.nameTableChanges_push(new NameTableChange(container.id(), oldName,
517                                                              NameTableChange.STATE_REMOVED));
518         }
519
520         container.nameTarget(name);
521
522         if (name != null) {
523             if (oldName == null) {
524                 garbageCollector.notifyNewObjectName(container);
525             }
526             wizardTa.nameTable.addForKey(container.id(), name);
527             wizardTa.nameTableChanges_push(new NameTableChange(container.id(), name, NameTableChange.STATE_ADDED));
528         }
529     }
530
531
532     public synchronized DxBag clusterOfID(ObjectID id) throws Exception JavaDoc {
533         if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
534             env.logWriter.newEntry(this, "clusterOfID()", LogWriter.DEBUG3);
535         }
536
537         ClusterID cid = (ClusterID) idTable.elementForKey(id);
538         if (cid == null) {
539             throw new ObjectNotFoundException("");
540         }
541
542         org.ozoneDB.core.storage.Cluster cluster = clusterStore.loadCluster(cid, true);
543
544         try {
545
546             DxBag result = new DxArrayBag();
547             DxIterator it = cluster.containers().iterator();
548             while (it.next() != null) {
549                 ObjectContainer container = (ObjectContainer) it.object();
550                 result.add(container.id());
551             }
552             return result;
553         } finally {
554             if (cluster instanceof WizardCluster) {
555                 ((WizardCluster)cluster).unpin();
556             }
557         }
558     }
559
560
561     public synchronized void prepareCommitTransaction(Transaction ta) throws IOException, ClassNotFoundException JavaDoc {
562         if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
563             env.logWriter.newEntry(this, "prepareCommitTransaction()", LogWriter.DEBUG3);
564         }
565
566         WizardTransaction wizardTa = (WizardTransaction) ta;
567
568         // initialize transaction data fields
569
wizardTa.commitClusterIDs = new DxHashSet(64);
570
571         DxIterator it = wizardTa.idTable.iterator();
572 // env.logWriter.newEntry( this, "idTable count: " + taData.idTable.count(), LogWriter.DEBUG2 );
573
ClusterID cid;
574
575         while ((cid = (ClusterID) it.next()) != null) {
576             if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
577                 env.logWriter.newEntry(this, "checking cluster: " + cid + " ...", LogWriter.DEBUG3);
578             }
579
580             if (!wizardTa.commitClusterIDs.contains(cid)) {
581 // env.logWriter.newEntry( this, "prepare commit cluster: " + cid, LogWriter.DEBUG2 );
582
wizardTa.commitClusterIDs.add(cid);
583
584                 org.ozoneDB.core.storage.Cluster cluster = clusterStore.loadCluster(cid, true);
585
586                 try {
587                     // we don't need to do all the stuff if there is no WRITE
588
// lock
589
if (cluster.lock().level(ta) >= Lock.LEVEL_WRITE) {
590
591                         // delete containers from cluster and
592
// prepare newID and deletedID tables
593
DxIterator it2 = cluster.containers().iterator();
594                         StorageObjectContainer container;
595                         while ((container = (StorageObjectContainer) it2.next()) != null) {
596
597                             if (container.isDeleted()) {
598                                 if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
599                                     env.logWriter.newEntry(this, "container deleted: " + container.id(), LogWriter.DEBUG3);
600                                 }
601
602                                 clusterStore.invalidateContainer(container);
603                                 wizardTa.idTableChanges_push(new IDTableChange(container.id(), cid, IDTableChange.STATE_REMOVED));
604
605                                 if (container.name() != null) {
606                                     wizardTa.nameTableChanges_push(new NameTableChange(container.id(), container.name(), NameTableChange.STATE_REMOVED));
607                                 }
608                             }
609                             container.clearState();
610                         }
611                     }
612                 } finally {
613                     if (cluster instanceof WizardCluster) {
614                         ((WizardCluster)cluster).unpin();
615                     }
616                 }
617                 clusterStore.prepareCommitCluster(ta, cid);
618             }
619         }
620     }
621
622
623     protected boolean isCleanShutdown() {
624         return !(new File(COMMIT_FLAG_NAME).exists());
625     }
626
627
628     protected void beginCommit(Transaction ta) throws IOException {
629 // env.logWriter.newEntry( this, "beginCommit...", LogWriter.DEBUG2 );
630

631         // do nothing if this was just a read transaction
632
if (ta.maxLockLevel() < Lock.LEVEL_WRITE) {
633             return;
634         }
635
636         int commitCount = 0;
637
638         // read the current commitCount from file
639
File f = new File(env.getDatabaseDir() + COMMIT_FLAG_NAME);
640         if (f.exists()) {
641             DataInputStream in = null;
642             try {
643                 in = new DataInputStream(new FileInputStream(f));
644                 commitCount = in.readInt();
645             } finally {
646                 if (in != null) {
647                     in.close();
648                 }
649             }
650         }
651         commitCount++;
652
653         DataOutputStream out = null;
654         try {
655             out = new DataOutputStream(new FileOutputStream(f));
656             out.writeInt(commitCount);
657         } finally {
658             if (out != null) {
659                 out.close();
660             }
661         }
662     }
663
664
665     protected void endCommit(Transaction ta) throws IOException {
666 // env.logWriter.newEntry( this, "endCommit...", LogWriter.DEBUG2 );
667

668         // do nothing if this was just a read transaction
669
if (ta.maxLockLevel() < Lock.LEVEL_WRITE) {
670             return;
671         }
672
673         int commitCount = 0;
674
675         // read the current commitCount from file
676
File f = new File(env.getDatabaseDir() + COMMIT_FLAG_NAME);
677         if (f.exists()) {
678             DataInputStream in = null;
679             try {
680                 in = new DataInputStream(new FileInputStream(f));
681                 commitCount = in.readInt();
682             } finally {
683                 if (in != null) {
684                     in.close();
685                 }
686             }
687         } else {
688             throw new RuntimeException JavaDoc("No commit flag file present.");
689         }
690         commitCount--;
691
692         if (commitCount > 0) {
693             DataOutputStream out = null;
694             try {
695                 out = new DataOutputStream(new FileOutputStream(f));
696                 out.writeInt(commitCount);
697             } finally {
698                 if (out != null) {
699                     out.close();
700                 }
701             }
702         } else {
703             if (!(f.delete())) {
704                 throw new RuntimeException JavaDoc("Unable to delete commit flag file. ");
705             }
706         }
707     }
708
709
710     public synchronized void commitTransaction(Transaction ta) throws IOException, ClassNotFoundException JavaDoc {
711         if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
712             env.logWriter.newEntry(this, "commitTransaction()", LogWriter.DEBUG3);
713         }
714
715         beginCommit(ta);
716
717         WizardTransaction wizardTa = (WizardTransaction) ta;
718
719         // actually write changed clusters to disk
720
DxSet commitClusterIDs = wizardTa.commitClusterIDs;
721         DxIterator it = commitClusterIDs.iterator();
722
723         ClusterID cid;
724         while ((cid = (ClusterID) it.next()) != null) {
725             if (env.logWriter.hasTarget(LogWriter.DEBUG2)) {
726                 env.logWriter.newEntry(this, "commit cluster: " + cid, LogWriter.DEBUG2);
727             }
728             clusterStore.commitCluster(ta, cid);
729         }
730
731         // update global idTable
732
boolean isIDTableChanged = false;
733         IDTableChange idChange = null;
734
735         while ((idChange = wizardTa.idTableChanges_pop()) != null) {
736             isIDTableChanged = true;
737
738             switch (idChange.state) {
739                 case IDTableChange.STATE_ADDED:
740                     {
741 // env.logWriter.newEntry( this, "commit added oid: " + idChange.oid, LogWriter.DEBUG2 );
742
if (idTable.addForKey(idChange.cid, idChange.oid) == false) {
743                             throw new IllegalStateException JavaDoc("Unable to add OID to global ID table.");
744                         }
745                         break;
746                     }
747                 case IDTableChange.STATE_REMOVED:
748                     {
749                         if (false) {
750                             env.logWriter.newEntry(this, "commit removed oid: " + idChange.oid, LogWriter.DEBUG2);
751                         }
752
753                         if (idTable.removeForKey(idChange.oid) == null) {
754                             throw new IllegalStateException JavaDoc("Unable to remove OID from global ID table.");
755                         }
756                         break;
757                     }
758                 default:
759                     {
760                         throw new RuntimeException JavaDoc("ID change table entry has inproper state.");
761                     }
762             }
763         }
764
765         // write changes to disk
766
if (isIDTableChanged) {
767             commitIDTable();
768         }
769
770         // update global nameTable
771
boolean isNameTableChanged = false;
772         NameTableChange nameChange = wizardTa.nameTableChanges_pop();
773
774         while (nameChange != null) {
775             isNameTableChanged = true;
776
777             switch (nameChange.state) {
778                 case NameTableChange.STATE_ADDED:
779                     {
780                         nameTable.addForKey(nameChange.oid, nameChange.name);
781                         break;
782                     }
783                 case NameTableChange.STATE_REMOVED:
784                     {
785                         nameTable.removeForKey(nameChange.name);
786                         break;
787                     }
788                 default:
789                     {
790                         throw new RuntimeException JavaDoc("Name change table entry has inproper state.");
791                     }
792             }
793             nameChange = wizardTa.nameTableChanges_pop();
794         }
795
796         // write changes to disk
797
if (isNameTableChanged) {
798             commitNameTable();
799         }
800
801         endCommit(ta);
802
803         if (env.logWriter.hasTarget(LogWriter.DEBUG2)) {
804             env.logWriter.newEntry(this, " idTable.count(): " + idTable.count(), LogWriter.DEBUG2);
805             env.logWriter.newEntry(this, " nameTable.count(): " + nameTable.count(), LogWriter.DEBUG2);
806         }
807     }
808
809
810     /**
811      * @param ta ID of the comitting transaction.
812      */

813     public synchronized void abortTransaction(Transaction ta) throws IOException, ClassNotFoundException JavaDoc {
814         if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
815             env.logWriter.newEntry(this, "abortTransaction()", LogWriter.DEBUG3);
816         }
817
818         WizardTransaction wizardTa = (WizardTransaction) ta;
819
820         wizardTa.commitClusterIDs = new DxHashSet(64);
821
822         DxIterator it = wizardTa.idTable.iterator();
823         ClusterID cid;
824         while ((cid = (ClusterID) it.next()) != null) {
825             if (!wizardTa.commitClusterIDs.contains(cid)) {
826                 // We MUST NOT abort read locked clusters (because they may be read locked from other transactions, too)
827

828                 org.ozoneDB.core.storage.Cluster cluster = clusterStore.loadCluster(cid, true);
829
830                 if (cluster.lock().level(ta) > Lock.LEVEL_READ) {
831                     if (env.logWriter.hasTarget(LogWriter.DEBUG2)) {
832                         env.logWriter.newEntry(this, "abort cluster: " + cid, LogWriter.DEBUG2);
833                     }
834
835                     clusterStore.abortCluster(ta, cid);
836                 } else {
837                     // Do a plain unlock, and we are fine.
838
cluster.lock().release(ta);
839                 }
840                 wizardTa.commitClusterIDs.add(cid);
841             }
842         }
843     }
844
845     /**
846      Tells this StoreManager to report every named object to the garbage collector.
847      */

848     public void reportNamedObjectsToGarbageCollector() {
849         synchronized (this) {
850             DxIterator i = nameTable.elementSet().iterator();
851
852             while (i.next() != null) {
853                 garbageCollector.notifyNamedObject((ObjectID) i.object());
854             }
855         }
856     }
857
858     public Transaction createTransaction(Env env, User user) {
859         return new WizardTransaction(env, user);
860     }
861
862 }
863
Popular Tags