Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/Revlog.java @ 628:6526d8adbc0f
Explicit HgRuntimeException to facilitate easy switch from runtime to checked exceptions
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Wed, 22 May 2013 15:52:31 +0200 |
| parents | e1b29756f901 |
| children | 32b0d19e8aba |
comparison
equal
deleted
inserted
replaced
| 627:5153eb73b18d | 628:6526d8adbc0f |
|---|---|
| 92 return repo; | 92 return repo; |
| 93 } | 93 } |
| 94 | 94 |
| 95 /** | 95 /** |
| 96 * @return total number of revisions kept in this revlog | 96 * @return total number of revisions kept in this revlog |
| 97 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | 97 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> |
| 98 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> | |
| 98 */ | 99 */ |
| 99 public final int getRevisionCount() throws HgRuntimeException { | 100 public final int getRevisionCount() throws HgRuntimeException { |
| 100 return content.revisionCount(); | 101 return content.revisionCount(); |
| 101 } | 102 } |
| 102 | 103 |
| 103 /** | 104 /** |
| 104 * @return index of last known revision, a.k.a. {@link HgRepository#TIP}, or {@link HgRepository#NO_REVISION} if revlog is empty | 105 * @return index of last known revision, a.k.a. {@link HgRepository#TIP}, or {@link HgRepository#NO_REVISION} if revlog is empty |
| 105 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | 106 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> |
| 107 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> | |
| 106 */ | 108 */ |
| 107 public final int getLastRevision() throws HgRuntimeException { | 109 public final int getLastRevision() throws HgRuntimeException { |
| 108 // although old code gives correct result when revlog is empty (NO_REVISION deliberately == -1), | 110 // although old code gives correct result when revlog is empty (NO_REVISION deliberately == -1), |
| 109 // it's still better to be explicit | 111 // it's still better to be explicit |
| 110 int revCount = content.revisionCount(); | 112 int revCount = content.revisionCount(); |
| 115 * Map revision index to unique revision identifier (nodeid). | 117 * Map revision index to unique revision identifier (nodeid). |
| 116 * | 118 * |
| 117 * @param revisionIndex index of the entry in this revlog, may be {@link HgRepository#TIP} | 119 * @param revisionIndex index of the entry in this revlog, may be {@link HgRepository#TIP} |
| 118 * @return revision nodeid of the entry | 120 * @return revision nodeid of the entry |
| 119 * | 121 * |
| 120 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | 122 * @throws HgInvalidRevisionException if any supplied revision doesn't identify revision from this revlog. <em>Runtime exception</em> |
| 123 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> | |
| 124 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> | |
| 121 */ | 125 */ |
| 122 public final Nodeid getRevision(int revisionIndex) throws HgRuntimeException { | 126 public final Nodeid getRevision(int revisionIndex) throws HgRuntimeException { |
| 123 // XXX cache nodeids? Rather, if context.getCache(this).getRevisionMap(create == false) != null, use it | 127 // XXX cache nodeids? Rather, if context.getCache(this).getRevisionMap(create == false) != null, use it |
| 124 return Nodeid.fromBinary(content.nodeid(revisionIndex), 0); | 128 return Nodeid.fromBinary(content.nodeid(revisionIndex), 0); |
| 125 } | 129 } |
| 128 * Effective alternative to map few revision indexes to corresponding nodeids at once. | 132 * Effective alternative to map few revision indexes to corresponding nodeids at once. |
| 129 * <p>Note, there are few aspects to be careful about when using this method<ul> | 133 * <p>Note, there are few aspects to be careful about when using this method<ul> |
| 130 * <li>ordering of the revisions in the return list is unspecified, it's likely won't match that of the method argument | 134 * <li>ordering of the revisions in the return list is unspecified, it's likely won't match that of the method argument |
| 131 * <li>supplied array get modified (sorted)</ul> | 135 * <li>supplied array get modified (sorted)</ul> |
| 132 * @return list of mapped revisions in no particular order | 136 * @return list of mapped revisions in no particular order |
| 133 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | 137 * @throws HgInvalidRevisionException if any supplied revision doesn't identify revision from this revlog. <em>Runtime exception</em> |
| 138 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> | |
| 139 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> | |
| 134 */ | 140 */ |
| 135 public final List<Nodeid> getRevisions(int... revisions) throws HgRuntimeException { | 141 public final List<Nodeid> getRevisions(int... revisions) throws HgRuntimeException { |
| 136 ArrayList<Nodeid> rv = new ArrayList<Nodeid>(revisions.length); | 142 ArrayList<Nodeid> rv = new ArrayList<Nodeid>(revisions.length); |
| 137 Arrays.sort(revisions); | 143 Arrays.sort(revisions); |
| 138 getRevisionsInternal(rv, revisions); | 144 getRevisionsInternal(rv, revisions); |
| 139 return rv; | 145 return rv; |
| 140 } | 146 } |
| 141 | 147 |
| 142 /*package-local*/ void getRevisionsInternal(final List<Nodeid> retVal, int[] sortedRevs) throws HgInvalidRevisionException, HgInvalidControlFileException { | 148 /*package-local*/ void getRevisionsInternal(final List<Nodeid> retVal, int[] sortedRevs) throws HgRuntimeException { |
| 143 // once I have getRevisionMap and may find out whether it is avalable from cache, | 149 // once I have getRevisionMap and may find out whether it is avalable from cache, |
| 144 // may use it, perhaps only for small number of revisions | 150 // may use it, perhaps only for small number of revisions |
| 145 content.iterate(sortedRevs, false, new RevlogStream.Inspector() { | 151 content.iterate(sortedRevs, false, new RevlogStream.Inspector() { |
| 146 | 152 |
| 147 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) { | 153 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) { |
| 157 * For occasional queries, this method works with decent performance, despite its O(n/2) approach. | 163 * For occasional queries, this method works with decent performance, despite its O(n/2) approach. |
| 158 * Alternatively, if you need to perform multiple queries (e.g. at least 15-20), {@link HgRevisionMap} may come handy. | 164 * Alternatively, if you need to perform multiple queries (e.g. at least 15-20), {@link HgRevisionMap} may come handy. |
| 159 * | 165 * |
| 160 * @param nid revision to look up | 166 * @param nid revision to look up |
| 161 * @return revision local index in this revlog | 167 * @return revision local index in this revlog |
| 162 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | 168 * @throws HgInvalidRevisionException if revision was not found in this revlog. <em>Runtime exception</em> |
| 169 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> | |
| 170 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> | |
| 163 */ | 171 */ |
| 164 public final int getRevisionIndex(Nodeid nid) throws HgRuntimeException { | 172 public final int getRevisionIndex(Nodeid nid) throws HgRuntimeException { |
| 165 final int revision = doFindWithCache(nid); | 173 final int revision = doFindWithCache(nid); |
| 166 if (revision == BAD_REVISION) { | 174 if (revision == BAD_REVISION) { |
| 167 // using toString() to identify revlog. HgDataFile.toString includes path, HgManifest and HgChangelog instances | 175 // using toString() to identify revlog. HgDataFile.toString includes path, HgManifest and HgChangelog instances |
| 170 throw new HgInvalidRevisionException(String.format("Can't find revision %s in %s", nid.shortNotation(), this), nid, null); | 178 throw new HgInvalidRevisionException(String.format("Can't find revision %s in %s", nid.shortNotation(), this), nid, null); |
| 171 } | 179 } |
| 172 return revision; | 180 return revision; |
| 173 } | 181 } |
| 174 | 182 |
| 175 private int doFindWithCache(Nodeid nid) { | 183 private int doFindWithCache(Nodeid nid) throws HgRuntimeException { |
| 176 if (useRevisionLookup) { | 184 if (useRevisionLookup) { |
| 177 if (revisionLookup == null || content.shallDropDerivedCaches()) { | 185 if (revisionLookup == null || content.shallDropDerivedCaches()) { |
| 178 content.detach(revisionLookupCleaner); | 186 content.detach(revisionLookupCleaner); |
| 179 setRevisionLookup(RevisionLookup.createFor(content)); | 187 setRevisionLookup(RevisionLookup.createFor(content)); |
| 180 } | 188 } |
| 197 /** | 205 /** |
| 198 * Note, {@link Nodeid#NULL} nodeid is not reported as known in any revlog. | 206 * Note, {@link Nodeid#NULL} nodeid is not reported as known in any revlog. |
| 199 * | 207 * |
| 200 * @param nodeid | 208 * @param nodeid |
| 201 * @return <code>true</code> if revision is part of this revlog | 209 * @return <code>true</code> if revision is part of this revlog |
| 202 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | 210 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> |
| 211 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> | |
| 203 */ | 212 */ |
| 204 public final boolean isKnown(Nodeid nodeid) throws HgRuntimeException { | 213 public final boolean isKnown(Nodeid nodeid) throws HgRuntimeException { |
| 205 final int rn = doFindWithCache(nodeid); | 214 final int rn = doFindWithCache(nodeid); |
| 206 if (BAD_REVISION == rn) { | 215 if (BAD_REVISION == rn) { |
| 207 return false; | 216 return false; |
| 217 * Access to revision data as is, equivalent to <code>rawContent(getRevisionIndex(nodeid), sink)</code> | 226 * Access to revision data as is, equivalent to <code>rawContent(getRevisionIndex(nodeid), sink)</code> |
| 218 * | 227 * |
| 219 * @param nodeid revision to retrieve | 228 * @param nodeid revision to retrieve |
| 220 * @param sink data destination | 229 * @param sink data destination |
| 221 * | 230 * |
| 222 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog | 231 * @see #rawContent(int, ByteChannel) |
| 223 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | 232 * |
| 224 * @throws CancelledException if content retrieval operation was cancelled | 233 * @throws CancelledException if content retrieval operation was cancelled |
| 225 * | 234 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog. <em>Runtime exception</em> |
| 226 * @see #rawContent(int, ByteChannel) | 235 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> |
| 227 */ | 236 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> |
| 228 protected void rawContent(Nodeid nodeid, ByteChannel sink) throws HgInvalidControlFileException, CancelledException, HgInvalidRevisionException { | 237 */ |
| 238 protected void rawContent(Nodeid nodeid, ByteChannel sink) throws CancelledException, HgRuntimeException { | |
| 229 rawContent(getRevisionIndex(nodeid), sink); | 239 rawContent(getRevisionIndex(nodeid), sink); |
| 230 } | 240 } |
| 231 | 241 |
| 232 /** | 242 /** |
| 233 * Access to revision data as is (decompressed, but otherwise unprocessed, i.e. not parsed for e.g. changeset or manifest entries). | 243 * Access to revision data as is (decompressed, but otherwise unprocessed, i.e. not parsed for e.g. changeset or manifest entries). |
| 234 * | 244 * |
| 235 * @param revisionIndex index of this revlog change (not a changelog revision index), non-negative. From predefined constants, only {@link HgRepository#TIP} makes sense. | 245 * @param revisionIndex index of this revlog change (not a changelog revision index), non-negative. From predefined constants, only {@link HgRepository#TIP} makes sense. |
| 236 * @param sink data destination | 246 * @param sink data destination |
| 237 * | 247 * |
| 238 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog | |
| 239 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | |
| 240 * @throws CancelledException if content retrieval operation was cancelled | 248 * @throws CancelledException if content retrieval operation was cancelled |
| 241 */ | 249 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog. <em>Runtime exception</em> |
| 242 protected void rawContent(int revisionIndex, ByteChannel sink) throws HgInvalidControlFileException, CancelledException, HgInvalidRevisionException { | 250 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> |
| 251 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> | |
| 252 */ | |
| 253 protected void rawContent(int revisionIndex, ByteChannel sink) throws CancelledException, HgRuntimeException { | |
| 243 if (sink == null) { | 254 if (sink == null) { |
| 244 throw new IllegalArgumentException(); | 255 throw new IllegalArgumentException(); |
| 245 } | 256 } |
| 246 try { | 257 try { |
| 247 ContentPipe insp = new ContentPipe(sink, 0, repo.getSessionContext().getLog()); | 258 ContentPipe insp = new ContentPipe(sink, 0, repo.getSessionContext().getLog()); |
| 346 final IntMap<Nodeid> missingParents = parentInsp == null || _start == 0 ? null : new IntMap<Nodeid>(16); | 357 final IntMap<Nodeid> missingParents = parentInsp == null || _start == 0 ? null : new IntMap<Nodeid>(16); |
| 347 | 358 |
| 348 content.iterate(_start, end, false, new RevlogStream.Inspector() { | 359 content.iterate(_start, end, false, new RevlogStream.Inspector() { |
| 349 private int i = 0; | 360 private int i = 0; |
| 350 | 361 |
| 351 public void next(int revisionIndex, int actualLen, int baseRevIndex, int linkRevIndex, int parent1RevIndex, int parent2RevIndex, byte[] nodeid, DataAccess data) { | 362 public void next(int revisionIndex, int actualLen, int baseRevIndex, int linkRevIndex, int parent1RevIndex, int parent2RevIndex, byte[] nodeid, DataAccess data) throws HgRuntimeException { |
| 352 Nodeid nid = Nodeid.fromBinary(nodeid, 0); | 363 Nodeid nid = Nodeid.fromBinary(nodeid, 0); |
| 353 if (revisionInsp != null) { | 364 if (revisionInsp != null) { |
| 354 revisionInsp.next(revisionIndex, nid, linkRevIndex); | 365 revisionInsp.next(revisionIndex, nid, linkRevIndex); |
| 355 } | 366 } |
| 356 if (parentInsp != null) { | 367 if (parentInsp != null) { |
| 415 public interface Inspector { | 426 public interface Inspector { |
| 416 } | 427 } |
| 417 | 428 |
| 418 @Experimental | 429 @Experimental |
| 419 public interface RevisionInspector extends Inspector { | 430 public interface RevisionInspector extends Inspector { |
| 420 void next(int revisionIndex, Nodeid revision, int linkedRevisionIndex); | 431 void next(int revisionIndex, Nodeid revision, int linkedRevisionIndex) throws HgRuntimeException; |
| 421 } | 432 } |
| 422 | 433 |
| 423 @Experimental | 434 @Experimental |
| 424 public interface ParentInspector extends Inspector { | 435 public interface ParentInspector extends Inspector { |
| 425 // XXX document whether parentX is -1 or a constant (BAD_REVISION? or dedicated?) | 436 // XXX document whether parentX is -1 or a constant (BAD_REVISION? or dedicated?) |
| 426 void next(int revisionIndex, Nodeid revision, int parent1, int parent2, Nodeid nidParent1, Nodeid nidParent2); | 437 void next(int revisionIndex, Nodeid revision, int parent1, int parent2, Nodeid nidParent1, Nodeid nidParent2) throws HgRuntimeException; |
| 427 } | 438 } |
| 428 | 439 |
| 429 protected HgParentChildMap<? extends Revlog> getParentWalker() { | 440 protected HgParentChildMap<? extends Revlog> getParentWalker() throws HgRuntimeException { |
| 430 HgParentChildMap<Revlog> pw = new HgParentChildMap<Revlog>(this); | 441 HgParentChildMap<Revlog> pw = new HgParentChildMap<Revlog>(this); |
| 431 pw.init(); | 442 pw.init(); |
| 432 return pw; | 443 return pw; |
| 433 } | 444 } |
| 434 | 445 |
