comparison src/org/tmatesoft/hg/internal/RevlogStream.java @ 420:6c22bdc0bdfd

Respect long offsets in revlogs
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 22 Mar 2012 22:56:01 +0100
parents c76c57f6b961
children 9c9c442b5f2e
comparison
equal deleted inserted replaced
419:7f136a3fa671 420:6c22bdc0bdfd
64 this.dataAccess = dap; 64 this.dataAccess = dap;
65 this.indexFile = indexFile; 65 this.indexFile = indexFile;
66 } 66 }
67 67
68 /*package*/ DataAccess getIndexStream() { 68 /*package*/ DataAccess getIndexStream() {
69 // XXX may supply a hint that I'll need really few bytes of data (perhaps, at some offset) 69 // TODO post 1.0 may supply a hint that I'll need really few bytes of data (perhaps, at some offset)
70 // to avoid mmap files when only few bytes are to be read (i.e. #dataLength()) 70 // to avoid mmap files when only few bytes are to be read (i.e. #dataLength())
71 return dataAccess.create(indexFile); 71 return dataAccess.create(indexFile);
72 } 72 }
73 73
74 /*package*/ DataAccess getDataStream() { 74 /*package*/ DataAccess getDataStream() {
324 int versionField = da.readInt(); 324 int versionField = da.readInt();
325 da.readInt(); // just to skip next 4 bytes of offset + flags 325 da.readInt(); // just to skip next 4 bytes of offset + flags
326 final int INLINEDATA = 1 << 16; 326 final int INLINEDATA = 1 << 16;
327 inline = (versionField & INLINEDATA) != 0; 327 inline = (versionField & INLINEDATA) != 0;
328 IntVector resBases, resOffsets = null; 328 IntVector resBases, resOffsets = null;
329 int entryCountGuess = da.length() / REVLOGV1_RECORD_SIZE; 329 int entryCountGuess = Internals.ltoi(da.longLength() / REVLOGV1_RECORD_SIZE);
330 if (inline) { 330 if (inline) {
331 entryCountGuess >>>= 2; // pure guess, assume useful data takes 3/4 of total space 331 entryCountGuess >>>= 2; // pure guess, assume useful data takes 3/4 of total space
332 resOffsets = new IntVector(entryCountGuess, 5000); 332 resOffsets = new IntVector(entryCountGuess, 5000);
333 } 333 }
334 resBases = new IntVector(entryCountGuess, 5000); 334 resBases = new IntVector(entryCountGuess, 5000);
345 // int parent1Revision = di.readInt(); 345 // int parent1Revision = di.readInt();
346 // int parent2Revision = di.readInt(); 346 // int parent2Revision = di.readInt();
347 // byte[] nodeid = new byte[32]; 347 // byte[] nodeid = new byte[32];
348 resBases.add(baseRevision); 348 resBases.add(baseRevision);
349 if (inline) { 349 if (inline) {
350 int o = (int) offset; 350 int o = Internals.ltoi(offset);
351 if (o != offset) { 351 if (o != offset) {
352 // just in case, can't happen, ever, unless HG (or some other bad tool) produces index file 352 // just in case, can't happen, ever, unless HG (or some other bad tool) produces index file
353 // with inlined data of size greater than 2 Gb. 353 // with inlined data of size greater than 2 Gb.
354 throw new HgBadStateException("Data too big, offset didn't fit to sizeof(int)"); 354 throw new HgBadStateException("Data too big, offset didn't fit to sizeof(int)");
355 } 355 }
463 daIndex.seek(getIndexOffsetInt(i)); 463 daIndex.seek(getIndexOffsetInt(i));
464 } 464 }
465 long l = daIndex.readLong(); // 0 465 long l = daIndex.readLong(); // 0
466 long offset = i == 0 ? 0 : (l >>> 16); 466 long offset = i == 0 ? 0 : (l >>> 16);
467 @SuppressWarnings("unused") 467 @SuppressWarnings("unused")
468 int flags = (int) (l & 0X0FFFF); 468 int flags = (int) (l & 0x0FFFF);
469 int compressedLen = daIndex.readInt(); // +8 469 int compressedLen = daIndex.readInt(); // +8
470 int actualLen = daIndex.readInt(); // +12 470 int actualLen = daIndex.readInt(); // +12
471 int baseRevision = daIndex.readInt(); // +16 471 int baseRevision = daIndex.readInt(); // +16
472 int linkRevision = daIndex.readInt(); // +20 472 int linkRevision = daIndex.readInt(); // +20
473 int parent1Revision = daIndex.readInt(); 473 int parent1Revision = daIndex.readInt();
475 // Hg has 32 bytes here, uses 20 for nodeid, and keeps 12 last bytes empty 475 // Hg has 32 bytes here, uses 20 for nodeid, and keeps 12 last bytes empty
476 daIndex.readBytes(nodeidBuf, 0, 20); // +32 476 daIndex.readBytes(nodeidBuf, 0, 20); // +32
477 daIndex.skip(12); 477 daIndex.skip(12);
478 DataAccess userDataAccess = null; 478 DataAccess userDataAccess = null;
479 if (needData) { 479 if (needData) {
480 int streamOffset; 480 long streamOffset;
481 DataAccess streamDataAccess; 481 DataAccess streamDataAccess;
482 if (inline) { 482 if (inline) {
483 streamDataAccess = daIndex; 483 streamDataAccess = daIndex;
484 streamOffset = getIndexOffsetInt(i) + REVLOGV1_RECORD_SIZE; // don't need to do seek as it's actual position in the index stream 484 streamOffset = getIndexOffsetInt(i) + REVLOGV1_RECORD_SIZE; // don't need to do seek as it's actual position in the index stream
485 } else { 485 } else {
486 streamOffset = (int) offset; 486 streamOffset = offset;
487 streamDataAccess = daData; 487 streamDataAccess = daData;
488 daData.seek(streamOffset); 488 daData.longSeek(streamOffset);
489 } 489 }
490 final boolean patchToPrevious = baseRevision != i; // the only way I found to tell if it's a patch 490 final boolean patchToPrevious = baseRevision != i; // the only way I found to tell if it's a patch
491 if (streamDataAccess.isEmpty() || compressedLen == 0) { 491 if (streamDataAccess.isEmpty() || compressedLen == 0) {
492 userDataAccess = new DataAccess(); // empty 492 userDataAccess = new DataAccess(); // empty
493 } else { 493 } else {