RuneHive-Game
Loading...
Searching...
No Matches
Cache.java
Go to the documentation of this file.
1package com.runehive.fs.cache;
2
3import com.google.common.base.Preconditions;
4
5import java.io.IOException;
6import java.nio.ByteBuffer;
7import java.nio.channels.SeekableByteChannel;
8
9/**
10 * Represents a {@link Sector} and {@link Index} cache.
11 * @author Artem Batutin <artembatutin@gmail.com>
12 * @author Ryley Kimmel <ryley.kimmel@live.com>
13 */
14public final class Cache {
15
16 /**
17 * Represents the size of a index file.
18 * Calculating the total size of a index file. the total size may be that of a {@code long}.
19 */
20 public static final int INDEX_SIZE = 6;
21
22 /**
23 * Represents the size of a {@link Sector}s header.
24 * Calculating the total size of the sector header. the total size may be that of a {@code long}.
25 */
26 public static final int SECTOR_HEADER_SIZE = 8;
27
28 /**
29 * Represents the size of a {@link Sector}s header.
30 * Calculating the total size of the sector header. the total size may be that of a {@code long}
31 */
32 public static final int SECTOR_SIZE = 520;
33
34 /**
35 * A {@link ByteBuffer} allocated to {@link #SECTOR_SIZE}.
36 * <p>
37 * This byte buffer is used to read index and sector data from their
38 * respective byte channels.
39 * </p>
40 */
41 private final ByteBuffer buffer = ByteBuffer.allocate(SECTOR_SIZE);
42
43 /**
44 * A byte channel that contains a series of variable-length bytes which
45 * represent a sector.
46 */
47 private final SeekableByteChannel sectorChannel;
48
49 /**
50 * A byte channel that contains a series of variable-length bytes which
51 * represent a index.
52 */
53 private final SeekableByteChannel indexChannel;
54
55 /**
56 * Represents the id of this {@link Cache}.
57 */
58 private final int id;
59
60 /**
61 * Constructs a new {@link Cache} with the specified sector and index
62 * channels and id.
63 * @param sectorChannel The cache sectors byte channel.
64 * @param indexChannel The cache sectors index channel.
65 * @param id This caches id.
66 */
67 protected Cache(SeekableByteChannel sectorChannel, SeekableByteChannel indexChannel, int id) {
68 this.sectorChannel = sectorChannel;
69 this.indexChannel = indexChannel;
70 this.id = ++id;
71 }
72
73 /**
74 * Gets a {@link ByteBuffer} of data within this cache for the specified
75 * index id.
76 * @param indexId The file id to get.
77 * @return A wrapped byte buffer of the specified files data, never
78 * {@code null}.
79 * @throws IOException If some I/O exception occurs.
80 */
81 public ByteBuffer get(final int indexId) throws IOException {
82 final Index index = readIndex(indexId);
83 if (!index.check()) {
84 return null;
85 }
86
87 long position = (long) index.getId() * SECTOR_HEADER_SIZE;
88
89 Preconditions.checkArgument(sectorChannel.size() >= position + SECTOR_SIZE);
90
91 byte[] data = new byte[index.getLength()];
92 int next = index.getId();
93 int offset = 0;
94
95 for (int chunk = 0; offset < index.getLength(); chunk++) {
96 int read = Math.min(index.getLength() - offset, 512);
97
98 Sector sector = readSector(next, data, offset, read);
99 sector.check(id, indexId, chunk);
100
101 next = sector.getNextIndexId();
102 offset += read;
103 }
104
105 return ByteBuffer.wrap(data);
106 }
107
108 /**
109 * Reads an {@link Index} for the specified {@code indexId} and returns the
110 * decoded data.
111 * @param indexId The id of the index to read.
112 * @return The decoded index.
113 * @throws IOException If some I/O exception occurs.
114 */
115 private Index readIndex(int indexId) throws IOException {
116 long position = (long) indexId * INDEX_SIZE;
117
118 buffer.clear().limit(INDEX_SIZE);
119 indexChannel.position(position);
120 indexChannel.read(buffer);
121 buffer.flip();
122
123 return Index.decode(buffer);
124 }
125
126 /**
127 * Reads a {@link Sector} for the specified {@code sectorId} and returns the
128 * decoded data.
129 * @param sectorId The id of the sector to read.
130 * @param data The sectors data.
131 * @param offset The sectors data offset.
132 * @param length The length of the sectors data.
133 * @return The decoded sector.
134 * @throws IOException If some I/O exception occurs.
135 */
136 private Sector readSector(int sectorId, byte[] data, int offset, int length) throws IOException {
137 long position = (long) sectorId * SECTOR_SIZE;
138
139 buffer.clear().limit(length + SECTOR_HEADER_SIZE);
140 sectorChannel.position(position);
141 sectorChannel.read(buffer);
142 buffer.flip();
143
144 return Sector.decode(buffer, data, offset, length);
145 }
146
147}
Sector readSector(int sectorId, byte[] data, int offset, int length)
Reads a Sector for the specified sectorId and returns the decoded data.
Definition Cache.java:136
static final int INDEX_SIZE
Represents the size of a index file.
Definition Cache.java:20
final int id
Represents the id of this Cache.
Definition Cache.java:58
final SeekableByteChannel indexChannel
A byte channel that contains a series of variable-length bytes which represent a index.
Definition Cache.java:53
Index readIndex(int indexId)
Reads an Index for the specified indexId and returns the decoded data.
Definition Cache.java:115
static final int SECTOR_HEADER_SIZE
Represents the size of a Sectors header.
Definition Cache.java:26
static final int SECTOR_SIZE
Represents the size of a Sectors header.
Definition Cache.java:32
Cache(SeekableByteChannel sectorChannel, SeekableByteChannel indexChannel, int id)
Constructs a new Cache with the specified sector and index channels and id.
Definition Cache.java:67
final ByteBuffer buffer
A ByteBuffer allocated to SECTOR_SIZE.
Definition Cache.java:41
final SeekableByteChannel sectorChannel
A byte channel that contains a series of variable-length bytes which represent a sector.
Definition Cache.java:47
Represents an index within some Cache.
Definition Index.java:13
static Index decode(ByteBuffer buffer)
Decodes an Index from the specified ByteBuffer.
Definition Index.java:40
Represents a sector within some Cache.
Definition Sector.java:13
void check(int cacheId, int indexId, int chunk)
Tests whether or not this sector is valid.
Definition Sector.java:70
int getNextIndexId()
Returns the next index within this sector.
Definition Sector.java:87
static Sector decode(ByteBuffer buffer, byte[] data, int offset, int length)
Decodes a Sector from the specified ByteBuffer.
Definition Sector.java:54