Source Code Cross Referenced for TransactionSystem.java in  » Database-DBMS » mckoi » com » mckoi » database » 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 » mckoi » com.mckoi.database 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * com.mckoi.database.TransactionSystem  24 Mar 2002
0003:         *
0004:         * Mckoi SQL Database ( http://www.mckoi.com/database )
0005:         * Copyright (C) 2000, 2001, 2002  Diehl and Associates, Inc.
0006:         *
0007:         * This program is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU General Public License
0009:         * Version 2 as published by the Free Software Foundation.
0010:         *
0011:         * This program is distributed in the hope that it will be useful,
0012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014:         * GNU General Public License Version 2 for more details.
0015:         *
0016:         * You should have received a copy of the GNU General Public License
0017:         * Version 2 along with this program; if not, write to the Free Software
0018:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
0019:         *
0020:         * Change Log:
0021:         * 
0022:         * 
0023:         */package com.mckoi.database;
0024:
0025:        import com.mckoi.store.LoggingBufferManager;
0026:        import com.mckoi.util.Stats;
0027:        import com.mckoi.util.StringUtil;
0028:        import com.mckoi.util.LogWriter;
0029:        import com.mckoi.debug.*;
0030:        import com.mckoi.database.control.DBConfig;
0031:        import java.io.File;
0032:        import java.io.IOException;
0033:        import java.io.PrintWriter;
0034:        import java.io.Writer;
0035:        import java.util.Date;
0036:        import java.util.List;
0037:        import java.util.ArrayList;
0038:        import java.util.Properties;
0039:
0040:        /**
0041:         * A class that provides information and global functions for the transaction
0042:         * layer in the engine.  Shared information includes configuration details,
0043:         * logging, etc.
0044:         *
0045:         * @author Tobias Downer
0046:         */
0047:
0048:        public class TransactionSystem {
0049:
0050:            /**
0051:             * The stats object that keeps track of database statistics.
0052:             */
0053:            private final Stats stats = new Stats();
0054:
0055:            /**
0056:             * A logger to output any debugging messages.
0057:             * NOTE: This MUST be final, because other objects may retain a reference
0058:             *   to the object.  If it is not final, then different objects will be
0059:             *   logging to different places if this reference is changed.
0060:             */
0061:            private final DefaultDebugLogger logger;
0062:
0063:            /**
0064:             * The ResourceBundle that contains properties of the entire database
0065:             * system.
0066:             */
0067:            private DBConfig config = null;
0068:
0069:            /**
0070:             * The path in the file system for the database files.  Note that this will
0071:             * be null if the database does not exist in a local file system.  For this
0072:             * reason it's best not to write code that relies on the use of this value.
0073:             */
0074:            private File db_path;
0075:
0076:            /**
0077:             * Set to true if lookup comparison lists are enabled.
0078:             */
0079:            private boolean lookup_comparison_list_enabled = false;
0080:
0081:            /**
0082:             * Set to true if the database is in read only mode.  This is set from the
0083:             * configuration file.
0084:             */
0085:            private boolean read_only_access = false;
0086:
0087:            /**
0088:             * Set to true if locking checks should be performed each time a table is
0089:             * accessed.
0090:             */
0091:            private boolean table_lock_check = false;
0092:
0093:            /**
0094:             * Set to false if there is conservative index memory storage.  If true,
0095:             * all root selectable schemes are stored behind a soft reference that will
0096:             * be garbage collected.
0097:             */
0098:            private boolean soft_index_storage = false;
0099:
0100:            /**
0101:             * If this is set to true, during boot up the engine will reindex all the
0102:             * tables that weren't closed.  If false, the engine will only reindex the
0103:             * tables that have unchecked in modifications.
0104:             */
0105:            private boolean always_reindex_dirty_tables = false;
0106:
0107:            /**
0108:             * Set to true if the file handles should NOT be synchronized with the
0109:             * system file IO when the indices are written.  If this is true, then the
0110:             * database is not as fail safe, however File IO performance is improved.
0111:             */
0112:            private boolean dont_synch_filesystem = false;
0113:
0114:            /**
0115:             * Set to true if the parser should ignore case when searching for a schema,
0116:             * table or column using an identifier.
0117:             */
0118:            private boolean ignore_case_for_identifiers = false;
0119:
0120:            /**
0121:             * Transaction option, if this is true then a transaction error is generated
0122:             * during commit if a transaction selects data from a table that has
0123:             * committed changes to it during commit time.
0124:             * <p>
0125:             * True by default.
0126:             */
0127:            private boolean transaction_error_on_dirty_select = true;
0128:
0129:            /**
0130:             * The DataCellCache that is a shared resource between on database's.
0131:             */
0132:            private DataCellCache data_cell_cache = null;
0133:
0134:            /**
0135:             * The list of FunctionFactory objects that handle different functions from
0136:             * SQL.
0137:             */
0138:            private ArrayList function_factory_list;
0139:
0140:            /**
0141:             * The FunctionLookup object that can resolve a FunctionDef object to a
0142:             * Function object.
0143:             */
0144:            private DSFunctionLookup function_lookup;
0145:
0146:            /**
0147:             * The regular expression library bridge for the library we are configured
0148:             * to use.
0149:             */
0150:            private RegexLibrary regex_library;
0151:
0152:            /**
0153:             * The log directory.
0154:             */
0155:            private File log_directory;
0156:
0157:            /**
0158:             * A LoggingBufferManager object used to manage pages of ScatteringFileStore
0159:             * objects in the file system.  We can configure the maximum pages and page
0160:             * size via this object, so we have control over how much memory from the
0161:             * heap is used for buffering.
0162:             */
0163:            private LoggingBufferManager buffer_manager;
0164:
0165:            /**
0166:             * The underlying StoreSystem implementation that encapsulates the behaviour
0167:             * for storing data persistantly.
0168:             */
0169:            private StoreSystem store_system;
0170:
0171:            // ---------- Low level row listeners ----------
0172:
0173:            /**
0174:             * A list of table names and listeners that are notified of add and remove
0175:             * events in a table.
0176:             */
0177:            private ArrayList table_listeners;
0178:
0179:            /**
0180:             * Constructor.
0181:             */
0182:            public TransactionSystem() {
0183:                // Setup generate properties from the JVM.
0184:                logger = new DefaultDebugLogger();
0185:                Properties p = System.getProperties();
0186:                stats.set(0, "Runtime.java.version: "
0187:                        + p.getProperty("java.version"));
0188:                stats.set(0, "Runtime.java.vendor: "
0189:                        + p.getProperty("java.vendor"));
0190:                stats.set(0, "Runtime.java.vm.name: "
0191:                        + p.getProperty("java.vm.name"));
0192:                stats.set(0, "Runtime.os.name: " + p.getProperty("os.name"));
0193:                stats.set(0, "Runtime.os.arch: " + p.getProperty("os.arch"));
0194:                stats.set(0, "Runtime.os.version: "
0195:                        + p.getProperty("os.version"));
0196:                table_listeners = new ArrayList();
0197:            }
0198:
0199:            /**
0200:             * Parses a file string to an absolute position in the file system.  We must
0201:             * provide the path to the root directory (eg. the directory where the
0202:             * config bundle is located).
0203:             */
0204:            private static File parseFileString(File root_path,
0205:                    String root_info, String path_string) {
0206:                File path = new File(path_string);
0207:                File res;
0208:                // If the path is absolute then return the absoluate reference
0209:                if (path.isAbsolute()) {
0210:                    res = path;
0211:                } else {
0212:                    // If the root path source is the jvm then just return the path.
0213:                    if (root_info != null && root_info.equals("jvm")) {
0214:                        return path;
0215:                    }
0216:                    // If the root path source is the configuration file then
0217:                    // concat the configuration path with the path string and return it.
0218:                    else {
0219:                        res = new File(root_path, path_string);
0220:                    }
0221:                }
0222:                return res;
0223:            }
0224:
0225:            /**
0226:             * Sets up the log file from the config information.
0227:             */
0228:            private void setupLog(DBConfig config) {
0229:                String log_path_string = config.getValue("log_path");
0230:                String root_path_var = config.getValue("root_path");
0231:                String read_only_access = config.getValue("read_only");
0232:                String debug_logs = config.getValue("debug_logs");
0233:                boolean read_only_bool = false;
0234:                if (read_only_access != null) {
0235:                    read_only_bool = read_only_access
0236:                            .equalsIgnoreCase("enabled");
0237:                }
0238:                boolean debug_logs_bool = true;
0239:                if (debug_logs != null) {
0240:                    debug_logs_bool = debug_logs.equalsIgnoreCase("enabled");
0241:                }
0242:
0243:                // Conditions for not initializing a log directory;
0244:                //  1. read only access is enabled
0245:                //  2. log_path is empty or not set
0246:
0247:                if (debug_logs_bool && !read_only_bool
0248:                        && log_path_string != null
0249:                        && !log_path_string.equals("")) {
0250:                    // First set up the debug information in this VM for the 'Debug' class.
0251:                    File log_path = parseFileString(config.currentPath(),
0252:                            root_path_var, log_path_string);
0253:                    // If the path doesn't exist the make it.
0254:                    if (!log_path.exists()) {
0255:                        log_path.mkdirs();
0256:                    }
0257:                    // Set the log directory in the DatabaseSystem
0258:                    setLogDirectory(log_path);
0259:
0260:                    LogWriter f_writer;
0261:                    File debug_log_file;
0262:                    String dlog_file_name = "";
0263:                    try {
0264:                        dlog_file_name = config.getValue("debug_log_file");
0265:                        debug_log_file = new File(log_path.getCanonicalPath(),
0266:                                dlog_file_name);
0267:
0268:                        // Allow log size to grow to 512k and allow 12 archives of the log
0269:                        f_writer = new LogWriter(debug_log_file, 512 * 1024, 12);
0270:                        f_writer.write("**** Debug log started: "
0271:                                + new Date(System.currentTimeMillis())
0272:                                + " ****\n");
0273:                        f_writer.flush();
0274:                    } catch (IOException e) {
0275:                        throw new RuntimeException(
0276:                                "Unable to open debug file '" + dlog_file_name
0277:                                        + "' in path '" + log_path + "'");
0278:                    }
0279:                    setDebugOutput(f_writer);
0280:                }
0281:
0282:                // If 'debug_logs=disabled', don't write out any debug logs
0283:                if (!debug_logs_bool) {
0284:                    // Otherwise set it up so the output from the logs goes to a PrintWriter
0285:                    // that doesn't do anything.  Basically - this means all log information
0286:                    // will get sent into a black hole.
0287:                    setDebugOutput(new PrintWriter(new Writer() {
0288:                        public void write(int c) throws IOException {
0289:                        }
0290:
0291:                        public void write(char cbuf[], int off, int len)
0292:                                throws IOException {
0293:                        }
0294:
0295:                        public void write(String str, int off, int len)
0296:                                throws IOException {
0297:                        }
0298:
0299:                        public void flush() throws IOException {
0300:                        }
0301:
0302:                        public void close() throws IOException {
0303:                        }
0304:                    }));
0305:                }
0306:
0307:                int debug_level = Integer.parseInt(config
0308:                        .getValue("debug_level"));
0309:                if (debug_level == -1) {
0310:                    setDebugLevel(255);
0311:                } else {
0312:                    setDebugLevel(debug_level);
0313:                }
0314:            }
0315:
0316:            /**
0317:             * Returns a configuration value, or the default if it's not found.
0318:             */
0319:            public final String getConfigString(String property,
0320:                    String default_val) {
0321:                String v = config.getValue(property);
0322:                if (v == null) {
0323:                    return default_val;
0324:                }
0325:                return v.trim();
0326:            }
0327:
0328:            /**
0329:             * Returns a configuration value, or the default if it's not found.
0330:             */
0331:            public final int getConfigInt(String property, int default_val) {
0332:                String v = config.getValue(property);
0333:                if (v == null) {
0334:                    return default_val;
0335:                }
0336:                return Integer.parseInt(v);
0337:            }
0338:
0339:            /**
0340:             * Returns a configuration value, or the default if it's not found.
0341:             */
0342:            public final boolean getConfigBoolean(String property,
0343:                    boolean default_val) {
0344:                String v = config.getValue(property);
0345:                if (v == null) {
0346:                    return default_val;
0347:                }
0348:                return v.trim().equalsIgnoreCase("enabled");
0349:            }
0350:
0351:            /**
0352:             * Given a regular expression string representing a particular library, this
0353:             * will return the name of the class to use as a bridge between the library
0354:             * and Mckoi.  Returns null if the library name is invalid.
0355:             */
0356:            private static String regexStringToClass(String lib) {
0357:                if (lib.equals("java.util.regexp")) {
0358:                    return "com.mckoi.database.regexbridge.JavaRegex";
0359:                } else if (lib.equals("org.apache.regexp")) {
0360:                    return "com.mckoi.database.regexbridge.ApacheRegex";
0361:                } else if (lib.equals("gnu.regexp")) {
0362:                    return "com.mckoi.database.regexbridge.GNURegex";
0363:                } else {
0364:                    return null;
0365:                }
0366:            }
0367:
0368:            /**
0369:             * Inits the TransactionSystem with the configuration properties of the
0370:             * system.
0371:             * This can only be called once, and should be called at database boot time.
0372:             */
0373:            public void init(DBConfig config) {
0374:
0375:                function_factory_list = new ArrayList();
0376:                function_lookup = new DSFunctionLookup();
0377:
0378:                if (config != null) {
0379:                    this .config = config;
0380:
0381:                    // Set the read_only property
0382:                    read_only_access = getConfigBoolean("read_only", false);
0383:
0384:                    // Setup the log
0385:                    setupLog(config);
0386:
0387:                    // The storage encapsulation that has been configured.
0388:                    String storage_system = getConfigString("storage_system",
0389:                            "v1file");
0390:
0391:                    boolean is_file_store_mode;
0392:
0393:                    // Construct the system store.
0394:                    if (storage_system.equalsIgnoreCase("v1file")) {
0395:                        Debug().write(Lvl.MESSAGE, this ,
0396:                                "Storage System: v1 file storage mode.");
0397:
0398:                        // The path where the database data files are stored.
0399:                        String database_path = getConfigString("database_path",
0400:                                "./data");
0401:                        // The root path variable
0402:                        String root_path_var = getConfigString("root_path",
0403:                                "jvm");
0404:
0405:                        // Set the absolute database path
0406:                        db_path = parseFileString(config.currentPath(),
0407:                                root_path_var, database_path);
0408:
0409:                        store_system = new V1FileStoreSystem(this , db_path,
0410:                                read_only_access);
0411:                        is_file_store_mode = true;
0412:                    }
0413:
0414:                    else if (storage_system.equalsIgnoreCase("v1javaheap")) {
0415:                        Debug().write(Lvl.MESSAGE, this ,
0416:                                "Storage System: v1 Java heap storage mode.");
0417:                        store_system = new V1HeapStoreSystem();
0418:                        is_file_store_mode = false;
0419:                    }
0420:
0421:                    else {
0422:                        String error_msg = "Unknown storage_system property: "
0423:                                + storage_system;
0424:                        Debug().write(Lvl.ERROR, this , error_msg);
0425:                        throw new RuntimeException(error_msg);
0426:                    }
0427:
0428:                    // Register the internal function factory,
0429:                    addFunctionFactory(new InternalFunctionFactory());
0430:
0431:                    String status;
0432:
0433:                    // Set up the DataCellCache from the values in the configuration
0434:                    int max_cache_size = 0, max_cache_entry_size = 0;
0435:
0436:                    max_cache_size = getConfigInt("data_cache_size", 0);
0437:                    max_cache_entry_size = getConfigInt("max_cache_entry_size",
0438:                            0);
0439:
0440:                    if (max_cache_size >= 4096 && max_cache_entry_size >= 16
0441:                            && max_cache_entry_size < (max_cache_size / 2)) {
0442:
0443:                        Debug().write(
0444:                                Lvl.MESSAGE,
0445:                                this ,
0446:                                "Internal Data Cache size:          "
0447:                                        + max_cache_size);
0448:                        Debug().write(
0449:                                Lvl.MESSAGE,
0450:                                this ,
0451:                                "Internal Data Cache max cell size: "
0452:                                        + max_cache_entry_size);
0453:
0454:                        // Find a prime hash size depending on the size of the cache.
0455:                        int hash_size = DataCellCache
0456:                                .closestPrime(max_cache_size / 55);
0457:
0458:                        // Set up the data_cell_cache
0459:                        data_cell_cache = new DataCellCache(this ,
0460:                                max_cache_size, max_cache_entry_size, hash_size);
0461:
0462:                    } else {
0463:                        Debug().write(Lvl.MESSAGE, this ,
0464:                                "Internal Data Cache disabled.");
0465:                    }
0466:
0467:                    // Are lookup comparison lists enabled?
0468:                    //      lookup_comparison_list_enabled =
0469:                    //                            getConfigBoolean("lookup_comparison_list", false);
0470:                    lookup_comparison_list_enabled = false;
0471:                    Debug().write(
0472:                            Lvl.MESSAGE,
0473:                            this ,
0474:                            "lookup_comparison_list = "
0475:                                    + lookup_comparison_list_enabled);
0476:
0477:                    // Should we open the database in read only mode?
0478:                    Debug().write(Lvl.MESSAGE, this ,
0479:                            "read_only = " + read_only_access);
0480:                    if (read_only_access)
0481:                        stats.set(1, "DatabaseSystem.read_only");
0482:
0483:                    //      // Hard Sync file system whenever we update index files?
0484:                    //      if (is_file_store_mode) {
0485:                    //        dont_synch_filesystem = getConfigBoolean("dont_synch_filesystem", false);
0486:                    //        Debug().write(Lvl.MESSAGE, this,
0487:                    //                      "dont_synch_filesystem = " + dont_synch_filesystem);
0488:                    //      }
0489:
0490:                    // Generate transaction error if dirty selects are detected?
0491:                    transaction_error_on_dirty_select = getConfigBoolean(
0492:                            "transaction_error_on_dirty_select", true);
0493:                    Debug().write(
0494:                            Lvl.MESSAGE,
0495:                            this ,
0496:                            "transaction_error_on_dirty_select = "
0497:                                    + transaction_error_on_dirty_select);
0498:
0499:                    // Case insensitive identifiers?
0500:                    ignore_case_for_identifiers = getConfigBoolean(
0501:                            "ignore_case_for_identifiers", false);
0502:                    Debug().write(
0503:                            Lvl.MESSAGE,
0504:                            this ,
0505:                            "ignore_case_for_identifiers = "
0506:                                    + ignore_case_for_identifiers);
0507:
0508:                    // ---- Store system setup ----
0509:
0510:                    // See if this JVM supports the java.nio interface
0511:                    // (first introduced in 1.4)
0512:                    if (is_file_store_mode) {
0513:                        boolean nio_interface_available;
0514:                        try {
0515:                            Class.forName("java.nio.channels.FileChannel");
0516:                            nio_interface_available = true;
0517:                            Debug().write(Lvl.MESSAGE, this ,
0518:                                    "Java NIO API is available.");
0519:                        } catch (ClassNotFoundException e) {
0520:                            nio_interface_available = false;
0521:                            Debug().write(Lvl.MESSAGE, this ,
0522:                                    "Java NIO API is not available.");
0523:                        }
0524:
0525:                        // Bug workaround - there are problems with memory mapped NIO under 95/98
0526:                        //   which we workaround by disabling NIO support on 95/98.
0527:                        boolean nio_bugged_os;
0528:                        String os_name = System.getProperties().getProperty(
0529:                                "os.name");
0530:                        nio_bugged_os = (os_name.equalsIgnoreCase("Windows 95") || os_name
0531:                                .equalsIgnoreCase("Windows 98"));
0532:
0533:                        // Get the safety level of the file system where 10 is the most safe
0534:                        // and 1 is the least safe.
0535:                        int io_safety_level = getConfigInt("io_safety_level",
0536:                                10);
0537:                        if (io_safety_level < 1 || io_safety_level > 10) {
0538:                            Debug()
0539:                                    .write(Lvl.MESSAGE, this ,
0540:                                            "Invalid io_safety_level value.  Setting to the most safe level.");
0541:                            io_safety_level = 10;
0542:                        }
0543:                        Debug().write(Lvl.MESSAGE, this ,
0544:                                "io_safety_level = " + io_safety_level);
0545:
0546:                        // Logging is disabled when safety level is less or equal to 2
0547:                        boolean enable_logging = true;
0548:                        if (io_safety_level <= 2) {
0549:                            Debug().write(Lvl.MESSAGE, this ,
0550:                                    "Disabling journaling and file sync.");
0551:                            enable_logging = false;
0552:                        }
0553:
0554:                        // If the configuration property 'use_nio_if_available' is enabled then
0555:                        // we setup a LoggingBufferManager that uses NIO (default to 'false')
0556:                        boolean use_nio_if_available = getConfigBoolean(
0557:                                "use_nio_if_available", false);
0558:                        boolean force_use_nio = getConfigBoolean(
0559:                                "force_use_nio", false);
0560:
0561:                        String api_to_use;
0562:                        int page_size;
0563:                        int max_pages;
0564:
0565:                        final boolean disable_nio = true;
0566:
0567:                        // If NIO interface available and configuration tells us to use NIO and
0568:                        // we are not running on an OS where NIO is buggy, we set the NIO options
0569:                        // here.
0570:                        if (!disable_nio
0571:                                && (force_use_nio || (nio_interface_available
0572:                                        && use_nio_if_available && !nio_bugged_os))) {
0573:                            Debug()
0574:                                    .write(Lvl.MESSAGE, this ,
0575:                                            "Using NIO API for OS memory mapped file access.");
0576:                            page_size = getConfigInt("buffered_nio_page_size",
0577:                                    1024 * 1024);
0578:                            max_pages = getConfigInt("buffered_nio_max_pages",
0579:                                    64);
0580:                            api_to_use = "Java NIO";
0581:                        } else {
0582:                            Debug()
0583:                                    .write(Lvl.MESSAGE, this ,
0584:                                            "Using stardard IO API for heap buffered file access.");
0585:                            page_size = getConfigInt("buffered_io_page_size",
0586:                                    8192);
0587:                            max_pages = getConfigInt("buffered_io_max_pages",
0588:                                    256);
0589:                            api_to_use = "Java IO";
0590:                        }
0591:
0592:                        // Output this information to the log
0593:                        Debug().write(Lvl.MESSAGE, this ,
0594:                                "[Buffer Manager] Using IO API: " + api_to_use);
0595:                        Debug().write(Lvl.MESSAGE, this ,
0596:                                "[Buffer Manager] Page Size: " + page_size);
0597:                        Debug().write(Lvl.MESSAGE, this ,
0598:                                "[Buffer Manager] Max pages: " + max_pages);
0599:
0600:                        // Journal path is currently always the same as database path.
0601:                        final File journal_path = db_path;
0602:                        // Max slice size is 1 GB for file scattering class
0603:                        final long max_slice_size = 16384 * 65536;
0604:                        // First file extention is 'koi'
0605:                        final String first_file_ext = "koi";
0606:
0607:                        // Set up the BufferManager
0608:                        buffer_manager = new LoggingBufferManager(db_path,
0609:                                journal_path, read_only_access, max_pages,
0610:                                page_size, first_file_ext, max_slice_size,
0611:                                Debug(), enable_logging);
0612:                        // ^ This is a big constructor.  It sets up the logging manager and
0613:                        //   sets a resource store data accessor converter to a scattering
0614:                        //   implementation with a max slice size of 1 GB
0615:
0616:                        // Start the buffer manager.
0617:                        try {
0618:                            buffer_manager.start();
0619:                        } catch (IOException e) {
0620:                            Debug().write(Lvl.ERROR, this ,
0621:                                    "Error starting buffer manager");
0622:                            Debug().writeException(Lvl.ERROR, e);
0623:                            throw new Error("IO Error: " + e.getMessage());
0624:                        }
0625:
0626:                    }
0627:
0628:                    // What regular expression library are we using?
0629:                    // If we want the engine to support other regular expression libraries
0630:                    // then include the additional entries here.
0631:
0632:                    // Test to see if the regex API exists
0633:                    boolean regex_api_exists;
0634:                    try {
0635:                        Class.forName("java.util.regex.Pattern");
0636:                        regex_api_exists = true;
0637:                    } catch (ClassNotFoundException e) {
0638:                        // Internal API doesn't exist
0639:                        regex_api_exists = false;
0640:                        Debug().write(Lvl.MESSAGE, this ,
0641:                                "Java regex API not available.");
0642:                    }
0643:
0644:                    String regex_bridge;
0645:                    String lib_used;
0646:
0647:                    String force_lib = getConfigString("force_regex_library",
0648:                            null);
0649:
0650:                    // Are we forcing a particular regular expression library?
0651:                    if (force_lib != null) {
0652:                        lib_used = force_lib;
0653:                        // Convert the library string to a class name
0654:                        regex_bridge = regexStringToClass(force_lib);
0655:                    } else {
0656:                        String lib = getConfigString("regex_library", null);
0657:                        lib_used = lib;
0658:                        // Use the standard Java 1.4 regular expression library if it is found.
0659:                        if (regex_api_exists) {
0660:                            regex_bridge = "com.mckoi.database.regexbridge.JavaRegex";
0661:                        } else if (lib != null) {
0662:                            // Convert the library string to a class name
0663:                            regex_bridge = regexStringToClass(lib);
0664:                        } else {
0665:                            regex_bridge = null;
0666:                        }
0667:                    }
0668:
0669:                    if (regex_bridge != null) {
0670:                        try {
0671:                            Class c = Class.forName(regex_bridge);
0672:                            regex_library = (RegexLibrary) c.newInstance();
0673:                            Debug().write(Lvl.MESSAGE, this ,
0674:                                    "Using regex bridge: " + lib_used);
0675:                        } catch (Throwable e) {
0676:                            Debug().write(
0677:                                    Lvl.ERROR,
0678:                                    this ,
0679:                                    "Unable to load regex bridge: "
0680:                                            + regex_bridge);
0681:                            Debug().writeException(Lvl.WARNING, e);
0682:                        }
0683:                    } else {
0684:                        if (lib_used != null) {
0685:                            Debug().write(Lvl.ERROR, this ,
0686:                                    "Regex library not known: " + lib_used);
0687:                        }
0688:                        Debug().write(Lvl.MESSAGE, this ,
0689:                                "Regex features disabled.");
0690:                    }
0691:
0692:                    // ---------- Plug ins ---------
0693:
0694:                    try {
0695:                        // The 'function_factories' property.
0696:                        String function_factories = getConfigString(
0697:                                "function_factories", null);
0698:                        if (function_factories != null) {
0699:                            List factories = StringUtil.explode(
0700:                                    function_factories, ";");
0701:                            for (int i = 0; i < factories.size(); ++i) {
0702:                                String factory_class = factories.get(i)
0703:                                        .toString();
0704:                                Class c = Class.forName(factory_class);
0705:                                FunctionFactory fun_factory = (FunctionFactory) c
0706:                                        .newInstance();
0707:                                addFunctionFactory(fun_factory);
0708:                                Debug().write(
0709:                                        Lvl.MESSAGE,
0710:                                        this ,
0711:                                        "Successfully added function factory: "
0712:                                                + factory_class);
0713:                            }
0714:                        } else {
0715:                            Debug()
0716:                                    .write(Lvl.MESSAGE, this ,
0717:                                            "No 'function_factories' config property found.");
0718:                            // If resource missing, do nothing...
0719:                        }
0720:                    } catch (Throwable e) {
0721:                        Debug()
0722:                                .write(Lvl.ERROR, this ,
0723:                                        "Error parsing 'function_factories' configuration property.");
0724:                        Debug().writeException(e);
0725:                    }
0726:
0727:                    // Flush the contents of the function lookup object.
0728:                    flushCachedFunctionLookup();
0729:
0730:                }
0731:
0732:            }
0733:
0734:            /**
0735:             * Hack - set up the DataCellCache in DatabaseSystem so we can use the
0736:             * MasterTableDataSource object without having to boot a new DatabaseSystem.
0737:             */
0738:            public void setupRowCache(int max_cache_size,
0739:                    int max_cache_entry_size) {
0740:                // Set up the data_cell_cache
0741:                data_cell_cache = new DataCellCache(this , max_cache_size,
0742:                        max_cache_entry_size);
0743:            }
0744:
0745:            /**
0746:             * Returns true if the database is in read only mode.  In read only mode,
0747:             * any 'write' operations are not permitted.
0748:             */
0749:            public boolean readOnlyAccess() {
0750:                return read_only_access;
0751:            }
0752:
0753:            /**
0754:             * Returns the path of the database in the local file system if the database
0755:             * exists within the local file system.  If the database is not within the
0756:             * local file system then null is returned.  It is recommended this method
0757:             * is not used unless for legacy or compatability purposes.
0758:             */
0759:            public File getDatabasePath() {
0760:                return db_path;
0761:            }
0762:
0763:            /**
0764:             * Returns true if the database should perform checking of table locks.
0765:             */
0766:            public boolean tableLockingEnabled() {
0767:                return table_lock_check;
0768:            }
0769:
0770:            /**
0771:             * Returns true if we should generate lookup caches in InsertSearch otherwise
0772:             * returns false.
0773:             */
0774:            public boolean lookupComparisonListEnabled() {
0775:                return lookup_comparison_list_enabled;
0776:            }
0777:
0778:            /**
0779:             * Returns true if all table indices are kept behind a soft reference that
0780:             * can be garbage collected.
0781:             */
0782:            public boolean softIndexStorage() {
0783:                return soft_index_storage;
0784:            }
0785:
0786:            /**
0787:             * Returns the status of the 'always_reindex_dirty_tables' property.
0788:             */
0789:            public boolean alwaysReindexDirtyTables() {
0790:                return always_reindex_dirty_tables;
0791:            }
0792:
0793:            /**
0794:             * Returns true if we shouldn't synchronize with the file system when
0795:             * important indexing information is flushed to the disk.
0796:             */
0797:            public boolean dontSynchFileSystem() {
0798:                return dont_synch_filesystem;
0799:            }
0800:
0801:            /**
0802:             * Returns true if during commit the engine should look for any selects
0803:             * on a modified table and fail if they are detected.
0804:             */
0805:            public boolean transactionErrorOnDirtySelect() {
0806:                return transaction_error_on_dirty_select;
0807:            }
0808:
0809:            /**
0810:             * Returns true if the parser should ignore case when searching for
0811:             * schema/table/column identifiers.
0812:             */
0813:            public boolean ignoreIdentifierCase() {
0814:                return ignore_case_for_identifiers;
0815:            }
0816:
0817:            /**
0818:             * Returns the LoggingBufferManager object enabling us to create no file
0819:             * stores in the file system.  This provides access to the buffer scheme that
0820:             * has been configured.
0821:             */
0822:            public LoggingBufferManager getBufferManager() {
0823:                return buffer_manager;
0824:            }
0825:
0826:            /**
0827:             * Returns the regular expression library from the configuration file.
0828:             */
0829:            public RegexLibrary getRegexLibrary() {
0830:                if (regex_library != null) {
0831:                    return regex_library;
0832:                }
0833:                throw new Error(
0834:                        "No regular expression library found in classpath "
0835:                                + "and/or in configuration file.");
0836:            }
0837:
0838:            // ---------- Store System encapsulation ----------
0839:
0840:            /**
0841:             * Returns the StoreSystem encapsulation being used in this database.
0842:             */
0843:            public final StoreSystem storeSystem() {
0844:                return store_system;
0845:            }
0846:
0847:            // ---------- Debug logger methods ----------
0848:
0849:            /**
0850:             * Sets the Writer output for the debug logger.
0851:             */
0852:            public final void setDebugOutput(java.io.Writer writer) {
0853:                //    System.out.println("**** Setting debug log output ****" + writer);
0854:                //    System.out.println(logger);
0855:                logger.setOutput(writer);
0856:            }
0857:
0858:            /**
0859:             * Sets the debug minimum level that is output to the logger.
0860:             */
0861:            public final void setDebugLevel(int level) {
0862:                logger.setDebugLevel(level);
0863:            }
0864:
0865:            /**
0866:             * Returns the DebugLogger object that is used to log debug message.  This
0867:             * method must always return a debug logger that we can log to.
0868:             */
0869:            public final DebugLogger Debug() {
0870:                return logger;
0871:            }
0872:
0873:            // ---------- Function factories ----------
0874:
0875:            /**
0876:             * Registers a new FunctionFactory with the database system.  The function
0877:             * factories are used to resolve a function name into a Function object.
0878:             * Function factories are checked in the order they are added to the database
0879:             * system.
0880:             */
0881:            public void addFunctionFactory(FunctionFactory factory) {
0882:                synchronized (function_factory_list) {
0883:                    function_factory_list.add(factory);
0884:                }
0885:                factory.init();
0886:            }
0887:
0888:            /**
0889:             * Flushes the 'FunctionLookup' object returned by the getFunctionLookup
0890:             * method.  This should be called if the function factory list has been
0891:             * modified in some way.
0892:             */
0893:            public void flushCachedFunctionLookup() {
0894:                FunctionFactory[] factories;
0895:                synchronized (function_factory_list) {
0896:                    factories = (FunctionFactory[]) function_factory_list
0897:                            .toArray(new FunctionFactory[function_factory_list
0898:                                    .size()]);
0899:                }
0900:                function_lookup.flushContents(factories);
0901:            }
0902:
0903:            /**
0904:             * Returns a FunctionLookup object that will search through the function
0905:             * factories in this database system and find and resolve a function.  The
0906:             * returned object may throw an exception from the 'generateFunction' method
0907:             * if the FunctionDef is invalid.  For example, if the number of parameters
0908:             * is incorrect or the name can not be found.
0909:             */
0910:            public FunctionLookup getFunctionLookup() {
0911:                return function_lookup;
0912:            }
0913:
0914:            // ---------- System preparers ----------
0915:
0916:            /**
0917:             * Given a Transaction.CheckExpression, this will prepare the expression and
0918:             * return a new prepared CheckExpression.  The default implementation of this
0919:             * is to do nothing.  However, a sub-class of the system choose to prepare
0920:             * the expression, such as resolving the functions via the function lookup,
0921:             * and resolving the sub-queries, etc.
0922:             */
0923:            public Transaction.CheckExpression prepareTransactionCheckConstraint(
0924:                    DataTableDef table_def, Transaction.CheckExpression check) {
0925:
0926:                //    ExpressionPreparer expression_preparer = getFunctionExpressionPreparer();
0927:                // Resolve the expression to this table and row and evaluate the
0928:                // check constraint.
0929:                Expression exp = check.expression;
0930:                table_def.resolveColumns(ignoreIdentifierCase(), exp);
0931:                //    try {
0932:                //      // Prepare the functions
0933:                //      exp.prepare(expression_preparer);
0934:                //    }
0935:                //    catch (Exception e) {
0936:                //      Debug().writeException(e);
0937:                //      throw new RuntimeException(e.getMessage());
0938:                //    }
0939:
0940:                return check;
0941:            }
0942:
0943:            // ---------- Database System Statistics Methods ----------
0944:
0945:            /**
0946:             * Returns a com.mckoi.util.Stats object that can be used to keep track
0947:             * of database statistics for this VM.
0948:             */
0949:            public final Stats stats() {
0950:                return stats;
0951:            }
0952:
0953:            // ---------- Log directory management ----------
0954:
0955:            /**
0956:             * Sets the log directory.  This should preferably be called during
0957:             * initialization.  If the log directory is not set or is set to 'null' then
0958:             * no logging to files occurs.
0959:             */
0960:            public final void setLogDirectory(File log_path) {
0961:                this .log_directory = log_path;
0962:            }
0963:
0964:            /**
0965:             * Returns the current log directory or null if no logging should occur.
0966:             */
0967:            public final File getLogDirectory() {
0968:                return log_directory;
0969:            }
0970:
0971:            // ---------- Cache Methods ----------
0972:
0973:            /**
0974:             * Returns a DataCellCache object that is a shared resource between all
0975:             * database's running on this VM.  If this returns 'null' then the internal
0976:             * cache is disabled.
0977:             */
0978:            DataCellCache getDataCellCache() {
0979:                return data_cell_cache;
0980:            }
0981:
0982:            // ---------- Dispatch methods ----------
0983:
0984:            /**
0985:             * The dispatcher.
0986:             */
0987:            private DatabaseDispatcher dispatcher;
0988:
0989:            /**
0990:             * Returns the DatabaseDispatcher object.
0991:             */
0992:            private DatabaseDispatcher getDispatcher() {
0993:                synchronized (this ) {
0994:                    if (dispatcher == null) {
0995:                        dispatcher = new DatabaseDispatcher(this );
0996:                    }
0997:                    return dispatcher;
0998:                }
0999:            }
1000:
1001:            /**
1002:             * Creates an event object that is passed into 'postEvent' method
1003:             * to run the given Runnable method after the time has passed.
1004:             * <p>
1005:             * The event created here can be safely posted on the event queue as many
1006:             * times as you like.  It's useful to create an event as a persistant object
1007:             * to service some event.  Just post it on the dispatcher when you want
1008:             * it run!
1009:             */
1010:            Object createEvent(Runnable runnable) {
1011:                return getDispatcher().createEvent(runnable);
1012:            }
1013:
1014:            /**
1015:             * Adds a new event to be dispatched on the queue after 'time_to_wait'
1016:             * milliseconds has passed.
1017:             * <p>
1018:             * 'event' must be an event object returned via 'createEvent'.
1019:             */
1020:            void postEvent(int time_to_wait, Object event) {
1021:                getDispatcher().postEvent(time_to_wait, event);
1022:            }
1023:
1024:            /**
1025:             * Disposes this object.
1026:             */
1027:            public void dispose() {
1028:                if (buffer_manager != null) {
1029:                    try {
1030:                        // Set a check point
1031:                        store_system.setCheckPoint();
1032:                        // Stop the buffer manager
1033:                        buffer_manager.stop();
1034:                    } catch (IOException e) {
1035:                        System.out.println("Error stopping buffer manager.");
1036:                        e.printStackTrace();
1037:                    }
1038:                }
1039:                buffer_manager = null;
1040:                regex_library = null;
1041:                data_cell_cache = null;
1042:                config = null;
1043:                log_directory = null;
1044:                function_factory_list = null;
1045:                store_system = null;
1046:                if (dispatcher != null) {
1047:                    dispatcher.finish();
1048:                }
1049:                //    trigger_manager = null;
1050:                dispatcher = null;
1051:            }
1052:
1053:            // ---------- Inner classes ----------
1054:
1055:            /**
1056:             * A FunctionLookup implementation that will look up a function from a
1057:             * list of FunctionFactory objects provided with.
1058:             */
1059:            private static class DSFunctionLookup implements  FunctionLookup {
1060:
1061:                private FunctionFactory[] factories;
1062:
1063:                public synchronized Function generateFunction(
1064:                        FunctionDef function_def) {
1065:                    for (int i = 0; i < factories.length; ++i) {
1066:                        Function f = factories[i]
1067:                                .generateFunction(function_def);
1068:                        if (f != null) {
1069:                            return f;
1070:                        }
1071:                    }
1072:                    return null;
1073:                }
1074:
1075:                public synchronized boolean isAggregate(FunctionDef function_def) {
1076:                    for (int i = 0; i < factories.length; ++i) {
1077:                        FunctionInfo f_info = factories[i]
1078:                                .getFunctionInfo(function_def.getName());
1079:                        if (f_info != null) {
1080:                            return f_info.getType() == FunctionInfo.AGGREGATE;
1081:                        }
1082:                    }
1083:                    return false;
1084:                }
1085:
1086:                public synchronized void flushContents(
1087:                        FunctionFactory[] factories) {
1088:                    this.factories = factories;
1089:                }
1090:
1091:            }
1092:
1093:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.