Mercurial > hg4j
diff src/org/tmatesoft/hg/repo/Revlog.java @ 277:74e7493a042a
Favor delegation over generalization
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Mon, 29 Aug 2011 23:14:59 +0200 |
parents | 9fb50c04f03c |
children | 2f2ab5c27f41 |
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/Revlog.java Mon Aug 29 22:15:12 2011 +0200 +++ b/src/org/tmatesoft/hg/repo/Revlog.java Mon Aug 29 23:14:59 2011 +0200 @@ -449,58 +449,13 @@ } } - - protected static class ContentPipe implements RevlogStream.Inspector, CancelSupport { - private final ByteChannel sink; - private final CancelSupport cancelSupport; + protected abstract static class ErrorHandlingInspector implements RevlogStream.Inspector, CancelSupport { private Exception failure; - private final int offset; - - /** - * @param _sink - cannot be <code>null</code> - * @param seekOffset - when positive, orders to pipe bytes to the sink starting from specified offset, not from the first byte available in DataAccess - */ - public ContentPipe(ByteChannel _sink, int seekOffset) { - assert _sink != null; - sink = _sink; - cancelSupport = CancelSupport.Factory.get(_sink); - offset = seekOffset; - } + private CancelSupport cancelSupport; - protected void prepare(int revisionNumber, DataAccess da) throws HgException, IOException { - if (offset > 0) { // save few useless reset/rewind operations - da.seek(offset); - } - } - - public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { - try { - prepare(revisionNumber, da); // XXX perhaps, prepare shall return DA (sliced, if needed) - final ProgressSupport progressSupport = ProgressSupport.Factory.get(sink); - ByteBuffer buf = ByteBuffer.allocate(512); - progressSupport.start(da.length()); - while (!da.isEmpty()) { - cancelSupport.checkCancelled(); - da.readBytes(buf); - buf.flip(); - // XXX I may not rely on returned number of bytes but track change in buf position instead. - int consumed = sink.write(buf); - // FIXME in fact, bad sink implementation (that consumes no bytes) would result in endless loop. Need to account for this - buf.compact(); - progressSupport.worked(consumed); - } - progressSupport.done(); // XXX shall specify whether #done() is invoked always or only if completed successfully. - } catch (IOException ex) { - recordFailure(ex); - } catch (CancelledException ex) { - recordFailure(ex); - } catch (HgException ex) { - recordFailure(ex); - } - } - - public void checkCancelled() throws CancelledException { - cancelSupport.checkCancelled(); + protected void setCancelSupport(CancelSupport cs) { + assert cancelSupport == null; // no reason to set it twice + cancelSupport = cs; } protected void recordFailure(Exception ex) { @@ -523,5 +478,59 @@ } throw new HgBadStateException(failure); } + + public void checkCancelled() throws CancelledException { + if (cancelSupport != null) { + cancelSupport.checkCancelled(); + } + } + } + + protected static class ContentPipe extends ErrorHandlingInspector implements RevlogStream.Inspector, CancelSupport { + private final ByteChannel sink; + private final int offset; + + /** + * @param _sink - cannot be <code>null</code> + * @param seekOffset - when positive, orders to pipe bytes to the sink starting from specified offset, not from the first byte available in DataAccess + */ + public ContentPipe(ByteChannel _sink, int seekOffset) { + assert _sink != null; + sink = _sink; + setCancelSupport(CancelSupport.Factory.get(_sink)); + offset = seekOffset; + } + + protected void prepare(int revisionNumber, DataAccess da) throws HgException, IOException { + if (offset > 0) { // save few useless reset/rewind operations + da.seek(offset); + } + } + + public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { + try { + prepare(revisionNumber, da); // XXX perhaps, prepare shall return DA (sliced, if needed) + final ProgressSupport progressSupport = ProgressSupport.Factory.get(sink); + ByteBuffer buf = ByteBuffer.allocate(512); + progressSupport.start(da.length()); + while (!da.isEmpty()) { + checkCancelled(); + da.readBytes(buf); + buf.flip(); + // XXX I may not rely on returned number of bytes but track change in buf position instead. + int consumed = sink.write(buf); + // FIXME in fact, bad sink implementation (that consumes no bytes) would result in endless loop. Need to account for this + buf.compact(); + progressSupport.worked(consumed); + } + progressSupport.done(); // XXX shall specify whether #done() is invoked always or only if completed successfully. + } catch (IOException ex) { + recordFailure(ex); + } catch (CancelledException ex) { + recordFailure(ex); + } catch (HgException ex) { + recordFailure(ex); + } + } } }