001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.io;
022:
023: import com.db4o.*;
024: import com.db4o.foundation.*;
025:
026: /**
027: * IoAdapter for in-memory operation. <br>
028: * <br>
029: * Configure db4o to operate with this in-memory IoAdapter with
030: * <code>MemoryIoAdapter memoryIoAdapter = new MemoryIoAdapter();<br>
031: * Db4o.configure().io(memoryIoAdapter);</code><br>
032: * <br>
033: * <br>
034: * Use the normal #openFile() and #openServer() commands to open
035: * ObjectContainers and ObjectServers. The names specified as file names will be
036: * used to identify the <code>byte[]</code> content of the in-memory files in
037: * the _memoryFiles Hashtable in the adapter. After working with an in-memory
038: * ObjectContainer/ObjectServer the <code>byte[]</code> content is available
039: * in the MemoryIoAdapter by using {@link #get(String)}. To add old existing
040: * database <code>byte[]</code> content to a MemoryIoAdapter use
041: * {@link #put(String, byte[])}. To reduce memory consumption of memory file
042: * names that will no longer be used call {@link #put(String, byte[])} and pass
043: * an empty byte array.
044: */
045: public class MemoryIoAdapter extends IoAdapter {
046:
047: private byte[] _bytes;
048:
049: private int _length;
050:
051: private int _seekPos;
052:
053: private Hashtable4 _memoryFiles;
054:
055: private int _growBy;
056:
057: public MemoryIoAdapter() {
058: _memoryFiles = new Hashtable4();
059: _growBy = 10000;
060: }
061:
062: private MemoryIoAdapter(MemoryIoAdapter adapter, byte[] bytes) {
063: _bytes = bytes;
064: _length = bytes.length;
065: _growBy = adapter._growBy;
066: }
067:
068: private MemoryIoAdapter(MemoryIoAdapter adapter, int initialLength) {
069: this (adapter, new byte[initialLength]);
070: }
071:
072: /**
073: * creates an in-memory database with the passed content bytes and adds it
074: * to the adapter for the specified name.
075: *
076: * @param name
077: * the name to be use for #openFile() or #openServer() calls
078: * @param bytes
079: * the database content
080: */
081: public void put(String name, byte[] bytes) {
082: if (bytes == null) {
083: bytes = new byte[0];
084: }
085: _memoryFiles.put(name, new MemoryIoAdapter(this , bytes));
086: }
087:
088: /**
089: * returns the content bytes for a database with the given name.
090: *
091: * @param name
092: * the name to be use for #openFile() or #openServer() calls
093: * @return the content bytes
094: */
095: public byte[] get(String name) {
096: MemoryIoAdapter mia = (MemoryIoAdapter) _memoryFiles.get(name);
097: if (mia == null) {
098: return null;
099: }
100: return mia._bytes;
101: }
102:
103: /**
104: * configures the length a memory file should grow, if no more free slots
105: * are found within. <br>
106: * <br>
107: * Specify a large value (100,000 or more) for best performance. Specify a
108: * small value (100) for the smallest memory consumption. The default
109: * setting is 10,000.
110: *
111: * @param length
112: * the length in bytes
113: */
114: public void growBy(int length) {
115: if (length < 1) {
116: length = 1;
117: }
118: _growBy = length;
119: }
120:
121: /**
122: * for internal processing only.
123: */
124: public void close() throws Db4oIOException {
125: // do nothing
126: }
127:
128: public void delete(String path) {
129: _memoryFiles.remove(path);
130: }
131:
132: /**
133: * for internal processing only.
134: */
135: public boolean exists(String path) {
136: MemoryIoAdapter mia = (MemoryIoAdapter) _memoryFiles.get(path);
137: if (mia == null) {
138: return false;
139: }
140: return mia._length > 0;
141: }
142:
143: /**
144: * for internal processing only.
145: */
146: public long getLength() throws Db4oIOException {
147: return _length;
148: }
149:
150: /**
151: * for internal processing only.
152: */
153: public IoAdapter open(String path, boolean lockFile,
154: long initialLength, boolean readOnly)
155: throws Db4oIOException {
156: MemoryIoAdapter mia = (MemoryIoAdapter) _memoryFiles.get(path);
157: if (mia == null) {
158: mia = new MemoryIoAdapter(this , (int) initialLength);
159: _memoryFiles.put(path, mia);
160: }
161: return mia;
162: }
163:
164: /**
165: * for internal processing only.
166: */
167: public int read(byte[] bytes, int length) throws Db4oIOException {
168: System.arraycopy(_bytes, _seekPos, bytes, 0, length);
169: _seekPos += length;
170: return length;
171: }
172:
173: /**
174: * for internal processing only.
175: */
176: public void seek(long pos) throws Db4oIOException {
177: _seekPos = (int) pos;
178: }
179:
180: /**
181: * for internal processing only.
182: */
183: public void sync() throws Db4oIOException {
184: }
185:
186: /**
187: * for internal processing only.
188: */
189: public void write(byte[] buffer, int length) throws Db4oIOException {
190: if (_seekPos + length > _bytes.length) {
191: int growBy = _growBy;
192: if (_seekPos + length > growBy) {
193: growBy = _seekPos + length;
194: }
195: byte[] temp = new byte[_bytes.length + growBy];
196: System.arraycopy(_bytes, 0, temp, 0, _length);
197: _bytes = temp;
198: }
199: System.arraycopy(buffer, 0, _bytes, _seekPos, length);
200: _seekPos += length;
201: if (_seekPos > _length) {
202: _length = _seekPos;
203: }
204: }
205:
206: }
|