Mercurial > jhg
comparison src/org/tmatesoft/hg/internal/RevlogStream.java @ 354:5f9073eabf06
Propagate errors with exceptions up to a end client
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Thu, 01 Dec 2011 05:21:40 +0100 |
| parents | 8da7ade36c57 |
| children | 189dc6dc1c3e |
comparison
equal
deleted
inserted
replaced
| 353:0f3687e79f5a | 354:5f9073eabf06 |
|---|---|
| 22 import java.io.File; | 22 import java.io.File; |
| 23 import java.io.IOException; | 23 import java.io.IOException; |
| 24 import java.util.zip.Inflater; | 24 import java.util.zip.Inflater; |
| 25 | 25 |
| 26 import org.tmatesoft.hg.core.HgBadStateException; | 26 import org.tmatesoft.hg.core.HgBadStateException; |
| 27 import org.tmatesoft.hg.core.HgInvalidControlFileException; | |
| 27 import org.tmatesoft.hg.core.HgInvalidRevisionException; | 28 import org.tmatesoft.hg.core.HgInvalidRevisionException; |
| 28 import org.tmatesoft.hg.core.Nodeid; | 29 import org.tmatesoft.hg.core.Nodeid; |
| 29 import org.tmatesoft.hg.repo.HgInternals; | 30 import org.tmatesoft.hg.repo.HgInternals; |
| 30 import org.tmatesoft.hg.repo.HgRepository; | 31 import org.tmatesoft.hg.repo.HgRepository; |
| 31 | 32 |
| 78 initOutline(); | 79 initOutline(); |
| 79 return baseRevisions.length; | 80 return baseRevisions.length; |
| 80 } | 81 } |
| 81 | 82 |
| 82 /** | 83 /** |
| 83 * @throws HgBadStateException if internal read operation failed | 84 * @throws HgInvalidControlFileException if attempt to read index file failed |
| 84 */ | 85 * @throws HgInvalidRevisionException if revisionIndex argument doesn't represent a valid record in the revlog |
| 85 public int dataLength(int revision) { | 86 */ |
| 87 public int dataLength(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { | |
| 86 // XXX in fact, use of iterate() instead of this implementation may be quite reasonable. | 88 // XXX in fact, use of iterate() instead of this implementation may be quite reasonable. |
| 87 // | 89 // |
| 88 final int indexSize = revisionCount(); | 90 revisionIndex = checkRevisionIndex(revisionIndex); |
| 89 DataAccess daIndex = getIndexStream(); | 91 DataAccess daIndex = getIndexStream(); |
| 90 if (revision == TIP) { | 92 try { |
| 91 revision = indexSize - 1; | 93 int recordOffset = getIndexOffsetInt(revisionIndex); |
| 92 } | |
| 93 try { | |
| 94 int recordOffset = getIndexOffsetInt(revision); | |
| 95 daIndex.seek(recordOffset + 12); // 6+2+4 | 94 daIndex.seek(recordOffset + 12); // 6+2+4 |
| 96 int actualLen = daIndex.readInt(); | 95 int actualLen = daIndex.readInt(); |
| 97 return actualLen; | 96 return actualLen; |
| 98 } catch (IOException ex) { | 97 } catch (IOException ex) { |
| 99 ex.printStackTrace(); // log error. FIXME better handling | 98 throw new HgInvalidControlFileException(null, ex, indexFile); |
| 100 throw new HgBadStateException(ex); | |
| 101 } finally { | 99 } finally { |
| 102 daIndex.done(); | 100 daIndex.done(); |
| 103 } | 101 } |
| 104 } | 102 } |
| 105 | 103 |
| 106 /** | 104 /** |
| 107 * @throws HgBadStateException if internal read operation failed | 105 * Read nodeid at given index |
| 108 */ | 106 * |
| 109 public byte[] nodeid(int revision) throws HgInvalidRevisionException { | 107 * @throws HgInvalidControlFileException if attempt to read index file failed |
| 110 final int indexSize = revisionCount(); | 108 * @throws HgInvalidRevisionException if revisionIndex argument doesn't represent a valid record in the revlog |
| 111 if (revision == TIP) { | 109 */ |
| 112 revision = indexSize - 1; | 110 public byte[] nodeid(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { |
| 113 } | 111 revisionIndex = checkRevisionIndex(revisionIndex); |
| 114 if (revision < 0 || revision >= indexSize) { | |
| 115 throw new HgInvalidRevisionException(revision).setRevisionIndex(revision, 0, indexSize); | |
| 116 } | |
| 117 DataAccess daIndex = getIndexStream(); | 112 DataAccess daIndex = getIndexStream(); |
| 118 try { | 113 try { |
| 119 int recordOffset = getIndexOffsetInt(revision); | 114 int recordOffset = getIndexOffsetInt(revisionIndex); |
| 120 daIndex.seek(recordOffset + 32); | 115 daIndex.seek(recordOffset + 32); |
| 121 byte[] rv = new byte[20]; | 116 byte[] rv = new byte[20]; |
| 122 daIndex.readBytes(rv, 0, 20); | 117 daIndex.readBytes(rv, 0, 20); |
| 123 return rv; | 118 return rv; |
| 124 } catch (IOException ex) { | 119 } catch (IOException ex) { |
| 125 ex.printStackTrace(); | 120 throw new HgInvalidControlFileException(null, ex, indexFile); |
| 126 throw new HgBadStateException(); | |
| 127 } finally { | 121 } finally { |
| 128 daIndex.done(); | 122 daIndex.done(); |
| 129 } | 123 } |
| 130 } | 124 } |
| 131 | 125 |
| 132 /** | 126 /** |
| 133 * Get link field from the index record. | 127 * Get link field from the index record. |
| 134 * @throws HgBadStateException if internal read operation failed | 128 * |
| 135 */ | 129 * @throws HgInvalidControlFileException if attempt to read index file failed |
| 136 public int linkRevision(int revision) { | 130 * @throws HgInvalidRevisionException if revisionIndex argument doesn't represent a valid record in the revlog |
| 137 final int last = revisionCount() - 1; | 131 */ |
| 138 if (revision == TIP) { | 132 public int linkRevision(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { |
| 139 revision = last; | 133 revisionIndex = checkRevisionIndex(revisionIndex); |
| 140 } | |
| 141 if (revision < 0 || revision > last) { | |
| 142 throw new IllegalArgumentException(Integer.toString(revision)); | |
| 143 } | |
| 144 DataAccess daIndex = getIndexStream(); | 134 DataAccess daIndex = getIndexStream(); |
| 145 try { | 135 try { |
| 146 int recordOffset = getIndexOffsetInt(revision); | 136 int recordOffset = getIndexOffsetInt(revisionIndex); |
| 147 daIndex.seek(recordOffset + 20); | 137 daIndex.seek(recordOffset + 20); |
| 148 int linkRev = daIndex.readInt(); | 138 int linkRev = daIndex.readInt(); |
| 149 return linkRev; | 139 return linkRev; |
| 150 } catch (IOException ex) { | 140 } catch (IOException ex) { |
| 151 ex.printStackTrace(); | 141 throw new HgInvalidControlFileException(null, ex, indexFile); |
| 152 throw new HgBadStateException(); | |
| 153 } finally { | 142 } finally { |
| 154 daIndex.done(); | 143 daIndex.done(); |
| 155 } | 144 } |
| 156 } | 145 } |
| 157 | 146 |
| 159 // while Nodeids should be kept on the level up, in Revlog. Guess, Revlog better keep | 148 // while Nodeids should be kept on the level up, in Revlog. Guess, Revlog better keep |
| 160 // map of nodeids, and once this comes true, we may get rid of this method. | 149 // map of nodeids, and once this comes true, we may get rid of this method. |
| 161 // Unlike its counterpart, {@link Revlog#getLocalRevisionNumber()}, doesn't fail with exception if node not found, | 150 // Unlike its counterpart, {@link Revlog#getLocalRevisionNumber()}, doesn't fail with exception if node not found, |
| 162 /** | 151 /** |
| 163 * @return integer in [0..revisionCount()) or {@link HgRepository#BAD_REVISION} if not found | 152 * @return integer in [0..revisionCount()) or {@link HgRepository#BAD_REVISION} if not found |
| 164 */ | 153 * @throws HgInvalidControlFileException if attempt to read index file failed |
| 165 public int findLocalRevisionNumber(Nodeid nodeid) { | 154 */ |
| 155 public int findLocalRevisionNumber(Nodeid nodeid) throws HgInvalidControlFileException { | |
| 166 // XXX this one may be implemented with iterate() once there's mechanism to stop iterations | 156 // XXX this one may be implemented with iterate() once there's mechanism to stop iterations |
| 167 final int indexSize = revisionCount(); | 157 final int indexSize = revisionCount(); |
| 168 DataAccess daIndex = getIndexStream(); | 158 DataAccess daIndex = getIndexStream(); |
| 169 try { | 159 try { |
| 170 byte[] nodeidBuf = new byte[20]; | 160 byte[] nodeidBuf = new byte[20]; |
| 177 return i; | 167 return i; |
| 178 } | 168 } |
| 179 daIndex.skip(inline ? 12 + compressedLen : 12); | 169 daIndex.skip(inline ? 12 + compressedLen : 12); |
| 180 } | 170 } |
| 181 } catch (IOException ex) { | 171 } catch (IOException ex) { |
| 182 ex.printStackTrace(); // log error. FIXME better handling. Perhaps, shall return BAD_REVISION here as well? | 172 throw new HgInvalidControlFileException("Failed", ex, indexFile).setRevision(nodeid); |
| 183 throw new IllegalStateException(ex); | |
| 184 } finally { | 173 } finally { |
| 185 daIndex.done(); | 174 daIndex.done(); |
| 186 } | 175 } |
| 187 return BAD_REVISION; | 176 return BAD_REVISION; |
| 188 } | 177 } |
| 265 private int getBaseRevision(int revision) { | 254 private int getBaseRevision(int revision) { |
| 266 return baseRevisions[revision]; | 255 return baseRevisions[revision]; |
| 267 } | 256 } |
| 268 | 257 |
| 269 /** | 258 /** |
| 259 * @param revisionIndex shall be valid index, [0..baseRevisions.length-1]. | |
| 260 * It's advised to use {@link #checkRevisionIndex(int)} to ensure argument is correct. | |
| 270 * @return offset of the revision's record in the index (.i) stream | 261 * @return offset of the revision's record in the index (.i) stream |
| 271 */ | 262 */ |
| 272 private int getIndexOffsetInt(int revision) { | 263 private int getIndexOffsetInt(int revisionIndex) { |
| 273 return inline ? indexRecordOffset[revision] : revision * REVLOGV1_RECORD_SIZE; | 264 return inline ? indexRecordOffset[revisionIndex] : revisionIndex * REVLOGV1_RECORD_SIZE; |
| 265 } | |
| 266 | |
| 267 private int checkRevisionIndex(int revisionIndex) throws HgInvalidRevisionException { | |
| 268 final int last = revisionCount() - 1; | |
| 269 if (revisionIndex == TIP) { | |
| 270 revisionIndex = last; | |
| 271 } | |
| 272 if (revisionIndex < 0 || revisionIndex > last) { | |
| 273 throw new HgInvalidRevisionException(revisionIndex).setRevisionIndex(revisionIndex, 0, last); | |
| 274 } | |
| 275 return revisionIndex; | |
| 274 } | 276 } |
| 275 | 277 |
| 276 private void initOutline() { | 278 private void initOutline() { |
| 277 if (baseRevisions != null && baseRevisions.length > 0) { | 279 if (baseRevisions != null && baseRevisions.length > 0) { |
| 278 return; | 280 return; |
