Mercurial > hg4j
comparison src/org/tmatesoft/hg/internal/DataAccessProvider.java @ 158:b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Wed, 09 Mar 2011 13:16:37 +0100 |
| parents | d5268ca7715b |
| children | 981f9f50bb6c |
comparison
equal
deleted
inserted
replaced
| 157:d5268ca7715b | 158:b413b16d10a5 |
|---|---|
| 21 import java.io.IOException; | 21 import java.io.IOException; |
| 22 import java.nio.ByteBuffer; | 22 import java.nio.ByteBuffer; |
| 23 import java.nio.MappedByteBuffer; | 23 import java.nio.MappedByteBuffer; |
| 24 import java.nio.channels.FileChannel; | 24 import java.nio.channels.FileChannel; |
| 25 | 25 |
| 26 import org.tmatesoft.hg.core.HgBadStateException; | |
| 27 | |
| 26 /** | 28 /** |
| 27 * | 29 * |
| 28 * @author Artem Tikhomirov | 30 * @author Artem Tikhomirov |
| 29 * @author TMate Software Ltd. | 31 * @author TMate Software Ltd. |
| 30 */ | 32 */ |
| 46 if (!f.exists()) { | 48 if (!f.exists()) { |
| 47 return new DataAccess(); | 49 return new DataAccess(); |
| 48 } | 50 } |
| 49 try { | 51 try { |
| 50 FileChannel fc = new FileInputStream(f).getChannel(); | 52 FileChannel fc = new FileInputStream(f).getChannel(); |
| 51 if (fc.size() > mapioMagicBoundary) { | 53 int flen = (int) fc.size(); |
| 54 if (fc.size() - flen != 0) { | |
| 55 throw new HgBadStateException("Files greater than 2Gb are not yet supported"); | |
| 56 } | |
| 57 if (flen > mapioMagicBoundary) { | |
| 52 // TESTS: bufLen of 1024 was used to test MemMapFileAccess | 58 // TESTS: bufLen of 1024 was used to test MemMapFileAccess |
| 53 return new MemoryMapFileAccess(fc, fc.size(), mapioMagicBoundary); | 59 return new MemoryMapFileAccess(fc, flen, mapioMagicBoundary); |
| 54 } else { | 60 } else { |
| 55 // XXX once implementation is more or less stable, | 61 // XXX once implementation is more or less stable, |
| 56 // may want to try ByteBuffer.allocateDirect() to see | 62 // may want to try ByteBuffer.allocateDirect() to see |
| 57 // if there's any performance gain. | 63 // if there's any performance gain. |
| 58 boolean useDirectBuffer = false; | 64 boolean useDirectBuffer = false; |
| 59 // TESTS: bufferSize of 100 was used to check buffer underflow states when readBytes reads chunks bigger than bufSize | 65 // TESTS: bufferSize of 100 was used to check buffer underflow states when readBytes reads chunks bigger than bufSize |
| 60 return new FileAccess(fc, fc.size(), bufferSize, useDirectBuffer); | 66 return new FileAccess(fc, flen, bufferSize, useDirectBuffer); |
| 61 } | 67 } |
| 62 } catch (IOException ex) { | 68 } catch (IOException ex) { |
| 63 // unlikely to happen, we've made sure file exists. | 69 // unlikely to happen, we've made sure file exists. |
| 64 ex.printStackTrace(); // FIXME log error | 70 ex.printStackTrace(); // FIXME log error |
| 65 } | 71 } |
| 67 } | 73 } |
| 68 | 74 |
| 69 // DOESN'T WORK YET | 75 // DOESN'T WORK YET |
| 70 private static class MemoryMapFileAccess extends DataAccess { | 76 private static class MemoryMapFileAccess extends DataAccess { |
| 71 private FileChannel fileChannel; | 77 private FileChannel fileChannel; |
| 72 private final long size; | 78 private final int size; |
| 73 private long position = 0; // always points to buffer's absolute position in the file | 79 private long position = 0; // always points to buffer's absolute position in the file |
| 74 private final int memBufferSize; | 80 private final int memBufferSize; |
| 75 private MappedByteBuffer buffer; | 81 private MappedByteBuffer buffer; |
| 76 | 82 |
| 77 public MemoryMapFileAccess(FileChannel fc, long channelSize, int /*long?*/ bufferSize) { | 83 public MemoryMapFileAccess(FileChannel fc, int channelSize, int /*long?*/ bufferSize) { |
| 78 fileChannel = fc; | 84 fileChannel = fc; |
| 79 size = channelSize; | 85 size = channelSize; |
| 80 memBufferSize = bufferSize; | 86 memBufferSize = bufferSize; |
| 81 } | 87 } |
| 82 | 88 |
| 84 public boolean isEmpty() { | 90 public boolean isEmpty() { |
| 85 return position + (buffer == null ? 0 : buffer.position()) >= size; | 91 return position + (buffer == null ? 0 : buffer.position()) >= size; |
| 86 } | 92 } |
| 87 | 93 |
| 88 @Override | 94 @Override |
| 89 public long length() { | 95 public int length() { |
| 90 return size; | 96 return size; |
| 91 } | 97 } |
| 92 | 98 |
| 93 @Override | 99 @Override |
| 94 public DataAccess reset() throws IOException { | 100 public DataAccess reset() throws IOException { |
| 95 seek(0); | 101 seek(0); |
| 96 return this; | 102 return this; |
| 97 } | 103 } |
| 98 | 104 |
| 99 @Override | 105 @Override |
| 100 public void seek(long offset) { | 106 public void seek(int offset) { |
| 101 assert offset >= 0; | 107 assert offset >= 0; |
| 102 // offset may not necessarily be further than current position in the file (e.g. rewind) | 108 // offset may not necessarily be further than current position in the file (e.g. rewind) |
| 103 if (buffer != null && /*offset is within buffer*/ offset >= position && (offset - position) < buffer.limit()) { | 109 if (buffer != null && /*offset is within buffer*/ offset >= position && (offset - position) < buffer.limit()) { |
| 104 buffer.position((int) (offset - position)); | 110 buffer.position((int) (offset - position)); |
| 105 } else { | 111 } else { |
| 179 } | 185 } |
| 180 | 186 |
| 181 // (almost) regular file access - FileChannel and buffers. | 187 // (almost) regular file access - FileChannel and buffers. |
| 182 private static class FileAccess extends DataAccess { | 188 private static class FileAccess extends DataAccess { |
| 183 private FileChannel fileChannel; | 189 private FileChannel fileChannel; |
| 184 private final long size; | 190 private final int size; |
| 185 private ByteBuffer buffer; | 191 private ByteBuffer buffer; |
| 186 private long bufferStartInFile = 0; // offset of this.buffer in the file. | 192 private int bufferStartInFile = 0; // offset of this.buffer in the file. |
| 187 | 193 |
| 188 public FileAccess(FileChannel fc, long channelSize, int bufferSizeHint, boolean useDirect) { | 194 public FileAccess(FileChannel fc, int channelSize, int bufferSizeHint, boolean useDirect) { |
| 189 fileChannel = fc; | 195 fileChannel = fc; |
| 190 size = channelSize; | 196 size = channelSize; |
| 191 final int capacity = size < bufferSizeHint ? (int) size : bufferSizeHint; | 197 final int capacity = size < bufferSizeHint ? size : bufferSizeHint; |
| 192 buffer = useDirect ? ByteBuffer.allocateDirect(capacity) : ByteBuffer.allocate(capacity); | 198 buffer = useDirect ? ByteBuffer.allocateDirect(capacity) : ByteBuffer.allocate(capacity); |
| 193 buffer.flip(); // or .limit(0) to indicate it's empty | 199 buffer.flip(); // or .limit(0) to indicate it's empty |
| 194 } | 200 } |
| 195 | 201 |
| 196 @Override | 202 @Override |
| 197 public boolean isEmpty() { | 203 public boolean isEmpty() { |
| 198 return bufferStartInFile + buffer.position() >= size; | 204 return bufferStartInFile + buffer.position() >= size; |
| 199 } | 205 } |
| 200 | 206 |
| 201 @Override | 207 @Override |
| 202 public long length() { | 208 public int length() { |
| 203 return size; | 209 return size; |
| 204 } | 210 } |
| 205 | 211 |
| 206 @Override | 212 @Override |
| 207 public DataAccess reset() throws IOException { | 213 public DataAccess reset() throws IOException { |
| 208 seek(0); | 214 seek(0); |
| 209 return this; | 215 return this; |
| 210 } | 216 } |
| 211 | 217 |
| 212 @Override | 218 @Override |
| 213 public void seek(long offset) throws IOException { | 219 public void seek(int offset) throws IOException { |
| 214 if (offset > size) { | 220 if (offset > size) { |
| 215 throw new IllegalArgumentException(); | 221 throw new IllegalArgumentException(); |
| 216 } | 222 } |
| 217 if (offset < bufferStartInFile + buffer.limit() && offset >= bufferStartInFile) { | 223 if (offset < bufferStartInFile + buffer.limit() && offset >= bufferStartInFile) { |
| 218 buffer.position((int) (offset - bufferStartInFile)); | 224 buffer.position((int) (offset - bufferStartInFile)); |
