Mercurial > jhg
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 { |
