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 java.io.*;
024:
025: import com.db4o.*;
026:
027: /**
028: * Workaround for two I/O bugs in Symbian JDK versions:<br>
029: * - seek() cannot move beyond the current file length.<br>
030: * Fix: Write padding bytes up to the seek target if necessary<br>
031: * - Under certain (rare) conditions, calls to RAF.length() seems
032: * to garble up following reads.<br>
033: * Fix: Use a second RAF handle to the file for length() calls
034: * only.<br><br>
035: *
036: * <b>Usage:</b><br>
037: * Db4o.configure().io(new com.db4o.io.SymbianIoAdapter())<br><br>
038: *
039: * TODO:<br>
040: * - BasicClusterTest C/S fails (in AllTests context only)
041: *
042: * @sharpen.ignore
043: */
044: public class SymbianIoAdapter extends RandomAccessFileAdapter {
045: private byte[] _seekBytes = new byte[500];
046: private String _path;
047: private long _pos;
048: private long _length;
049:
050: protected SymbianIoAdapter(String path, boolean lockFile,
051: long initialLength, boolean readOnly)
052: throws Db4oIOException {
053: super (path, lockFile, initialLength, readOnly);
054: _path = path;
055: _pos = 0;
056: setLength();
057: }
058:
059: private void setLength() throws Db4oIOException {
060: _length = retrieveLength();
061: }
062:
063: private long retrieveLength() throws Db4oIOException {
064: RandomAccessFile file = null;
065: try {
066: file = new RandomAccessFile(_path, "r");
067: return file.length();
068: } catch (IOException e) {
069: throw new Db4oIOException(e);
070: } finally {
071: try {
072: if (file != null) {
073: file.close();
074: }
075: } catch (IOException e) {
076: throw new Db4oIOException(e);
077: }
078: }
079: }
080:
081: public SymbianIoAdapter() {
082: super ();
083: }
084:
085: public IoAdapter open(String path, boolean lockFile,
086: long initialLength, boolean readOnly)
087: throws Db4oIOException {
088: return new SymbianIoAdapter(path, lockFile, initialLength,
089: readOnly);
090: }
091:
092: public long getLength() throws Db4oIOException {
093: setLength();
094: return _length;
095: }
096:
097: public int read(byte[] bytes, int length) throws Db4oIOException {
098: int ret = super .read(bytes, length);
099: _pos += ret;
100: return ret;
101: }
102:
103: public void write(byte[] buffer, int length) throws Db4oIOException {
104: super .write(buffer, length);
105: _pos += length;
106: if (_pos > _length) {
107: setLength();
108: }
109: }
110:
111: public void seek(long pos) throws Db4oIOException {
112: if (pos > _length) {
113: setLength();
114: }
115: if (pos > _length) {
116: int len = (int) (pos - _length);
117: super .seek(_length);
118: _pos = _length;
119: if (len < 500) {
120: write(_seekBytes, len);
121: } else {
122: write(new byte[len]);
123: }
124: }
125: super.seek(pos);
126: _pos = pos;
127: }
128: }
|