Skip to content

Commit

Permalink
Add options for concurrent dcopy
Browse files Browse the repository at this point in the history
  • Loading branch information
otiai10 committed Sep 3, 2023
1 parent 6a6d5f1 commit 78d861c
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 8 deletions.
7 changes: 7 additions & 0 deletions copy.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package copy

import (
"context"
"io"
"io/fs"
"io/ioutil"
"os"
"path/filepath"
"time"

"golang.org/x/sync/semaphore"
)

type timespec struct {
Expand All @@ -18,6 +21,10 @@ type timespec struct {
// Copy copies src to dest, doesn't matter if src is a directory or a file.
func Copy(src, dest string, opts ...Options) error {
opt := assureOptions(src, dest, opts...)
if opt.NumberOfWorkers > 1 {
opt.intent.sem = semaphore.NewWeighted(opt.NumberOfWorkers)
opt.intent.ctx = context.Background()
}
if opt.FS != nil {
info, err := fs.Stat(opt.FS, src)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ go 1.18

require (
github.com/otiai10/mint v1.5.1
golang.org/x/sync v0.3.0
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
44 changes: 36 additions & 8 deletions options.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package copy

import (
"context"
"io"
"io/fs"
"os"

"golang.org/x/sync/semaphore"
)

// Options specifies optional actions on copying.
Expand Down Expand Up @@ -65,10 +68,28 @@ type Options struct {
// e.g., You can use embed.FS to copy files from embedded filesystem.
FS fs.FS

intent struct {
src string
dest string
}
// NumberOfWorkers represents the number of workers used for
// concurrent copying contents of directories.
// If 0 or 1, it does not use goroutine for copying directories.
// Please refer to https://pkg.go.dev/golang.org/x/sync/semaphore for more details.
NumberOfWorkers int64

// PreferConcurrent is a function to determine whether or not
// to use goroutine for copying contents of directories.
// If PreferConcurrent is nil, which is default, it does concurrent
// copying for all directories.
// If NumberOfWorkers is 0 or 1, this function will be ignored.
PreferConcurrent func(srcdir, destdir string) (bool, error)

// Internal use only
intent intent
}

type intent struct {
src string
dest string
sem *semaphore.Weighted
ctx context.Context
}

// SymlinkAction represents what to do on symlink.
Expand Down Expand Up @@ -112,10 +133,7 @@ func getDefaultOptions(src, dest string) Options {
PreserveTimes: false, // Do not preserve the modification time
CopyBufferSize: 0, // Do not specify, use default bufsize (32*1024)
WrapReader: nil, // Do not wrap src files, use them as they are.
intent: struct {
src string
dest string
}{src, dest},
intent: intent{src, dest, nil, nil},
}
}

Expand All @@ -141,3 +159,13 @@ func assureOptions(src, dest string, opts ...Options) Options {
opts[0].intent.dest = defopt.intent.dest
return opts[0]
}

func shouldCopyDirectoryConcurrent(opt Options, srcdir, destdir string) (bool, error) {
if opt.NumberOfWorkers <= 1 {
return false, nil
}
if opt.PreferConcurrent == nil {
return true, nil
}
return opt.PreferConcurrent(srcdir, destdir)
}

0 comments on commit 78d861c

Please sign in to comment.