KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > db > Database


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.db;
31
32 import com.caucho.db.sql.Parser;
33 import com.caucho.db.sql.Query;
34 import com.caucho.db.store.BlockManager;
35 import com.caucho.db.store.Lock;
36 import com.caucho.db.store.Store;
37 import com.caucho.db.table.Table;
38 import com.caucho.db.table.TableFactory;
39 import com.caucho.lifecycle.Lifecycle;
40 import com.caucho.loader.CloseListener;
41 import com.caucho.loader.Environment;
42 import com.caucho.log.Log;
43 import com.caucho.sql.SQLExceptionWrapper;
44 import com.caucho.util.L10N;
45 import com.caucho.util.LruCache;
46 import com.caucho.vfs.Path;
47
48 import javax.annotation.PostConstruct;
49 import java.io.IOException JavaDoc;
50 import java.sql.SQLException JavaDoc;
51 import java.util.HashMap JavaDoc;
52 import java.util.logging.Level JavaDoc;
53 import java.util.logging.Logger JavaDoc;
54
55 /**
56  * Manager for a basic Java-based database.
57  */

58 public class Database {
59   private static final Logger JavaDoc log = Log.open(Database.class);
60   private static final L10N L = new L10N(Database.class);
61
62   private Path _dir;
63
64   private BlockManager _blockManager;
65   private HashMap JavaDoc<String JavaDoc,Table> _tables = new HashMap JavaDoc<String JavaDoc,Table>();
66
67   private LruCache<String JavaDoc,Query> _cachedQueries = new LruCache<String JavaDoc,Query>(128);
68
69   private Lock _databaseLock = new Lock("db");
70
71   private boolean _removeOnError;
72
73   private long _timeout = 1000L;
74
75   private final Lifecycle _lifecycle = new Lifecycle(log, null, Level.FINER);
76
77   /**
78    * Creates the database.
79    */

80   public Database()
81   {
82     this(null);
83   }
84
85   /**
86    * Creates the database.
87    */

88   public Database(Path dir)
89   {
90     Environment.addClassLoaderListener(new CloseListener(this));
91
92     _lifecycle.setName(toString());
93
94     if (dir != null)
95       setPath(dir);
96
97     long minSize = 8 * 1024 * 1024;
98
99     long memorySize = Runtime.getRuntime().maxMemory() / 8;
100
101     if (minSize < memorySize)
102       minSize = memorySize;
103
104     _blockManager = BlockManager.create((int) (minSize / Store.BLOCK_SIZE));
105   }
106
107   /**
108    * Sets the directory.
109    */

110   public void setPath(Path dir)
111   {
112     _dir = dir;
113   }
114
115   /**
116    * Set if error tables should be removed.
117    */

118   public void setRemoveOnError(boolean remove)
119   {
120     _removeOnError = remove;
121   }
122
123   /**
124    * Ensure a minimum memory size.
125    *
126    * @param minCapacity the minimum capacity in bytes
127    */

128   public void ensureMemoryCapacity(long minCapacity)
129   {
130     int minBlocks = (int) ((minCapacity + Store.BLOCK_SIZE - 1) /
131                            Store.BLOCK_SIZE);
132
133     _blockManager.ensureCapacity(minBlocks);
134   }
135
136   /**
137    * Initializes the database. All *.db files in the database directory
138    * are read for stored tables.
139    */

140   @PostConstruct
141   public void init()
142     throws SQLException JavaDoc
143   {
144     if (! _lifecycle.toActive())
145       return;
146
147     Path dir = _dir;
148
149     if (dir != null) {
150       String JavaDoc []list = null;
151
152       try {
153     list = dir.list();
154       } catch (IOException JavaDoc e) {
155     log.log(Level.WARNING, e.toString(), e);
156       }
157
158       for (int i = 0; i < list.length; i++) {
159     String JavaDoc name = list[i];
160
161     if (! name.endsWith(".db"))
162       continue;
163
164     name = name.substring(0, name.length() - 3);
165
166     try {
167       Table table = Table.loadFromFile(this, name);
168
169       table.init();
170
171       _tables.put(name, table);
172     } catch (Throwable JavaDoc e) {
173       if (_removeOnError) {
174         if (log.isLoggable(Level.FINER))
175           log.log(Level.FINER, e.toString(), e);
176         else
177           log.warning(e.toString());
178
179         try {
180           dir.lookup(name + ".db").remove();
181         } catch (IOException JavaDoc e1) {
182         }
183       }
184       else
185         throw new SQLExceptionWrapper(e);
186     }
187       }
188     }
189   }
190
191   /**
192    * Returns the path.
193    */

194   public Path getPath()
195   {
196     return _dir;
197   }
198
199   /**
200    * Returns the block manager.
201    */

202   public BlockManager getBlockManager()
203   {
204     return _blockManager;
205   }
206
207   /**
208    * Returns the database lock.
209    */

210   public Lock getDatabaseLock()
211   {
212     return _databaseLock;
213   }
214
215   /**
216    * Creates a table factory.
217    */

218   public TableFactory createTableFactory()
219   {
220     return new TableFactory(this);
221   }
222
223   /**
224    * Adds a table.
225    */

226   public void addTable(Table table)
227     throws IOException JavaDoc
228   {
229     log.fine("adding table " + table.getName());
230
231     table.init();
232
233     _tables.put(table.getName(), table);
234   }
235
236   /**
237    * Gets a table.
238    */

239   public Table getTable(String JavaDoc name)
240   {
241     return _tables.get(name);
242   }
243
244   /**
245    * Drops a table.
246    */

247   public void dropTable(String JavaDoc name)
248     throws SQLException JavaDoc
249   {
250     Table table = null;
251
252     synchronized (this) {
253       table = _tables.get(name);
254       if (table == null)
255     throw new SQLException JavaDoc(L.l("Table {0} does not exist. DROP TABLE can only drop an existing table.",
256                    name));
257
258       _tables.remove(name);
259
260       _cachedQueries.clear();
261     }
262
263     table.remove();
264   }
265
266   /**
267    * Updates the database.
268    */

269   /*
270   public void update(String sql, Transaction xa)
271     throws SQLException
272   {
273     Query query = parseQuery(sql);
274
275     query.execute(xa);
276   }
277   */

278
279   /**
280    * Queries the database.
281    */

282   /*
283   public ResultSetImpl query(String sql, Transaction xa)
284     throws SQLException
285   {
286     Query query = parseQuery(sql);
287
288     return query.execute(xa);
289   }
290   */

291
292   /**
293    * Parses a query.
294    */

295   public Query parseQuery(String JavaDoc sql)
296     throws SQLException JavaDoc
297   {
298     // XXX: currently, can't cache because the params are improperly shared
299
/*
300     Query query = _cachedQueries.get(sql);
301
302     if (query == null) {
303       query = Parser.parse(this, sql);
304       _cachedQueries.put(sql, query);
305     }
306     */

307     if (log.isLoggable(Level.FINER))
308       log.finer(this + ": " + sql);
309     
310     Query query = Parser.parse(this, sql);
311
312     return query;
313   }
314
315   /*
316   public void lockRead(Transaction xa, long lockId)
317     throws SQLException
318   {
319     Lock databaseLock = _databaseLock;
320
321     try {
322       synchronized (databaseLock) {
323     if (xa.hasReadLock(databaseLock))
324       return;
325
326     databaseLock.lockRead(xa, _timeout);
327
328     xa.addReadLock(databaseLock);
329       }
330     } catch (SQLException e) {
331       xa.setRollbackOnly(e);
332     }
333   }
334   */

335
336   /**
337    * Closes the database.
338    */

339   public void close()
340   {
341     if (! _lifecycle.toDestroy())
342       return;
343
344     for (Table table : _tables.values()) {
345       try {
346     table.close();
347       } catch (Throwable JavaDoc e) {
348     log.log(Level.WARNING, e.toString(), e);
349       }
350     }
351   }
352
353   public String JavaDoc toString()
354   {
355     return "Database[" + _dir + "]";
356   }
357 }
358
Popular Tags