KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > engine > Database


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.engine;
6
7 import java.io.File JavaDoc;
8 import java.io.FileInputStream JavaDoc;
9 import java.io.IOException JavaDoc;
10 import java.sql.SQLException JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.HashSet JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import java.util.StringTokenizer JavaDoc;
15
16 import org.h2.api.DatabaseEventListener;
17 import org.h2.command.dml.SetTypes;
18 import org.h2.index.Cursor;
19 import org.h2.index.Index;
20 import org.h2.index.IndexType;
21 import org.h2.jdbc.JdbcSQLException;
22 import org.h2.message.Message;
23 import org.h2.message.Trace;
24 import org.h2.message.TraceSystem;
25 import org.h2.result.Row;
26 import org.h2.result.SearchRow;
27 import org.h2.schema.Schema;
28 import org.h2.schema.SchemaObject;
29 import org.h2.schema.Sequence;
30 import org.h2.store.DataHandler;
31 import org.h2.store.DataPage;
32 import org.h2.store.DiskFile;
33 import org.h2.store.FileLock;
34 import org.h2.store.FileStore;
35 import org.h2.store.LogSystem;
36 import org.h2.store.RecordReader;
37 import org.h2.store.Storage;
38 import org.h2.store.WriterThread;
39 import org.h2.table.Column;
40 import org.h2.table.MetaTable;
41 import org.h2.table.Table;
42 import org.h2.table.TableData;
43 import org.h2.table.TableView;
44 import org.h2.tools.DeleteDbFiles;
45 import org.h2.util.BitField;
46 import org.h2.util.ByteUtils;
47 import org.h2.util.CacheLRU;
48 import org.h2.util.FileUtils;
49 import org.h2.util.IOUtils;
50 import org.h2.util.MemoryFile;
51 import org.h2.util.ObjectArray;
52 import org.h2.util.StringUtils;
53 import org.h2.value.CompareMode;
54 import org.h2.value.Value;
55 import org.h2.value.ValueInt;
56
57 /**
58  * @author Thomas
59  * @since 2004-04-15 22:49
60  */

61
62 /*
63  * MetaData format:
64  * int id
65  * int headPos (for indexes)
66  * int objectType
67  * String sql
68  */

69 public class Database implements DataHandler {
70
71     private boolean textStorage;
72     private String JavaDoc databaseName;
73     private String JavaDoc databaseShortName;
74     private String JavaDoc databaseURL;
75     private HashMap JavaDoc roles = new HashMap JavaDoc();
76     private HashMap JavaDoc users = new HashMap JavaDoc();
77     private HashMap JavaDoc settings = new HashMap JavaDoc();
78     private HashMap JavaDoc schemas = new HashMap JavaDoc();
79     private HashMap JavaDoc rights = new HashMap JavaDoc();
80     private HashMap JavaDoc functionAliases = new HashMap JavaDoc();
81     private HashMap JavaDoc userDataTypes = new HashMap JavaDoc();
82     private HashMap JavaDoc comments = new HashMap JavaDoc();
83     private Schema mainSchema;
84     private Schema infoSchema;
85     private int nextSessionId;
86     private HashSet JavaDoc sessions = new HashSet JavaDoc();
87     private User systemUser;
88     private Session systemSession;
89     private TableData meta;
90     private Index metaIdIndex;
91     private BitField objectIds = new BitField();
92     private FileLock lock;
93     private LogSystem log;
94     private WriterThread writer;
95     private ObjectArray storages = new ObjectArray();
96     private boolean starting;
97     private DiskFile fileData, fileIndex;
98     private TraceSystem traceSystem;
99     private boolean persistent;
100     private String JavaDoc cipher;
101     private byte[] filePasswordHash;
102     private DataPage dummy;
103     private int fileLockMethod;
104     private Role publicRole;
105     private long modificationDataId;
106     private long modificationMetaId;
107     private CompareMode compareMode;
108     private String JavaDoc cluster = Constants.CLUSTERING_DISABLED;
109     private boolean readOnly;
110     private boolean noDiskSpace;
111     private int writeDelay = Constants.DEFAULT_WRITE_DELAY;
112     private DatabaseEventListener eventListener;
113     private FileStore emergencyReserve;
114     private int maxMemoryRows = Constants.DEFAULT_MAX_MEMORY_ROWS;
115     private int maxMemoryUndo = Constants.DEFAULT_MAX_MEMORY_UNDO;
116     private int lockMode = Constants.LOCK_MODE_TABLE;
117     private boolean logIndexChanges;
118     private int logLevel = 1;
119     private int cacheSize;
120     private int maxLengthInplaceLob = Constants.DEFAULT_MAX_LENGTH_INPLACE_LOB;
121     private long biggestFileSize;
122     private int allowLiterals = Constants.DEFAULT_ALLOW_LITERALS;
123
124     private static int initialPowerOffCount;
125     private int powerOffCount = initialPowerOffCount;
126     private int closeDelay;
127     private DatabaseCloser delayedCloser;
128     private boolean recovery;
129     private volatile boolean closing;
130     private boolean ignoreCase;
131     private boolean deleteFilesOnDisconnect;
132     private String JavaDoc lobCompressionAlgorithm;
133     private boolean optimizeReuseResults = true;
134     private String JavaDoc cacheType;
135     private boolean indexSummaryValid = true;
136
137     public static void setInitialPowerOffCount(int count) {
138         initialPowerOffCount = count;
139     }
140
141     public void setPowerOffCount(int count) {
142         if(powerOffCount == -1) {
143             return;
144         }
145         powerOffCount = count;
146     }
147
148     public boolean getTextStorage() {
149         return textStorage;
150     }
151
152     public static boolean isTextStorage(String JavaDoc fileName, boolean defaultValue) throws SQLException JavaDoc {
153         byte[] magicText = Constants.MAGIC_FILE_HEADER_TEXT.getBytes();
154         byte[] magicBinary = Constants.MAGIC_FILE_HEADER.getBytes();
155         try {
156             byte[] magic;
157             if(FileUtils.isInMemory(fileName)) {
158                 MemoryFile file = FileUtils.getMemoryFile(fileName);
159                 magic = file.getMagic();
160             } else {
161                 FileInputStream JavaDoc fin = new FileInputStream JavaDoc(fileName);
162                 magic = IOUtils.readBytesAndClose(fin, magicBinary.length);
163             }
164             if(ByteUtils.compareNotNull(magic, magicText) == 0) {
165                 return true;
166             } else if(ByteUtils.compareNotNull(magic, magicBinary) == 0) {
167                 return false;
168             } else if(magic.length < magicText.length) {
169                 // file size is 0 or too small
170
return defaultValue;
171             }
172             throw Message.getSQLException(Message.FILE_VERSION_ERROR_1, fileName);
173         } catch(IOException JavaDoc e) {
174             throw Message.convert(e);
175         }
176     }
177
178     public static byte[] getMagic(boolean textStorage) {
179         if(textStorage) {
180             return Constants.MAGIC_FILE_HEADER_TEXT.getBytes();
181         } else {
182             return Constants.MAGIC_FILE_HEADER.getBytes();
183         }
184     }
185
186     public byte[] getMagic() {
187         return getMagic(textStorage);
188     }
189
190     public boolean areEqual(Value a, Value b) throws SQLException JavaDoc {
191         // TODO optimization possible
192
// boolean is = a.compareEqual(b);
193
// boolean is2 = a.compareTo(b, compareMode) == 0;
194
// if(is != is2) {
195
// is = a.compareEqual(b);
196
// System.out.println("hey!");
197
// }
198
// return a.compareEqual(b);
199
return a.compareTo(b, compareMode) == 0;
200     }
201
202     public int compare(Value a, Value b) throws SQLException JavaDoc {
203         return a.compareTo(b, compareMode);
204     }
205
206     public int compareTypeSave(Value a, Value b) throws SQLException JavaDoc {
207         return a.compareTypeSave(b, compareMode);
208     }
209
210     public long getModificationDataId() {
211         return modificationDataId;
212     }
213
214     public long getNextModificationDataId() {
215         return ++modificationDataId;
216     }
217
218     public long getModificationMetaId() {
219         return modificationMetaId;
220     }
221
222     public long getNextModificationMetaId() {
223         // if the meta data has been modified, the data is modified as well (because MetaTable returns modificationDataId)
224
modificationDataId++;
225         return modificationMetaId++;
226     }
227
228     public int getPowerOffCount() {
229         return powerOffCount;
230     }
231
232     public void checkPowerOff() throws SQLException JavaDoc {
233         if(powerOffCount==0) {
234             return;
235         }
236         if(powerOffCount > 1) {
237             powerOffCount--;
238             return;
239         }
240         if(powerOffCount != -1) {
241             try {
242                 powerOffCount = -1;
243                 if(log != null) {
244                     try {
245                         stopWriter();
246                         log.close();
247                     } catch(SQLException JavaDoc e) {
248                         // ignore
249
}
250                     log = null;
251                 }
252                 if(fileData != null) {
253                     try {
254                         fileData.close();
255                     } catch(SQLException JavaDoc e) {
256                         // ignore
257
}
258                     fileData = null;
259                 }
260                 if(fileIndex != null) {
261                     try {
262                         fileIndex.close();
263                     } catch(SQLException JavaDoc e) {
264                         // ignore
265
}
266                     fileIndex = null;
267                 }
268                 if(lock != null) {
269                     lock.unlock();
270                     lock = null;
271                 }
272                 if(emergencyReserve != null) {
273                     emergencyReserve.closeAndDeleteSilently();
274                     emergencyReserve = null;
275                 }
276             } catch(Exception JavaDoc e) {
277                 TraceSystem.traceThrowable(e);
278             }
279         }
280         Engine.getInstance().close(databaseName);
281         throw Message.getSQLException(Message.SIMULATED_POWER_OFF);
282     }
283
284     public static boolean exists(String JavaDoc name) {
285        return FileUtils.exists(name+Constants.SUFFIX_DATA_FILE);
286     }
287
288     public Trace getTrace(String JavaDoc module) {
289         return traceSystem.getTrace(module);
290     }
291
292     public FileStore openFile(String JavaDoc name, boolean mustExist) throws SQLException JavaDoc {
293         return openFile(name, false, mustExist);
294     }
295
296     public FileStore openFile(String JavaDoc name, boolean notEncrypted, boolean mustExist) throws SQLException JavaDoc {
297         String JavaDoc c = notEncrypted ? null : cipher;
298         byte[] h = notEncrypted ? null : filePasswordHash;
299         if(mustExist && !FileUtils.exists(name)) {
300             throw Message.getSQLException(Message.FILE_CORRUPTED_1, name);
301         }
302         FileStore store = FileStore.open(this, name, getMagic(), c, h);
303         try {
304             store.init();
305         } catch(SQLException JavaDoc e) {
306             store.closeSilently();
307             throw e;
308         }
309         return store;
310     }
311
312     public void checkFilePasswordHash(String JavaDoc c, byte[] hash) throws JdbcSQLException {
313         if(!ByteUtils.compareSecure(hash, filePasswordHash) || !StringUtils.equals(c, cipher)) {
314             throw Message.getSQLException(Message.WRONG_USER_OR_PASSWORD);
315         }
316     }
317
318     private void openFileData() throws SQLException JavaDoc {
319         fileData = new DiskFile(this, databaseName+Constants.SUFFIX_DATA_FILE, true, true, Constants.DEFAULT_CACHE_SIZE);
320     }
321
322     private void openFileIndex() throws SQLException JavaDoc {
323         fileIndex = new DiskFile(this, databaseName+Constants.SUFFIX_INDEX_FILE, false, logIndexChanges, Constants.DEFAULT_CACHE_SIZE_INDEX);
324     }
325
326     public DataPage getDataPage() {
327         return dummy;
328     }
329
330     private String JavaDoc parseDatabaseShortName() {
331         String JavaDoc n = databaseName;
332         if(n.endsWith(":")) {
333             n = null;
334         }
335         if(n != null) {
336             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(n, "/\\:,;");
337             while(tokenizer.hasMoreTokens()) {
338                 n = tokenizer.nextToken();
339             }
340         }
341         if(n == null || n.length() == 0) {
342             n = "UNNAMED";
343         }
344         return StringUtils.toUpperEnglish(n);
345     }
346
347     public Database(String JavaDoc name, ConnectionInfo ci, String JavaDoc cipher) throws SQLException JavaDoc {
348         this.compareMode = new CompareMode(null, null);
349         this.persistent = ci.isPersistent();
350         this.filePasswordHash = ci.getFilePasswordHash();
351         this.databaseName = name;
352         this.databaseShortName = parseDatabaseShortName();
353         this.cipher = cipher;
354         String JavaDoc lockMethodName = ci.removeProperty("FILE_LOCK", null);
355         this.fileLockMethod = FileLock.getFileLockMethod(lockMethodName);
356         this.textStorage = ci.getTextStorage();
357         this.databaseURL = ci.getURL();
358         String JavaDoc listener = ci.removeProperty("DATABASE_EVENT_LISTENER", null);
359         if(listener != null) {
360             if(listener.startsWith("'")) {
361                 listener = listener.substring(1);
362             }
363             if(listener.endsWith("'")) {
364                 listener = listener.substring(0, listener.length()-1);
365             }
366             setEventListener(listener);
367         }
368         String JavaDoc log = ci.getProperty(SetTypes.LOG, null);
369         if(log != null) {
370             this.logIndexChanges = log.equals("2");
371         }
372         String JavaDoc ignoreSummary = ci.getProperty("RECOVER", null);
373         if(ignoreSummary != null) {
374             this.recovery = true;
375         }
376         boolean closeAtVmShutdown = ci.removeProperty("DB_CLOSE_ON_EXIT", true);
377         int traceLevelFile = ci.getIntProperty(SetTypes.TRACE_LEVEL_FILE, TraceSystem.DEFAULT_TRACE_LEVEL_FILE);
378         int traceLevelSystemOut = ci.getIntProperty(SetTypes.TRACE_LEVEL_SYSTEM_OUT, TraceSystem.DEFAULT_TRACE_LEVEL_SYSTEM_OUT);
379         this.cacheType = StringUtils.toUpperEnglish(ci.removeProperty("CACHE_TYPE", CacheLRU.TYPE_NAME));
380         try {
381             synchronized(this) {
382                 open(traceLevelFile, traceLevelSystemOut);
383             }
384             if(closeAtVmShutdown) {
385                 DatabaseCloser closeOnExit = new DatabaseCloser(this, 0, true);
386                 try {
387                     Runtime.getRuntime().addShutdownHook(closeOnExit);
388                 } catch(IllegalStateException JavaDoc e) {
389                     // shutdown in progress - just don't register the handler
390
// (maybe an application wants to write something into a database at shutdown time)
391
}
392             }
393         } catch(SQLException JavaDoc e) {
394             if(traceSystem != null) {
395                 traceSystem.getTrace(Trace.DATABASE).error("opening " + databaseName, e);
396             }
397             synchronized(this) {
398                 closeOpenFilesAndUnlock();
399             }
400             throw Message.convert(e);
401         }
402     }
403
404     private void open(int traceLevelFile, int traceLevelSystemOut) throws SQLException JavaDoc {
405         if(persistent) {
406             String JavaDoc dataFileName = databaseName + Constants.SUFFIX_DATA_FILE;
407             if(FileUtils.exists(dataFileName)) {
408                 readOnly = FileUtils.isReadOnly(dataFileName);
409                 textStorage = isTextStorage(dataFileName, textStorage);
410             }
411         }
412         dummy = DataPage.create(this, 0);
413         if(persistent) {
414             if(readOnly || FileUtils.isInMemory(databaseName)) {
415                 traceSystem = new TraceSystem(null);
416             } else {
417                 traceSystem = new TraceSystem(databaseName+Constants.SUFFIX_TRACE_FILE);
418             }
419             traceSystem.setLevelFile(traceLevelFile);
420             traceSystem.setLevelSystemOut(traceLevelSystemOut);
421             traceSystem.getTrace(Trace.DATABASE).info("opening " + databaseName + " (build "+Constants.BUILD_ID+")");
422             if(!readOnly && fileLockMethod != FileLock.LOCK_NO) {
423                 lock = new FileLock(traceSystem, Constants.LOCK_SLEEP);
424                 lock.lock(databaseName+Constants.SUFFIX_LOCK_FILE, fileLockMethod == FileLock.LOCK_SOCKET);
425             }
426             deleteOldTempFiles();
427             log = new LogSystem(this, databaseName, readOnly);
428             openFileData();
429             openFileIndex();
430             if(!readOnly) {
431                 log.recover();
432             }
433             fileData.init();
434             try {
435                 fileIndex.init();
436             } catch(SQLException JavaDoc e) {
437                 if(recovery) {
438                     traceSystem.getTrace(Trace.DATABASE).error("opening index", e);
439                     fileIndex.close();
440                     fileIndex.delete();
441                     openFileIndex();
442                 } else {
443                     throw e;
444                 }
445             }
446             reserveLobFileObjectIds();
447             writer = WriterThread.create(this, writeDelay);
448         } else {
449             traceSystem = new TraceSystem(null);
450             log = new LogSystem(null, null, false);
451         }
452         systemUser = new User(this, 0, Constants.DBA_NAME, true);
453         mainSchema = new Schema(this, 0, Constants.SCHEMA_MAIN, systemUser, true);
454         infoSchema = new Schema(this, 0, Constants.SCHEMA_INFORMATION, systemUser, true);
455         schemas.put(mainSchema.getName(), mainSchema);
456         schemas.put(infoSchema.getName(), infoSchema);
457         publicRole = new Role(this, 0, Constants.PUBLIC_ROLE_NAME, true);
458         roles.put(Constants.PUBLIC_ROLE_NAME, publicRole);
459         systemUser.setAdmin(true);
460         systemSession = new Session(this, systemUser, 0);
461         // TODO storage: antivir scans .script files, maybe other scanners scan .db files?
462
ObjectArray cols = new ObjectArray();
463         Column columnId = new Column("ID", Value.INT, 0, 0);
464         columnId.setNullable(false);
465         cols.add(columnId);
466         cols.add(new Column("HEAD", Value.INT, 0, 0));
467         cols.add(new Column("TYPE", Value.INT, 0, 0));
468         cols.add(new Column("SQL", Value.STRING, 0, 0));
469         meta = new TableData(mainSchema, "SYS", 0, cols, persistent);
470         metaIdIndex = meta.addIndex(systemSession, "SYS_ID", 0, new Column[]{columnId}, IndexType.createPrimaryKey(false, false), Index.EMPTY_HEAD, null);
471         objectIds.set(0);
472         // there could be views on system tables, so they must be added first
473
addMetaData(MetaTable.TABLES);
474         addMetaData(MetaTable.COLUMNS);
475         addMetaData(MetaTable.INDEXES);
476         addMetaData(MetaTable.TABLE_TYPES);
477         addMetaData(MetaTable.TYPE_INFO);
478         addMetaData(MetaTable.CATALOGS);
479         addMetaData(MetaTable.SETTINGS);
480         addMetaData(MetaTable.HELP);
481         addMetaData(MetaTable.SEQUENCES);
482         addMetaData(MetaTable.USERS);
483         addMetaData(MetaTable.ROLES);
484         addMetaData(MetaTable.RIGHTS);
485         addMetaData(MetaTable.FUNCTION_ALIASES);
486         addMetaData(MetaTable.SCHEMATA);
487         addMetaData(MetaTable.TABLE_PRIVILEGES);
488         addMetaData(MetaTable.COLUMN_PRIVILEGES);
489         addMetaData(MetaTable.COLLATIONS);
490         addMetaData(MetaTable.VIEWS);
491         addMetaData(MetaTable.IN_DOUBT);
492         addMetaData(MetaTable.CROSS_REFERENCES);
493         addMetaData(MetaTable.CONSTRAINTS);
494         addMetaData(MetaTable.FUNCTION_COLUMNS);
495         addMetaData(MetaTable.CONSTANTS);
496         addMetaData(MetaTable.DOMAINS);
497         addMetaData(MetaTable.TRIGGERS);
498         starting = true;
499         Cursor cursor = metaIdIndex.find(systemSession, null, null);
500         // first, create all function aliases and sequences because
501
// they might be used in create table / view / constrants and so on
502
ObjectArray records = new ObjectArray();
503         while (cursor.next()) {
504             MetaRecord rec = new MetaRecord(cursor.get());
505             objectIds.set(rec.getId());
506             records.add(rec);
507         }
508         MetaRecord.sort(records);
509         for(int i=0; i<records.size(); i++) {
510             MetaRecord rec = (MetaRecord) records.get(i);
511             rec.execute(this, systemSession, eventListener);
512         }
513         // try to recompile the views that are invalid
514
recompileInvalidViews();
515         starting = false;
516         addDefaultSetting(SetTypes.DEFAULT_LOCK_TIMEOUT, null, Constants.INITIAL_LOCK_TIMEOUT);
517         addDefaultSetting(SetTypes.DEFAULT_TABLE_TYPE, null, Constants.DEFAULT_TABLE_TYPE);
518         addDefaultSetting(SetTypes.TRACE_LEVEL_FILE, null, traceSystem.getLevelFile());
519         addDefaultSetting(SetTypes.TRACE_LEVEL_SYSTEM_OUT, null, traceSystem.getLevelSystemOut());
520         addDefaultSetting(SetTypes.CACHE_SIZE, null, Constants.DEFAULT_CACHE_SIZE);
521         addDefaultSetting(SetTypes.CLUSTER, Constants.CLUSTERING_DISABLED, 0);
522         addDefaultSetting(SetTypes.WRITE_DELAY, null, Constants.DEFAULT_WRITE_DELAY);
523         removeUnusedStorages();
524         systemSession.commit();
525         if(!readOnly) {
526             emergencyReserve = openFile(createTempFile(), false);
527             emergencyReserve.autoDelete();
528             emergencyReserve.setLength(Constants.EMERGENCY_SPACE_INITIAL);
529         }
530         traceSystem.getTrace(Trace.DATABASE).info("opened " + databaseName);
531     }
532
533     private void recompileInvalidViews() {
534         boolean recompileSuccessful;
535         do {
536             recompileSuccessful = false;
537             ObjectArray list = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
538             for(int i=0; i<list.size(); i++) {
539                 DbObject obj = (DbObject) list.get(i);
540                 if(obj instanceof TableView) {
541                     TableView view = (TableView) obj;
542                     if(view.getInvalid()) {
543                         try {
544                             view.recompile(systemSession);
545                         } catch(Throwable JavaDoc e) {
546                             // ignore
547
}
548                         if(!view.getInvalid()) {
549                             recompileSuccessful = true;
550                         }
551                     }
552                 }
553             }
554         } while(recompileSuccessful);
555     }
556
557     private void removeUnusedStorages() throws SQLException JavaDoc {
558         if(persistent) {
559             for(int i=0; i<storages.size(); i++) {
560                 Storage storage = (Storage) storages.get(i);
561                 if(storage != null && storage.getRecordReader()==null) {
562                     storage.delete(systemSession);
563                 }
564             }
565         }
566     }
567
568     private void addDefaultSetting(int type, String JavaDoc stringValue, int intValue) throws SQLException JavaDoc {
569         if(readOnly) {
570             return;
571         }
572         String JavaDoc name = SetTypes.getTypeName(type);
573         if(settings.get(name) == null) {
574             Setting setting = new Setting(this, allocateObjectId(false, true), name);
575             if(stringValue == null) {
576                 setting.setIntValue(intValue);
577             } else {
578                 setting.setStringValue(stringValue);
579             }
580             addDatabaseObject(systemSession, setting);
581         }
582     }
583
584     public void removeStorage(int id, DiskFile file) {
585         if(Constants.CHECK) {
586             Storage s = (Storage) storages.get(id);
587             if(s==null || s.getDiskFile() != file) {
588                 throw Message.getInternalError();
589             }
590         }
591         storages.set(id, null);
592     }
593
594     public Storage getStorage(int id, DiskFile file) {
595         Storage storage = null;
596         if(storages.size() > id) {
597             storage = (Storage) storages.get(id);
598             if(storage != null) {
599                 if(Constants.CHECK && storage.getDiskFile() != file) {
600                     throw Message.getInternalError();
601                 }
602             }
603         }
604         if(storage == null) {
605             storage = new Storage(this, file, null, id);
606             while(storages.size()<=id) {
607                 storages.add(null);
608             }
609             storages.set(id, storage);
610         }
611         return storage;
612     }
613
614     private void addMetaData(int type) throws SQLException JavaDoc {
615         MetaTable m = new MetaTable(infoSchema, type);
616         infoSchema.add(m);
617     }
618
619     private void addMeta(Session session, DbObject obj) throws SQLException JavaDoc {
620         if(obj.getTemporary()) {
621             return;
622         }
623         Row r = meta.getTemplateRow();
624         MetaRecord rec = new MetaRecord(obj);
625         rec.setRecord(r);
626         objectIds.set(obj.getId());
627         meta.lock(session, true);
628         meta.addRow(session, r);
629     }
630
631     private void removeMeta(Session session, int id) throws SQLException JavaDoc {
632         SearchRow r = meta.getTemplateSimpleRow(false);
633         r.setValue(0, ValueInt.get(id));
634         Cursor cursor = metaIdIndex.find(session, r, r);
635         cursor.next();
636         Row found = cursor.get();
637         if(found!=null) {
638             meta.lock(session, true);
639             meta.removeRow(session, found);
640             objectIds.clear(id);
641             if(Constants.CHECK) {
642                 checkMetaFree(id);
643             }
644         }
645     }
646
647     private HashMap JavaDoc getMap(int type) {
648         switch(type) {
649         case DbObject.USER:
650             return users;
651         case DbObject.SETTING:
652             return settings;
653         case DbObject.ROLE:
654             return roles;
655         case DbObject.RIGHT:
656             return rights;
657         case DbObject.FUNCTION_ALIAS:
658             return functionAliases;
659         case DbObject.SCHEMA:
660             return schemas;
661         case DbObject.USER_DATATYPE:
662             return userDataTypes;
663         case DbObject.COMMENT:
664             return comments;
665         default:
666             throw Message.getInternalError("type="+type);
667         }
668     }
669
670     public void addSchemaObject(Session session, SchemaObject obj) throws SQLException JavaDoc {
671         obj.getSchema().add(obj);
672         int id = obj.getId();
673         if(id > 0 && !starting) {
674             addMeta(session, obj);
675         }
676     }
677
678     public void addDatabaseObject(Session session, DbObject obj) throws SQLException JavaDoc {
679         HashMap JavaDoc map = getMap(obj.getType());
680         if(obj.getType()==DbObject.USER) {
681             User user = (User) obj;
682             if(user.getAdmin() && systemUser.getName().equals(Constants.DBA_NAME)) {
683                 systemUser.rename(user.getName());
684             }
685         }
686         String JavaDoc name = obj.getName();
687         if(Constants.CHECK && map.get(name) != null) {
688             throw Message.getInternalError("object already exists");
689         }
690         int id = obj.getId();
691         if(id > 0 && !starting) {
692             addMeta(session, obj);
693         }
694         map.put(name, obj);
695     }
696
697     public Setting findSetting(String JavaDoc name) {
698         return (Setting) settings.get(name);
699     }
700
701     public Comment findComment(DbObject object) {
702         if(object.getType() == DbObject.COMMENT) {
703             return null;
704         }
705         String JavaDoc key = Comment.getKey(object);
706         return (Comment) comments.get(key);
707     }
708
709     public User findUser(String JavaDoc name) {
710         return (User) users.get(name);
711     }
712
713     public FunctionAlias findFunctionAlias(String JavaDoc name) {
714         return (FunctionAlias) functionAliases.get(name);
715     }
716
717     public UserDataType findUserDataType(String JavaDoc name) {
718         return (UserDataType) userDataTypes.get(name);
719     }
720
721     public User getUser(String JavaDoc name) throws SQLException JavaDoc {
722         User user = (User) users.get(name);
723         if (user == null) {
724             // TODO security: from the stack trace the attacker now knows the user name is ok
725
throw Message.getSQLException(Message.WRONG_USER_OR_PASSWORD, name);
726         }
727         return user;
728     }
729
730     public synchronized Session createSession(User user) {
731         Session session = new Session(this, user, nextSessionId++);
732         sessions.add(session);
733         traceSystem.getTrace(Trace.SESSION).info("connecting #" + session.getId() + " to " + databaseName);
734         if(delayedCloser != null) {
735             delayedCloser.reset();
736             delayedCloser = null;
737         }
738         return session;
739     }
740
741     public synchronized void removeSession(Session session) throws SQLException JavaDoc {
742         if(session != null) {
743             sessions.remove(session);
744             if(session != systemSession) {
745                 traceSystem.getTrace(Trace.SESSION).info("disconnecting #" + session.getId());
746             }
747         }
748         if (sessions.size() == 0 && session != systemSession) {
749             if(closeDelay == 0) {
750                 close(false);
751             } else if(closeDelay < 0) {
752                 return;
753             } else {
754                 delayedCloser = new DatabaseCloser(this, closeDelay * 1000, false);
755                 delayedCloser.setName("H2 Close Delay " + getShortName());
756                 delayedCloser.setDaemon(true);
757                 delayedCloser.start();
758             }
759         }
760         if(session != systemSession && session != null) {
761             traceSystem.getTrace(Trace.SESSION).info("disconnected #" + session.getId());
762         }
763     }
764
765     synchronized void close(boolean fromShutdownHook) {
766         this.closing = true;
767         if(sessions.size() > 0) {
768             if(!fromShutdownHook) {
769                 return;
770             }
771             traceSystem.getTrace(Trace.DATABASE).info("closing " + databaseName + " from shutdown hook");
772             Session[] all = new Session[sessions.size()];
773             sessions.toArray(all);
774             for(int i=0; i<all.length; i++) {
775                 Session s = all[i];
776                 try {
777                     s.close();
778                 } catch(SQLException JavaDoc e) {
779                     traceSystem.getTrace(Trace.SESSION).error("disconnecting #" + s.getId(), e);
780                 }
781             }
782         }
783         traceSystem.getTrace(Trace.DATABASE).info("closing " + databaseName);
784         if(eventListener != null) {
785             eventListener.closingDatabase();
786             eventListener = null;
787         }
788         try {
789             if(persistent && fileData != null) {
790                 ObjectArray tablesAndViews = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
791                 for (int i=0; i<tablesAndViews.size(); i++) {
792                     Table table = (Table) tablesAndViews.get(i);
793                     table.close(systemSession);
794                 }
795                 ObjectArray sequences = getAllSchemaObjects(DbObject.SEQUENCE);
796                 for (int i=0; i<sequences.size(); i++) {
797                     Sequence sequence = (Sequence) sequences.get(i);
798                     sequence.close();
799                 }
800                 meta.close(systemSession);
801                 indexSummaryValid = true;
802             }
803         } catch(SQLException JavaDoc e) {
804             traceSystem.getTrace(Trace.DATABASE).error("close", e);
805         }
806         try {
807             closeOpenFilesAndUnlock();
808         } catch(SQLException JavaDoc e) {
809             traceSystem.getTrace(Trace.DATABASE).error("close", e);
810         }
811         traceSystem.getTrace(Trace.DATABASE).info("closed");
812         traceSystem.close();
813         Engine.getInstance().close(databaseName);
814         if(deleteFilesOnDisconnect && persistent) {
815             deleteFilesOnDisconnect = false;
816             String JavaDoc directory = FileUtils.getParent(databaseName);
817             try {
818                 DeleteDbFiles.execute(directory, databaseShortName, true);
819             } catch(Exception JavaDoc e) {
820                 // ignore (the trace is closed already)
821
}
822         }
823     }
824
825     private void stopWriter() {
826         if(writer != null) {
827             writer.stopThread();
828             writer = null;
829         }
830     }
831
832     private void closeOpenFilesAndUnlock() throws SQLException JavaDoc {
833         if (log != null) {
834             stopWriter();
835             log.close();
836             log = null;
837         }
838         closeFiles();
839         deleteOldTempFiles();
840         if(systemSession != null) {
841             systemSession.close();
842             systemSession = null;
843         }
844         if (lock != null) {
845             lock.unlock();
846             lock = null;
847         }
848     }
849
850     private void closeFiles() throws SQLException JavaDoc {
851         try {
852             if(fileData != null) {
853                 fileData.close();
854                 fileData = null;
855             }
856             if(fileIndex != null) {
857                 fileIndex.close();
858                 fileIndex = null;
859             }
860         } catch(SQLException JavaDoc e) {
861             traceSystem.getTrace(Trace.DATABASE).error("close", e);
862         }
863         storages = new ObjectArray();
864     }
865
866     private void checkMetaFree(int id) throws SQLException JavaDoc {
867         SearchRow r = meta.getTemplateSimpleRow(false);
868         r.setValue(0, ValueInt.get(id));
869         Cursor cursor = metaIdIndex.find(systemSession, r, r);
870         cursor.next();
871         if(cursor.getPos() != Cursor.POS_NO_ROW) {
872             throw Message.getInternalError();
873         }
874     }
875
876     public int allocateObjectId(boolean needFresh, boolean dataFile) {
877         // TODO refactor: use hash map instead of bit field for object ids
878
needFresh=true;
879         int i;
880         if(needFresh) {
881             i = objectIds.getLastSetBit()+1;
882             if((i & 1) != (dataFile ? 1 : 0)) {
883                 i++;
884             }
885             while(i<storages.size() || objectIds.get(i)) {
886                 i++;
887                 if((i & 1) != (dataFile ? 1 : 0)) {
888                     i++;
889                 }
890             }
891         } else {
892             i = objectIds.nextClearBit(0);
893         }
894         if(Constants.CHECK && objectIds.get(i)) {
895             throw Message.getInternalError();
896         }
897         objectIds.set(i);
898         return i;
899     }
900
901     public ObjectArray getAllSettings() {
902         return new ObjectArray(settings.values());
903     }
904
905     public ObjectArray getAllUsers() {
906         return new ObjectArray(users.values());
907     }
908
909     public ObjectArray getAllRoles() {
910         return new ObjectArray(roles.values());
911     }
912
913     public ObjectArray getAllRights() {
914         return new ObjectArray(rights.values());
915     }
916     
917     public ObjectArray getAllComments() {
918         return new ObjectArray(comments.values());
919     }
920
921     public ObjectArray getAllSchemas() {
922         return new ObjectArray(schemas.values());
923     }
924
925     public ObjectArray getAllFunctionAliases() {
926         return new ObjectArray(functionAliases.values());
927     }
928
929     public ObjectArray getAllUserDataTypes() {
930         return new ObjectArray(userDataTypes.values());
931     }
932
933     public ObjectArray getAllSchemaObjects(int type) {
934         ObjectArray list = new ObjectArray();
935         for(Iterator JavaDoc it = schemas.values().iterator(); it.hasNext(); ) {
936             Schema schema = (Schema)it.next();
937             list.addAll(schema.getAll(type));
938         }
939         return list;
940     }
941
942     public String JavaDoc getShortName() {
943         return databaseShortName;
944     }
945
946     public String JavaDoc getName() {
947         return databaseName;
948     }
949
950     public LogSystem getLog() {
951         return log;
952     }
953
954     public synchronized Session[] getSessions() {
955         Session[] list = new Session[sessions.size()];
956         sessions.toArray(list);
957         return list;
958     }
959
960     public void update(Session session, DbObject obj) throws SQLException JavaDoc {
961         int id = obj.getId();
962         removeMeta(session, id);
963         addMeta(session, obj);
964     }
965
966     public void renameSchemaObject(Session session, SchemaObject obj, String JavaDoc newName) throws SQLException JavaDoc {
967         obj.getSchema().rename(obj, newName);
968         updateWithChildren(session, obj);
969     }
970
971     private void updateWithChildren(Session session, DbObject obj) throws SQLException JavaDoc {
972         ObjectArray list = obj.getChildren();
973         Comment comment = findComment(obj);
974         if(comment != null) {
975             throw Message.getInternalError();
976         }
977         update(session, obj);
978         // remember that this scans only one level deep!
979
for(int i = 0; list!=null && i<list.size(); i++) {
980             DbObject o = (DbObject)list.get(i);
981             if(o.getCreateSQL() != null) {
982                 update(session, o);
983             }
984         }
985     }
986
987     public void renameDatabaseObject(Session session, DbObject obj, String JavaDoc newName) throws SQLException JavaDoc {
988         int type = obj.getType();
989         HashMap JavaDoc map = getMap(type);
990         if(Constants.CHECK) {
991             if(!map.containsKey(obj.getName())) {
992                 throw Message.getInternalError("not found: "+obj.getName());
993             }
994             if(obj.getName().equals(newName) || map.containsKey(newName)) {
995                 throw Message.getInternalError("object already exists: "+newName);
996             }
997         }
998         int id = obj.getId();
999         removeMeta(session, id);
1000        map.remove(obj.getName());
1001        obj.rename(newName);
1002        map.put(newName, obj);
1003        updateWithChildren(session, obj);
1004    }
1005
1006    public String JavaDoc createTempFile() throws SQLException JavaDoc {
1007        try {
1008            return FileUtils.createTempFile(databaseName, Constants.SUFFIX_TEMP_FILE, true);
1009        } catch (IOException JavaDoc e) {
1010            throw Message.convert(e);
1011        }
1012    }
1013
1014    private void reserveLobFileObjectIds() throws SQLException JavaDoc {
1015        String JavaDoc prefix = FileUtils.normalize(databaseName);
1016        String JavaDoc path = FileUtils.getParent(databaseName);
1017        String JavaDoc[] list = FileUtils.listFiles(path);
1018        for(int i=0; i<list.length; i++) {
1019            String JavaDoc name = list[i];
1020            if(name.endsWith(Constants.SUFFIX_LOB_FILE) && FileUtils.fileStartsWith(name, prefix)) {
1021                name = name.substring(prefix.length() + 1);
1022                name = name.substring(0, name.length() - Constants.SUFFIX_LOB_FILE.length());
1023                int dot = name.indexOf('.');
1024                if(dot >= 0) {
1025                    String JavaDoc id = name.substring(dot + 1);
1026                    int objectId = Integer.parseInt(id);
1027                    objectIds.set(objectId);
1028                }
1029            }
1030        }
1031    }
1032
1033    private void deleteOldTempFiles() throws SQLException JavaDoc {
1034        if(emergencyReserve != null) {
1035            emergencyReserve.closeAndDeleteSilently();
1036            emergencyReserve = null;
1037        }
1038        String JavaDoc path = FileUtils.getParent(databaseName);
1039        String JavaDoc prefix = FileUtils.normalize(databaseName);
1040        String JavaDoc[] list = FileUtils.listFiles(path);
1041        for(int i=0; i<list.length; i++) {
1042            String JavaDoc name = list[i];
1043            if(name.endsWith(Constants.SUFFIX_TEMP_FILE) && FileUtils.fileStartsWith(name, prefix)) {
1044                // can't always delete the files, they may still be open
1045
FileUtils.tryDelete(name);
1046            }
1047        }
1048    }
1049
1050    public Storage getStorage(RecordReader reader, int id, boolean dataFile) {
1051        DiskFile file;
1052        if(dataFile) {
1053            file = fileData;
1054        } else {
1055            file = fileIndex;
1056        }
1057        Storage storage = getStorage(id, file);
1058        storage.setReader(reader);
1059        return storage;
1060    }
1061
1062    public Role findRole(String JavaDoc roleName) {
1063        return (Role) roles.get(roleName);
1064    }
1065
1066    public Schema findSchema(String JavaDoc schemaName) {
1067        return (Schema) schemas.get(schemaName);
1068    }
1069    
1070    public Schema getSchema(String JavaDoc schemaName) throws SQLException JavaDoc {
1071        Schema schema = findSchema(schemaName);
1072        if(schema == null) {
1073            throw Message.getSQLException(Message.SCHEMA_NOT_FOUND_1, schemaName);
1074        }
1075        return schema;
1076    }
1077
1078    public void removeDatabaseObject(Session session, DbObject obj) throws SQLException JavaDoc {
1079        String JavaDoc objName = obj.getName();
1080        int type = obj.getType();
1081        HashMap JavaDoc map = getMap(type);
1082        if(Constants.CHECK && !map.containsKey(objName)) {
1083            throw Message.getInternalError("not found: "+objName);
1084        }
1085        Comment comment = findComment(obj);
1086        if(comment != null) {
1087            removeDatabaseObject(session, comment);
1088        }
1089        int id = obj.getId();
1090        obj.removeChildrenAndResources(session);
1091        map.remove(objName);
1092        removeMeta(session, id);
1093    }
1094
1095    private String JavaDoc getFirstInvalidTable() {
1096        String JavaDoc conflict = null;
1097        try {
1098            ObjectArray list = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
1099            for(int i=0; i<list.size(); i++) {
1100                Table t = (Table)list.get(i);
1101                conflict = t.getSQL();
1102                systemSession.prepare(t.getCreateSQL());
1103            }
1104        } catch(SQLException JavaDoc e) {
1105            return conflict;
1106        }
1107        return null;
1108    }
1109
1110    public void removeSchemaObject(Session session, SchemaObject obj) throws SQLException JavaDoc {
1111        if(obj.getType() == DbObject.TABLE_OR_VIEW) {
1112            Table table = (Table) obj;
1113            if(table.getTemporary() && !table.getGlobalTemporary()) {
1114                session.removeLocalTempTable(table);
1115                return;
1116            }
1117        }
1118        Comment comment = findComment(obj);
1119        if(comment != null) {
1120            removeDatabaseObject(session, comment);
1121        }
1122        obj.getSchema().remove(session, obj);
1123        String JavaDoc invalid = getFirstInvalidTable();
1124        if(invalid != null) {
1125            obj.getSchema().add(obj);
1126            throw Message.getSQLException(Message.CANT_DROP_2, new String JavaDoc[]{obj.getSQL(), invalid}, null);
1127        }
1128        int id = obj.getId();
1129        obj.removeChildrenAndResources(session);
1130        removeMeta(session, id);
1131    }
1132
1133    public boolean isPersistent() {
1134        return persistent;
1135    }
1136
1137    public TraceSystem getTraceSystem() {
1138        return traceSystem;
1139    }
1140
1141    public DiskFile getDataFile() {
1142        return fileData;
1143    }
1144
1145    public DiskFile getIndexFile() {
1146        return fileIndex;
1147    }
1148
1149    public void setCacheSize(int value) throws SQLException JavaDoc {
1150        if(fileData != null) {
1151            synchronized(fileData) {
1152                fileData.getCache().setMaxSize(value);
1153            }
1154            int valueIndex = value <= (1<<8) ? value : (value>>>Constants.CACHE_SIZE_INDEX_SHIFT);
1155            synchronized(fileIndex) {
1156                fileIndex.getCache().setMaxSize(valueIndex);
1157            }
1158            cacheSize = value;
1159        }
1160    }
1161
1162    public void setMasterUser(User user) throws SQLException JavaDoc {
1163        synchronized(this) {
1164            addDatabaseObject(systemSession, user);
1165            systemSession.commit();
1166        }
1167    }
1168
1169    public Role getPublicRole() {
1170        return publicRole;
1171    }
1172
1173    public String JavaDoc getTempTableName(int sessionId) {
1174        String JavaDoc tempName;
1175        for(int i = 0;; i++) {
1176            tempName = Constants.TEMP_TABLE_PREFIX + sessionId + "_" + i;
1177            if(mainSchema.findTableOrView(null, tempName) == null) {
1178                break;
1179            }
1180        }
1181        return tempName;
1182    }
1183
1184    public void setCompareMode(CompareMode compareMode) {
1185        this.compareMode = compareMode;
1186    }
1187
1188    public CompareMode getCompareMode() {
1189        return compareMode;
1190    }
1191
1192    public String JavaDoc getCluster() {
1193        return cluster;
1194    }
1195
1196    public void setCluster(String JavaDoc cluster) {
1197        this.cluster = cluster;
1198    }
1199
1200    public void checkWritingAllowed() throws SQLException JavaDoc {
1201        if(readOnly) {
1202            throw Message.getSQLException(Message.DATABASE_IS_READ_ONLY);
1203        }
1204        if(noDiskSpace) {
1205            throw Message.getSQLException(Message.NO_DISK_SPACE_AVAILABLE);
1206        }
1207    }
1208
1209    public boolean getReadOnly() {
1210        return readOnly;
1211    }
1212
1213    public void setWriteDelay(int value) {
1214        writeDelay = value;
1215        if(writer != null) {
1216            writer.setWriteDelay(value);
1217        }
1218    }
1219    
1220    public Class JavaDoc loadClass(String JavaDoc className) throws ClassNotFoundException JavaDoc {
1221        return Class.forName(className);
1222    }
1223
1224    public void setEventListener(String JavaDoc className) throws SQLException JavaDoc {
1225        if(className == null || className.length() == 0) {
1226            eventListener = null;
1227        } else {
1228            try {
1229                eventListener = (DatabaseEventListener)loadClass(className).newInstance();
1230                eventListener.init(databaseURL);
1231            } catch (Throwable JavaDoc e) {
1232                throw Message.getSQLException(Message.ERROR_SETTING_DATABASE_EVENT_LISTENER, new String JavaDoc[]{className}, e);
1233            }
1234        }
1235    }
1236
1237    public void freeUpDiskSpace() throws SQLException JavaDoc {
1238        long sizeAvailable = 0;
1239        if(emergencyReserve != null) {
1240            sizeAvailable = emergencyReserve.length();
1241            long newLength = sizeAvailable / 2;
1242            if(newLength < Constants.EMERGENCY_SPACE_MIN) {
1243                newLength = 0;
1244                noDiskSpace = true;
1245            }
1246            emergencyReserve.setLength(newLength);
1247        }
1248        if(eventListener != null) {
1249            eventListener.diskSpaceIsLow(sizeAvailable);
1250        }
1251    }
1252
1253    public void setProgress(int state, String JavaDoc name, int x, int max) {
1254        if(eventListener != null) {
1255            try {
1256                eventListener.setProgress(state, name, x, max);
1257            } catch(Exception JavaDoc e2) {
1258                // ignore this second (user made) exception
1259
}
1260        }
1261    }
1262
1263    public void exceptionThrown(SQLException JavaDoc e) {
1264        if(eventListener != null) {
1265            try {
1266                eventListener.exceptionThrown(e);
1267            } catch(Exception JavaDoc e2) {
1268                // ignore this second (user made) exception
1269
}
1270        }
1271    }
1272
1273    public void sync() throws SQLException JavaDoc {
1274        if(log != null) {
1275            log.sync();
1276        }
1277        if(fileData != null) {
1278            fileData.sync();
1279        }
1280        if(fileIndex != null) {
1281            fileIndex.sync();
1282        }
1283    }
1284
1285    public int getMaxMemoryRows() {
1286        return maxMemoryRows;
1287    }
1288
1289    public void setMaxMemoryRows(int value) {
1290        this.maxMemoryRows = value;
1291    }
1292
1293    public void setMaxMemoryUndo(int value) {
1294        this.maxMemoryUndo = value;
1295    }
1296
1297    public int getMaxMemoryUndo() {
1298        return maxMemoryUndo;
1299    }
1300
1301    public int getChecksum(byte[] data, int start, int end) {
1302        int x = 0;
1303        while(start < end) {
1304            x += data[start++];
1305        }
1306        return x;
1307    }
1308
1309    public void setLockMode(int lockMode) {
1310        this.lockMode = lockMode;
1311    }
1312
1313    public int getLockMode() {
1314        return lockMode;
1315    }
1316
1317    public synchronized void setCloseDelay(int value) {
1318        this.closeDelay = value;
1319    }
1320
1321    public boolean getLogIndexChanges() {
1322        return logIndexChanges;
1323    }
1324
1325    public void setLog(int level) throws SQLException JavaDoc {
1326        if(logLevel == level) {
1327            return;
1328        }
1329        boolean logData;
1330        boolean logIndex;
1331        switch(level) {
1332        case 0:
1333            logData = false;
1334            logIndex = false;
1335            break;
1336        case 1:
1337            logData = true;
1338            logIndex = false;
1339            break;
1340        case 2:
1341            logData = true;
1342            logIndex = true;
1343            break;
1344        default:
1345            throw Message.getInternalError("level="+level);
1346        }
1347        if(fileIndex != null) {
1348            fileIndex.setLogChanges(logIndex);
1349        }
1350        if(log != null) {
1351            log.setDisabled(!logData);
1352            log.checkpoint();
1353        }
1354        logLevel = level;
1355    }
1356
1357    public ObjectArray getAllStorages() {
1358        return storages;
1359    }
1360
1361    public boolean getRecovery() {
1362        return recovery;
1363    }
1364
1365    public Session getSystemSession() {
1366        return systemSession;
1367    }
1368
1369    public String JavaDoc getDatabasePath() {
1370        if(persistent) {
1371            File JavaDoc parent = new File JavaDoc(databaseName).getAbsoluteFile();
1372            return parent.getAbsolutePath();
1373        } else {
1374            return null;
1375        }
1376    }
1377
1378    public void handleInvalidChecksum() throws SQLException JavaDoc {
1379        SQLException JavaDoc e = Message.getSQLException(Message.FILE_CORRUPTED_1, "wrong checksum");
1380        if(!recovery) {
1381            throw e;
1382        } else {
1383            traceSystem.getTrace(Trace.DATABASE).error("recover", e);
1384        }
1385    }
1386
1387    public boolean isClosing() {
1388        return closing;
1389    }
1390
1391    public int getWriteDelay() {
1392        return writeDelay;
1393    }
1394
1395    public int getCacheSize() {
1396        return cacheSize;
1397    }
1398
1399    public void setMaxLengthInplaceLob(int value) {
1400        this.maxLengthInplaceLob = value;
1401    }
1402
1403    public int getMaxLengthInplaceLob() {
1404        return maxLengthInplaceLob;
1405    }
1406
1407    public void setIgnoreCase(boolean b) {
1408        ignoreCase = b;
1409    }
1410
1411    public boolean getIgnoreCase() {
1412        if(starting) {
1413            // tables created at startup must not be converted to ignorecase
1414
return false;
1415        }
1416        return ignoreCase;
1417    }
1418
1419    public synchronized void setDeleteFilesOnDisconnect(boolean b) {
1420        this.deleteFilesOnDisconnect = b;
1421    }
1422
1423    public String JavaDoc getLobCompressionAlgorithm(int type) {
1424        return lobCompressionAlgorithm;
1425    }
1426
1427    public void setLobCompressionAlgorithm(String JavaDoc stringValue) {
1428        this.lobCompressionAlgorithm = stringValue;
1429    }
1430
1431    public void notifyFileSize(long length) {
1432        if(length > biggestFileSize) {
1433            biggestFileSize = length;
1434            setMaxLogSize(0);
1435        }
1436    }
1437
1438    public void setMaxLogSize(long value) {
1439        long minLogSize = biggestFileSize / Constants.LOG_SIZE_DIVIDER;
1440        minLogSize = Math.max(value, minLogSize);
1441        long currentLogSize = getLog().getMaxLogSize();
1442        if(minLogSize > currentLogSize || (value > 0 && minLogSize > value)) {
1443            // works for currentLogSize <= 0 as well
1444
value = minLogSize;
1445        }
1446        if(value > 0) {
1447            getLog().setMaxLogSize(value);
1448        }
1449    }
1450
1451    public void setAllowLiterals(int value) {
1452        this.allowLiterals = value;
1453    }
1454
1455    public int getAllowLiterals() {
1456        if(starting) {
1457            return Constants.ALLOW_LITERALS_ALL;
1458        }
1459        return allowLiterals;
1460    }
1461
1462    public boolean getOptimizeReuseResults() {
1463        return optimizeReuseResults;
1464    }
1465    
1466    public void setOptimizeReuseResults(boolean b) {
1467        optimizeReuseResults = b;
1468    }
1469    
1470    public String JavaDoc getCacheType() {
1471        return cacheType;
1472    }
1473
1474    public void invalidateIndexSummary() throws SQLException JavaDoc {
1475        if(indexSummaryValid ) {
1476            indexSummaryValid = false;
1477            log.invalidateIndexSummary();
1478        }
1479    }
1480    
1481    public boolean getIndexSummaryValid() {
1482        return indexSummaryValid;
1483    }
1484
1485}
1486
Popular Tags