Source Code Cross Referenced for Database.java in  » Database-DBMS » h2database » org » h2 » engine » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » h2database » org.h2.engine 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
0003:         * (http://h2database.com/html/license.html).
0004:         * Initial Developer: H2 Group
0005:         */
0006:        package org.h2.engine;
0007:
0008:        import java.io.IOException;
0009:        import java.io.InputStream;
0010:        import java.sql.SQLException;
0011:        import java.util.Collections;
0012:        import java.util.HashMap;
0013:        import java.util.HashSet;
0014:        import java.util.Iterator;
0015:        import java.util.Set;
0016:        import java.util.StringTokenizer;
0017:
0018:        import org.h2.api.DatabaseEventListener;
0019:        import org.h2.command.dml.SetTypes;
0020:        import org.h2.constant.ErrorCode;
0021:        import org.h2.constant.SysProperties;
0022:        import org.h2.index.Cursor;
0023:        import org.h2.index.Index;
0024:        import org.h2.index.IndexType;
0025:        import org.h2.log.LogSystem;
0026:        import org.h2.log.UndoLogRecord;
0027:        import org.h2.message.Message;
0028:        import org.h2.message.Trace;
0029:        import org.h2.message.TraceSystem;
0030:        import org.h2.result.Row;
0031:        import org.h2.result.SearchRow;
0032:        import org.h2.schema.Schema;
0033:        import org.h2.schema.SchemaObject;
0034:        import org.h2.schema.Sequence;
0035:        import org.h2.store.DataHandler;
0036:        import org.h2.store.DataPage;
0037:        import org.h2.store.DiskFile;
0038:        import org.h2.store.FileLock;
0039:        import org.h2.store.FileStore;
0040:        import org.h2.store.RecordReader;
0041:        import org.h2.store.Storage;
0042:        import org.h2.store.WriterThread;
0043:        import org.h2.store.fs.FileSystem;
0044:        import org.h2.table.Column;
0045:        import org.h2.table.IndexColumn;
0046:        import org.h2.table.MetaTable;
0047:        import org.h2.table.Table;
0048:        import org.h2.table.TableData;
0049:        import org.h2.table.TableView;
0050:        import org.h2.tools.DeleteDbFiles;
0051:        import org.h2.util.BitField;
0052:        import org.h2.util.ByteUtils;
0053:        import org.h2.util.CacheLRU;
0054:        import org.h2.util.ClassUtils;
0055:        import org.h2.util.FileUtils;
0056:        import org.h2.util.IOUtils;
0057:        import org.h2.util.IntHashMap;
0058:        import org.h2.util.ObjectArray;
0059:        import org.h2.util.SmallLRUCache;
0060:        import org.h2.util.StringUtils;
0061:        import org.h2.value.CompareMode;
0062:        import org.h2.value.Value;
0063:        import org.h2.value.ValueInt;
0064:        import org.h2.value.ValueLob;
0065:
0066:        /**
0067:         * There is one database object per open database.
0068:         *
0069:         * The format of the meta data table is:
0070:         *  id int, headPos int (for indexes), objectType int, sql varchar
0071:         *
0072:         * @since 2004-04-15 22:49
0073:         */
0074:        public class Database implements  DataHandler {
0075:
0076:            private final boolean persistent;
0077:            private final String databaseName;
0078:            private final String databaseShortName;
0079:            private final String databaseURL;
0080:            private final String cipher;
0081:            private final byte[] filePasswordHash;
0082:
0083:            private final HashMap roles = new HashMap();
0084:            private final HashMap users = new HashMap();
0085:            private final HashMap settings = new HashMap();
0086:            private final HashMap schemas = new HashMap();
0087:            private final HashMap rights = new HashMap();
0088:            private final HashMap functionAliases = new HashMap();
0089:            private final HashMap userDataTypes = new HashMap();
0090:            private final HashMap aggregates = new HashMap();
0091:            private final HashMap comments = new HashMap();
0092:            private final Set sessions = Collections
0093:                    .synchronizedSet(new HashSet());
0094:            private Session exclusiveSession;
0095:            private final BitField objectIds = new BitField();
0096:            private final Object lobSyncObject = new Object();
0097:
0098:            private boolean textStorage;
0099:            private Schema mainSchema;
0100:            private Schema infoSchema;
0101:            private int nextSessionId;
0102:            private User systemUser;
0103:            private Session systemSession;
0104:            private TableData meta;
0105:            private Index metaIdIndex;
0106:            private FileLock lock;
0107:            private LogSystem log;
0108:            private WriterThread writer;
0109:            private IntHashMap storageMap = new IntHashMap();
0110:            private boolean starting;
0111:            private DiskFile fileData, fileIndex;
0112:            private TraceSystem traceSystem;
0113:            private DataPage dummy;
0114:            private int fileLockMethod;
0115:            private Role publicRole;
0116:            private long modificationDataId;
0117:            private long modificationMetaId;
0118:            private CompareMode compareMode;
0119:            private String cluster = Constants.CLUSTERING_DISABLED;
0120:            private boolean readOnly;
0121:            private boolean noDiskSpace;
0122:            private int writeDelay = Constants.DEFAULT_WRITE_DELAY;
0123:            private DatabaseEventListener eventListener;
0124:            private FileStore emergencyReserve;
0125:            private int maxMemoryRows = Constants.DEFAULT_MAX_MEMORY_ROWS;
0126:            private int maxMemoryUndo = SysProperties.DEFAULT_MAX_MEMORY_UNDO;
0127:            private int lockMode = SysProperties.DEFAULT_LOCK_MODE;
0128:            private boolean logIndexChanges;
0129:            private int logLevel = 1;
0130:            private int cacheSize;
0131:            private int maxLengthInplaceLob = Constants.DEFAULT_MAX_LENGTH_INPLACE_LOB;
0132:            private long biggestFileSize;
0133:            private int allowLiterals = Constants.DEFAULT_ALLOW_LITERALS;
0134:
0135:            private static int initialPowerOffCount;
0136:            private int powerOffCount = initialPowerOffCount;
0137:            private int closeDelay;
0138:            private DatabaseCloser delayedCloser;
0139:            private boolean recovery;
0140:            private volatile boolean closing;
0141:            private boolean ignoreCase;
0142:            private boolean deleteFilesOnDisconnect;
0143:            private String lobCompressionAlgorithm;
0144:            private boolean optimizeReuseResults = true;
0145:            private String cacheType;
0146:            private boolean indexSummaryValid = true;
0147:            private String accessModeLog, accessModeData;
0148:            private boolean referentialIntegrity = true;
0149:            private boolean multiVersion;
0150:            private DatabaseCloser closeOnExit;
0151:            private Mode mode = Mode.getInstance(Mode.REGULAR);
0152:            // TODO change in version 1.1
0153:            private boolean multiThreaded;
0154:            private int maxOperationMemory = SysProperties.DEFAULT_MAX_OPERATION_MEMORY;
0155:            private boolean lobFilesInDirectories = SysProperties.LOB_FILES_IN_DIRECTORIES;
0156:            private SmallLRUCache lobFileListCache = new SmallLRUCache(128);
0157:
0158:            public Database(String name, ConnectionInfo ci, String cipher)
0159:                    throws SQLException {
0160:                this .compareMode = new CompareMode(null, null, 0);
0161:                this .persistent = ci.isPersistent();
0162:                this .filePasswordHash = ci.getFilePasswordHash();
0163:                this .databaseName = name;
0164:                this .databaseShortName = parseDatabaseShortName();
0165:                this .cipher = cipher;
0166:                String lockMethodName = ci.removeProperty("FILE_LOCK", null);
0167:                this .accessModeLog = ci.removeProperty("ACCESS_MODE_LOG", "rw")
0168:                        .toLowerCase();
0169:                this .accessModeData = ci.removeProperty("ACCESS_MODE_DATA",
0170:                        "rw").toLowerCase();
0171:                if ("r".equals(accessModeData)) {
0172:                    readOnly = true;
0173:                    accessModeLog = "r";
0174:                }
0175:                this .fileLockMethod = FileLock
0176:                        .getFileLockMethod(lockMethodName);
0177:                this .textStorage = ci.getTextStorage();
0178:                this .databaseURL = ci.getURL();
0179:                this .eventListener = ci.removeDatabaseEventListenerObject();
0180:                if (eventListener == null) {
0181:                    String listener = ci.removeProperty(
0182:                            "DATABASE_EVENT_LISTENER", null);
0183:                    if (listener != null) {
0184:                        if (listener.startsWith("'")) {
0185:                            listener = listener.substring(1);
0186:                        }
0187:                        if (listener.endsWith("'")) {
0188:                            listener = listener.substring(0,
0189:                                    listener.length() - 1);
0190:                        }
0191:                        setEventListener(listener);
0192:                    }
0193:                }
0194:                String log = ci.getProperty(SetTypes.LOG, null);
0195:                if (log != null) {
0196:                    this .logIndexChanges = "2".equals(log);
0197:                }
0198:                String ignoreSummary = ci.getProperty("RECOVER", null);
0199:                if (ignoreSummary != null) {
0200:                    this .recovery = true;
0201:                }
0202:                this .multiVersion = ci.removeProperty("MVCC", false);
0203:                boolean closeAtVmShutdown = ci.removeProperty(
0204:                        "DB_CLOSE_ON_EXIT", true);
0205:                int traceLevelFile = ci.getIntProperty(
0206:                        SetTypes.TRACE_LEVEL_FILE,
0207:                        TraceSystem.DEFAULT_TRACE_LEVEL_FILE);
0208:                int traceLevelSystemOut = ci.getIntProperty(
0209:                        SetTypes.TRACE_LEVEL_SYSTEM_OUT,
0210:                        TraceSystem.DEFAULT_TRACE_LEVEL_SYSTEM_OUT);
0211:                this .cacheType = StringUtils.toUpperEnglish(ci.removeProperty(
0212:                        "CACHE_TYPE", CacheLRU.TYPE_NAME));
0213:                try {
0214:                    open(traceLevelFile, traceLevelSystemOut);
0215:                    if (closeAtVmShutdown) {
0216:                        closeOnExit = new DatabaseCloser(this , 0, true);
0217:                        try {
0218:                            Runtime.getRuntime().addShutdownHook(closeOnExit);
0219:                        } catch (IllegalStateException e) {
0220:                            // shutdown in progress - just don't register the handler
0221:                            // (maybe an application wants to write something into a
0222:                            // database at shutdown time)
0223:                        } catch (SecurityException e) {
0224:                            // applets may not do that - ignore
0225:                        }
0226:                    }
0227:                } catch (Throwable e) {
0228:                    if (traceSystem != null) {
0229:                        traceSystem.getTrace(Trace.DATABASE).error(
0230:                                "opening " + databaseName, e);
0231:                        traceSystem.close();
0232:                    }
0233:                    closeOpenFilesAndUnlock();
0234:                    throw Message.convert(e);
0235:                }
0236:            }
0237:
0238:            public static void setInitialPowerOffCount(int count) {
0239:                initialPowerOffCount = count;
0240:            }
0241:
0242:            public void setPowerOffCount(int count) {
0243:                if (powerOffCount == -1) {
0244:                    return;
0245:                }
0246:                powerOffCount = count;
0247:            }
0248:
0249:            public boolean getTextStorage() {
0250:                return textStorage;
0251:            }
0252:
0253:            public static boolean isTextStorage(String fileName,
0254:                    boolean defaultValue) throws SQLException {
0255:                byte[] magicText = Constants.MAGIC_FILE_HEADER_TEXT.getBytes();
0256:                byte[] magicBinary = Constants.MAGIC_FILE_HEADER.getBytes();
0257:                try {
0258:                    InputStream fin = FileUtils.openFileInputStream(fileName);
0259:                    byte[] magic = IOUtils.readBytesAndClose(fin,
0260:                            magicBinary.length);
0261:                    if (ByteUtils.compareNotNull(magic, magicText) == 0) {
0262:                        return true;
0263:                    } else if (ByteUtils.compareNotNull(magic, magicBinary) == 0) {
0264:                        return false;
0265:                    } else if (magic.length < magicText.length) {
0266:                        // file size is 0 or too small
0267:                        return defaultValue;
0268:                    }
0269:                    throw Message.getSQLException(
0270:                            ErrorCode.FILE_VERSION_ERROR_1, fileName);
0271:                } catch (IOException e) {
0272:                    throw Message.convertIOException(e, fileName);
0273:                }
0274:            }
0275:
0276:            public static byte[] getMagic(boolean textStorage) {
0277:                if (textStorage) {
0278:                    return Constants.MAGIC_FILE_HEADER_TEXT.getBytes();
0279:                } else {
0280:                    return Constants.MAGIC_FILE_HEADER.getBytes();
0281:                }
0282:            }
0283:
0284:            public byte[] getMagic() {
0285:                return getMagic(textStorage);
0286:            }
0287:
0288:            public boolean areEqual(Value a, Value b) throws SQLException {
0289:                // TODO optimization possible
0290:                // boolean is = a.compareEqual(b);
0291:                // boolean is2 = a.compareTo(b, compareMode) == 0;
0292:                // if(is != is2) {
0293:                // is = a.compareEqual(b);
0294:                // System.out.println("hey!");
0295:                // }
0296:                // return a.compareEqual(b);
0297:                return a.compareTo(b, compareMode) == 0;
0298:            }
0299:
0300:            public int compare(Value a, Value b) throws SQLException {
0301:                return a.compareTo(b, compareMode);
0302:            }
0303:
0304:            public int compareTypeSave(Value a, Value b) throws SQLException {
0305:                return a.compareTypeSave(b, compareMode);
0306:            }
0307:
0308:            public long getModificationDataId() {
0309:                return modificationDataId;
0310:            }
0311:
0312:            public long getNextModificationDataId() {
0313:                return ++modificationDataId;
0314:            }
0315:
0316:            public long getModificationMetaId() {
0317:                return modificationMetaId;
0318:            }
0319:
0320:            public long getNextModificationMetaId() {
0321:                // if the meta data has been modified, the data is modified as well
0322:                // (because MetaTable returns modificationDataId)
0323:                modificationDataId++;
0324:                return modificationMetaId++;
0325:            }
0326:
0327:            public int getPowerOffCount() {
0328:                return powerOffCount;
0329:            }
0330:
0331:            public void checkPowerOff() throws SQLException {
0332:                if (powerOffCount == 0) {
0333:                    return;
0334:                }
0335:                if (powerOffCount > 1) {
0336:                    powerOffCount--;
0337:                    return;
0338:                }
0339:                if (powerOffCount != -1) {
0340:                    try {
0341:                        powerOffCount = -1;
0342:                        if (log != null) {
0343:                            try {
0344:                                stopWriter();
0345:                                log.close();
0346:                            } catch (SQLException e) {
0347:                                // ignore
0348:                            }
0349:                            log = null;
0350:                        }
0351:                        if (fileData != null) {
0352:                            try {
0353:                                fileData.close();
0354:                            } catch (SQLException e) {
0355:                                // ignore
0356:                            }
0357:                            fileData = null;
0358:                        }
0359:                        if (fileIndex != null) {
0360:                            try {
0361:                                fileIndex.close();
0362:                            } catch (SQLException e) {
0363:                                // ignore
0364:                            }
0365:                            fileIndex = null;
0366:                        }
0367:                        if (lock != null) {
0368:                            lock.unlock();
0369:                            lock = null;
0370:                        }
0371:                        if (emergencyReserve != null) {
0372:                            emergencyReserve.closeAndDeleteSilently();
0373:                            emergencyReserve = null;
0374:                        }
0375:                    } catch (Exception e) {
0376:                        TraceSystem.traceThrowable(e);
0377:                    }
0378:                }
0379:                Engine.getInstance().close(databaseName);
0380:                throw Message.getSQLException(ErrorCode.SIMULATED_POWER_OFF);
0381:            }
0382:
0383:            public static boolean exists(String name) {
0384:                return FileUtils.exists(name + Constants.SUFFIX_DATA_FILE);
0385:            }
0386:
0387:            public Trace getTrace(String module) {
0388:                return traceSystem.getTrace(module);
0389:            }
0390:
0391:            public FileStore openFile(String name, String mode,
0392:                    boolean mustExist) throws SQLException {
0393:                if (mustExist && !FileUtils.exists(name)) {
0394:                    throw Message.getSQLException(ErrorCode.FILE_NOT_FOUND_1,
0395:                            name);
0396:                }
0397:                FileStore store = FileStore.open(this , name, mode, getMagic(),
0398:                        cipher, filePasswordHash);
0399:                try {
0400:                    store.init();
0401:                } catch (SQLException e) {
0402:                    store.closeSilently();
0403:                    throw e;
0404:                }
0405:                return store;
0406:            }
0407:
0408:            public void checkFilePasswordHash(String c, byte[] hash)
0409:                    throws SQLException {
0410:                if (!ByteUtils.compareSecure(hash, filePasswordHash)
0411:                        || !StringUtils.equals(c, cipher)) {
0412:                    try {
0413:                        Thread.sleep(Constants.DELAY_WRONG_PASSWORD);
0414:                    } catch (InterruptedException e) {
0415:                        // ignore
0416:                    }
0417:                    throw Message
0418:                            .getSQLException(ErrorCode.WRONG_USER_OR_PASSWORD);
0419:                }
0420:            }
0421:
0422:            private void openFileData() throws SQLException {
0423:                fileData = new DiskFile(this , databaseName
0424:                        + Constants.SUFFIX_DATA_FILE, accessModeData, true,
0425:                        true, SysProperties.CACHE_SIZE_DEFAULT);
0426:            }
0427:
0428:            private void openFileIndex() throws SQLException {
0429:                fileIndex = new DiskFile(this , databaseName
0430:                        + Constants.SUFFIX_INDEX_FILE, accessModeData, false,
0431:                        logIndexChanges, SysProperties.CACHE_SIZE_INDEX_DEFAULT);
0432:            }
0433:
0434:            public DataPage getDataPage() {
0435:                return dummy;
0436:            }
0437:
0438:            private String parseDatabaseShortName() {
0439:                String n = databaseName;
0440:                if (n.endsWith(":")) {
0441:                    n = null;
0442:                }
0443:                if (n != null) {
0444:                    StringTokenizer tokenizer = new StringTokenizer(n, "/\\:,;");
0445:                    while (tokenizer.hasMoreTokens()) {
0446:                        n = tokenizer.nextToken();
0447:                    }
0448:                }
0449:                if (n == null || n.length() == 0) {
0450:                    n = "UNNAMED";
0451:                }
0452:                return StringUtils.toUpperEnglish(n);
0453:            }
0454:
0455:            private synchronized void open(int traceLevelFile,
0456:                    int traceLevelSystemOut) throws SQLException {
0457:                if (persistent) {
0458:                    String dataFileName = databaseName
0459:                            + Constants.SUFFIX_DATA_FILE;
0460:                    if (FileUtils.exists(dataFileName)) {
0461:                        // if it is already read-only because ACCESS_MODE_DATA=r
0462:                        readOnly = readOnly
0463:                                | FileUtils.isReadOnly(dataFileName);
0464:                        textStorage = isTextStorage(dataFileName, textStorage);
0465:                        lobFilesInDirectories |= FileUtils.exists(databaseName
0466:                                + Constants.SUFFIX_LOBS_DIRECTORY);
0467:                    }
0468:                }
0469:                dummy = DataPage.create(this , 0);
0470:                if (persistent) {
0471:                    if (readOnly) {
0472:                        traceSystem = new TraceSystem(null, false);
0473:                    } else {
0474:                        traceSystem = new TraceSystem(databaseName
0475:                                + Constants.SUFFIX_TRACE_FILE, true);
0476:                    }
0477:                    if (cipher != null) {
0478:                        traceSystem.setManualEnabling(false);
0479:                    }
0480:                    traceSystem.setLevelFile(traceLevelFile);
0481:                    traceSystem.setLevelSystemOut(traceLevelSystemOut);
0482:                    traceSystem.getTrace(Trace.DATABASE).info(
0483:                            "opening " + databaseName + " (build "
0484:                                    + Constants.BUILD_ID + ")");
0485:                    if (!readOnly && fileLockMethod != FileLock.LOCK_NO) {
0486:                        lock = new FileLock(traceSystem, Constants.LOCK_SLEEP);
0487:                        lock.lock(databaseName + Constants.SUFFIX_LOCK_FILE,
0488:                                fileLockMethod == FileLock.LOCK_SOCKET);
0489:                    }
0490:                    deleteOldTempFiles();
0491:                    log = new LogSystem(this , databaseName, readOnly,
0492:                            accessModeLog);
0493:                    openFileData();
0494:                    log.open();
0495:                    openFileIndex();
0496:                    log.recover();
0497:                    fileData.init();
0498:                    try {
0499:                        fileIndex.init();
0500:                    } catch (Throwable e) {
0501:                        if (recovery) {
0502:                            traceSystem.getTrace(Trace.DATABASE).error(
0503:                                    "opening index", e);
0504:                            fileIndex.close();
0505:                            fileIndex.delete();
0506:                            openFileIndex();
0507:                        } else {
0508:                            throw Message.convert(e);
0509:                        }
0510:                    }
0511:                    reserveLobFileObjectIds();
0512:                    writer = WriterThread.create(this , writeDelay);
0513:                } else {
0514:                    traceSystem = new TraceSystem(null, false);
0515:                    log = new LogSystem(null, null, false, null);
0516:                }
0517:                systemUser = new User(this , 0, Constants.DBA_NAME, true);
0518:                mainSchema = new Schema(this , 0, Constants.SCHEMA_MAIN,
0519:                        systemUser, true);
0520:                infoSchema = new Schema(this , -1, Constants.SCHEMA_INFORMATION,
0521:                        systemUser, true);
0522:                schemas.put(mainSchema.getName(), mainSchema);
0523:                schemas.put(infoSchema.getName(), infoSchema);
0524:                publicRole = new Role(this , 0, Constants.PUBLIC_ROLE_NAME, true);
0525:                roles.put(Constants.PUBLIC_ROLE_NAME, publicRole);
0526:                systemUser.setAdmin(true);
0527:                systemSession = new Session(this , systemUser, ++nextSessionId);
0528:                ObjectArray cols = new ObjectArray();
0529:                Column columnId = new Column("ID", Value.INT);
0530:                columnId.setNullable(false);
0531:                cols.add(columnId);
0532:                cols.add(new Column("HEAD", Value.INT));
0533:                cols.add(new Column("TYPE", Value.INT));
0534:                cols.add(new Column("SQL", Value.STRING));
0535:                meta = mainSchema
0536:                        .createTable("SYS", 0, cols, persistent, false);
0537:                IndexColumn[] pkCols = IndexColumn
0538:                        .wrap(new Column[] { columnId });
0539:                metaIdIndex = meta.addIndex(systemSession, "SYS_ID", 0, pkCols,
0540:                        IndexType.createPrimaryKey(false, false),
0541:                        Index.EMPTY_HEAD, null);
0542:                objectIds.set(0);
0543:                // there could be views on system tables, so they must be added first
0544:                addMetaData(MetaTable.TABLES);
0545:                addMetaData(MetaTable.COLUMNS);
0546:                addMetaData(MetaTable.INDEXES);
0547:                addMetaData(MetaTable.TABLE_TYPES);
0548:                addMetaData(MetaTable.TYPE_INFO);
0549:                addMetaData(MetaTable.CATALOGS);
0550:                addMetaData(MetaTable.SETTINGS);
0551:                addMetaData(MetaTable.HELP);
0552:                addMetaData(MetaTable.SEQUENCES);
0553:                addMetaData(MetaTable.USERS);
0554:                addMetaData(MetaTable.ROLES);
0555:                addMetaData(MetaTable.RIGHTS);
0556:                addMetaData(MetaTable.FUNCTION_ALIASES);
0557:                addMetaData(MetaTable.SCHEMATA);
0558:                addMetaData(MetaTable.TABLE_PRIVILEGES);
0559:                addMetaData(MetaTable.COLUMN_PRIVILEGES);
0560:                addMetaData(MetaTable.COLLATIONS);
0561:                addMetaData(MetaTable.VIEWS);
0562:                addMetaData(MetaTable.IN_DOUBT);
0563:                addMetaData(MetaTable.CROSS_REFERENCES);
0564:                addMetaData(MetaTable.CONSTRAINTS);
0565:                addMetaData(MetaTable.FUNCTION_COLUMNS);
0566:                addMetaData(MetaTable.CONSTANTS);
0567:                addMetaData(MetaTable.DOMAINS);
0568:                addMetaData(MetaTable.TRIGGERS);
0569:                addMetaData(MetaTable.SESSIONS);
0570:                addMetaData(MetaTable.LOCKS);
0571:                starting = true;
0572:                Cursor cursor = metaIdIndex.find(systemSession, null, null);
0573:                // first, create all function aliases and sequences because
0574:                // they might be used in create table / view / constraints and so on
0575:                ObjectArray records = new ObjectArray();
0576:                while (cursor.next()) {
0577:                    MetaRecord rec = new MetaRecord(cursor.get());
0578:                    objectIds.set(rec.getId());
0579:                    records.add(rec);
0580:                }
0581:                MetaRecord.sort(records);
0582:                for (int i = 0; i < records.size(); i++) {
0583:                    MetaRecord rec = (MetaRecord) records.get(i);
0584:                    rec.execute(this , systemSession, eventListener);
0585:                }
0586:                // try to recompile the views that are invalid
0587:                recompileInvalidViews(systemSession);
0588:                starting = false;
0589:                addDefaultSetting(systemSession, SetTypes.DEFAULT_LOCK_TIMEOUT,
0590:                        null, Constants.INITIAL_LOCK_TIMEOUT);
0591:                addDefaultSetting(systemSession, SetTypes.DEFAULT_TABLE_TYPE,
0592:                        null, Constants.DEFAULT_TABLE_TYPE);
0593:                addDefaultSetting(systemSession, SetTypes.TRACE_LEVEL_FILE,
0594:                        null, traceSystem.getLevelFile());
0595:                addDefaultSetting(systemSession,
0596:                        SetTypes.TRACE_LEVEL_SYSTEM_OUT, null, traceSystem
0597:                                .getLevelSystemOut());
0598:                addDefaultSetting(systemSession, SetTypes.CACHE_SIZE, null,
0599:                        SysProperties.CACHE_SIZE_DEFAULT);
0600:                addDefaultSetting(systemSession, SetTypes.CLUSTER,
0601:                        Constants.CLUSTERING_DISABLED, 0);
0602:                addDefaultSetting(systemSession, SetTypes.WRITE_DELAY, null,
0603:                        Constants.DEFAULT_WRITE_DELAY);
0604:                addDefaultSetting(systemSession, SetTypes.CREATE_BUILD, null,
0605:                        Constants.BUILD_ID);
0606:                if (!readOnly) {
0607:                    removeUnusedStorages(systemSession);
0608:                }
0609:                systemSession.commit(true);
0610:                if (!readOnly && persistent) {
0611:                    emergencyReserve = openFile(createTempFile(), "rw", false);
0612:                    emergencyReserve.autoDelete();
0613:                    emergencyReserve
0614:                            .setLength(SysProperties.EMERGENCY_SPACE_INITIAL);
0615:                }
0616:                traceSystem.getTrace(Trace.DATABASE).info(
0617:                        "opened " + databaseName);
0618:            }
0619:
0620:            private void recompileInvalidViews(Session session) {
0621:                boolean recompileSuccessful;
0622:                do {
0623:                    recompileSuccessful = false;
0624:                    ObjectArray list = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
0625:                    for (int i = 0; i < list.size(); i++) {
0626:                        DbObject obj = (DbObject) list.get(i);
0627:                        if (obj instanceof  TableView) {
0628:                            TableView view = (TableView) obj;
0629:                            if (view.getInvalid()) {
0630:                                try {
0631:                                    view.recompile(session);
0632:                                } catch (Throwable e) {
0633:                                    // ignore
0634:                                }
0635:                                if (!view.getInvalid()) {
0636:                                    recompileSuccessful = true;
0637:                                }
0638:                            }
0639:                        }
0640:                    }
0641:                } while (recompileSuccessful);
0642:                // when opening a database, views are initialized before indexes, 
0643:                // so they may not have the optimal plan yet
0644:                // this is not a problem, it is just nice to see the newest plan
0645:                ObjectArray list = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
0646:                for (int i = 0; i < list.size(); i++) {
0647:                    DbObject obj = (DbObject) list.get(i);
0648:                    if (obj instanceof  TableView) {
0649:                        TableView view = (TableView) obj;
0650:                        if (!view.getInvalid()) {
0651:                            try {
0652:                                view.recompile(systemSession);
0653:                            } catch (SQLException e) {
0654:                                // ignore
0655:                            }
0656:                        }
0657:                    }
0658:                }
0659:            }
0660:
0661:            private void removeUnusedStorages(Session session)
0662:                    throws SQLException {
0663:                if (persistent) {
0664:                    ObjectArray storages = getAllStorages();
0665:                    for (int i = 0; i < storages.size(); i++) {
0666:                        Storage storage = (Storage) storages.get(i);
0667:                        if (storage != null
0668:                                && storage.getRecordReader() == null) {
0669:                            storage.delete(session);
0670:                        }
0671:                    }
0672:                }
0673:            }
0674:
0675:            private void addDefaultSetting(Session session, int type,
0676:                    String stringValue, int intValue) throws SQLException {
0677:                if (readOnly) {
0678:                    return;
0679:                }
0680:                String name = SetTypes.getTypeName(type);
0681:                if (settings.get(name) == null) {
0682:                    Setting setting = new Setting(this , allocateObjectId(false,
0683:                            true), name);
0684:                    if (stringValue == null) {
0685:                        setting.setIntValue(intValue);
0686:                    } else {
0687:                        setting.setStringValue(stringValue);
0688:                    }
0689:                    addDatabaseObject(session, setting);
0690:                }
0691:            }
0692:
0693:            public void removeStorage(int id, DiskFile file) {
0694:                if (SysProperties.CHECK) {
0695:                    Storage s = (Storage) storageMap.get(id);
0696:                    if (s == null || s.getDiskFile() != file) {
0697:                        throw Message.getInternalError();
0698:                    }
0699:                }
0700:                storageMap.remove(id);
0701:            }
0702:
0703:            public Storage getStorage(int id, DiskFile file) {
0704:                Storage storage = (Storage) storageMap.get(id);
0705:                if (storage != null) {
0706:                    if (SysProperties.CHECK && storage.getDiskFile() != file) {
0707:                        throw Message.getInternalError();
0708:                    }
0709:                } else {
0710:                    storage = new Storage(this , file, null, id);
0711:                    storageMap.put(id, storage);
0712:                }
0713:                return storage;
0714:            }
0715:
0716:            private void addMetaData(int type) throws SQLException {
0717:                MetaTable m = new MetaTable(infoSchema, -1 - type, type);
0718:                infoSchema.add(m);
0719:            }
0720:
0721:            private synchronized void addMeta(Session session, DbObject obj)
0722:                    throws SQLException {
0723:                if (obj.getTemporary()) {
0724:                    return;
0725:                }
0726:                Row r = meta.getTemplateRow();
0727:                MetaRecord rec = new MetaRecord(obj);
0728:                rec.setRecord(r);
0729:                objectIds.set(obj.getId());
0730:                meta.lock(session, true, true);
0731:                meta.addRow(session, r);
0732:                if (isMultiVersion()) {
0733:                    // TODO this should work without MVCC, but avoid risks at the moment
0734:                    session.log(meta, UndoLogRecord.INSERT, r);
0735:                }
0736:            }
0737:
0738:            public synchronized void removeMeta(Session session, int id)
0739:                    throws SQLException {
0740:                SearchRow r = meta.getTemplateSimpleRow(false);
0741:                r.setValue(0, ValueInt.get(id));
0742:                Cursor cursor = metaIdIndex.find(session, r, r);
0743:                if (cursor.next()) {
0744:                    Row found = cursor.get();
0745:                    meta.lock(session, true, true);
0746:                    meta.removeRow(session, found);
0747:                    if (isMultiVersion()) {
0748:                        // TODO this should work without MVCC, but avoid risks at the
0749:                        // moment
0750:                        session.log(meta, UndoLogRecord.DELETE, found);
0751:                    }
0752:                    objectIds.clear(id);
0753:                    if (SysProperties.CHECK) {
0754:                        checkMetaFree(session, id);
0755:                    }
0756:                }
0757:            }
0758:
0759:            private HashMap getMap(int type) {
0760:                switch (type) {
0761:                case DbObject.USER:
0762:                    return users;
0763:                case DbObject.SETTING:
0764:                    return settings;
0765:                case DbObject.ROLE:
0766:                    return roles;
0767:                case DbObject.RIGHT:
0768:                    return rights;
0769:                case DbObject.FUNCTION_ALIAS:
0770:                    return functionAliases;
0771:                case DbObject.SCHEMA:
0772:                    return schemas;
0773:                case DbObject.USER_DATATYPE:
0774:                    return userDataTypes;
0775:                case DbObject.COMMENT:
0776:                    return comments;
0777:                case DbObject.AGGREGATE:
0778:                    return aggregates;
0779:                default:
0780:                    throw Message.getInternalError("type=" + type);
0781:                }
0782:            }
0783:
0784:            public synchronized void addSchemaObject(Session session,
0785:                    SchemaObject obj) throws SQLException {
0786:                obj.getSchema().add(obj);
0787:                int id = obj.getId();
0788:                if (id > 0 && !starting) {
0789:                    addMeta(session, obj);
0790:                }
0791:            }
0792:
0793:            public synchronized void addDatabaseObject(Session session,
0794:                    DbObject obj) throws SQLException {
0795:                HashMap map = getMap(obj.getType());
0796:                if (obj.getType() == DbObject.USER) {
0797:                    User user = (User) obj;
0798:                    if (user.getAdmin()
0799:                            && systemUser.getName().equals(Constants.DBA_NAME)) {
0800:                        systemUser.rename(user.getName());
0801:                    }
0802:                }
0803:                String name = obj.getName();
0804:                if (SysProperties.CHECK && map.get(name) != null) {
0805:                    throw Message.getInternalError("object already exists");
0806:                }
0807:                int id = obj.getId();
0808:                if (id > 0 && !starting) {
0809:                    addMeta(session, obj);
0810:                }
0811:                map.put(name, obj);
0812:            }
0813:
0814:            public Setting findSetting(String name) {
0815:                return (Setting) settings.get(name);
0816:            }
0817:
0818:            public Comment findComment(DbObject object) {
0819:                if (object.getType() == DbObject.COMMENT) {
0820:                    return null;
0821:                }
0822:                String key = Comment.getKey(object);
0823:                return (Comment) comments.get(key);
0824:            }
0825:
0826:            public User findUser(String name) {
0827:                return (User) users.get(name);
0828:            }
0829:
0830:            public FunctionAlias findFunctionAlias(String name) {
0831:                return (FunctionAlias) functionAliases.get(name);
0832:            }
0833:
0834:            public UserAggregate findAggregate(String name) {
0835:                return (UserAggregate) aggregates.get(name);
0836:            }
0837:
0838:            public UserDataType findUserDataType(String name) {
0839:                return (UserDataType) userDataTypes.get(name);
0840:            }
0841:
0842:            public User getUser(String name, SQLException notFound)
0843:                    throws SQLException {
0844:                User user = (User) users.get(name);
0845:                if (user == null) {
0846:                    try {
0847:                        Thread.sleep(Constants.DELAY_WRONG_PASSWORD);
0848:                    } catch (InterruptedException e) {
0849:                        // ignore
0850:                    }
0851:                    throw notFound;
0852:                }
0853:                return user;
0854:            }
0855:
0856:            public User getUser(String name) throws SQLException {
0857:                return getUser(name, Message.getSQLException(
0858:                        ErrorCode.USER_NOT_FOUND_1, name));
0859:            }
0860:
0861:            public synchronized Session createSession(User user)
0862:                    throws SQLException {
0863:                if (exclusiveSession != null) {
0864:                    throw Message
0865:                            .getSQLException(ErrorCode.DATABASE_IS_IN_EXCLUSIVE_MODE);
0866:                }
0867:                Session session = new Session(this , user, ++nextSessionId);
0868:                sessions.add(session);
0869:                traceSystem.getTrace(Trace.SESSION).info(
0870:                        "connecting #" + session.getId() + " to "
0871:                                + databaseName);
0872:                if (delayedCloser != null) {
0873:                    delayedCloser.reset();
0874:                    delayedCloser = null;
0875:                }
0876:                return session;
0877:            }
0878:
0879:            public synchronized void removeSession(Session session)
0880:                    throws SQLException {
0881:                if (session != null) {
0882:                    if (exclusiveSession == session) {
0883:                        exclusiveSession = null;
0884:                    }
0885:                    sessions.remove(session);
0886:                    if (session != systemSession) {
0887:                        traceSystem.getTrace(Trace.SESSION).info(
0888:                                "disconnecting #" + session.getId());
0889:                    }
0890:                }
0891:                if (sessions.size() == 0 && session != systemSession) {
0892:                    if (closeDelay == 0) {
0893:                        close(false);
0894:                    } else if (closeDelay < 0) {
0895:                        return;
0896:                    } else {
0897:                        delayedCloser = new DatabaseCloser(this ,
0898:                                closeDelay * 1000, false);
0899:                        delayedCloser.setName("H2 Close Delay "
0900:                                + getShortName());
0901:                        delayedCloser.setDaemon(true);
0902:                        delayedCloser.start();
0903:                    }
0904:                }
0905:                if (session != systemSession && session != null) {
0906:                    traceSystem.getTrace(Trace.SESSION).info(
0907:                            "disconnected #" + session.getId());
0908:                }
0909:            }
0910:
0911:            synchronized void close(boolean fromShutdownHook) {
0912:                closing = true;
0913:                if (sessions.size() > 0) {
0914:                    if (!fromShutdownHook) {
0915:                        return;
0916:                    }
0917:                    traceSystem.getTrace(Trace.DATABASE).info(
0918:                            "closing " + databaseName + " from shutdown hook");
0919:                    Session[] all = new Session[sessions.size()];
0920:                    sessions.toArray(all);
0921:                    for (int i = 0; i < all.length; i++) {
0922:                        Session s = all[i];
0923:                        try {
0924:                            s.close();
0925:                        } catch (SQLException e) {
0926:                            traceSystem.getTrace(Trace.SESSION).error(
0927:                                    "disconnecting #" + s.getId(), e);
0928:                        }
0929:                    }
0930:                }
0931:                if (log != null) {
0932:                    log.setDisabled(false);
0933:                }
0934:                traceSystem.getTrace(Trace.DATABASE).info(
0935:                        "closing " + databaseName);
0936:                if (eventListener != null) {
0937:                    // allow the event listener to connect to the database
0938:                    closing = false;
0939:                    DatabaseEventListener e = eventListener;
0940:                    // set it to null, to make sure it's called only once
0941:                    eventListener = null;
0942:                    e.closingDatabase();
0943:                    if (sessions.size() > 0) {
0944:                        // if a connection was opened, we can't close the database
0945:                        return;
0946:                    }
0947:                    closing = true;
0948:                }
0949:                try {
0950:                    if (systemSession != null) {
0951:                        ObjectArray tablesAndViews = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
0952:                        for (int i = 0; i < tablesAndViews.size(); i++) {
0953:                            Table table = (Table) tablesAndViews.get(i);
0954:                            table.close(systemSession);
0955:                        }
0956:                        ObjectArray sequences = getAllSchemaObjects(DbObject.SEQUENCE);
0957:                        for (int i = 0; i < sequences.size(); i++) {
0958:                            Sequence sequence = (Sequence) sequences.get(i);
0959:                            sequence.close();
0960:                        }
0961:                        meta.close(systemSession);
0962:                        indexSummaryValid = true;
0963:                    }
0964:                } catch (SQLException e) {
0965:                    traceSystem.getTrace(Trace.DATABASE).error("close", e);
0966:                }
0967:                // remove all session variables
0968:                if (persistent) {
0969:                    try {
0970:                        ValueLob.removeAllForTable(this ,
0971:                                ValueLob.TABLE_ID_SESSION);
0972:                    } catch (SQLException e) {
0973:                        traceSystem.getTrace(Trace.DATABASE).error("close", e);
0974:                    }
0975:                }
0976:                try {
0977:                    closeOpenFilesAndUnlock();
0978:                } catch (SQLException e) {
0979:                    traceSystem.getTrace(Trace.DATABASE).error("close", e);
0980:                }
0981:                traceSystem.getTrace(Trace.DATABASE).info("closed");
0982:                traceSystem.close();
0983:                if (closeOnExit != null) {
0984:                    closeOnExit.reset();
0985:                    try {
0986:                        Runtime.getRuntime().removeShutdownHook(closeOnExit);
0987:                    } catch (IllegalStateException e) {
0988:                        // ignore
0989:                    } catch (SecurityException e) {
0990:                        // applets may not do that - ignore
0991:                    }
0992:                    closeOnExit = null;
0993:                }
0994:                Engine.getInstance().close(databaseName);
0995:                if (deleteFilesOnDisconnect && persistent) {
0996:                    deleteFilesOnDisconnect = false;
0997:                    try {
0998:                        String directory = FileUtils.getParent(databaseName);
0999:                        String name = FileUtils.getFileName(databaseName);
1000:                        DeleteDbFiles.execute(directory, name, true);
1001:                    } catch (Exception e) {
1002:                        // ignore (the trace is closed already)
1003:                    }
1004:                }
1005:            }
1006:
1007:            private void stopWriter() {
1008:                if (writer != null) {
1009:                    try {
1010:                        writer.stopThread();
1011:                    } catch (SQLException e) {
1012:                        traceSystem.getTrace(Trace.DATABASE).error("close", e);
1013:                    }
1014:                    writer = null;
1015:                }
1016:            }
1017:
1018:            private synchronized void closeOpenFilesAndUnlock()
1019:                    throws SQLException {
1020:                if (log != null) {
1021:                    stopWriter();
1022:                    log.close();
1023:                    log = null;
1024:                }
1025:                closeFiles();
1026:                if (persistent && lock == null
1027:                        && fileLockMethod != FileLock.LOCK_NO) {
1028:                    // everything already closed (maybe in checkPowerOff)
1029:                    // don't delete temp files in this case because
1030:                    // the database could be open now (even from within another process)
1031:                    return;
1032:                }
1033:                if (persistent) {
1034:                    deleteOldTempFiles();
1035:                }
1036:                if (systemSession != null) {
1037:                    systemSession.close();
1038:                    systemSession = null;
1039:                }
1040:                if (lock != null) {
1041:                    lock.unlock();
1042:                    lock = null;
1043:                }
1044:            }
1045:
1046:            private void closeFiles() throws SQLException {
1047:                try {
1048:                    if (fileData != null) {
1049:                        fileData.close();
1050:                        fileData = null;
1051:                    }
1052:                    if (fileIndex != null) {
1053:                        fileIndex.close();
1054:                        fileIndex = null;
1055:                    }
1056:                } catch (SQLException e) {
1057:                    traceSystem.getTrace(Trace.DATABASE).error("close", e);
1058:                }
1059:                storageMap.clear();
1060:            }
1061:
1062:            private void checkMetaFree(Session session, int id)
1063:                    throws SQLException {
1064:                SearchRow r = meta.getTemplateSimpleRow(false);
1065:                r.setValue(0, ValueInt.get(id));
1066:                Cursor cursor = metaIdIndex.find(session, r, r);
1067:                if (cursor.next()) {
1068:                    throw Message.getInternalError();
1069:                }
1070:            }
1071:
1072:            public synchronized int allocateObjectId(boolean needFresh,
1073:                    boolean dataFile) {
1074:                // TODO refactor: use hash map instead of bit field for object ids
1075:                needFresh = true;
1076:                int i;
1077:                if (needFresh) {
1078:                    i = objectIds.getLastSetBit() + 1;
1079:                    if ((i & 1) != (dataFile ? 1 : 0)) {
1080:                        i++;
1081:                    }
1082:
1083:                    while (storageMap.get(i) != null || objectIds.get(i)) {
1084:                        i++;
1085:                        if ((i & 1) != (dataFile ? 1 : 0)) {
1086:                            i++;
1087:                        }
1088:                    }
1089:                } else {
1090:                    i = objectIds.nextClearBit(0);
1091:                }
1092:                if (SysProperties.CHECK && objectIds.get(i)) {
1093:                    throw Message.getInternalError();
1094:                }
1095:                objectIds.set(i);
1096:                return i;
1097:            }
1098:
1099:            public ObjectArray getAllSettings() {
1100:                return new ObjectArray(settings.values());
1101:            }
1102:
1103:            public ObjectArray getAllUsers() {
1104:                return new ObjectArray(users.values());
1105:            }
1106:
1107:            public ObjectArray getAllRoles() {
1108:                return new ObjectArray(roles.values());
1109:            }
1110:
1111:            public ObjectArray getAllRights() {
1112:                return new ObjectArray(rights.values());
1113:            }
1114:
1115:            public ObjectArray getAllComments() {
1116:                return new ObjectArray(comments.values());
1117:            }
1118:
1119:            public ObjectArray getAllSchemas() {
1120:                return new ObjectArray(schemas.values());
1121:            }
1122:
1123:            public ObjectArray getAllFunctionAliases() {
1124:                return new ObjectArray(functionAliases.values());
1125:            }
1126:
1127:            public ObjectArray getAllAggregates() {
1128:                return new ObjectArray(aggregates.values());
1129:            }
1130:
1131:            public ObjectArray getAllUserDataTypes() {
1132:                return new ObjectArray(userDataTypes.values());
1133:            }
1134:
1135:            public ObjectArray getAllSchemaObjects(int type) {
1136:                ObjectArray list = new ObjectArray();
1137:                for (Iterator it = schemas.values().iterator(); it.hasNext();) {
1138:                    Schema schema = (Schema) it.next();
1139:                    list.addAll(schema.getAll(type));
1140:                }
1141:                return list;
1142:            }
1143:
1144:            public String getShortName() {
1145:                return databaseShortName;
1146:            }
1147:
1148:            public String getName() {
1149:                return databaseName;
1150:            }
1151:
1152:            public LogSystem getLog() {
1153:                return log;
1154:            }
1155:
1156:            public Session[] getSessions() {
1157:                Session[] list = new Session[sessions.size()];
1158:                sessions.toArray(list);
1159:                return list;
1160:            }
1161:
1162:            public synchronized void update(Session session, DbObject obj)
1163:                    throws SQLException {
1164:                int id = obj.getId();
1165:                removeMeta(session, id);
1166:                addMeta(session, obj);
1167:            }
1168:
1169:            /**
1170:             * Rename a schema object.
1171:             * 
1172:             * @param session the session
1173:             * @param obj the object
1174:             * @param newName the new name
1175:             */
1176:            public synchronized void renameSchemaObject(Session session,
1177:                    SchemaObject obj, String newName) throws SQLException {
1178:                obj.getSchema().rename(obj, newName);
1179:                updateWithChildren(session, obj);
1180:            }
1181:
1182:            private synchronized void updateWithChildren(Session session,
1183:                    DbObject obj) throws SQLException {
1184:                ObjectArray list = obj.getChildren();
1185:                Comment comment = findComment(obj);
1186:                if (comment != null) {
1187:                    throw Message.getInternalError();
1188:                }
1189:                update(session, obj);
1190:                // remember that this scans only one level deep!
1191:                for (int i = 0; list != null && i < list.size(); i++) {
1192:                    DbObject o = (DbObject) list.get(i);
1193:                    if (o.getCreateSQL() != null) {
1194:                        update(session, o);
1195:                    }
1196:                }
1197:            }
1198:
1199:            /**
1200:             * Rename a database object.
1201:             * 
1202:             * @param session the session
1203:             * @param obj the object
1204:             * @param newName the new name
1205:             */
1206:            public synchronized void renameDatabaseObject(Session session,
1207:                    DbObject obj, String newName) throws SQLException {
1208:                int type = obj.getType();
1209:                HashMap map = getMap(type);
1210:                if (SysProperties.CHECK) {
1211:                    if (!map.containsKey(obj.getName())) {
1212:                        throw Message.getInternalError("not found: "
1213:                                + obj.getName());
1214:                    }
1215:                    if (obj.getName().equals(newName)
1216:                            || map.containsKey(newName)) {
1217:                        throw Message
1218:                                .getInternalError("object already exists: "
1219:                                        + newName);
1220:                    }
1221:                }
1222:                int id = obj.getId();
1223:                removeMeta(session, id);
1224:                map.remove(obj.getName());
1225:                obj.rename(newName);
1226:                map.put(newName, obj);
1227:                updateWithChildren(session, obj);
1228:            }
1229:
1230:            public String createTempFile() throws SQLException {
1231:                try {
1232:                    boolean inTempDir = readOnly;
1233:                    String name = databaseName;
1234:                    if (!persistent) {
1235:                        name = FileSystem.MEMORY_PREFIX + name;
1236:                    }
1237:                    return FileUtils.createTempFile(name,
1238:                            Constants.SUFFIX_TEMP_FILE, true, inTempDir);
1239:                } catch (IOException e) {
1240:                    throw Message.convertIOException(e, databaseName);
1241:                }
1242:            }
1243:
1244:            private void reserveLobFileObjectIds() throws SQLException {
1245:                String prefix = FileUtils.normalize(databaseName) + ".";
1246:                String path = FileUtils.getParent(databaseName);
1247:                String[] list = FileUtils.listFiles(path);
1248:                for (int i = 0; i < list.length; i++) {
1249:                    String name = list[i];
1250:                    if (name.endsWith(Constants.SUFFIX_LOB_FILE)
1251:                            && FileUtils.fileStartsWith(name, prefix)) {
1252:                        name = name.substring(prefix.length());
1253:                        name = name.substring(0, name.length()
1254:                                - Constants.SUFFIX_LOB_FILE.length());
1255:                        int dot = name.indexOf('.');
1256:                        if (dot >= 0) {
1257:                            String id = name.substring(dot + 1);
1258:                            int objectId = Integer.parseInt(id);
1259:                            objectIds.set(objectId);
1260:                        }
1261:                    }
1262:                }
1263:            }
1264:
1265:            private void deleteOldTempFiles() throws SQLException {
1266:                if (emergencyReserve != null) {
1267:                    emergencyReserve.closeAndDeleteSilently();
1268:                    emergencyReserve = null;
1269:                }
1270:                String path = FileUtils.getParent(databaseName);
1271:                String prefix = FileUtils.normalize(databaseName);
1272:                String[] list = FileUtils.listFiles(path);
1273:                for (int i = 0; i < list.length; i++) {
1274:                    String name = list[i];
1275:                    if (name.endsWith(Constants.SUFFIX_TEMP_FILE)
1276:                            && FileUtils.fileStartsWith(name, prefix)) {
1277:                        // can't always delete the files, they may still be open
1278:                        FileUtils.tryDelete(name);
1279:                    }
1280:                }
1281:            }
1282:
1283:            /**
1284:             * Get or create the specified storage object.
1285:             * 
1286:             * @param reader the record reader
1287:             * @param id the object id
1288:             * @param dataFile true if the data is in the data file
1289:             * @return the storage
1290:             */
1291:            public Storage getStorage(RecordReader reader, int id,
1292:                    boolean dataFile) {
1293:                DiskFile file;
1294:                if (dataFile) {
1295:                    file = fileData;
1296:                } else {
1297:                    file = fileIndex;
1298:                }
1299:                Storage storage = getStorage(id, file);
1300:                storage.setReader(reader);
1301:                return storage;
1302:            }
1303:
1304:            public Role findRole(String roleName) {
1305:                return (Role) roles.get(roleName);
1306:            }
1307:
1308:            public Schema findSchema(String schemaName) {
1309:                return (Schema) schemas.get(schemaName);
1310:            }
1311:
1312:            public Schema getSchema(String schemaName) throws SQLException {
1313:                Schema schema = findSchema(schemaName);
1314:                if (schema == null) {
1315:                    throw Message.getSQLException(ErrorCode.SCHEMA_NOT_FOUND_1,
1316:                            schemaName);
1317:                }
1318:                return schema;
1319:            }
1320:
1321:            public synchronized void removeDatabaseObject(Session session,
1322:                    DbObject obj) throws SQLException {
1323:                String objName = obj.getName();
1324:                int type = obj.getType();
1325:                HashMap map = getMap(type);
1326:                if (SysProperties.CHECK && !map.containsKey(objName)) {
1327:                    throw Message.getInternalError("not found: " + objName);
1328:                }
1329:                Comment comment = findComment(obj);
1330:                if (comment != null) {
1331:                    removeDatabaseObject(session, comment);
1332:                }
1333:                int id = obj.getId();
1334:                obj.removeChildrenAndResources(session);
1335:                map.remove(objName);
1336:                removeMeta(session, id);
1337:            }
1338:
1339:            private String getDependentObject(SchemaObject obj) {
1340:                switch (obj.getType()) {
1341:                case DbObject.COMMENT:
1342:                case DbObject.CONSTRAINT:
1343:                case DbObject.INDEX:
1344:                case DbObject.RIGHT:
1345:                case DbObject.TRIGGER:
1346:                case DbObject.USER:
1347:                    return null;
1348:                }
1349:                ObjectArray list = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
1350:                HashSet set = new HashSet();
1351:                for (int i = 0; i < list.size(); i++) {
1352:                    Table t = (Table) list.get(i);
1353:                    set.clear();
1354:                    t.addDependencies(set);
1355:                    if (set.contains(obj)) {
1356:                        return t.getSQL();
1357:                    }
1358:                }
1359:                return null;
1360:            }
1361:
1362:            private String getFirstInvalidTable(Session session) {
1363:                String conflict = null;
1364:                try {
1365:                    ObjectArray list = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
1366:                    for (int i = 0; i < list.size(); i++) {
1367:                        Table t = (Table) list.get(i);
1368:                        conflict = t.getSQL();
1369:                        session.prepare(t.getCreateSQL());
1370:                    }
1371:                } catch (SQLException e) {
1372:                    return conflict;
1373:                }
1374:                return null;
1375:            }
1376:
1377:            public synchronized void removeSchemaObject(Session session,
1378:                    SchemaObject obj) throws SQLException {
1379:                if (obj.getType() == DbObject.TABLE_OR_VIEW) {
1380:                    Table table = (Table) obj;
1381:                    if (table.getTemporary() && !table.getGlobalTemporary()) {
1382:                        session.removeLocalTempTable(table);
1383:                        return;
1384:                    }
1385:                }
1386:                Comment comment = findComment(obj);
1387:                if (comment != null) {
1388:                    removeDatabaseObject(session, comment);
1389:                }
1390:                obj.getSchema().remove(session, obj);
1391:                String invalid;
1392:                if (SysProperties.OPTIMIZE_DROP_DEPENDENCIES) {
1393:                    invalid = getDependentObject(obj);
1394:                } else {
1395:                    invalid = getFirstInvalidTable(session);
1396:                }
1397:                if (invalid != null) {
1398:                    obj.getSchema().add(obj);
1399:                    throw Message.getSQLException(ErrorCode.CANNOT_DROP_2,
1400:                            new String[] { obj.getSQL(), invalid });
1401:                }
1402:                int id = obj.getId();
1403:                obj.removeChildrenAndResources(session);
1404:                removeMeta(session, id);
1405:            }
1406:
1407:            public boolean isPersistent() {
1408:                return persistent;
1409:            }
1410:
1411:            public TraceSystem getTraceSystem() {
1412:                return traceSystem;
1413:            }
1414:
1415:            public DiskFile getDataFile() {
1416:                return fileData;
1417:            }
1418:
1419:            public DiskFile getIndexFile() {
1420:                return fileIndex;
1421:            }
1422:
1423:            public synchronized void setCacheSize(int kb) throws SQLException {
1424:                if (fileData != null) {
1425:                    fileData.getCache().setMaxSize(kb);
1426:                    int valueIndex = kb <= 32 ? kb
1427:                            : (kb >>> SysProperties.CACHE_SIZE_INDEX_SHIFT);
1428:                    fileIndex.getCache().setMaxSize(valueIndex);
1429:                    cacheSize = kb;
1430:                }
1431:            }
1432:
1433:            public synchronized void setMasterUser(User user)
1434:                    throws SQLException {
1435:                addDatabaseObject(systemSession, user);
1436:                systemSession.commit(true);
1437:            }
1438:
1439:            public Role getPublicRole() {
1440:                return publicRole;
1441:            }
1442:
1443:            public String getTempTableName(int sessionId) {
1444:                String tempName;
1445:                for (int i = 0;; i++) {
1446:                    tempName = Constants.TEMP_TABLE_PREFIX + sessionId + "_"
1447:                            + i;
1448:                    if (mainSchema.findTableOrView(null, tempName) == null) {
1449:                        break;
1450:                    }
1451:                }
1452:                return tempName;
1453:            }
1454:
1455:            public void setCompareMode(CompareMode compareMode) {
1456:                this .compareMode = compareMode;
1457:            }
1458:
1459:            public CompareMode getCompareMode() {
1460:                return compareMode;
1461:            }
1462:
1463:            public String getCluster() {
1464:                return cluster;
1465:            }
1466:
1467:            public void setCluster(String cluster) {
1468:                this .cluster = cluster;
1469:            }
1470:
1471:            public void checkWritingAllowed() throws SQLException {
1472:                if (readOnly) {
1473:                    throw Message
1474:                            .getSQLException(ErrorCode.DATABASE_IS_READ_ONLY);
1475:                }
1476:                if (noDiskSpace) {
1477:                    throw Message
1478:                            .getSQLException(ErrorCode.NO_DISK_SPACE_AVAILABLE);
1479:                }
1480:            }
1481:
1482:            public boolean getReadOnly() {
1483:                return readOnly;
1484:            }
1485:
1486:            public void setWriteDelay(int value) {
1487:                writeDelay = value;
1488:                if (writer != null) {
1489:                    writer.setWriteDelay(value);
1490:                }
1491:            }
1492:
1493:            public void deleteLogFileLater(String fileName) throws SQLException {
1494:                if (writer != null) {
1495:                    writer.deleteLogFileLater(fileName);
1496:                } else {
1497:                    FileUtils.delete(fileName);
1498:                }
1499:            }
1500:
1501:            public Class loadUserClass(String className) throws SQLException {
1502:                try {
1503:                    return ClassUtils.loadUserClass(className);
1504:                } catch (ClassNotFoundException e) {
1505:                    throw Message.getSQLException(ErrorCode.CLASS_NOT_FOUND_1,
1506:                            new String[] { className }, e);
1507:                } catch (NoClassDefFoundError e) {
1508:                    throw Message.getSQLException(ErrorCode.CLASS_NOT_FOUND_1,
1509:                            new String[] { className }, e);
1510:                }
1511:            }
1512:
1513:            public void setEventListener(String className) throws SQLException {
1514:                if (className == null || className.length() == 0) {
1515:                    eventListener = null;
1516:                } else {
1517:                    try {
1518:                        eventListener = (DatabaseEventListener) loadUserClass(
1519:                                className).newInstance();
1520:                        String url = databaseURL;
1521:                        if (cipher != null) {
1522:                            url += ";CIPHER=" + cipher;
1523:                        }
1524:                        eventListener.init(url);
1525:                    } catch (Throwable e) {
1526:                        throw Message
1527:                                .getSQLException(
1528:                                        ErrorCode.ERROR_SETTING_DATABASE_EVENT_LISTENER_2,
1529:                                        new String[] { className, e.toString() },
1530:                                        e);
1531:                    }
1532:                }
1533:            }
1534:
1535:            public synchronized void freeUpDiskSpace() throws SQLException {
1536:                long sizeAvailable = 0;
1537:                if (emergencyReserve != null) {
1538:                    sizeAvailable = emergencyReserve.length();
1539:                    long newLength = sizeAvailable / 4;
1540:                    if (newLength < SysProperties.EMERGENCY_SPACE_MIN) {
1541:                        newLength = 0;
1542:                        noDiskSpace = true;
1543:                    }
1544:                    emergencyReserve.setLength(newLength);
1545:                }
1546:                if (eventListener != null) {
1547:                    eventListener.diskSpaceIsLow(sizeAvailable);
1548:                }
1549:            }
1550:
1551:            /**
1552:             * Set the progress of a long running operation.
1553:             * This method calls the {@link DatabaseEventListener} if one is registered.
1554:             * 
1555:             * @param state the {@link DatabaseEventListener} state
1556:             * @param name the object name
1557:             * @param x the current position
1558:             * @param max the highest value
1559:             */
1560:
1561:            public void setProgress(int state, String name, int x, int max) {
1562:                if (eventListener != null) {
1563:                    try {
1564:                        eventListener.setProgress(state, name, x, max);
1565:                    } catch (Exception e2) {
1566:                        // ignore this second (user made) exception
1567:                    }
1568:                }
1569:            }
1570:
1571:            public void exceptionThrown(SQLException e, String sql) {
1572:                if (eventListener != null) {
1573:                    try {
1574:                        eventListener.exceptionThrown(e, sql);
1575:                    } catch (Exception e2) {
1576:                        // ignore this second (user made) exception
1577:                    }
1578:                }
1579:            }
1580:
1581:            public void sync() throws SQLException {
1582:                if (log != null) {
1583:                    log.sync();
1584:                }
1585:                if (fileData != null) {
1586:                    fileData.sync();
1587:                }
1588:                if (fileIndex != null) {
1589:                    fileIndex.sync();
1590:                }
1591:            }
1592:
1593:            public int getMaxMemoryRows() {
1594:                return maxMemoryRows;
1595:            }
1596:
1597:            public void setMaxMemoryRows(int value) {
1598:                this .maxMemoryRows = value;
1599:            }
1600:
1601:            public void setMaxMemoryUndo(int value) {
1602:                this .maxMemoryUndo = value;
1603:            }
1604:
1605:            public int getMaxMemoryUndo() {
1606:                return maxMemoryUndo;
1607:            }
1608:
1609:            public int getChecksum(byte[] data, int start, int end) {
1610:                int x = 0;
1611:                while (start < end) {
1612:                    x += data[start++];
1613:                }
1614:                return x;
1615:            }
1616:
1617:            public void setLockMode(int lockMode) {
1618:                this .lockMode = lockMode;
1619:            }
1620:
1621:            public int getLockMode() {
1622:                return lockMode;
1623:            }
1624:
1625:            public synchronized void setCloseDelay(int value) {
1626:                this .closeDelay = value;
1627:            }
1628:
1629:            public boolean getLogIndexChanges() {
1630:                return logIndexChanges;
1631:            }
1632:
1633:            public synchronized void setLog(int level) throws SQLException {
1634:                if (logLevel == level) {
1635:                    return;
1636:                }
1637:                boolean logData;
1638:                boolean logIndex;
1639:                switch (level) {
1640:                case 0:
1641:                    logData = false;
1642:                    logIndex = false;
1643:                    break;
1644:                case 1:
1645:                    logData = true;
1646:                    logIndex = false;
1647:                    break;
1648:                case 2:
1649:                    logData = true;
1650:                    logIndex = true;
1651:                    break;
1652:                default:
1653:                    throw Message.getInternalError("level=" + level);
1654:                }
1655:                if (fileIndex != null) {
1656:                    fileIndex.setLogChanges(logIndex);
1657:                }
1658:                if (log != null) {
1659:                    log.setDisabled(!logData);
1660:                    log.checkpoint();
1661:                }
1662:                traceSystem.getTrace(Trace.DATABASE).error("SET LOG " + level,
1663:                        null);
1664:                logLevel = level;
1665:            }
1666:
1667:            public ObjectArray getAllStorages() {
1668:                return new ObjectArray(storageMap.values());
1669:            }
1670:
1671:            public boolean getRecovery() {
1672:                return recovery;
1673:            }
1674:
1675:            public Session getSystemSession() {
1676:                return systemSession;
1677:            }
1678:
1679:            public String getDatabasePath() {
1680:                if (persistent) {
1681:                    return FileUtils.getAbsolutePath(databaseName);
1682:                } else {
1683:                    return null;
1684:                }
1685:            }
1686:
1687:            public void handleInvalidChecksum() throws SQLException {
1688:                SQLException e = Message.getSQLException(
1689:                        ErrorCode.FILE_CORRUPTED_1, "wrong checksum");
1690:                if (!recovery) {
1691:                    throw e;
1692:                } else {
1693:                    traceSystem.getTrace(Trace.DATABASE).error("recover", e);
1694:                }
1695:            }
1696:
1697:            public boolean isClosing() {
1698:                return closing;
1699:            }
1700:
1701:            public int getWriteDelay() {
1702:                return writeDelay;
1703:            }
1704:
1705:            public int getCacheSize() {
1706:                return cacheSize;
1707:            }
1708:
1709:            public void setMaxLengthInplaceLob(int value) {
1710:                this .maxLengthInplaceLob = value;
1711:            }
1712:
1713:            public int getMaxLengthInplaceLob() {
1714:                return maxLengthInplaceLob;
1715:            }
1716:
1717:            public void setIgnoreCase(boolean b) {
1718:                ignoreCase = b;
1719:            }
1720:
1721:            public boolean getIgnoreCase() {
1722:                if (starting) {
1723:                    // tables created at startup must not be converted to ignorecase
1724:                    return false;
1725:                }
1726:                return ignoreCase;
1727:            }
1728:
1729:            public synchronized void setDeleteFilesOnDisconnect(boolean b) {
1730:                this .deleteFilesOnDisconnect = b;
1731:            }
1732:
1733:            public String getLobCompressionAlgorithm(int type) {
1734:                return lobCompressionAlgorithm;
1735:            }
1736:
1737:            public void setLobCompressionAlgorithm(String stringValue) {
1738:                this .lobCompressionAlgorithm = stringValue;
1739:            }
1740:
1741:            public void notifyFileSize(long length) {
1742:                if (length > biggestFileSize) {
1743:                    biggestFileSize = length;
1744:                    setMaxLogSize(0);
1745:                }
1746:            }
1747:
1748:            public synchronized void setMaxLogSize(long value) {
1749:                long minLogSize = biggestFileSize / Constants.LOG_SIZE_DIVIDER;
1750:                minLogSize = Math.max(value, minLogSize);
1751:                long currentLogSize = getLog().getMaxLogSize();
1752:                if (minLogSize > currentLogSize
1753:                        || (value > 0 && minLogSize > value)) {
1754:                    // works for currentLogSize <= 0 as well
1755:                    value = minLogSize;
1756:                }
1757:                if (value > 0) {
1758:                    getLog().setMaxLogSize(value);
1759:                }
1760:            }
1761:
1762:            public void setAllowLiterals(int value) {
1763:                this .allowLiterals = value;
1764:            }
1765:
1766:            public int getAllowLiterals() {
1767:                if (starting) {
1768:                    return Constants.ALLOW_LITERALS_ALL;
1769:                }
1770:                return allowLiterals;
1771:            }
1772:
1773:            public boolean getOptimizeReuseResults() {
1774:                return optimizeReuseResults;
1775:            }
1776:
1777:            public void setOptimizeReuseResults(boolean b) {
1778:                optimizeReuseResults = b;
1779:            }
1780:
1781:            public String getCacheType() {
1782:                return cacheType;
1783:            }
1784:
1785:            public void invalidateIndexSummary() throws SQLException {
1786:                if (indexSummaryValid) {
1787:                    indexSummaryValid = false;
1788:                    log.invalidateIndexSummary();
1789:                }
1790:            }
1791:
1792:            public boolean getIndexSummaryValid() {
1793:                return indexSummaryValid;
1794:            }
1795:
1796:            public Object getLobSyncObject() {
1797:                return lobSyncObject;
1798:            }
1799:
1800:            public int getSessionCount() {
1801:                return sessions.size();
1802:            }
1803:
1804:            public void setReferentialIntegrity(boolean b) {
1805:                referentialIntegrity = b;
1806:            }
1807:
1808:            public boolean getReferentialIntegrity() {
1809:                return referentialIntegrity;
1810:            }
1811:
1812:            public boolean isStarting() {
1813:                return starting;
1814:            }
1815:
1816:            public boolean isMultiVersion() {
1817:                return multiVersion;
1818:            }
1819:
1820:            public void opened() throws SQLException {
1821:                if (eventListener != null) {
1822:                    eventListener.opened();
1823:                }
1824:            }
1825:
1826:            public void setMode(Mode mode) {
1827:                this .mode = mode;
1828:            }
1829:
1830:            public Mode getMode() {
1831:                return mode;
1832:            }
1833:
1834:            public boolean getMultiThreaded() {
1835:                return multiThreaded;
1836:            }
1837:
1838:            public void setMultiThreaded(boolean multiThreaded) {
1839:                this .multiThreaded = multiThreaded;
1840:            }
1841:
1842:            public void setMaxOperationMemory(int maxOperationMemory) {
1843:                this .maxOperationMemory = maxOperationMemory;
1844:            }
1845:
1846:            public int getMaxOperationMemory() {
1847:                return maxOperationMemory;
1848:            }
1849:
1850:            public Session getExclusiveSession() {
1851:                return exclusiveSession;
1852:            }
1853:
1854:            public void setExclusiveSession(Session session) {
1855:                this .exclusiveSession = session;
1856:            }
1857:
1858:            public boolean getLobFilesInDirectories() {
1859:                return lobFilesInDirectories;
1860:            }
1861:
1862:            public SmallLRUCache getLobFileListCache() {
1863:                return lobFileListCache;
1864:            }
1865:
1866:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.