diff --git a/model/blockqueue.go b/model/blockqueue.go index e88482385..ef14ab3c5 100644 --- a/model/blockqueue.go +++ b/model/blockqueue.go @@ -16,6 +16,7 @@ type bqBlock struct { file scanner.File block scanner.Block // get this block from the network copy []scanner.Block // copy these blocks from the old version of the file + first bool last bool } @@ -47,24 +48,30 @@ func (q *blockQueue) addBlock(a bqAdd) { return } } + + l := len(a.need) + if len(a.have) > 0 { // First queue a copy operation q.queued = append(q.queued, bqBlock{ - file: a.file, - copy: a.have, + file: a.file, + copy: a.have, + first: true, + last: l == 0, }) } + // Queue the needed blocks individually - l := len(a.need) for i, b := range a.need { q.queued = append(q.queued, bqBlock{ file: a.file, block: b, + first: len(a.have) == 0 && i == 0, last: i == l-1, }) } - if l == 0 { + if len(a.need)+len(a.have) == 0 { // If we didn't have anything to fetch, queue an empty block with the "last" flag set to close the file. q.queued = append(q.queued, bqBlock{ file: a.file, diff --git a/model/puller.go b/model/puller.go index 1ac29cb5c..d375cc601 100644 --- a/model/puller.go +++ b/model/puller.go @@ -373,6 +373,29 @@ func (p *puller) handleBlock(b bqBlock) bool { return true } + if len(b.copy) > 0 && len(b.copy) == len(b.file.Blocks) && b.last { + // We are supposed to copy the entire file, and then fetch nothing. + // We don't actually need to make the copy. + if debug { + l.Debugln("taking shortcut:", f) + } + fp := filepath.Join(p.repoCfg.Directory, f.Name) + t := time.Unix(f.Modified, 0) + err := os.Chtimes(fp, t, t) + if debug && err != nil { + l.Debugf("pull: error: %q / %q: %v", p.repoCfg.ID, f.Name, err) + } + if !p.repoCfg.IgnorePerms && protocol.HasPermissionBits(f.Flags) { + err = os.Chmod(fp, os.FileMode(f.Flags&0777)) + if debug && err != nil { + l.Debugf("pull: error: %q / %q: %v", p.repoCfg.ID, f.Name, err) + } + } + + p.model.updateLocal(p.repoCfg.ID, f) + return true + } + of, ok := p.openFiles[f.Name] of.done = b.last diff --git a/model/util_test.go b/model/util_test.go index b4f821ffc..6709f0f2b 100644 --- a/model/util_test.go +++ b/model/util_test.go @@ -20,24 +20,6 @@ var testcases = []struct { remote: protocol.ClusterConfigMessage{ClientName: "c", ClientVersion: "d"}, err: "", }, - { - local: protocol.ClusterConfigMessage{ - Repositories: []protocol.Repository{ - {ID: "foo"}, - }, - }, - remote: protocol.ClusterConfigMessage{ClientName: "c", ClientVersion: "d"}, - err: `remote is missing repository "foo"`, - }, - { - local: protocol.ClusterConfigMessage{ClientName: "c", ClientVersion: "d"}, - remote: protocol.ClusterConfigMessage{ - Repositories: []protocol.Repository{ - {ID: "foo"}, - }, - }, - err: `remote has extra repository "foo"`, - }, { local: protocol.ClusterConfigMessage{ Repositories: []protocol.Repository{ @@ -53,38 +35,6 @@ var testcases = []struct { }, err: "", }, - { - local: protocol.ClusterConfigMessage{ - Repositories: []protocol.Repository{ - {ID: "quux"}, - {ID: "foo"}, - {ID: "bar"}, - }, - }, - remote: protocol.ClusterConfigMessage{ - Repositories: []protocol.Repository{ - {ID: "bar"}, - {ID: "quux"}, - }, - }, - err: `remote is missing repository "foo"`, - }, - { - local: protocol.ClusterConfigMessage{ - Repositories: []protocol.Repository{ - {ID: "quux"}, - {ID: "bar"}, - }, - }, - remote: protocol.ClusterConfigMessage{ - Repositories: []protocol.Repository{ - {ID: "bar"}, - {ID: "foo"}, - {ID: "quux"}, - }, - }, - err: `remote has extra repository "foo"`, - }, { local: protocol.ClusterConfigMessage{ Repositories: []protocol.Repository{ diff --git a/protocol/debug.go b/protocol/debug.go new file mode 100644 index 000000000..f1ebaf400 --- /dev/null +++ b/protocol/debug.go @@ -0,0 +1,13 @@ +package protocol + +import ( + "os" + "strings" + + "github.com/calmh/syncthing/logger" +) + +var ( + debug = strings.Contains(os.Getenv("STTRACE"), "protocol") || os.Getenv("STTRACE") == "all" + l = logger.DefaultLogger +) diff --git a/upnp/upnp.go b/upnp/upnp.go index 9de719aa5..6e11bf79d 100644 --- a/upnp/upnp.go +++ b/upnp/upnp.go @@ -60,14 +60,14 @@ func Discover() (*IGD, error) { return nil, err } - search := []byte(` -M-SEARCH * HTTP/1.1 + searchStr := `M-SEARCH * HTTP/1.1 Host: 239.255.255.250:1900 St: urn:schemas-upnp-org:device:InternetGatewayDevice:1 Man: "ssdp:discover" Mx: 3 -`) +` + search := []byte(strings.Replace(searchStr, "\n", "\r\n", -1)) _, err = socket.WriteTo(search, ssdp) if err != nil {