KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > MultiVersionTableIndices


1 /**
2  * com.mckoi.database.MultiVersionTableIndices 05 Dec 2000
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database;
26
27 import java.util.ArrayList JavaDoc;
28 import com.mckoi.debug.*;
29
30 /**
31  * This class manages a set of indices for a table over different versions.
32  * The indices include the list of rows (required), and any index data
33  * (optional). This object manages table indexes at multiple revision levels.
34  * When indexes are requested, what is returned is an isolated version of the
35  * current indexes. Index changes automatically create a new version and
36  * each version of the index found is isolated from any concurrent changes.
37  * <p>
38  * This class is not thread safe, but it assumes thread safety by the
39  * callee. It is not safe for multi-threaded access.
40  *
41  * @author Tobias Downer
42  */

43
44 final class MultiVersionTableIndices {
45
46   /**
47    * The name of the table.
48    */

49   private final TableName table_name;
50
51   /**
52    * The number of columns in the referenced table.
53    */

54   private final int column_count;
55
56   /**
57    * The system object.
58    */

59   private final TransactionSystem system;
60
61
62
63   /**
64    * A list of MasterTableJournal objects that represent the changes
65    * that have occurred to this master index after various transactions
66    * have been committed.
67    * <p>
68    * This list can be used to build the indices and a table row enumerator for
69    * snapshots of the table at various transaction check points.
70    */

71   private ArrayList JavaDoc transaction_mod_list;
72
73
74
75
76
77   // ---------- Stat keys ----------
78

79   private String JavaDoc journal_count_stat_key;
80
81   /**
82    * Constructs this object with the given number of column.
83    */

84   MultiVersionTableIndices(TransactionSystem system,
85                            TableName table_name, int column_count) {
86     this.system = system;
87     this.table_name = table_name;
88     this.column_count = column_count;
89
90     transaction_mod_list = new ArrayList JavaDoc();
91
92     journal_count_stat_key = "MultiVersionTableIndices.journal_entries." +
93                                                                     table_name;
94
95   }
96
97   private long TS_merge_count = 0;
98   private long TS_merge_size = 0;
99
100   /**
101    * Returns the DebugLogger object used to log debug messages.
102    */

103   public final DebugLogger Debug() {
104     return system.Debug();
105   }
106
107   /**
108    * Updates the master records from the journal logs up to the given
109    * 'commit_id'. This could be a fairly expensive operation if there are
110    * a lot of modifications because each change could require a lookup
111    * of records in the data source.
112    * <p>
113    * NOTE: It's extremely important that when this is called, there are no
114    * transactions open that are using the merged journal. If there is, then
115    * a transaction may be able to see changes in a table that were made
116    * after the transaction started.
117    * <p>
118    * Returns true if all journal changes were merged.
119    */

120   boolean mergeJournalChanges(long commit_id) {
121
122     // Average size of pending transactions when this method is called...
123
++TS_merge_count;
124     TS_merge_size += transaction_mod_list.size();
125     if ((TS_merge_count % 32) == 0) {
126       system.stats().set(
127           (int) ((TS_merge_size * 1000000L) / TS_merge_count),
128           "MultiVersionTableIndices.average_journal_merge_mul_1000000");
129 // DatabaseSystem.stats().set(
130
// TS_merge_size / TS_merge_count,
131
// "MultiVersionTableIndices.average_journal_merge");
132
// DatabaseSystem.stats().set(
133
// TS_merge_size,
134
// "MultiVersionTableIndices.TS_merge_size");
135
// DatabaseSystem.stats().set(
136
// TS_merge_count,
137
// "MultiVersionTableIndices.TS_merge_count");
138
}
139
140     int merge_count = 0;
141     int size = transaction_mod_list.size();
142     while (transaction_mod_list.size() > 0) {
143
144       MasterTableJournal journal =
145                              (MasterTableJournal) transaction_mod_list.get(0);
146
147       if (commit_id > journal.getCommitID()) {
148
149         ++merge_count;
150         if (Debug().isInterestedIn(Lvl.INFORMATION)) {
151           Debug().write(Lvl.INFORMATION, this,
152                       "Merging '" + table_name + "' journal: " + journal);
153         }
154
155         // Remove the top journal entry from the list.
156
transaction_mod_list.remove(0);
157         system.stats().decrement(journal_count_stat_key);
158
159       }
160       else { // If (commit_id <= journal.getCommitID())
161
return false;
162       }
163     }
164
165     return true;
166
167   }
168
169   /**
170    * Returns a list of all MasterTableJournal objects that have been
171    * successfully committed against this table that have an 'commit_id' that
172    * is greater or equal to the given.
173    * <p>
174    * This is part of the conglomerate commit check phase and will be on a
175    * commit_lock.
176    */

177   MasterTableJournal[] findAllJournalsSince(long commit_id) {
178
179     ArrayList JavaDoc all_since = new ArrayList JavaDoc();
180
181     int size = transaction_mod_list.size();
182     for (int i = 0; i < size; ++i) {
183       MasterTableJournal journal =
184                              (MasterTableJournal) transaction_mod_list.get(i);
185       long journal_commit_id = journal.getCommitID();
186       // All journals that are greater or equal to the given commit id
187
if (journal_commit_id >= commit_id) {
188         all_since.add(journal);
189       }
190     }
191
192     return (MasterTableJournal[])
193                   all_since.toArray(new MasterTableJournal[all_since.size()]);
194   }
195
196   /**
197    * Adds a transaction journal to the list of modifications on the indices
198    * kept here.
199    */

200   void addTransactionJournal(MasterTableJournal change) {
201     transaction_mod_list.add(change);
202     system.stats().increment(journal_count_stat_key);
203   }
204
205   /**
206    * Returns true if this table has any journal modifications that have not
207    * yet been incorporated into master index.
208    */

209   boolean hasTransactionChangesPending() {
210 // System.out.println(transaction_mod_list);
211
return transaction_mod_list.size() > 0;
212   }
213
214   /**
215    * Returns a string describing the transactions pending on this table.
216    */

217   String JavaDoc transactionChangeString() {
218     return transaction_mod_list.toString();
219   }
220
221 }
222
Popular Tags