Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgManifest.java @ 312:f9f3e9b67ccc
Facilitate cancellation and progress reporting in changelog and manifest iterations
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Tue, 27 Sep 2011 05:29:12 +0200 |
parents | 85b8efde5586 |
children | c1e3c18fd2f2 |
comparison
equal
deleted
inserted
replaced
311:b9592e21176a | 312:f9f3e9b67ccc |
---|---|
26 import org.tmatesoft.hg.core.HgBadStateException; | 26 import org.tmatesoft.hg.core.HgBadStateException; |
27 import org.tmatesoft.hg.core.Nodeid; | 27 import org.tmatesoft.hg.core.Nodeid; |
28 import org.tmatesoft.hg.internal.DataAccess; | 28 import org.tmatesoft.hg.internal.DataAccess; |
29 import org.tmatesoft.hg.internal.DigestHelper; | 29 import org.tmatesoft.hg.internal.DigestHelper; |
30 import org.tmatesoft.hg.internal.Experimental; | 30 import org.tmatesoft.hg.internal.Experimental; |
31 import org.tmatesoft.hg.internal.IterateControlMediator; | |
31 import org.tmatesoft.hg.internal.Lifecycle; | 32 import org.tmatesoft.hg.internal.Lifecycle; |
32 import org.tmatesoft.hg.internal.Pool2; | 33 import org.tmatesoft.hg.internal.Pool2; |
33 import org.tmatesoft.hg.internal.RevlogStream; | 34 import org.tmatesoft.hg.internal.RevlogStream; |
35 import org.tmatesoft.hg.util.CancelSupport; | |
34 import org.tmatesoft.hg.util.Path; | 36 import org.tmatesoft.hg.util.Path; |
37 import org.tmatesoft.hg.util.ProgressSupport; | |
35 | 38 |
36 | 39 |
37 /** | 40 /** |
38 * | 41 * |
39 * @author Artem Tikhomirov | 42 * @author Artem Tikhomirov |
275 } | 278 } |
276 return result; | 279 return result; |
277 } | 280 } |
278 } | 281 } |
279 | 282 |
280 private static class ManifestParser implements RevlogStream.Inspector { | 283 private static class ManifestParser implements RevlogStream.Inspector, Lifecycle { |
281 private boolean gtg = true; // good to go | |
282 private final Inspector inspector; | 284 private final Inspector inspector; |
283 private final Inspector2 inspector2; | 285 private final Inspector2 inspector2; |
284 private Pool2<Nodeid> nodeidPool, thisRevPool; | 286 private Pool2<Nodeid> nodeidPool, thisRevPool; |
285 private final Pool2<PathProxy> fnamePool; | 287 private final Pool2<PathProxy> fnamePool; |
286 private byte[] nodeidLookupBuffer = new byte[20]; // get reassigned each time new Nodeid is added to pool | 288 private byte[] nodeidLookupBuffer = new byte[20]; // get reassigned each time new Nodeid is added to pool |
289 private final ProgressSupport progressHelper; | |
290 private IterateControlMediator iterateControl; | |
287 | 291 |
288 public ManifestParser(Inspector delegate) { | 292 public ManifestParser(Inspector delegate) { |
289 assert delegate != null; | 293 assert delegate != null; |
290 inspector = delegate; | 294 inspector = delegate; |
291 inspector2 = delegate instanceof Inspector2 ? (Inspector2) delegate : null; | 295 inspector2 = delegate instanceof Inspector2 ? (Inspector2) delegate : null; |
292 nodeidPool = new Pool2<Nodeid>(); | 296 nodeidPool = new Pool2<Nodeid>(); |
293 fnamePool = new Pool2<PathProxy>(); | 297 fnamePool = new Pool2<PathProxy>(); |
294 thisRevPool = new Pool2<Nodeid>(); | 298 thisRevPool = new Pool2<Nodeid>(); |
299 progressHelper = ProgressSupport.Factory.get(delegate); | |
295 } | 300 } |
296 | 301 |
297 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { | 302 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { |
298 if (!gtg) { | |
299 return; | |
300 } | |
301 try { | 303 try { |
302 gtg = gtg && inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision); | 304 if (!inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision)) { |
305 iterateControl.stop(); | |
306 return; | |
307 } | |
303 Path fname = null; | 308 Path fname = null; |
304 Flags flags = null; | 309 Flags flags = null; |
305 Nodeid nid = null; | 310 Nodeid nid = null; |
306 int i; | 311 int i; |
307 byte[] data = da.byteArray(); | 312 byte[] data = da.byteArray(); |
308 for (i = 0; gtg && i < actualLen; i++) { | 313 for (i = 0; i < actualLen; i++) { |
309 int x = i; | 314 int x = i; |
310 for( ; data[i] != '\n' && i < actualLen; i++) { | 315 for( ; data[i] != '\n' && i < actualLen; i++) { |
311 if (fname == null && data[i] == 0) { | 316 if (fname == null && data[i] == 0) { |
312 PathProxy px = fnamePool.unify(new PathProxy(data, x, i - x)); | 317 PathProxy px = fnamePool.unify(new PathProxy(data, x, i - x)); |
313 // if (cached = fnamePool.unify(px))== px then cacheMiss, else cacheHit | 318 // if (cached = fnamePool.unify(px))== px then cacheMiss, else cacheHit |
335 // for cpython 0..10k, there are 4361062 flag checks, and there's only 1 unique flag | 340 // for cpython 0..10k, there are 4361062 flag checks, and there's only 1 unique flag |
336 flags = Flags.parse(data, x + nodeidLen, i-x-nodeidLen); | 341 flags = Flags.parse(data, x + nodeidLen, i-x-nodeidLen); |
337 } else { | 342 } else { |
338 flags = null; | 343 flags = null; |
339 } | 344 } |
345 boolean good2go; | |
340 if (inspector2 == null) { | 346 if (inspector2 == null) { |
341 String flagString = flags == null ? null : flags.nativeString(); | 347 String flagString = flags == null ? null : flags.nativeString(); |
342 gtg = inspector.next(nid, fname.toString(), flagString); | 348 good2go = inspector.next(nid, fname.toString(), flagString); |
343 } else { | 349 } else { |
344 gtg = inspector2.next(nid, fname, flags); | 350 good2go = inspector2.next(nid, fname, flags); |
351 } | |
352 if (!good2go) { | |
353 iterateControl.stop(); | |
354 return; | |
345 } | 355 } |
346 } | 356 } |
347 nid = null; | 357 nid = null; |
348 fname = null; | 358 fname = null; |
349 flags = null; | 359 flags = null; |
350 } | 360 } |
351 gtg = gtg && inspector.end(revisionNumber); | 361 if (!inspector.end(revisionNumber)) { |
362 iterateControl.stop(); | |
363 return; | |
364 } | |
352 // | 365 // |
353 // keep only actual file revisions, found at this version | 366 // keep only actual file revisions, found at this version |
354 // (next manifest is likely to refer to most of them, although in specific cases | 367 // (next manifest is likely to refer to most of them, although in specific cases |
355 // like commit in another branch a lot may be useless) | 368 // like commit in another branch a lot may be useless) |
356 nodeidPool.clear(); | 369 nodeidPool.clear(); |
357 Pool2<Nodeid> t = nodeidPool; | 370 Pool2<Nodeid> t = nodeidPool; |
358 nodeidPool = thisRevPool; | 371 nodeidPool = thisRevPool; |
359 thisRevPool = t; | 372 thisRevPool = t; |
373 progressHelper.worked(1); | |
360 } catch (IOException ex) { | 374 } catch (IOException ex) { |
361 throw new HgBadStateException(ex); | 375 throw new HgBadStateException(ex); |
362 } | 376 } |
377 } | |
378 | |
379 public void start(int count, Callback callback, Object token) { | |
380 CancelSupport cs = CancelSupport.Factory.get(inspector, null); | |
381 iterateControl = new IterateControlMediator(cs, callback); | |
382 progressHelper.start(count); | |
383 } | |
384 | |
385 public void finish(Object token) { | |
386 progressHelper.done(); | |
363 } | 387 } |
364 } | 388 } |
365 | 389 |
366 private static class RevisionMapper implements RevlogStream.Inspector, Lifecycle { | 390 private static class RevisionMapper implements RevlogStream.Inspector, Lifecycle { |
367 | 391 |