Source Code Cross Referenced for Database.java in  » Database-DBMS » Quadcap-Embeddable-Database » com » quadcap » sql » 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 » Quadcap Embeddable Database » com.quadcap.sql 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package com.quadcap.sql;
0002:
0003:        /* Copyright 1999 - 2003 Quadcap Software.  All rights reserved.
0004:         *
0005:         * This software is distributed under the Quadcap Free Software License.
0006:         * This software may be used or modified for any purpose, personal or
0007:         * commercial.  Open Source redistributions are permitted.  Commercial
0008:         * redistribution of larger works derived from, or works which bundle
0009:         * this software requires a "Commercial Redistribution License"; see
0010:         * http://www.quadcap.com/purchase.
0011:         *
0012:         * Redistributions qualify as "Open Source" under  one of the following terms:
0013:         *   
0014:         *    Redistributions are made at no charge beyond the reasonable cost of
0015:         *    materials and delivery.
0016:         *
0017:         *    Redistributions are accompanied by a copy of the Source Code or by an
0018:         *    irrevocable offer to provide a copy of the Source Code for up to three
0019:         *    years at the cost of materials and delivery.  Such redistributions
0020:         *    must allow further use, modification, and redistribution of the Source
0021:         *    Code under substantially the same terms as this license.
0022:         *
0023:         * Redistributions of source code must retain the copyright notices as they
0024:         * appear in each source code file, these license terms, and the
0025:         * disclaimer/limitation of liability set forth as paragraph 6 below.
0026:         *
0027:         * Redistributions in binary form must reproduce this Copyright Notice,
0028:         * these license terms, and the disclaimer/limitation of liability set
0029:         * forth as paragraph 6 below, in the documentation and/or other materials
0030:         * provided with the distribution.
0031:         *
0032:         * The Software is provided on an "AS IS" basis.  No warranty is
0033:         * provided that the Software is free of defects, or fit for a
0034:         * particular purpose.  
0035:         *
0036:         * Limitation of Liability. Quadcap Software shall not be liable
0037:         * for any damages suffered by the Licensee or any third party resulting
0038:         * from use of the Software.
0039:         */
0040:
0041:        import java.io.BufferedWriter;
0042:        import java.io.File;
0043:        import java.io.FileOutputStream;
0044:        import java.io.IOException;
0045:        import java.io.OutputStream;
0046:        import java.io.OutputStreamWriter;
0047:        import java.io.PrintWriter;
0048:
0049:        import java.util.ArrayList;
0050:        import java.util.Calendar;
0051:        import java.util.Collection;
0052:        import java.util.Enumeration;
0053:        import java.util.Iterator;
0054:        import java.util.HashMap;
0055:        import java.util.List;
0056:        import java.util.Map;
0057:        import java.util.Properties;
0058:
0059:        import java.util.zip.GZIPOutputStream;
0060:
0061:        import java.sql.SQLException;
0062:
0063:        import com.quadcap.sql.file.BlockFile;
0064:        import com.quadcap.sql.file.ByteUtil;
0065:        import com.quadcap.sql.file.Datafile;
0066:        import com.quadcap.sql.file.Log;
0067:        import com.quadcap.sql.file.SubPageManager;
0068:
0069:        import com.quadcap.sql.index.BCursor;
0070:        import com.quadcap.sql.index.Btree;
0071:
0072:        import com.quadcap.sql.lock.Transaction;
0073:
0074:        import com.quadcap.util.collections.LongIterator;
0075:        import com.quadcap.util.collections.LongMap;
0076:
0077:        import com.quadcap.util.ConfigString;
0078:        import com.quadcap.util.Debug;
0079:        import com.quadcap.util.Util;
0080:
0081:        /**
0082:         * This class implements the QED SQL database outer API.
0083:         *
0084:         * @author Stan Bailes
0085:         */
0086:        public class Database extends Datafile {
0087:            QDriver driver;
0088:            Btree tableIndex;
0089:            // map index name to table name
0090:            Btree indexIndex;
0091:            Btree blobPermRefCounts;
0092:            Map tableMap = new HashMap();
0093:            MultiSet forwardDeps = null;
0094:            MultiSet reverseDeps = null;
0095:            long rootBlock = 0;
0096:            public DatabaseRoot nroot;
0097:
0098:            /** The Morgue; BLOB/CLOBs with zero (persistent) refcounts:
0099:                blobRef -> any */
0100:            LongMap blobMorgue = new LongMap(32);
0101:
0102:            /** Map blob -> Vector<transid> */
0103:            LongMap blobActivity = new LongMap(128);
0104:
0105:            int connectionCount = 0;
0106:            int closeCount = 0;
0107:            long nextTransId = 0;
0108:
0109:            public Object driverLock;
0110:
0111:            static final ConfigString backupClass = ConfigString.find(
0112:                    "qed.backupClass", "com.quadcap.sql.tools.XmlDump");
0113:
0114:            /**
0115:             * Constructor
0116:             */
0117:            public Database() {
0118:            }
0119:
0120:            public void init(QDriver driver, String url, String fileName,
0121:                    Properties props) throws IOException, SQLException {
0122:                this .driver = driver;
0123:                init(url, fileName, props);
0124:            }
0125:
0126:            /**
0127:             * Create a new root block
0128:             */
0129:            public void createRoot(String fileName, Properties props)
0130:                    throws IOException {
0131:                this .rootBlock = getFile().getUserBlock(0);
0132:                this .root = this .nroot = new DatabaseRoot(this , fileName, props);
0133:                if (!readOnly && !inMemory) {
0134:                    new File(fileName, "logfile").delete();
0135:                    flushRoot();
0136:                }
0137:            }
0138:
0139:            /**
0140:             * Read the root block from an existing database
0141:             */
0142:            public void readRoot() throws IOException {
0143:                this .rootBlock = getFile().getUserBlock(0);
0144:                root = nroot = (DatabaseRoot) file.getObject(rootBlock);
0145:                nroot.setDatabase(this );
0146:            }
0147:
0148:            /**
0149:             * Write the database root
0150:             */
0151:            public void flushRoot() throws IOException {
0152:                if (!inMemory /*?*/&& !readOnly) {
0153:                    getFile().updateObject(rootBlock, root);
0154:                }
0155:            }
0156:
0157:            /**
0158:             * Get ready to rumble!!!
0159:             */
0160:            public void bootFromRoot(boolean restart) throws IOException {
0161:                nextTransId = root.getNextTransId();
0162:                nroot.setNextTransId((nextTransId | 0xff) + 1);
0163:
0164:                blobPermRefCounts = new Btree(file,
0165:                        nroot.getBlobRefCountRoot(), !restart);
0166:                tableIndex = new Btree(file, nroot.getRelationIndexNode(),
0167:                        !restart);
0168:                indexIndex = new Btree(file, nroot.getIndexIndexNode(),
0169:                        !restart);
0170:                forwardDeps = new MultiSet(new Btree(file, nroot
0171:                        .getForwardDepsNode(), !restart));
0172:                reverseDeps = new MultiSet(new Btree(file, nroot
0173:                        .getReverseDepsNode(), !restart));
0174:            }
0175:
0176:            /**
0177:             * Return the next available transaction ID.
0178:             */
0179:            public long getNextTransId() throws IOException {
0180:                synchronized (fileLock) {
0181:                    long t = nextTransId++;
0182:                    if (!inMemory && (nextTransId & 0xff) == 0) {
0183:                        nroot.setNextTransId(nextTransId + 0x100);
0184:                        flushRoot();
0185:                    }
0186:                    return t;
0187:                }
0188:            }
0189:
0190:            /**
0191:             * Figure out if it's time to do a backup.
0192:             */
0193:            public void maybeBackup() throws IOException {
0194:                if (inMemory)
0195:                    return;
0196:                // are backups enabled?
0197:                int days = getBackupDays();
0198:                if (days == 0)
0199:                    return;
0200:
0201:                // is today the day?
0202:                Calendar now = Calendar.getInstance();
0203:                int nowDay = now.get(Calendar.DAY_OF_WEEK);
0204:                if (((days >> nowDay) & 1) == 0)
0205:                    return;
0206:
0207:                // is now the time?
0208:                int time = getBackupTime();
0209:                int today = now.get(Calendar.DAY_OF_YEAR);
0210:                int nowTime = now.get(Calendar.HOUR_OF_DAY) * 60
0211:                        + now.get(Calendar.MINUTE);
0212:                if (nowTime < time || today == getBackupLastDay())
0213:                    return;
0214:
0215:                // cycle the old backup files
0216:                int count = getBackupCount();
0217:                for (int i = count - 2; i >= 0; i--) {
0218:                    makeBackupFile(i).renameTo(makeBackupFile(i + 1));
0219:                }
0220:
0221:                // write new backup in correct format
0222:                OutputStream w = new FileOutputStream(makeBackupFile(0));
0223:                if (getBackupFormat().equals("xml.gz")) {
0224:                    w = new GZIPOutputStream(w);
0225:                }
0226:                OutputStreamWriter ow = new OutputStreamWriter(w);
0227:                BufferedWriter bw = new BufferedWriter(ow);
0228:
0229:                // create the backup helper and do it.
0230:                try {
0231:                    java.sql.Connection conn = driver.makeConnection(this ,
0232:                            "backup", null);
0233:                    Class c = Class.forName(backupClass.toString());
0234:                    Backup b = (Backup) c.newInstance();
0235:                    b.backup(conn, bw);
0236:                    bw.close();
0237:                } catch (IOException e) {
0238:                    throw e;
0239:                } catch (Throwable t) {
0240:                    throw new IOException(t.toString());
0241:                }
0242:                setBackupLastDay(today);
0243:            }
0244:
0245:            File makeBackupFile(int n) throws IOException {
0246:                File bdir = new File(getBackupDir());
0247:                if (!bdir.exists()) {
0248:                    if (!bdir.mkdirs()) {
0249:                        throw new IOException("can't create backup directory: "
0250:                                + bdir.getAbsolutePath());
0251:                    }
0252:                }
0253:                String name = "backup-" + n + "." + getBackupFormat();
0254:                return new File(bdir, name);
0255:            }
0256:
0257:            /**
0258:             * TODO: XXX Unicode!!!
0259:             * Add a new named index for the specified table.
0260:             */
0261:            public void addIndex(String indexName, String tableName)
0262:                    throws IOException {
0263:                synchronized (fileLock) {
0264:                    indexIndex.set(indexName.getBytes(), tableName.getBytes());
0265:                }
0266:            }
0267:
0268:            /**
0269:             * Return the table for the index of the specified name.
0270:             */
0271:            public String getTableForIndex(String indexName) throws IOException {
0272:                synchronized (fileLock) {
0273:                    byte[] ret = indexIndex.get(indexName.getBytes());
0274:                    if (ret == null)
0275:                        return null;
0276:                    return new String(ret);
0277:                }
0278:            }
0279:
0280:            /**
0281:             * Remove the specified index
0282:             */
0283:            public void deleteIndex(String indexName) throws IOException {
0284:                synchronized (fileLock) {
0285:                    indexIndex.delete(indexName.getBytes());
0286:                }
0287:            }
0288:
0289:            /**
0290:             * RENAME TABLE percolates into the index index...
0291:             */
0292:            void renameIndexedTable(String oldN, String newN)
0293:                    throws IOException {
0294:                synchronized (fileLock) {
0295:                    BCursor bc = indexIndex.getCursor(false);
0296:                    if (bc != null) {
0297:                        try {
0298:                            while (bc.next()) {
0299:                                String name = new String(bc.getVal());
0300:                                if (name.equals(oldN)) {
0301:                                    bc.prev();
0302:                                    bc.replace(newN.getBytes());
0303:                                    bc.next();
0304:                                }
0305:                            }
0306:                        } finally {
0307:                            bc.release();
0308:                        }
0309:                    }
0310:                }
0311:            }
0312:
0313:            /**
0314:             * Return the table identity for the table
0315:             *
0316:             * @exception SQLException if the table can't be located
0317:             */
0318:            public long getTableIdentity(String name) throws IOException,
0319:                    SQLException {
0320:                synchronized (fileLock) {
0321:                    if (inMemory) {
0322:                        Table t = (Table) getRelation(name);
0323:                        return t.tableIdentity;
0324:                    } else {
0325:                        BCursor tc = tableIndex.getCursor(true);
0326:                        try {
0327:                            if (tc.seek(name.getBytes())
0328:                                    && tc.getValLen() >= 16) {
0329:                                return ByteUtil.getLong(tc.getValBuf(), 8);
0330:                            } else {
0331:                                throw new SQLException("getTableIdentity("
0332:                                        + name + "): no table");
0333:                            }
0334:                        } finally {
0335:                            tc.release();
0336:                        }
0337:                    }
0338:                }
0339:            }
0340:
0341:            /**
0342:             * The "table identity" is a long value stored along with the table
0343:             * stream pointer, so that it can easily be updated as long as the index
0344:             * is in memory, without touching any data pages.
0345:             */
0346:            public void updateTableIdentity(String name, long num)
0347:                    throws IOException, SQLException {
0348:                synchronized (fileLock) {
0349:                    if (inMemory) {
0350:                        Table t = (Table) getRelation(name);
0351:                        t.tableIdentity = num;
0352:                    } else {
0353:                        BCursor tc = tableIndex.getCursor(true);
0354:                        try {
0355:                            if (tc.seek(name.getBytes())) {
0356:                                int cnt = tc.getVal(temp);
0357:                                ByteUtil.putLong(temp, 8, num);
0358:                                tc.replace(temp, 0, cnt);
0359:                                return;
0360:                            } else {
0361:                                throw new SQLException("getTableIdentity("
0362:                                        + name + "): no table");
0363:                            }
0364:                        } finally {
0365:                            tc.release();
0366:                        }
0367:                    }
0368:                }
0369:            }
0370:
0371:            /**
0372:             * Helper to execute a single SQL statement (in its own connection)
0373:             * and return a result set.
0374:             */
0375:            public java.sql.ResultSet execute(String sql) throws SQLException,
0376:                    IOException {
0377:                Connection c = new Connection(this , "__NO_AUTH__", null);
0378:                Session session = c.createSession();
0379:                return execute(session, sql);
0380:            }
0381:
0382:            /**
0383:             * Helper to execute a single SQL statement for the given session.
0384:             */
0385:            public java.sql.ResultSet execute(Session session, String sql)
0386:                    throws IOException, SQLException {
0387:                SQLParser p = new SQLParser(session, sql, true);
0388:                Stmt s = null;
0389:                try {
0390:                    s = p.statement();
0391:                } catch (Throwable t) {
0392:                    Debug.print(t);
0393:                }
0394:
0395:                if (s == null) {
0396:                    throw new SQLException("Parse error", "42000");
0397:                }
0398:                session.doStatement(s);
0399:                return session.getResultSet();
0400:            }
0401:
0402:            /**
0403:             * Return the table/view with the specified name
0404:             *
0405:             * XXX Fix this "cache" implementation 
0406:             */
0407:            public Relation getRelation(String name) throws IOException {
0408:                Relation t = null;
0409:                synchronized (fileLock) {
0410:                    t = (Relation) tableMap.get(name);
0411:                    if (!inMemory && t == null) {
0412:                        BCursor tc = tableIndex.getCursor(true);
0413:                        try {
0414:                            if (tc.seek(name.getBytes())) {
0415:                                byte[] d = tc.getValBuf();
0416:                                t = (Relation) getFile().getObject(
0417:                                        ByteUtil.getLong(d, 0));
0418:                                if (t != null) {
0419:                                    tableMap.put(name, t);
0420:                                }
0421:                            }
0422:                        } finally {
0423:                            tc.release();
0424:                        }
0425:                    }
0426:                }
0427:                //#ifdef DEBUG
0428:                if (Trace.bit(0)) {
0429:                    Debug.println("getRelation(" + name + ") = "
0430:                            + ((t == null) ? "NOT FOUND" : "FOUND"));
0431:                }
0432:                //#endif
0433:                return t;
0434:            }
0435:
0436:            /**
0437:             * Add a new table/view
0438:            '     */
0439:            public void addRelation(Relation table) throws IOException,
0440:                    SQLException {
0441:                synchronized (fileLock) {
0442:                    String name = table.getName();
0443:                    //#ifdef TRACE
0444:                    if (Trace.bit(0)) {
0445:                        Debug.println("addRelation(" + name + ")");
0446:                    }
0447:                    //#endif
0448:                    if (tableMap.get(name) == null) {
0449:                        tableMap.put(name, table);
0450:                        if (!inMemory) {
0451:                            BCursor tc = tableIndex.getCursor(true);
0452:                            try {
0453:                                byte[] tkey = name.getBytes();
0454:                                if (!tc.seek(name.getBytes())) {
0455:                                    long ref = getFile().putObject(table);
0456:                                    ByteUtil.putLong(temp, 0, ref);
0457:                                    ByteUtil.putLong(temp, 8, 1); // start counting at '1'
0458:                                    tc.insert(tkey, tkey.length, temp, 0, 16);
0459:                                }
0460:                            } finally {
0461:                                tc.release();
0462:                            }
0463:                        }
0464:                    } else {
0465:                        throw new SQLException("Table/view already exists: "
0466:                                + name, "42000");
0467:                    }
0468:                }
0469:            }
0470:
0471:            /**
0472:             * Delete the specified table/view
0473:             */
0474:            public void removeRelation(String name) throws IOException,
0475:                    SQLException {
0476:                synchronized (fileLock) {
0477:                    //#ifdef DEBUG
0478:                    if (Trace.bit(0)) {
0479:                        Debug.println("removeRelation(" + name + ")");
0480:                    }
0481:                    //#endif
0482:                    Relation t = getRelation(name);
0483:                    if (t == null) {
0484:                        throw new SQLException("No such table/view: " + name,
0485:                                "42000");
0486:                    }
0487:                    removeViewDependencies(name);
0488:                    tableMap.remove(name);
0489:                    if (!inMemory) {
0490:                        BCursor tc = tableIndex.getCursor(true);
0491:                        try {
0492:                            if (tc.seek(name.getBytes())) {
0493:                                getFile().removeObject(tc.getValAsLong());
0494:                                tc.delete();
0495:                            }
0496:                        } finally {
0497:                            tc.release();
0498:                        }
0499:                    }
0500:                }
0501:                //#ifdef DEBUG
0502:                if (getRelation(name) != null) {
0503:                    throw new SQLException("Relation not removed!!!");
0504:                }
0505:                //#endif
0506:            }
0507:
0508:            /**
0509:             * Rename a relation.  This involves:
0510:             *
0511:             * 1. Changing the cached relation
0512:             * 2. Changing the btree index to the relation
0513:             * 3. Changing any indexIndex entries referring to the rel
0514:             * 4. Changing any forwardDeps or backwardDeps which
0515:             *    refer to the relation
0516:             */
0517:            public void renameRelation(Relation r, String newN)
0518:                    throws IOException {
0519:                synchronized (fileLock) {
0520:                    String oldN = r.getName();
0521:                    r.setName(newN);
0522:                    tableMap.remove(oldN);
0523:                    tableMap.put(newN, r);
0524:                    if (!inMemory) {
0525:                        BCursor tc = tableIndex.getCursor(true);
0526:                        try {
0527:                            if (tc.seek(oldN.getBytes())) {
0528:                                byte[] d = tc.getValBuf();
0529:                                long ref = ByteUtil.getLong(d, 0);
0530:                                tc.delete();
0531:                                byte[] nb = newN.getBytes();
0532:                                if (!tc.seek(nb)) {
0533:                                    tc.insert(nb, nb.length, d, 0, 16);
0534:                                    getFile().updateObject(ref, r);
0535:                                }
0536:                            }
0537:                        } finally {
0538:                            tc.release();
0539:                        }
0540:                    }
0541:                    if (true) {
0542:                        forwardDeps.rename(oldN, newN, reverseDeps);
0543:                        reverseDeps.rename(oldN, newN, forwardDeps);
0544:                    }
0545:                    if (true) {
0546:                        renameIndexedTable(oldN, newN);
0547:                    }
0548:                }
0549:            }
0550:
0551:            /**
0552:             * Store a modified version of the specified view/table to the
0553:             * store
0554:             */
0555:            public void updateRelation(Relation table) throws IOException {
0556:                synchronized (fileLock) {
0557:                    //#ifdef TRACE
0558:                    if (Trace.bit(0)) {
0559:                        Debug
0560:                                .println("updateRelation(" + table.getName()
0561:                                        + ")");
0562:                        //Debug.println("updateRelation(" + table.getName() + ": " + table + ")"); // + Util.stackTrace());
0563:                    }
0564:                    //#endif
0565:                    tableMap.put(table.getName(), table);
0566:                    if (!inMemory) {
0567:                        BCursor tc = tableIndex.getCursor(true);
0568:                        try {
0569:                            if (tc.seek(table.getName().getBytes())) {
0570:                                getFile()
0571:                                        .updateObject(tc.getValAsLong(), table);
0572:                            } else {
0573:                                throw new IOException("Not found: "
0574:                                        + table.getName());
0575:                            }
0576:                        } finally {
0577:                            tc.release();
0578:                        }
0579:                    }
0580:                }
0581:            }
0582:
0583:            /**
0584:             * Establish the dependency link between a view and a base table
0585:             */
0586:            public void addViewDependency(String base, String view)
0587:                    throws IOException {
0588:                //#ifdef TRACE
0589:                if (Trace.bit(0)) {
0590:                    Debug.println("addViewDependency(" + base + ", " + view
0591:                            + ")");
0592:                }
0593:                //#endif
0594:
0595:                synchronized (fileLock) {
0596:                    forwardDeps.put(base, view);
0597:                    reverseDeps.put(view, base);
0598:                }
0599:            }
0600:
0601:            /**
0602:             * Make sure that the specified view dependency is valid
0603:             */
0604:            public void checkViewDependency(String base, String view)
0605:                    throws SQLException, IOException {
0606:                Relation baseR = getRelation(base);
0607:                if (baseR == null) {
0608:                    throw new SQLException("Base table not found: " + base,
0609:                            "42000");
0610:                }
0611:                if (baseR instanceof  Table) {
0612:                    Table baseT = (Table) baseR;
0613:                    int modifiers = baseT.getModifiers();
0614:                    if ((modifiers & Table.TEMPORARY) != 0) {
0615:                        throw new SQLException(
0616:                                "Can't create view of temporary " + "table "
0617:                                        + base, "42000");
0618:                    }
0619:                }
0620:            }
0621:
0622:            /**
0623:             * Return an enumeration of all views for the specified base table
0624:             */
0625:            public Enumeration getViews(String base) throws IOException {
0626:                synchronized (fileLock) {
0627:                    return forwardDeps.get(base);
0628:                }
0629:            }
0630:
0631:            /**
0632:             * Return an enumeration containing all base tables for the specified
0633:             * view
0634:             */
0635:            public Enumeration getBases(String view) throws IOException {
0636:                synchronized (fileLock) {
0637:                    return reverseDeps.get(view);
0638:                }
0639:            }
0640:
0641:            public void removeViewDependencies(String view)
0642:                    throws SQLException, IOException {
0643:                //#ifdef TRACE
0644:                if (Trace.bit(0)) {
0645:                    Debug.println("removeViewDependencies(" + view + ")");
0646:                }
0647:                //#endif
0648:                synchronized (fileLock) {
0649:                    Enumeration views = getViews(view);
0650:                    if (views.hasMoreElements()) {
0651:                        throw new SQLException(
0652:                                "view has dependencies: " + view, "42000");
0653:                    }
0654:                    Enumeration bases = getBases(view);
0655:                    while (bases.hasMoreElements()) {
0656:                        forwardDeps
0657:                                .delete(bases.nextElement().toString(), view);
0658:                    }
0659:                }
0660:            }
0661:
0662:            /**
0663:             * This hacky crack of encapsulation is for sql.meta.MetaTables, to
0664:             * support DatabaseMetaData.getTables().  All he really needs is
0665:             * an Iterator which returns the table names....
0666:             */
0667:            //     public Btree getRelationIndex() {
0668:            // 	return tableIndex;
0669:            //     }
0670:            public Iterator getRelationNameIterator() throws IOException {
0671:                if (inMemory) {
0672:                    return tableMap.keySet().iterator();
0673:                } else {
0674:                    final BCursor tc = tableIndex.getCursor(false);
0675:                    return new Iterator() {
0676:                        boolean called = false;
0677:                        boolean last = false;
0678:                        boolean closed = false;
0679:
0680:                        public boolean hasNext() {
0681:                            try {
0682:                                if (!closed && !called) {
0683:                                    last = tc.next();
0684:                                    called = true;
0685:                                }
0686:                            } catch (IOException ex) {
0687:                                last = false;
0688:                            }
0689:                            if (!last && !closed) {
0690:                                closed = true;
0691:                                try {
0692:                                    tc.release();
0693:                                } catch (Throwable t) {
0694:                                    Debug.print(t);
0695:                                }
0696:                            }
0697:                            return last;
0698:                        }
0699:
0700:                        public Object next() {
0701:                            Object ret = null;
0702:                            try {
0703:                                if (!called && !closed) {
0704:                                    last = tc.next();
0705:                                }
0706:                                if (!last) {
0707:                                    if (!closed) {
0708:                                        closed = true;
0709:                                        try {
0710:                                            tc.release();
0711:                                        } catch (Throwable t) {
0712:                                            Debug.print(t);
0713:                                        }
0714:                                    }
0715:                                } else {
0716:                                    ret = new String(tc.getKey());
0717:                                    called = false;
0718:                                }
0719:                            } catch (IOException ex) {
0720:                                ret = "<Exception: " + ex + ">";
0721:                            }
0722:                            return ret;
0723:                        }
0724:
0725:                        public void remove() {
0726:                            try {
0727:                                tc.delete();
0728:                            } catch (IOException e) {
0729:                                Debug.print(e);
0730:                                throw new RuntimeException(
0731:                                        "Error deleting record", e);
0732:                            }
0733:                        }
0734:                    };
0735:                }
0736:            }
0737:
0738:            //     public Collection getRelationNames() throws IOException {
0739:            //         ArrayList list = new ArrayList();
0740:            //         synchronized (fileLock) {
0741:            //             if (inMemory) {
0742:            //                 return tableMap.keySet();
0743:            //             }
0744:            //             BCursor tc = tableIndex.getCursor(false);
0745:            //             try {
0746:            //                 while (tc.next()) {
0747:            //                     list.add(new String(tc.getKey()));
0748:            //                 }
0749:            //             } finally {
0750:            //                 tc.release();
0751:            //             }
0752:            //         }
0753:            //         return list;
0754:            //     }
0755:
0756:            /**
0757:             * Add a new connection (just remember the count...)
0758:             */
0759:            public int addConnection() {
0760:                synchronized (driverLock) {
0761:                    //#ifdef TRACE
0762:                    if (Trace.bit(8)) {
0763:                        Debug.println("addConnection, count now: "
0764:                                + (connectionCount + 1));
0765:                    }
0766:                    //#endif
0767:                    return ++connectionCount;
0768:                }
0769:            }
0770:
0771:            /**
0772:             * Sleight of hand to get my driver interface
0773:             */
0774:            public QDriver getDriver() {
0775:                return driver;
0776:            }
0777:
0778:            /**
0779:             * Remove a connection.  If the connection count drops to zero, we
0780:             * get crafty.
0781:             */
0782:            public void removeConnection() {
0783:                synchronized (driverLock) {
0784:                    if (--connectionCount == 0 && closeCount++ < 1) {
0785:                        try {
0786:                            getLog().checkpoint();
0787:                        } catch (Throwable e) {
0788:                        }
0789:                    }
0790:                    //#ifdef TRACE
0791:                    if (Trace.bit(8)) {
0792:                        Debug.println("removeConnection, count now: "
0793:                                + (connectionCount));
0794:                    }
0795:                    //#endif
0796:                    if (connectionCount == 0 && closeCount == 1) {
0797:                        driver.closeDatabase(origFileName);
0798:                    }
0799:                }
0800:            }
0801:
0802:            /**
0803:             * Return the number of active connections
0804:             */
0805:            public int getConnectionCount() {
0806:                return connectionCount;
0807:            }
0808:
0809:            /**
0810:             * Return the backup directory name
0811:             */
0812:            public String getBackupDir() {
0813:                return nroot.getBackupDir();
0814:            }
0815:
0816:            /**
0817:             * Set the backup directory
0818:             */
0819:            public void setBackupDir(String str) throws IOException {
0820:                nroot.setBackupDir(str);
0821:                flushRoot();
0822:            }
0823:
0824:            /**
0825:             * Return the backup count
0826:             */
0827:            public int getBackupCount() {
0828:                return nroot.getBackupCount();
0829:            }
0830:
0831:            /**
0832:             * Set the backup count
0833:             */
0834:            public void setBackupCount(int count) throws IOException {
0835:                nroot.setBackupCount(count);
0836:                flushRoot();
0837:            }
0838:
0839:            /**
0840:             * Return the backup days
0841:             */
0842:            public int getBackupDays() {
0843:                return nroot.getBackupDays();
0844:            }
0845:
0846:            /**
0847:             * Set the backup days
0848:             */
0849:            public void setBackupDays(int count) throws IOException {
0850:                nroot.setBackupDays(count);
0851:                flushRoot();
0852:            }
0853:
0854:            /**
0855:             * Return the backup last day
0856:             */
0857:            public int getBackupLastDay() {
0858:                return nroot.getBackupLastDay();
0859:            }
0860:
0861:            /**
0862:             * Set the backup last day
0863:             */
0864:            public void setBackupLastDay(int day) throws IOException {
0865:                nroot.setBackupLastDay(day);
0866:                flushRoot();
0867:            }
0868:
0869:            /**
0870:             * Return the backup time
0871:             */
0872:            public int getBackupTime() {
0873:                return nroot.getBackupTime();
0874:            }
0875:
0876:            /**
0877:             * Set the backup time
0878:             */
0879:            public void setBackupTime(int time) throws IOException {
0880:                nroot.setBackupTime(time);
0881:                flushRoot();
0882:            }
0883:
0884:            /**
0885:             * Return the backup format
0886:             */
0887:            public String getBackupFormat() {
0888:                return nroot.getBackupFormat();
0889:            }
0890:
0891:            /**
0892:             * Set the backup format
0893:             */
0894:            public void setBackupFormat(String str) throws IOException {
0895:                nroot.setBackupFormat(str);
0896:                flushRoot();
0897:            }
0898:
0899:            /**
0900:             * Check the specified authentication credentials;  throw an exception
0901:             * if authorization shouldn't be granted.
0902:             *
0903:             * We really don't care about passwords.  This is an embedded database,
0904:             * remember;  it's really just a fancy API on top of a simple file!
0905:             */
0906:            public void checkAuth(String user, String passwd)
0907:                    throws SQLException {
0908:                // XXX impl
0909:            }
0910:
0911:            /**
0912:             * Return the current persistent refcount for the specified blob.
0913:             */
0914:            public int getPermBlobRefCount(long blob) throws IOException {
0915:                synchronized (fileLock) {
0916:                    ByteUtil.putLong(key, 0, blob);
0917:                    byte[] val = blobPermRefCounts.get(key);
0918:                    int refcount = val == null ? 0 : ByteUtil.getInt(val, 0);
0919:                    return refcount;
0920:                }
0921:            }
0922:
0923:            //------------------------------------------------------------------
0924:            // private functions
0925:            //------------------------------------------------------------------
0926:
0927:            private byte[] key = new byte[8];
0928:
0929:            public int refCountBlob(long transId, long blob, int incr)
0930:                    throws IOException {
0931:                synchronized (fileLock) {
0932:                    // find the current refcount
0933:                    ByteUtil.putLong(key, 0, blob);
0934:                    byte[] val = blobPermRefCounts.get(key);
0935:                    int refcount = val == null ? 0 : ByteUtil.getInt(val, 0);
0936:                    int preRefcount = refcount;
0937:
0938:                    // if refcount 0 -> 1, remove from morgue
0939:                    if (refcount == 0 && incr == 1) {
0940:                        val = new byte[4];
0941:                        delMorgue(blob);
0942:                    }
0943:                    refcount += incr;
0944:                    if (refcount < 0) {
0945:                        throw new RuntimeException("freePermBlobRef(" + blob
0946:                                + "), refcount negative");
0947:                    }
0948:
0949:                    if (refcount <= 0) {
0950:                        if (preRefcount > 0) {
0951:                            addMorgue(blob, transId);
0952:                        }
0953:                        blobPermRefCounts.delete(key);
0954:                    } else {
0955:                        // otherwise, update perm refcount
0956:                        ByteUtil.putInt(val, 0, refcount);
0957:                        blobPermRefCounts.set(key, val);
0958:                    }
0959:
0960:                    return refcount;
0961:                }
0962:            }
0963:
0964:            /**
0965:             * Add a blob/clob to the morgue
0966:             */
0967:            public void addMorgue(long blob, long transId) {
0968:                synchronized (fileLock) {
0969:                    blobMorgue.put(blob, new Long(transId));
0970:                }
0971:            }
0972:
0973:            /**
0974:             * Remove a blob/clob from the morgue
0975:             */
0976:            public void delMorgue(long blob) {
0977:                synchronized (fileLock) {
0978:                    blobMorgue.remove(blob);
0979:                }
0980:            }
0981:
0982:            /**
0983:             * Enumerate the morgue.
0984:             */
0985:            public LongIterator enumerateMorgue() {
0986:                return blobMorgue.keys();
0987:            }
0988:
0989:            /**
0990:             * Called during a checkpoint operation.
0991:             *
0992:             * @param activeTransactions is a map whose keys are the set of
0993:             *   ids of active transactions.
0994:             */
0995:            public void checkpointHandler(LongMap activeTransactions)
0996:                    throws IOException {
0997:                emptyMorgue(activeTransactions);
0998:            }
0999:
1000:            /**
1001:             * Empty the BLOB morgue.  Remove any BLOBS in the morge that were
1002:             * deleted by transactions which have committed.
1003:             */
1004:            public void emptyMorgue(LongMap activeTransactions)
1005:                    throws IOException {
1006:                // ---- temporarily disassociate the log from the file so we don't
1007:                // ---- log the file writes we're about to do.  This is OK because
1008:                // ---- we're doing a checkpoint now.
1009:                Log saveLog = getLog();
1010:                getFile().setLog(null);
1011:                try {
1012:                    synchronized (fileLock) {
1013:                        LongIterator iter = enumerateMorgue();
1014:                        while (iter.hasNext()) {
1015:                            long blob = iter.nextLong();
1016:                            long transId = ((Long) (blobMorgue.get(blob)))
1017:                                    .longValue();
1018:                            if (activeTransactions.get(transId) == null) {
1019:                                try {
1020:                                    getFile().freeStream(blob);
1021:                                } catch (Throwable t) {
1022:                                    Debug.println("Error removing blob: "
1023:                                            + blob);
1024:                                    Debug.print(t);
1025:                                }
1026:                                iter.remove();
1027:                            }
1028:                        }
1029:                    }
1030:                } finally {
1031:                    // ---- restore the {file <--> log} association
1032:                    getFile().setLog(saveLog);
1033:                }
1034:            }
1035:
1036:            Session zSession = null;
1037:            Connection zConn = null;
1038:
1039:            final Session getSession(Transaction t) throws IOException,
1040:                    SQLException {
1041:                if (zSession == null) {
1042:                    synchronized (this ) {
1043:                        if (zSession == null) {
1044:                            zConn = new Connection(this , "__SYSTEM", null);
1045:                            zSession = zConn.createSession();
1046:                        }
1047:                    }
1048:                }
1049:                zConn.transId = t.getTransactionId(); // XXX what about sync?
1050:                zConn.trans = t;
1051:                return zSession;
1052:            }
1053:
1054:            //#ifdef DEBUG
1055:            public void display(PrintWriter w) throws IOException {
1056:                w.println("Root:");
1057:                w.println("    blobs:        " + nroot.getBlobRefCountRoot());
1058:                w.println("    relations:    " + nroot.getRelationIndexNode());
1059:                w.println("    indexes:      " + nroot.getIndexIndexNode());
1060:                w.println("    forward deps: " + nroot.getForwardDepsNode());
1061:                w.println("    reverse deps: " + nroot.getReverseDepsNode());
1062:                w.println("    next trans:   " + nroot.getNextTransId());
1063:                if (true) {// iterate tables, build node map
1064:                }
1065:                if (true) { // display indexes, update node map
1066:                    w.println("indexIndex:");
1067:                    indexIndex.display(w);
1068:                    w.println("tableIndex:");
1069:                    tableIndex.display(w);
1070:                }
1071:                if (true) { // traverse freelists, update node map
1072:                    w.println("forwardDeps:");
1073:                    forwardDeps.display(w);
1074:                    w.println("reverseDeps:");
1075:                    reverseDeps.display(w);
1076:                }
1077:                if (true) { // search for blocks missing from node map
1078:                }
1079:                if (true) { // dump node map in block order
1080:                }
1081:                // traverse block file with node map used for annotations.
1082:            }
1083:
1084:            //#endif
1085:
1086:            /**
1087:             * Convenience method to write a new row to the database
1088:             */
1089:            public long putRow(Session session, BlockFile f, Tuple t, Row row)
1090:                    throws SQLException, IOException {
1091:                long rowId;
1092:                if (inMemory) {
1093:                    rowId = f.putObject(row = new Row(row, t));
1094:                } else {
1095:                    byte[] buf = LazyRow.writeRow(session, t, row);
1096:                    rowId = f.putBytes(buf);
1097:                }
1098:                //#ifdef TRACE
1099:                if (Trace.bit(11)) {
1100:                    Debug.println((f == this .file ? "file" : "temp")
1101:                            + "."
1102:                            + ((t == null) ? "temp"
1103:                                    : ("Table[" + t.getName() + "]"))
1104:                            + ".putRow(" + row + "): " + rowId);
1105:                }
1106:                //#endif
1107:                return rowId;
1108:            }
1109:
1110:            /**
1111:             * Convenience method to update a table row
1112:             */
1113:            public final void putRow(Session session, Tuple t, long rowId,
1114:                    Row row) throws SQLException, IOException {
1115:                //#ifdef TRACE
1116:                if (Trace.bit(11)) {
1117:                    Debug.println("Table[" + t.getName() + "].putRow(" + row
1118:                            + ")");
1119:                }
1120:                //#endif
1121:                if (inMemory) {
1122:                    getFile().updateObject(rowId, new Row(row, t));
1123:                } else {
1124:                    byte[] ret = LazyRow.writeRow(session, t, row);
1125:                    getFile().updateBytes(rowId, ret);
1126:                }
1127:            }
1128:
1129:            public void getRow(long rowId, LazyRow row, boolean isTemp)
1130:                    throws IOException, SQLException {
1131:                BlockFile f = isTemp ? getTempFile(false) : getFile();
1132:                if (inMemory) {
1133:                    Row r = (Row) f.getObject(rowId);
1134:                    if (r == null) {
1135:                        throw new IOException("No row: " + rowId);
1136:                    }
1137:                    if (r.size() != row.size()) {
1138:                        //#ifdef DEBUG
1139:                        Debug.println((isTemp ? "temp" : "file") + ".getRow("
1140:                                + rowId + ") = " + row);
1141:                        Debug.println("Bad row size in getRow: " + r.size()
1142:                                + " vs " + row.size());
1143:                        //#endif
1144:                        throw new IOException("Bad row size in getRow: "
1145:                                + r.size() + " vs " + row.size());
1146:                    }
1147:                    for (int i = 1; i <= row.size(); i++) {
1148:                        row.set(i, r.getItem(i));
1149:                    }
1150:                } else {
1151:                    byte[] rowBytes = f.getBytes(rowId);
1152:                    row.reset(rowBytes, this );
1153:                }
1154:                //#ifdef TRACE
1155:                if (Trace.bit(11)) {
1156:                    Debug.println((isTemp ? "temp" : "file") + ".getRow("
1157:                            + rowId + ") = " + row);
1158:                }
1159:                //#endif
1160:            }
1161:
1162:            public void removeRow(long rowId) throws IOException {
1163:                removeRow(getFile(), rowId);
1164:            }
1165:
1166:            public void removeRow(BlockFile file, long rowId)
1167:                    throws IOException {
1168:                if (inMemory) {
1169:                    file.removeObject(rowId);
1170:                } else {
1171:                    file.freeStream(rowId);
1172:                }
1173:            }
1174:
1175:            public boolean inMemory() {
1176:                return inMemory;
1177:            }
1178:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.