Db4o input/output implementation comes as a pluggable module. It means that you can write your own IO system based on IoAdapter class.
Pluggable IO Adapter has control over the following:
Some of the popular implementations of IoAdapter:
You can look at the db4o source to see some of these implementations (search for classes inheriting from IoAdapter).
By default db4o uses RandomAccessFileAdapter. You can install another IoAdapter with a single call:
Java: Db4o.configure().io(new SpecificIoAdapter())
Please, note: this call should be issued before opening of a database file. IoAdapter can be changed only while the database is closed.
For a test, let's try to create debugging IoAdapter, which will log all the information about its actions to the output stream:
001/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 002
003
package com.db4odoc.ios; 004
005
import java.io.File; 006
import java.io.IOException; 007
import java.io.PrintStream; 008
import java.io.RandomAccessFile; 009
010
import com.db4o.DTrace; 011
import com.db4o.ext.DatabaseFileLockedException; 012
import com.db4o.ext.Db4oIOException; 013
import com.db4o.internal.Platform4; 014
import com.db4o.io.IoAdapter; 015
016
public class LoggingAdapter extends IoAdapter { 017
018
@Override 019
public IoAdapter open(String path, boolean lockFile, long initialLength, boolean readOnly) throws Db4oIOException { 020
_out.println("Opening file " + path); 021
return new LoggingAdapter(path, lockFile, initialLength, readOnly); 022
} 023
024
025
private String _path; 026
private RandomAccessFile _delegate; 027
private PrintStream _out = System.out; 028
029
public LoggingAdapter(){ 030
} 031
032
protected LoggingAdapter(String path, boolean lockFile, long initialLength, boolean readOnly) throws Db4oIOException { 033
try { 034
String mode = readOnly ? "r" : "rw"; 035
_path=new File(path).getCanonicalPath(); 036
_delegate = new RandomAccessFile(path, mode); 037
if(initialLength>0) { 038
_delegate.seek(initialLength - 1); 039
_delegate.write(new byte[] {0}); 040
} 041
if(lockFile){ 042
try { 043
Platform4.lockFile(_path, _delegate); 044
} catch (DatabaseFileLockedException e) { 045
_delegate.close(); 046
throw e; 047
} 048
} 049
} catch (IOException e) { 050
throw new Db4oIOException(e); 051
} 052
} 053
054
public void setOut(PrintStream out){ 055
_out = out; 056
} 057
058
public void close() throws Db4oIOException { 059
_out.println("Closing file"); 060
try { 061
Platform4.unlockFile(_path,_delegate); 062
_delegate.close(); 063
} catch (IOException e) { 064
throw new Db4oIOException(e); 065
} catch (Exception e) { 066
} 067
} 068
069
070
public void delete(String path) { 071
_out.println("Deleting file " + path); 072
new File(path).delete(); 073
} 074
075
public boolean exists(String path){ 076
File existingFile = new File(path); 077
return existingFile.exists() && existingFile.length() > 0; 078
} 079
080
public long getLength() throws Db4oIOException { 081
long length; 082
try { 083
_out.println("File length:" + _delegate.length()); 084
length = _delegate.length(); 085
} catch (IOException e) { 086
throw new Db4oIOException(e); 087
} 088
return length; 089
} 090
091
public int read(byte[] bytes, int length) throws Db4oIOException { 092
int readBytes; 093
try { 094
_out.println("Reading " + length + " bytes"); 095
readBytes = _delegate.read(bytes, 0, length); 096
} catch (IOException e) { 097
throw new Db4oIOException(e); 098
} 099
return readBytes; 100
} 101
102
103
public void seek(long pos) throws Db4oIOException { 104
105
if(DTrace.enabled){ 106
DTrace.REGULAR_SEEK.log(pos); 107
} 108
try { 109
_out.println("Setting pointer position to " + pos); 110
_delegate.seek(pos); 111
} catch (IOException e) { 112
throw new Db4oIOException(e); 113
} 114
} 115
116
117
public void sync() throws Db4oIOException { 118
_out.println("Synchronizing"); 119
try { 120
_delegate.getFD().sync(); 121
} catch (IOException e) { 122
throw new Db4oIOException(e); 123
} 124
} 125
126
127
public void write(byte[] buffer, int length) throws Db4oIOException { 128
_out.println("Writing " + length + " bytes"); 129
try { 130
_delegate.write(buffer, 0, length); 131
} catch (IOException e) { 132
new Db4oIOException(e); 133
} 134
135
} 136
137
}
Now let's test how it works:
01private static void testLoggingAdapter(){ 02
Configuration configuration = Db4o.newConfiguration(); 03
configuration.io(new LoggingAdapter()); 04
ObjectServer server = Db4o.openServer(configuration, DB4O_FILE_NAME, 0xdb40); 05
server.grantAccess("y", "y"); 06
ObjectContainer container = server.openClient(); 07
//ObjectContainer container = Db4o.openClient(configuration, "localhost", 0xdb40,"y", "y"); 08
try { 09
Pilot pilot = new Pilot("Michael Schumacher"); 10
container.set(pilot); 11
System.out.println("New pilot added"); 12
} finally { 13
14
container.close(); 15
server.close(); 16
} 17
18
container = Db4o.openFile(DB4O_FILE_NAME); 19
try { 20
ObjectSet result=container.get(Pilot.class); 21
listResult(result); 22
} finally { 23
container.close(); 24
} 25
}
The output can be used for debugging purposes.