@@ -98,10 +98,8 @@ public class RegionFile {
98
98
99
99
private static final byte [] emptySector = new byte [SECTOR_BYTES ];
100
100
private final int [] offsets ;
101
- private final int [] chunkTimestamps ;
102
101
private RandomAccessFile file ;
103
102
private BitSet sectorsUsed ;
104
- private int totalSectors ;
105
103
private final AtomicInteger sizeDelta = new AtomicInteger ();
106
104
/**
107
105
* Returns the modification timestamp of the region file when it was first opened by this
@@ -121,7 +119,6 @@ public class RegionFile {
121
119
*/
122
120
public RegionFile (File path ) throws IOException {
123
121
offsets = new int [SECTOR_INTS ];
124
- chunkTimestamps = new int [SECTOR_INTS ];
125
122
126
123
sizeDelta .set (0 );
127
124
@@ -167,24 +164,24 @@ public RegionFile(File path) throws IOException {
167
164
}
168
165
169
166
// set up the available sector map
170
- totalSectors = (int ) file .length () / SECTOR_BYTES ;
167
+ int totalSectors = (int ) Math . ceil ( file .length () / ( double ) SECTOR_BYTES ) ;
171
168
sectorsUsed = new BitSet (totalSectors );
172
169
173
- sectorsUsed . set ( 0 );
174
- sectorsUsed .set (1 );
170
+ // reserve the first two sectors
171
+ sectorsUsed .set (0 , 2 );
175
172
176
173
// read offset table and timestamp tables
177
174
file .seek (0 );
178
175
179
- ByteBuffer header = ByteBuffer .allocate (2 * SECTOR_BYTES );
176
+ ByteBuffer header = ByteBuffer .allocate (SECTOR_BYTES );
180
177
while (header .hasRemaining ()) {
181
178
if (file .getChannel ().read (header ) == -1 ) {
182
179
throw new EOFException ();
183
180
}
184
181
}
185
- header .clear ();
182
+ header .flip ();
186
183
187
- // populate the tables
184
+ // populate the offset table
188
185
IntBuffer headerAsInts = header .asIntBuffer ();
189
186
for (int i = 0 ; i < SECTOR_INTS ; ++i ) {
190
187
int offset = headerAsInts .get ();
@@ -194,20 +191,14 @@ public RegionFile(File path) throws IOException {
194
191
int numSectors = offset & 255 ;
195
192
196
193
if (offset != 0 && startSector >= 0 && startSector + numSectors <= totalSectors ) {
197
- for (int sectorNum = 0 ; sectorNum < numSectors ; ++sectorNum ) {
198
- sectorsUsed .set (startSector + sectorNum );
199
- }
194
+ sectorsUsed .set (startSector , startSector + numSectors + 1 );
200
195
} else if (offset != 0 ) {
201
196
GlowServer .logger .warning (
202
197
"Region \" " + path + "\" : offsets[" + i + "] = " + offset + " -> "
203
198
+ startSector
204
199
+ "," + numSectors + " does not fit" );
205
200
}
206
201
}
207
- // read timestamps from timestamp table
208
- for (int i = 0 ; i < SECTOR_INTS ; ++i ) {
209
- chunkTimestamps [i ] = headerAsInts .get ();
210
- }
211
202
}
212
203
213
204
/**
@@ -237,6 +228,7 @@ public DataInputStream getChunkDataInputStream(int x, int z) throws IOException
237
228
return null ;
238
229
}
239
230
231
+ int totalSectors = sectorsUsed .length ();
240
232
int sectorNumber = offset >> 8 ;
241
233
int numSectors = offset & 0xFF ;
242
234
if (sectorNumber + numSectors > totalSectors ) {
@@ -320,56 +312,52 @@ protected void write(int x, int z, byte[] data, int length) throws IOException {
320
312
/* we can simply overwrite the old sectors */
321
313
write (sectorNumber , data , length );
322
314
} else {
323
- /* we need to allocate new sectors */
324
-
325
315
/* mark the sectors previously used for this chunk as free */
326
- for ( int i = 0 ; i < sectorsAllocated ; ++ i ) {
327
- sectorsUsed .clear (sectorNumber + i );
316
+ if ( sectorNumber ! = 0 ) {
317
+ sectorsUsed .clear (sectorNumber , sectorNumber + sectorsAllocated + 1 );
328
318
}
329
319
330
320
/* scan for a free space large enough to store this chunk */
331
- int runStart = 2 ;
332
- int runLength = 0 ;
333
- int currentSector = 2 ;
334
- while (runLength < sectorsNeeded ) {
335
- int nextSector = sectorsUsed .nextClearBit (currentSector + 1 );
336
- if (currentSector + 1 == nextSector ) {
337
- runLength ++;
338
- } else {
339
- runStart = nextSector ;
340
- runLength = 1 ;
341
- }
342
- currentSector = nextSector ;
343
- }
344
-
345
- if (runLength >= sectorsNeeded ) {
346
- /* we found a free space large enough */
347
- sectorNumber = runStart ;
348
- setOffset (x , z , sectorNumber << 8 | sectorsNeeded );
349
- for (int i = 0 ; i < sectorsNeeded ; ++i ) {
350
- sectorsUsed .set (sectorNumber + i );
351
- }
352
- write (sectorNumber , data , length );
353
- } else {
321
+ sectorNumber = findNewSectorStart (sectorsNeeded );
322
+ if (sectorNumber == -1 ) {
354
323
/*
355
324
* no free space large enough found -- we need to grow the
356
325
* file
357
326
*/
358
327
file .seek (file .length ());
359
- sectorNumber = totalSectors ;
360
328
for (int i = 0 ; i < sectorsNeeded ; ++i ) {
361
329
file .write (emptySector );
362
- sectorsUsed .set (totalSectors + i );
363
330
}
364
- totalSectors += sectorsNeeded ;
365
331
sizeDelta .addAndGet (SECTOR_BYTES * sectorsNeeded );
332
+ sectorNumber = sectorsUsed .length ();
333
+ }
334
+
335
+ sectorsUsed .set (sectorNumber , sectorNumber + sectorsNeeded + 1 );
336
+ write (sectorNumber , data , length );
337
+ setOffset (x , z , sectorNumber << 8 | sectorsNeeded );
338
+ }
339
+ }
366
340
367
- write (sectorNumber , data , length );
368
- setOffset (x , z , sectorNumber << 8 | sectorsNeeded );
341
+ private int findNewSectorStart (int sectorsNeeded ) {
342
+ int start = -1 ;
343
+ int runLength = 0 ;
344
+ for (int i = sectorsUsed .nextClearBit (0 ); i < sectorsUsed .length (); i ++) {
345
+ if (sectorsUsed .get (i )) {
346
+ // must reset
347
+ start = -1 ;
348
+ runLength = 0 ;
349
+ } else {
350
+ if (start == -1 ) {
351
+ start = i ;
352
+ }
353
+ runLength ++;
354
+ if (runLength >= sectorsNeeded ) {
355
+ return start ;
356
+ }
369
357
}
370
358
}
371
- setTimestamp ( x , z , ( int ) ( System . currentTimeMillis () / 1000L ));
372
- //file.getChannel().force(true) ;
359
+ // reached the end, append to the end of the region instead
360
+ return - 1 ;
373
361
}
374
362
375
363
/* write a chunk data to the region file at specified sector number */
@@ -401,12 +389,6 @@ private void setOffset(int x, int z, int offset) throws IOException {
401
389
file .writeInt (offset );
402
390
}
403
391
404
- private void setTimestamp (int x , int z , int value ) throws IOException {
405
- chunkTimestamps [x + (z << 5 )] = value ;
406
- file .seek (SECTOR_BYTES + ((x + (z << 5 )) << 2 ));
407
- file .writeInt (value );
408
- }
409
-
410
392
public void close () throws IOException {
411
393
file .getChannel ().force (true );
412
394
file .close ();
0 commit comments