mirror of https://github.com/rclone/rclone.git
Make downloads work in parallel
This commit is contained in:
parent
9fb8a1afa2
commit
9a066460f1
78
swiftsync.go
78
swiftsync.go
|
@ -37,7 +37,7 @@ var (
|
||||||
userName = flag.String("user", os.Getenv("ST_USER"), "User name. Defaults to environment var ST_USER.")
|
userName = flag.String("user", os.Getenv("ST_USER"), "User name. Defaults to environment var ST_USER.")
|
||||||
apiKey = flag.String("key", os.Getenv("ST_KEY"), "API key (password). Defaults to environment var ST_KEY.")
|
apiKey = flag.String("key", os.Getenv("ST_KEY"), "API key (password). Defaults to environment var ST_KEY.")
|
||||||
checkers = flag.Int("checkers", 8, "Number of checkers to run in parallel.")
|
checkers = flag.Int("checkers", 8, "Number of checkers to run in parallel.")
|
||||||
uploaders = flag.Int("uploaders", 4, "Number of uploaders to run in parallel.")
|
transfers = flag.Int("transfers", 4, "Number of file transfers to run in parallel.")
|
||||||
)
|
)
|
||||||
|
|
||||||
// A filesystem like object which can either be a remote object or a
|
// A filesystem like object which can either be a remote object or a
|
||||||
|
@ -193,7 +193,7 @@ func (fs *FsObject) put(c *swift.Connection, container string) {
|
||||||
fs.Debugf("Uploaded")
|
fs.Debugf("Uploaded")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat a FsObject info info
|
// Stat a FsObject into info
|
||||||
func (fs *FsObject) lstat() error {
|
func (fs *FsObject) lstat() error {
|
||||||
info, err := os.Lstat(fs.path)
|
info, err := os.Lstat(fs.path)
|
||||||
fs.info = info
|
fs.info = info
|
||||||
|
@ -249,15 +249,24 @@ func walk(root string) FsObjectsChan {
|
||||||
// Read FsObjects on in and write them to out if they need uploading
|
// Read FsObjects on in and write them to out if they need uploading
|
||||||
//
|
//
|
||||||
// FIXME potentially doing lots of MD5SUMS at once
|
// FIXME potentially doing lots of MD5SUMS at once
|
||||||
func checker(c *swift.Connection, container string, in, out FsObjectsChan, wg *sync.WaitGroup) {
|
func checker(c *swift.Connection, container string, in, out FsObjectsChan, upload bool, wg *sync.WaitGroup) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for fs := range in {
|
for fs := range in {
|
||||||
|
if !upload {
|
||||||
|
_ = fs.lstat()
|
||||||
|
if fs.info == nil {
|
||||||
|
fs.Debugf("Couldn't find local file - download")
|
||||||
|
out <- fs
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check to see if can store this
|
// Check to see if can store this
|
||||||
if !fs.storable() {
|
if !fs.storable() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Check to see if changed or not
|
// Check to see if changed or not
|
||||||
if fs.Equal(c, container, true) {
|
if fs.Equal(c, container, upload) {
|
||||||
fs.Debugf("Unchanged skipping")
|
fs.Debugf("Unchanged skipping")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -278,17 +287,17 @@ func upload(c *swift.Connection, args []string) {
|
||||||
root, container := args[0], args[1]
|
root, container := args[0], args[1]
|
||||||
mkdir(c, []string{container})
|
mkdir(c, []string{container})
|
||||||
to_be_checked := walk(root)
|
to_be_checked := walk(root)
|
||||||
to_be_uploaded := make(FsObjectsChan, *uploaders)
|
to_be_uploaded := make(FsObjectsChan, *transfers)
|
||||||
|
|
||||||
var checkerWg sync.WaitGroup
|
var checkerWg sync.WaitGroup
|
||||||
checkerWg.Add(*checkers)
|
checkerWg.Add(*checkers)
|
||||||
for i := 0; i < *checkers; i++ {
|
for i := 0; i < *checkers; i++ {
|
||||||
go checker(c, container, to_be_checked, to_be_uploaded, &checkerWg)
|
go checker(c, container, to_be_checked, to_be_uploaded, true, &checkerWg)
|
||||||
}
|
}
|
||||||
|
|
||||||
var uploaderWg sync.WaitGroup
|
var uploaderWg sync.WaitGroup
|
||||||
uploaderWg.Add(*uploaders)
|
uploaderWg.Add(*transfers)
|
||||||
for i := 0; i < *uploaders; i++ {
|
for i := 0; i < *transfers; i++ {
|
||||||
go uploader(c, container, to_be_uploaded, &uploaderWg)
|
go uploader(c, container, to_be_uploaded, &uploaderWg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,12 +353,17 @@ func (fs *FsObject) get(c *swift.Connection, container string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read FsObjects on in and download them
|
||||||
|
func downloader(c *swift.Connection, container string, in FsObjectsChan, wg *sync.WaitGroup) {
|
||||||
|
defer wg.Done()
|
||||||
|
for fs := range in {
|
||||||
|
fs.get(c, container)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Syncs a container into a directory
|
// Syncs a container into a directory
|
||||||
//
|
//
|
||||||
// FIXME don't want to update the modification times on the
|
|
||||||
// remote server if they are different - want to modify the local
|
|
||||||
// file!
|
|
||||||
//
|
|
||||||
// FIXME need optional stat in FsObject and to be able to make FsObjects from ObjectsAll
|
// FIXME need optional stat in FsObject and to be able to make FsObjects from ObjectsAll
|
||||||
//
|
//
|
||||||
// FIXME should download and stat many at once
|
// FIXME should download and stat many at once
|
||||||
|
@ -366,26 +380,34 @@ func download(c *swift.Connection, args []string) {
|
||||||
log.Fatalf("Couldn't make directory %q: %s", root, err)
|
log.Fatalf("Couldn't make directory %q: %s", root, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to_be_checked := make(FsObjectsChan, *checkers)
|
||||||
|
to_be_downloaded := make(FsObjectsChan, *transfers)
|
||||||
|
|
||||||
|
var checkerWg sync.WaitGroup
|
||||||
|
checkerWg.Add(*checkers)
|
||||||
|
for i := 0; i < *checkers; i++ {
|
||||||
|
go checker(c, container, to_be_checked, to_be_downloaded, false, &checkerWg)
|
||||||
|
}
|
||||||
|
|
||||||
|
var downloaderWg sync.WaitGroup
|
||||||
|
downloaderWg.Add(*transfers)
|
||||||
|
for i := 0; i < *transfers; i++ {
|
||||||
|
go downloader(c, container, to_be_downloaded, &downloaderWg)
|
||||||
|
}
|
||||||
|
|
||||||
for i := range objects {
|
for i := range objects {
|
||||||
object := &objects[i]
|
object := &objects[i]
|
||||||
filepath := path.Join(root, object.Name)
|
filepath := path.Join(root, object.Name)
|
||||||
fs := FsObject{remote: object.Name, path: filepath}
|
to_be_checked <- &FsObject{remote: object.Name, path: filepath}
|
||||||
_ = fs.lstat()
|
|
||||||
if fs.info == nil {
|
|
||||||
fs.Debugf("Couldn't find local file - download")
|
|
||||||
} else {
|
|
||||||
fs.Debugf("Found local file - checking")
|
|
||||||
if !fs.storable() {
|
|
||||||
fs.Debugf("Not overwriting different type local file")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fs.Equal(c, container, false) {
|
|
||||||
fs.Debugf("Skip: not changed")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fs.get(c, container)
|
|
||||||
}
|
}
|
||||||
|
close(to_be_checked)
|
||||||
|
|
||||||
|
log.Printf("Waiting for checks to finish")
|
||||||
|
checkerWg.Wait()
|
||||||
|
close(to_be_downloaded)
|
||||||
|
log.Printf("Waiting for downloads to finish")
|
||||||
|
downloaderWg.Wait()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lists the containers
|
// Lists the containers
|
||||||
|
|
Loading…
Reference in New Issue