3import java.io.Closeable;
5import java.io.FileNotFoundException;
6import java.io.IOException;
7import java.io.RandomAccessFile;
8import java.nio.ByteBuffer;
9import java.util.zip.CRC32;
10import java.util.zip.GZIPOutputStream;
30 private RandomAccessFile[]
indices =
new RandomAccessFile[256];
35 private RandomAccessFile
data;
68 for (
int index = 0; index <
indices.length; index++) {
69 File f =
new File(base.getAbsolutePath() +
"/main_file_cache.idx" + index);
70 if (f.exists() && !f.isDirectory()) {
75 if (indexCount <= 0) {
76 throw new Exception(
"No index file(s) present");
79 File oldEngineData =
new File(base.getAbsolutePath() +
"/main_file_cache.dat");
80 File newEngineData =
new File(base.getAbsolutePath() +
"/main_file_cache.dat2");
81 if (oldEngineData.exists() && !oldEngineData.isDirectory()) {
82 data =
new RandomAccessFile(oldEngineData,
readOnly ?
"r" :
"rw");
83 }
else if (newEngineData.exists() && !oldEngineData.isDirectory()) {
84 data =
new RandomAccessFile(newEngineData,
readOnly ?
"r" :
"rw");
86 throw new Exception(
"No data file present");
102 int index = fd.getType();
103 if (index < 0 || index >=
indices.length) {
104 throw new IndexOutOfBoundsException();
108 RandomAccessFile indexFile =
indices[index];
109 synchronized (indexFile) {
113 indexFile.readFully(buffer);
115 throw new FileNotFoundException();
129 if (type < 0 || type >=
indices.length) {
130 throw new IndexOutOfBoundsException();
133 RandomAccessFile indexFile =
indices[type];
134 synchronized (indexFile) {
146 synchronized (
this) {
159 int[] crcs =
new int[archives];
162 CRC32 crc32 =
new CRC32();
163 for (
int i = 1; i < crcs.length; i++) {
167 byte[]
bytes =
new byte[bb.remaining()];
171 crcs[i] = (int) crc32.getValue();
175 ByteBuffer buf = ByteBuffer.allocate(crcs.length * 4 + 4);
176 for (
int i = 0; i < crcs.length; i++) {
177 hash = (hash << 1) + crcs[i];
185 synchronized (
this) {
190 throw new IOException(
"cannot get CRC table from a writable file system");
203 public static byte[]
gzip(
byte[]
bytes)
throws IOException {
205 InputStream is =
new ByteArrayInputStream(
bytes);
207 ByteArrayOutputStream bout =
new ByteArrayOutputStream();
208 OutputStream os =
new GZIPOutputStream(bout);
211 byte[] buf =
new byte[4096];
213 while ((len = is.read(buf, 0, buf.length)) != -1) {
214 os.write(buf, 0, len);
221 return bout.toByteArray();
241 CRC32 crc32 =
new CRC32();
263 for(
int i = 0; i < 6; i++) {
268 ByteBuffer buf = ByteBuffer.allocate(bufLen);
271 for(
int i = 0; i < 6; i++) {
274 buf.put((
byte) (value >> 16));
275 buf.put((
byte) (value >> 8));
276 buf.put((
byte) value);
277 for(
int f = 0; f < value; f++) {
280 byte[]
bytes =
new byte[bb.remaining()];
285 buf.putInt((
int) crc32.getValue());
290 byte[] uncompressed =
new byte[buf.remaining()];
292 buf.get(uncompressed);
295 byte[] compressed =
gzip(uncompressed);
296 System.out.println(
"comp" + compressed.length);
304 synchronized (
this) {
319 int[] crcs =
new int[archives];
322 CRC32 crc32 =
new CRC32();
323 for (
int i = 1; i < crcs.length; i++) {
327 byte[]
bytes =
new byte[bb.remaining()];
331 crcs[i] = (int) crc32.getValue();
335 ByteBuffer buf = ByteBuffer.allocate(crcs.length * 4 + 4);
336 for (
int i = 0; i < crcs.length; i++) {
337 hash = (hash << 1) + crcs[i];
345 synchronized (
this) {
350 throw new IOException(
"cannot get CRC table from a writable file system");
361 public ByteBuffer
getFile(
int type,
int file)
throws IOException {
373 ByteBuffer buffer = ByteBuffer.allocate(index.getSize());
378 int size = index.getSize();
384 for (
int i = 0; i < blocks; i++) {
388 synchronized (
data) {
390 data.readFully(header);
397 int nextFile = ((header[0] & 0xFF) << 8) | (header[1] & 0xFF);
398 int curChunk = ((header[2] & 0xFF) << 8) | (header[3] & 0xFF);
399 int nextBlock = ((header[4] & 0xFF) << 16) | ((header[5] & 0xFF) << 8) | (header[6] & 0xFF);
400 int nextType = header[7] & 0xFF;
404 throw new IOException(
"Chunk id mismatch.");
408 int chunkSize = size - read;
414 byte[] chunk =
new byte[chunkSize];
415 synchronized (
data) {
417 data.readFully(chunk);
428 if (nextType != (fd.getType() + 1)) {
429 throw new IOException(
"File type mismatch.");
432 if (nextFile != fd.getFile()) {
433 throw new IOException(
"File id mismatch.");
443 public void close() throws IOException {
445 synchronized (
data) {
450 for (RandomAccessFile index :
indices) {
452 synchronized (index) {
A class which points to a file in the cache.
Holds file system related constants.
static final int CHUNK_SIZE
The size of a chunk.
static final int HEADER_SIZE
The size of a header.
static final int BLOCK_SIZE
The size of a block.
static final int INDEX_SIZE
The size of an index.
An Index points to a file in the main_file_cache.dat file.
static Index decode(byte[] buffer)
Decodes a buffer into an index.
static byte[] gzip(byte[] bytes)
Compresses a GZIP file.
ByteBuffer getFile(int type, int file)
Gets a file.
Index getIndex(FileDescriptor fd)
Gets the index of a file.
IndexedFileSystem(File base, boolean readOnly)
Creates the file system with the specified base directory.
ByteBuffer getJireCRCTable()
void detectLayout(File base)
Automatically detect the layout of the specified directory.
ByteBuffer getFile(FileDescriptor fd)
Gets a file.
final boolean readOnly
Read only flag.
ByteBuffer crcTable
The cached CRC table.
int getFileCount(int type)
Gets the number of files with the specified type.
boolean isReadOnly()
Checks if this IndexedFileSystem is read only.
ByteBuffer getCrcTable()
Gets the CRC table.
RandomAccessFile[] indices
The index files.
RandomAccessFile data
The data file.