/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.io; import java.io.*; import com.db4o.*; import com.db4o.ext.*; import com.db4o.foundation.io.*; import com.db4o.internal.*; /** * Storage adapter to store db4o database data to physical * files on hard disc. */ public class FileStorage implements Storage { /** * opens a {@link Bin} on the specified URI (file system path). */ public Bin open(BinConfiguration config) throws Db4oIOException { return new FileBin(config); } /** * returns true if the specified file system path already exists. */ public boolean exists(String uri) { final File file = new File(uri); return file.exists() && file.length() > 0; } public static class FileBin implements Bin { private final String _path; private RandomAccessFile _file; public FileBin(BinConfiguration config) throws Db4oIOException { boolean ok = false; try { _path = new File(config.uri()).getCanonicalPath(); _file = RandomAccessFileFactory.newRandomAccessFile(_path, config.readOnly(), config.lockFile()); if (config.initialLength() > 0) { write(config.initialLength() - 1, new byte[] { 0 }, 1); } ok = true; } catch (IOException e) { throw new Db4oIOException(e); } finally { if(!ok) { close(); } } } public void close() throws Db4oIOException { Platform4.unlockFile(_path, _file); try { if (!isClosed()) { _file.close(); } } catch (IOException e) { throw new Db4oIOException(e); } finally { _file = null; } } boolean isClosed() { return _file == null; } public long length() throws Db4oIOException { try { return _file.length(); } catch (IOException e) { throw new Db4oIOException(e); } } public int read(long pos, byte[] bytes, int length) throws Db4oIOException { try { seek(pos); if(DTrace.enabled){ DTrace.FILE_READ.logLength(pos, length); } return _file.read(bytes, 0, length); } catch (IOException e) { throw new Db4oIOException(e); } } void seek(long pos) throws IOException { if (DTrace.enabled) { DTrace.REGULAR_SEEK.log(pos); } _file.seek(pos); } public void sync() throws Db4oIOException { try { _file.getFD().sync(); } catch (IOException e) { throw new Db4oIOException(e); } } public int syncRead(long position, byte[] bytes, int bytesToRead) { return read(position, bytes, bytesToRead); } public void write(long pos, byte[] buffer, int length) throws Db4oIOException { checkClosed(); try { seek(pos); if(DTrace.enabled){ DTrace.FILE_WRITE.logLength(pos, length); } _file.write(buffer, 0, length); } catch (IOException e) { throw new Db4oIOException(e); } } private void checkClosed() { if (isClosed()) { throw new Db4oIOException(); } } public void sync(Runnable runnable) { sync(); runnable.run(); sync(); } } public void delete(String uri) throws IOException { File4.delete(uri); } public void rename(String oldUri, String newUri) throws IOException { File4.rename(oldUri, newUri); } }