Skip to content
This repository has been archived by the owner on Sep 11, 2020. It is now read-only.

protocol/packp: sideband muxer and demuxer #143

Merged
merged 8 commits into from
Nov 30, 2016
Merged

protocol/packp: sideband muxer and demuxer #143

merged 8 commits into from
Nov 30, 2016

Conversation

mcuadros
Copy link
Contributor

This is the implementation of the sideband muxer and the demuxer.

"errors"
"fmt"
"io"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra space

case PackData:
return content[1:], err
case ProgressMessage:
_, err := d.Progress.(io.Writer).Write(content[1:])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Progress needs to be a Writer, shouldn't it be defined as io.ReadWriter instead of just io.Reader?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is preventing being written by external sources, also I can to declare the intent that should be used for reading

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

_, err := d.Progress.(io.Writer).Write(content[1:])
return nil, err
case ErrorMessage:
return nil, fmt.Errorf("unexepcted error: %s", content[1:])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unexepcted -> unexpected

"testing"

. "gopkg.in/check.v1"
"gopkg.in/src-d/go-git.v4/plumbing/format/pktline"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import group order

}

if !d.s.Scan() {
return nil, io.EOF
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if there is no more input, shouldn't the scanner error be checked instead of always returning io.EOF?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And Error is always nil, when Scan returns io.EOF @alcortesm

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, Error() is not always nil and Scan() does not return io.EOF, it returns a boolean instead: from pktline.Scanner.Scan(), plumbing/format/pktline/scanner.go:44 :

// Scan advances the Scanner to the next pkt-line, whose payload will
// then be available through the Bytes method.  Scanning stops at EOF
// or the first I/O error.  After Scan returns false, the Err method
// will return any error that occurred during scanning, except that if
// it was io.EOF, Err will return nil.
func (s *Scanner) Scan() bool {

We should definitely check the scanner error in this case and return io.EOF if the error is nil.

This is a similar behavior as bufio.Scanner, see https://golang.org/pkg/bufio/#example_Scanner_lines for example.

"testing"

. "gopkg.in/check.v1"
"gopkg.in/src-d/go-git.v4/plumbing/format/pktline"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad import order?

// be return if an error happends when reading or if a message is sent in the
// ErrorMessage channel.
//
// If a ProgressMessage is read, it's not copied into b, intead of this is
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove duplicated 'is'

// If a ProgressMessage is read, it's not copied into b, intead of this is
// is stored, can be read through the reader Progress, the n value returned is
// zero, err is nil unless an error reading happends.
func (d *Demuxer) Read(b []byte) (n int, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewrite the second paragraph. An example:

If a ProgressMessage is read, it won't be copied to b. Instead of this, it is stored and can be read through the reader Progress. If the n value returned is zero, err will be nil unless an error reading happens.

}
}

// Read reads up to len(p) bytes from the PackData channel into p, an error can
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this description is not exact: I think this method reads from the 3 channels, not just the PackData channel.

I think this requires a better explanation, as there are 3 channels but only 2 readers. I would write a small table explaining how to read from each channel and how to know if there is data in any of them, maybe as an explanation to the package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have a more detailed explanation of Demux at the struct, I think is clear enough, this function (specially for the user), only reads Packdata into p

}

content := d.pending
d.pending = make([]byte, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this to:

d.pending =  nil

to avoid allocating memory that will be thrown away when size > wanted in doRead.

This is convoluted and a little confusing, as the whole function does not really read and it is just two lines:

content := d.pending
d.pending = nil

And then we have to reslice in the calling function. Better remove the function and reslice directly.

wanted := len(b)

if size > wanted {
d.pending = read[wanted:size]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simplify read[wanted:size] to read[wanted:].


content := make([]byte, 26)
d := NewDemuxer(Sideband64k, buf)
n, err := d.Read(content)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change Read to ReadFull.

The same for all the tests.


buf := bytes.NewBuffer(nil)
e := pktline.NewEncoder(buf)
e.Encode(append(PackData.Bytes(), expected[0:8]...))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome.

I think you should write this line as an example in the comment of the Channel.Byte() method, so everybody understand, at a single glance, what is its intended use case.

You can also call the method func (c Channel) WithPayload(b []byte) []byte, so its usage will be a little more clear:

e.Encode(PackData.WithPayload(expected[0:8])

And make it return a multireader to save memory.

@codecov-io
Copy link

codecov-io commented Nov 28, 2016

Current coverage is 73.57% (diff: 89.41%)

Merging #143 into master will decrease coverage by 2.73%

@@             master       #143   diff @@
==========================================
  Files            78         81     +3   
  Lines          5073       5176   +103   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
- Hits           3871       3808    -63   
- Misses          756        936   +180   
+ Partials        446        432    -14   

Powered by Codecov. Last update 7fe6bc7...71ce6e0

@mcuadros mcuadros merged commit 5cdb09c into src-d:master Nov 30, 2016
@mcuadros mcuadros deleted the sideband branch December 13, 2016 10:13
mcuadros added a commit that referenced this pull request Jan 31, 2017
* format/pakp: sideband demuxer

* format/pakp: sideband muxer

* format/pakp: sideband demuxer and muxer

* protocol/pakp: sideband demuxer and muxer

* documentation and improvements

* improvements

* handle scan errors properly
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants