mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-22 19:08:58 +00:00
Show warnings in GUI (fixes #66)
This commit is contained in:
parent
2cbe81f1c7
commit
91d5c4a1ae
@ -1,4 +1,4 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -1,4 +1,4 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -1,4 +1,4 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -1,4 +1,4 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
@ -1,4 +1,4 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
49
gui.go
49
gui.go
@ -2,18 +2,28 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/calmh/syncthing/model"
|
|
||||||
"github.com/codegangsta/martini"
|
"github.com/codegangsta/martini"
|
||||||
)
|
)
|
||||||
|
|
||||||
var configInSync = true
|
type guiError struct {
|
||||||
|
Time time.Time
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
func startGUI(addr string, m *model.Model) {
|
var (
|
||||||
|
configInSync = true
|
||||||
|
guiErrors = []guiError{}
|
||||||
|
guiErrorsMut sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
|
func startGUI(addr string, m *Model) {
|
||||||
router := martini.NewRouter()
|
router := martini.NewRouter()
|
||||||
router.Get("/", getRoot)
|
router.Get("/", getRoot)
|
||||||
router.Get("/rest/version", restGetVersion)
|
router.Get("/rest/version", restGetVersion)
|
||||||
@ -23,9 +33,11 @@ func startGUI(addr string, m *model.Model) {
|
|||||||
router.Get("/rest/config/sync", restGetConfigInSync)
|
router.Get("/rest/config/sync", restGetConfigInSync)
|
||||||
router.Get("/rest/need", restGetNeed)
|
router.Get("/rest/need", restGetNeed)
|
||||||
router.Get("/rest/system", restGetSystem)
|
router.Get("/rest/system", restGetSystem)
|
||||||
|
router.Get("/rest/errors", restGetErrors)
|
||||||
|
|
||||||
router.Post("/rest/config", restPostConfig)
|
router.Post("/rest/config", restPostConfig)
|
||||||
router.Post("/rest/restart", restPostRestart)
|
router.Post("/rest/restart", restPostRestart)
|
||||||
|
router.Post("/rest/error", restPostError)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
mr := martini.New()
|
mr := martini.New()
|
||||||
@ -48,7 +60,7 @@ func restGetVersion() string {
|
|||||||
return Version
|
return Version
|
||||||
}
|
}
|
||||||
|
|
||||||
func restGetModel(m *model.Model, w http.ResponseWriter) {
|
func restGetModel(m *Model, w http.ResponseWriter) {
|
||||||
var res = make(map[string]interface{})
|
var res = make(map[string]interface{})
|
||||||
|
|
||||||
globalFiles, globalDeleted, globalBytes := m.GlobalSize()
|
globalFiles, globalDeleted, globalBytes := m.GlobalSize()
|
||||||
@ -67,7 +79,7 @@ func restGetModel(m *model.Model, w http.ResponseWriter) {
|
|||||||
json.NewEncoder(w).Encode(res)
|
json.NewEncoder(w).Encode(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func restGetConnections(m *model.Model, w http.ResponseWriter) {
|
func restGetConnections(m *Model, w http.ResponseWriter) {
|
||||||
var res = m.ConnectionStats()
|
var res = m.ConnectionStats()
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(res)
|
json.NewEncoder(w).Encode(res)
|
||||||
@ -95,7 +107,7 @@ func restPostRestart(req *http.Request) {
|
|||||||
restart()
|
restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
type guiFile model.File
|
type guiFile File
|
||||||
|
|
||||||
func (f guiFile) MarshalJSON() ([]byte, error) {
|
func (f guiFile) MarshalJSON() ([]byte, error) {
|
||||||
type t struct {
|
type t struct {
|
||||||
@ -104,11 +116,11 @@ func (f guiFile) MarshalJSON() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
return json.Marshal(t{
|
return json.Marshal(t{
|
||||||
Name: f.Name,
|
Name: f.Name,
|
||||||
Size: model.File(f).Size(),
|
Size: File(f).Size(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func restGetNeed(m *model.Model, w http.ResponseWriter) {
|
func restGetNeed(m *Model, w http.ResponseWriter) {
|
||||||
files, _ := m.NeedFiles()
|
files, _ := m.NeedFiles()
|
||||||
gfs := make([]guiFile, len(files))
|
gfs := make([]guiFile, len(files))
|
||||||
for i, f := range files {
|
for i, f := range files {
|
||||||
@ -137,3 +149,24 @@ func restGetSystem(w http.ResponseWriter) {
|
|||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(res)
|
json.NewEncoder(w).Encode(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func restGetErrors(w http.ResponseWriter) {
|
||||||
|
guiErrorsMut.Lock()
|
||||||
|
json.NewEncoder(w).Encode(guiErrors)
|
||||||
|
guiErrorsMut.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func restPostError(req *http.Request) {
|
||||||
|
bs, _ := ioutil.ReadAll(req.Body)
|
||||||
|
req.Body.Close()
|
||||||
|
showGuiError(string(bs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func showGuiError(err string) {
|
||||||
|
guiErrorsMut.Lock()
|
||||||
|
guiErrors = append(guiErrors, guiError{time.Now(), err})
|
||||||
|
if len(guiErrors) > 5 {
|
||||||
|
guiErrors = guiErrors[len(guiErrors)-5:]
|
||||||
|
}
|
||||||
|
guiErrorsMut.Unlock()
|
||||||
|
}
|
||||||
|
29
gui/app.js
29
gui/app.js
@ -14,6 +14,8 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
|||||||
$scope.myID = '';
|
$scope.myID = '';
|
||||||
$scope.nodes = [];
|
$scope.nodes = [];
|
||||||
$scope.configInSync = true;
|
$scope.configInSync = true;
|
||||||
|
$scope.errors = [];
|
||||||
|
$scope.seenError = '';
|
||||||
|
|
||||||
// Strings before bools look better
|
// Strings before bools look better
|
||||||
$scope.settings = [
|
$scope.settings = [
|
||||||
@ -131,6 +133,9 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
|||||||
});
|
});
|
||||||
$scope.need = data;
|
$scope.need = data;
|
||||||
});
|
});
|
||||||
|
$http.get('/rest/errors').success(function (data) {
|
||||||
|
$scope.errors = data;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.nodeIcon = function (nodeCfg) {
|
$scope.nodeIcon = function (nodeCfg) {
|
||||||
@ -234,6 +239,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
|||||||
$scope.nodes = newNodes;
|
$scope.nodes = newNodes;
|
||||||
$scope.config.Repositories[0].Nodes = newNodes;
|
$scope.config.Repositories[0].Nodes = newNodes;
|
||||||
|
|
||||||
|
$scope.configInSync = false;
|
||||||
$http.post('/rest/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}});
|
$http.post('/rest/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -287,6 +293,29 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.errorList = function () {
|
||||||
|
var errors = [];
|
||||||
|
for (var i = 0; i < $scope.errors.length; i++) {
|
||||||
|
var e = $scope.errors[i];
|
||||||
|
if (e.Time > $scope.seenError) {
|
||||||
|
errors.push(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.clearErrors = function () {
|
||||||
|
$scope.seenError = $scope.errors[$scope.errors.length - 1].Time;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.friendlyNodes = function (str) {
|
||||||
|
for (var i = 0; i < $scope.nodes.length; i++) {
|
||||||
|
var cfg = $scope.nodes[i];
|
||||||
|
str = str.replace(cfg.NodeID, $scope.nodeName(cfg));
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
$scope.refresh();
|
$scope.refresh();
|
||||||
setInterval($scope.refresh, 10000);
|
setInterval($scope.refresh, 10000);
|
||||||
});
|
});
|
||||||
|
@ -55,6 +55,12 @@ thead tr th {
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
<div ng-if="errorList().length > 0" class="alert alert-warning">
|
||||||
|
<p ng-repeat="err in errorList()"><small>{{err.Time | date:"hh:mm:ss.sss"}}:</small> {{friendlyNodes(err.Error)}}</p>
|
||||||
|
<button type="button" class="pull-right btn btn-warning" ng-click="clearErrors()">OK</button>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="panel panel-info">
|
<div class="panel panel-info">
|
||||||
<div class="panel-heading"><h3 class="panel-title">Cluster</h3></div>
|
<div class="panel-heading"><h3 class="panel-title">Cluster</h3></div>
|
||||||
<table class="table table-condensed">
|
<table class="table table-condensed">
|
||||||
|
@ -41,11 +41,13 @@ func okf(format string, vals ...interface{}) {
|
|||||||
|
|
||||||
func warnln(vals ...interface{}) {
|
func warnln(vals ...interface{}) {
|
||||||
s := fmt.Sprintln(vals...)
|
s := fmt.Sprintln(vals...)
|
||||||
|
showGuiError(s)
|
||||||
logger.Output(2, "WARNING: "+s)
|
logger.Output(2, "WARNING: "+s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func warnf(format string, vals ...interface{}) {
|
func warnf(format string, vals ...interface{}) {
|
||||||
s := fmt.Sprintf(format, vals...)
|
s := fmt.Sprintf(format, vals...)
|
||||||
|
showGuiError(s)
|
||||||
logger.Output(2, "WARNING: "+s)
|
logger.Output(2, "WARNING: "+s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
main.go
19
main.go
@ -19,7 +19,6 @@ import (
|
|||||||
|
|
||||||
"github.com/calmh/ini"
|
"github.com/calmh/ini"
|
||||||
"github.com/calmh/syncthing/discover"
|
"github.com/calmh/syncthing/discover"
|
||||||
"github.com/calmh/syncthing/model"
|
|
||||||
"github.com/calmh/syncthing/protocol"
|
"github.com/calmh/syncthing/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -181,7 +180,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ensureDir(dir, -1)
|
ensureDir(dir, -1)
|
||||||
m := model.NewModel(dir, cfg.Options.MaxChangeKbps*1000)
|
m := NewModel(dir, cfg.Options.MaxChangeKbps*1000)
|
||||||
for _, t := range strings.Split(trace, ",") {
|
for _, t := range strings.Split(trace, ",") {
|
||||||
m.Trace(t)
|
m.Trace(t)
|
||||||
}
|
}
|
||||||
@ -250,7 +249,7 @@ func main() {
|
|||||||
okln("Ready to synchronize (read only; no external updates accepted)")
|
okln("Ready to synchronize (read only; no external updates accepted)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Periodically scan the repository and update the local model.
|
// Periodically scan the repository and update the local
|
||||||
// XXX: Should use some fsnotify mechanism.
|
// XXX: Should use some fsnotify mechanism.
|
||||||
go func() {
|
go func() {
|
||||||
td := time.Duration(cfg.Options.RescanIntervalS) * time.Second
|
td := time.Duration(cfg.Options.RescanIntervalS) * time.Second
|
||||||
@ -328,9 +327,9 @@ func saveConfig() {
|
|||||||
saveConfigCh <- struct{}{}
|
saveConfigCh <- struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printStatsLoop(m *model.Model) {
|
func printStatsLoop(m *Model) {
|
||||||
var lastUpdated int64
|
var lastUpdated int64
|
||||||
var lastStats = make(map[string]model.ConnectionInfo)
|
var lastStats = make(map[string]ConnectionInfo)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
time.Sleep(60 * time.Second)
|
time.Sleep(60 * time.Second)
|
||||||
@ -359,7 +358,7 @@ func printStatsLoop(m *model.Model) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func listen(myID string, addr string, m *model.Model, tlsCfg *tls.Config, connOpts map[string]string) {
|
func listen(myID string, addr string, m *Model, tlsCfg *tls.Config, connOpts map[string]string) {
|
||||||
if strings.Contains(trace, "connect") {
|
if strings.Contains(trace, "connect") {
|
||||||
debugln("NET: Listening on", addr)
|
debugln("NET: Listening on", addr)
|
||||||
}
|
}
|
||||||
@ -435,7 +434,7 @@ func discovery(addr string) *discover.Discoverer {
|
|||||||
return disc
|
return disc
|
||||||
}
|
}
|
||||||
|
|
||||||
func connect(myID string, disc *discover.Discoverer, m *model.Model, tlsCfg *tls.Config, connOpts map[string]string) {
|
func connect(myID string, disc *discover.Discoverer, m *Model, tlsCfg *tls.Config, connOpts map[string]string) {
|
||||||
for {
|
for {
|
||||||
nextNode:
|
nextNode:
|
||||||
for _, nodeCfg := range cfg.Repositories[0].Nodes {
|
for _, nodeCfg := range cfg.Repositories[0].Nodes {
|
||||||
@ -484,13 +483,13 @@ func connect(myID string, disc *discover.Discoverer, m *model.Model, tlsCfg *tls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateLocalModel(m *model.Model) {
|
func updateLocalModel(m *Model) {
|
||||||
files, _ := m.Walk(cfg.Options.FollowSymlinks)
|
files, _ := m.Walk(cfg.Options.FollowSymlinks)
|
||||||
m.ReplaceLocal(files)
|
m.ReplaceLocal(files)
|
||||||
saveIndex(m)
|
saveIndex(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveIndex(m *model.Model) {
|
func saveIndex(m *Model) {
|
||||||
name := m.RepoID() + ".idx.gz"
|
name := m.RepoID() + ".idx.gz"
|
||||||
fullName := path.Join(confDir, name)
|
fullName := path.Join(confDir, name)
|
||||||
idxf, err := os.Create(fullName + ".tmp")
|
idxf, err := os.Create(fullName + ".tmp")
|
||||||
@ -506,7 +505,7 @@ func saveIndex(m *model.Model) {
|
|||||||
os.Rename(fullName+".tmp", fullName)
|
os.Rename(fullName+".tmp", fullName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadIndex(m *model.Model) {
|
func loadIndex(m *Model) {
|
||||||
name := m.RepoID() + ".idx.gz"
|
name := m.RepoID() + ".idx.gz"
|
||||||
idxf, err := os.Open(path.Join(confDir, name))
|
idxf, err := os.Open(path.Join(confDir, name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -268,7 +267,7 @@ func (m *Model) Index(nodeID string, fs []protocol.FileInfo) {
|
|||||||
defer m.imut.Unlock()
|
defer m.imut.Unlock()
|
||||||
|
|
||||||
if m.trace["net"] {
|
if m.trace["net"] {
|
||||||
log.Printf("DEBUG: NET IDX(in): %s: %d files", nodeID, len(fs))
|
debugf("NET IDX(in): %s: %d files", nodeID, len(fs))
|
||||||
}
|
}
|
||||||
|
|
||||||
repo := make(map[string]File)
|
repo := make(map[string]File)
|
||||||
@ -296,13 +295,13 @@ func (m *Model) IndexUpdate(nodeID string, fs []protocol.FileInfo) {
|
|||||||
defer m.imut.Unlock()
|
defer m.imut.Unlock()
|
||||||
|
|
||||||
if m.trace["net"] {
|
if m.trace["net"] {
|
||||||
log.Printf("DEBUG: NET IDXUP(in): %s: %d files", nodeID, len(files))
|
debugf("NET IDXUP(in): %s: %d files", nodeID, len(files))
|
||||||
}
|
}
|
||||||
|
|
||||||
m.rmut.Lock()
|
m.rmut.Lock()
|
||||||
repo, ok := m.remote[nodeID]
|
repo, ok := m.remote[nodeID]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Printf("WARNING: Index update from node %s that does not have an index", nodeID)
|
warnf("Index update from node %s that does not have an index", nodeID)
|
||||||
m.rmut.Unlock()
|
m.rmut.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -322,11 +321,11 @@ func (m *Model) indexUpdate(repo map[string]File, f File) {
|
|||||||
if f.Flags&protocol.FlagDeleted != 0 {
|
if f.Flags&protocol.FlagDeleted != 0 {
|
||||||
flagComment = " (deleted)"
|
flagComment = " (deleted)"
|
||||||
}
|
}
|
||||||
log.Printf("DEBUG: IDX(in): %q m=%d f=%o%s v=%d (%d blocks)", f.Name, f.Modified, f.Flags, flagComment, f.Version, len(f.Blocks))
|
debugf("IDX(in): %q m=%d f=%o%s v=%d (%d blocks)", f.Name, f.Modified, f.Flags, flagComment, f.Version, len(f.Blocks))
|
||||||
}
|
}
|
||||||
|
|
||||||
if extraFlags := f.Flags &^ (protocol.FlagInvalid | protocol.FlagDeleted | 0xfff); extraFlags != 0 {
|
if extraFlags := f.Flags &^ (protocol.FlagInvalid | protocol.FlagDeleted | 0xfff); extraFlags != 0 {
|
||||||
log.Printf("WARNING: IDX(in): Unknown flags 0x%x in index record %+v", extraFlags, f)
|
warnf("IDX(in): Unknown flags 0x%x in index record %+v", extraFlags, f)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,10 +336,10 @@ func (m *Model) indexUpdate(repo map[string]File, f File) {
|
|||||||
// Implements the protocol.Model interface.
|
// Implements the protocol.Model interface.
|
||||||
func (m *Model) Close(node string, err error) {
|
func (m *Model) Close(node string, err error) {
|
||||||
if m.trace["net"] {
|
if m.trace["net"] {
|
||||||
log.Printf("DEBUG: NET: %s: %v", node, err)
|
debugf("NET: %s: %v", node, err)
|
||||||
}
|
}
|
||||||
if err == protocol.ErrClusterHash {
|
if err == protocol.ErrClusterHash {
|
||||||
log.Printf("WARNING: Connection to %s closed due to mismatched cluster hash. Ensure that the configured cluster members are identical on both nodes.", node)
|
warnf("Connection to %s closed due to mismatched cluster hash. Ensure that the configured cluster members are identical on both nodes.", node)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.fq.RemoveAvailable(node)
|
m.fq.RemoveAvailable(node)
|
||||||
@ -377,7 +376,7 @@ func (m *Model) Request(nodeID, name string, offset int64, size uint32, hash []b
|
|||||||
m.gmut.RUnlock()
|
m.gmut.RUnlock()
|
||||||
|
|
||||||
if !localOk || !globalOk {
|
if !localOk || !globalOk {
|
||||||
log.Printf("SECURITY (nonexistent file) REQ(in): %s: %q o=%d s=%d h=%x", nodeID, name, offset, size, hash)
|
warnf("SECURITY (nonexistent file) REQ(in): %s: %q o=%d s=%d h=%x", nodeID, name, offset, size, hash)
|
||||||
return nil, ErrNoSuchFile
|
return nil, ErrNoSuchFile
|
||||||
}
|
}
|
||||||
if lf.Flags&protocol.FlagInvalid != 0 {
|
if lf.Flags&protocol.FlagInvalid != 0 {
|
||||||
@ -385,7 +384,7 @@ func (m *Model) Request(nodeID, name string, offset int64, size uint32, hash []b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if m.trace["net"] && nodeID != "<local>" {
|
if m.trace["net"] && nodeID != "<local>" {
|
||||||
log.Printf("DEBUG: NET REQ(in): %s: %q o=%d s=%d h=%x", nodeID, name, offset, size, hash)
|
debugf("NET REQ(in): %s: %q o=%d s=%d h=%x", nodeID, name, offset, size, hash)
|
||||||
}
|
}
|
||||||
fn := path.Join(m.dir, name)
|
fn := path.Join(m.dir, name)
|
||||||
fd, err := os.Open(fn) // XXX: Inefficient, should cache fd?
|
fd, err := os.Open(fn) // XXX: Inefficient, should cache fd?
|
||||||
@ -502,13 +501,13 @@ func (m *Model) AddConnection(rawConn io.Closer, protoConn Connection) {
|
|||||||
i := i
|
i := i
|
||||||
go func() {
|
go func() {
|
||||||
if m.trace["pull"] {
|
if m.trace["pull"] {
|
||||||
log.Println("DEBUG: PULL: Starting", nodeID, i)
|
debugln("PULL: Starting", nodeID, i)
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
m.pmut.RLock()
|
m.pmut.RLock()
|
||||||
if _, ok := m.protoConn[nodeID]; !ok {
|
if _, ok := m.protoConn[nodeID]; !ok {
|
||||||
if m.trace["pull"] {
|
if m.trace["pull"] {
|
||||||
log.Println("DEBUG: PULL: Exiting", nodeID, i)
|
debugln("PULL: Exiting", nodeID, i)
|
||||||
}
|
}
|
||||||
m.pmut.RUnlock()
|
m.pmut.RUnlock()
|
||||||
return
|
return
|
||||||
@ -518,7 +517,7 @@ func (m *Model) AddConnection(rawConn io.Closer, protoConn Connection) {
|
|||||||
qb, ok := m.fq.Get(nodeID)
|
qb, ok := m.fq.Get(nodeID)
|
||||||
if ok {
|
if ok {
|
||||||
if m.trace["pull"] {
|
if m.trace["pull"] {
|
||||||
log.Println("DEBUG: PULL: Request", nodeID, i, qb.name, qb.block.Offset)
|
debugln("PULL: Request", nodeID, i, qb.name, qb.block.Offset)
|
||||||
}
|
}
|
||||||
data, _ := protoConn.Request(qb.name, qb.block.Offset, qb.block.Size, qb.block.Hash)
|
data, _ := protoConn.Request(qb.name, qb.block.Offset, qb.block.Size, qb.block.Hash)
|
||||||
m.fq.Done(qb.name, qb.block.Offset, data)
|
m.fq.Done(qb.name, qb.block.Offset, data)
|
||||||
@ -544,7 +543,7 @@ func (m *Model) ProtocolIndex() []protocol.FileInfo {
|
|||||||
if mf.Flags&protocol.FlagDeleted != 0 {
|
if mf.Flags&protocol.FlagDeleted != 0 {
|
||||||
flagComment = " (deleted)"
|
flagComment = " (deleted)"
|
||||||
}
|
}
|
||||||
log.Printf("DEBUG: IDX(out): %q m=%d f=%o%s v=%d (%d blocks)", mf.Name, mf.Modified, mf.Flags, flagComment, mf.Version, len(mf.Blocks))
|
debugf("IDX(out): %q m=%d f=%o%s v=%d (%d blocks)", mf.Name, mf.Modified, mf.Flags, flagComment, mf.Version, len(mf.Blocks))
|
||||||
}
|
}
|
||||||
index = append(index, mf)
|
index = append(index, mf)
|
||||||
}
|
}
|
||||||
@ -563,7 +562,7 @@ func (m *Model) requestGlobal(nodeID, name string, offset int64, size uint32, ha
|
|||||||
}
|
}
|
||||||
|
|
||||||
if m.trace["net"] {
|
if m.trace["net"] {
|
||||||
log.Printf("DEBUG: NET REQ(out): %s: %q o=%d s=%d h=%x", nodeID, name, offset, size, hash)
|
debugf("NET REQ(out): %s: %q o=%d s=%d h=%x", nodeID, name, offset, size, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nc.Request(name, offset, size, hash)
|
return nc.Request(name, offset, size, hash)
|
||||||
@ -591,7 +590,7 @@ func (m *Model) broadcastIndexLoop() {
|
|||||||
for _, node := range m.protoConn {
|
for _, node := range m.protoConn {
|
||||||
node := node
|
node := node
|
||||||
if m.trace["net"] {
|
if m.trace["net"] {
|
||||||
log.Printf("DEBUG: NET IDX(out/loop): %s: %d files", node.ID(), len(idx))
|
debugf("NET IDX(out/loop): %s: %d files", node.ID(), len(idx))
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
node.Index(idx)
|
node.Index(idx)
|
||||||
@ -803,7 +802,7 @@ func (m *Model) recomputeNeedForFile(gf File, toAdd []addOrder, toDelete []File)
|
|||||||
return toAdd, toDelete
|
return toAdd, toDelete
|
||||||
}
|
}
|
||||||
if m.trace["need"] {
|
if m.trace["need"] {
|
||||||
log.Printf("DEBUG: NEED: lf:%v gf:%v", lf, gf)
|
debugf("NEED: lf:%v gf:%v", lf, gf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if gf.Flags&protocol.FlagDeleted != 0 {
|
if gf.Flags&protocol.FlagDeleted != 0 {
|
||||||
@ -845,12 +844,12 @@ func (m *Model) WhoHas(name string) []string {
|
|||||||
func (m *Model) deleteLoop() {
|
func (m *Model) deleteLoop() {
|
||||||
for file := range m.dq {
|
for file := range m.dq {
|
||||||
if m.trace["file"] {
|
if m.trace["file"] {
|
||||||
log.Println("DEBUG: FILE: Delete", file.Name)
|
debugln("FILE: Delete", file.Name)
|
||||||
}
|
}
|
||||||
path := path.Clean(path.Join(m.dir, file.Name))
|
path := path.Clean(path.Join(m.dir, file.Name))
|
||||||
err := os.Remove(path)
|
err := os.Remove(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("WARNING: %s: %v", file.Name, err)
|
warnf("%s: %v", file.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.updateLocal(file)
|
m.updateLocal(file)
|
@ -1,4 +1,4 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -1,4 +1,4 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
@ -1,4 +1,4 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
0
model/testdata/bar → testdata/bar
vendored
0
model/testdata/bar → testdata/bar
vendored
0
model/testdata/empty → testdata/empty
vendored
0
model/testdata/empty → testdata/empty
vendored
0
model/testdata/foo → testdata/foo
vendored
0
model/testdata/foo → testdata/foo
vendored
@ -1,4 +1,4 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -1,4 +1,4 @@
|
|||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
Loading…
Reference in New Issue
Block a user