00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 package org.openmobileis.database.fastobjectdb.db.store;
00030
00031 import java.io.*;
00032
00033 import org.openmobileis.database.fastobjectdb.db.index.node.Node;
00034 import org.openmobileis.database.fastobjectdb.db.transaction.TransactionFile;
00035
00043 public class FODBObjectDatabaseFile implements TransactionFile {
00044
00045
00046
00047 protected static final long DEL_LIST_END = -1l;
00048 protected static final byte IS_DELETED = 0;
00049 protected static final byte IS_ACTIVE = 1;
00050
00051
00052
00053
00054 protected RandomAccessFile dataFile;
00055 protected String fileName;
00056 protected long firstDel = DEL_LIST_END;
00057
00058
00059
00060
00061 public FODBObjectDatabaseFile(String name) throws IOException {
00062 fileName = new String(name);
00063 }
00064
00065 public FODBObjectDatabaseFile(File file) throws IOException {
00066 fileName = new String(file.getName());
00067 }
00068
00069 protected void constructorHelper() throws IOException {
00070 dataFile.seek(0);
00071 if (dataFile.length() == 0) {
00072 dataFile.writeLong(DEL_LIST_END);
00073 firstDel = DEL_LIST_END;
00074 } else
00075 firstDel = dataFile.readLong();
00076 }
00077
00078
00079
00080
00081
00082
00083 public long writeObject(Object obj) throws IOException {
00084 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
00085 ObjectOutputStream ostrm = new ObjectOutputStream(bytes);
00086 ostrm.writeObject(obj);
00087 ostrm.flush();
00088
00089
00090 int datalen = bytes.size();
00091 int reclen = datalen;
00092 long pos;
00093
00094
00095 if (firstDel == DEL_LIST_END) {
00096 pos = dataFile.length();
00097 dataFile.seek(pos);
00098 } else {
00099
00100 long prev = DEL_LIST_END;
00101
00102 pos = firstDel;
00103
00104 while (true) {
00105 dataFile.seek(pos);
00106
00107
00108 byte deleted = dataFile.readByte();
00109 dataFile.readInt();
00110 reclen = dataFile.readInt();
00111
00112 long next = dataFile.readLong();
00113
00114
00115 if (deleted == IS_ACTIVE)
00116 throw new IOException("corrupt delete list");
00117
00118
00119 if (reclen >= datalen) {
00120 if (prev == DEL_LIST_END) {
00121 firstDel = next;
00122
00123
00124 dataFile.seek(0);
00125 dataFile.writeLong(firstDel);
00126 } else {
00127
00128 dataFile.seek(prev + 1 + 4 + 4);
00129 dataFile.writeLong(next);
00130 }
00131
00132 dataFile.seek(pos);
00133
00134 break;
00135 }
00136
00137
00138 prev = pos;
00139
00140
00141 if (next == DEL_LIST_END) {
00142 pos = dataFile.length();
00143 dataFile.seek(pos);
00144 reclen = datalen;
00145
00146 break;
00147 } else
00148 pos = next;
00149 }
00150 }
00151
00152
00153 if ((obj instanceof Node)) {
00154 ((Node) obj).filePtr = pos;
00155 bytes = new ByteArrayOutputStream();
00156 ostrm = new ObjectOutputStream(bytes);
00157 ostrm.writeObject(obj);
00158 ostrm.flush();
00159
00160
00161
00162
00163
00164 }
00165
00166 dataFile.writeByte(IS_ACTIVE);
00167 dataFile.writeInt(datalen);
00168 dataFile.writeInt(reclen);
00169
00170
00171
00172
00173
00174 dataFile.writeLong(DEL_LIST_END);
00175 dataFile.write(bytes.toByteArray());
00176
00177 return pos;
00178 }
00179
00180
00181 public void rewriteObject(Object obj) throws IOException {
00182 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
00183 ObjectOutputStream ostrm = new ObjectOutputStream(bytes);
00184 ostrm.writeObject(obj);
00185 ostrm.flush();
00186
00187
00188 int datalen = bytes.size();
00189 int reclen = datalen;
00190
00191
00192 long pos = dataFile.getFilePointer();
00193 dataFile.skipBytes(5);
00194 int oldreclen = dataFile.readInt();
00195 dataFile.seek(pos);
00196
00197 if (oldreclen < datalen) {
00198 throw new IOException("ERROR FODBObjectDatabaseFile : rewriteObject : object to big to be rewritten." + obj.getClass().getName());
00199 }
00200
00201
00202 dataFile.writeByte(IS_ACTIVE);
00203
00204
00205 dataFile.writeInt(datalen);
00206
00207
00208
00209 dataFile.skipBytes(4);
00210
00211
00212 dataFile.writeLong(DEL_LIST_END);
00213
00214
00215 dataFile.write(bytes.toByteArray());
00216 }
00217
00218
00219 public Object readObject() throws IOException, ClassNotFoundException {
00220
00221 byte deleted = dataFile.readByte();
00222
00223
00224 if (deleted != IS_ACTIVE)
00225 throw new IOException("Try to read where there is no record");
00226
00227 int datalen = dataFile.readInt();
00228
00229
00230 int reclen = dataFile.readInt();
00231
00232
00233 dataFile.skipBytes(8);
00234
00235
00236 byte[] data = new byte[datalen];
00237 dataFile.readFully(data);
00238
00239
00240 int diff = reclen - datalen;
00241
00242 if (diff > 0)
00243 dataFile.skipBytes(diff);
00244
00245 ByteArrayInputStream bytes = new ByteArrayInputStream(data);
00246 ObjectInputStream istrm = new ObjectInputStream(bytes);
00247 return istrm.readObject();
00248 }
00249
00250
00251 public void delete() throws IOException {
00252
00253 long pos = dataFile.getFilePointer();
00254
00255
00256 byte deleted = dataFile.readByte();
00257
00258 if (deleted == IS_DELETED)
00259 return;
00260
00261
00262 dataFile.seek(pos);
00263 dataFile.writeByte(IS_DELETED);
00264
00265
00266 dataFile.skipBytes(4 + 4);
00267 dataFile.writeLong(firstDel);
00268
00269
00270 firstDel = pos;
00271 dataFile.seek(0);
00272 dataFile.writeLong(firstDel);
00273 }
00274
00275
00276 public void rewind() throws IOException {
00277 dataFile.seek(8);
00278 }
00279
00280
00281 public void skip() throws IOException {
00282
00283 dataFile.skipBytes(1 + 4);
00284
00285
00286 int reclen = dataFile.readInt();
00287
00288
00289 dataFile.skipBytes(8 + reclen);
00290 }
00291
00292 public String getFileName() {
00293 return fileName;
00294 }
00295
00296
00297
00298
00299 public final FileDescriptor getFD() throws IOException {
00300 return dataFile.getFD();
00301 }
00302
00303 public long getFilePointer() throws IOException {
00304 return dataFile.getFilePointer();
00305 }
00306
00307 public void seek(long pos) throws IOException {
00308 dataFile.seek(pos);
00309 }
00310
00311 public long length() throws IOException {
00312 return dataFile.length();
00313 }
00314
00315 public void close() throws IOException {
00316 if (dataFile != null) {
00317 dataFile.close();
00318 dataFile = null;
00319 }
00320 }
00321
00322 public void open() throws IOException {
00323 try {
00324 dataFile = new RandomAccessFile(fileName, "rw");
00325 constructorHelper();
00326 } catch (Throwable ex) {
00327 try {
00328 if (dataFile != null) {
00329 dataFile.close();
00330 }
00331 } catch (Throwable exi) {
00332 org.openmobileis.common.util.log.LogManager.traceError(0, "ObjectDatabaseFile constructorHelper error :" + exi.getMessage());
00333 }
00334 throw new IOException(ex.getMessage());
00335 }
00336 }
00337 }