1
0
mirror of https://github.com/minio/mc.git synced 2025-11-14 23:42:27 +03:00
Files
mc/cmd-cp.go
Harshavardhana ad35fe72d0 Move colors to console package, now implement colored
- Fatal, Fatalf, Fatalln
 - Error, Errorln
 - Info, Infof, Infoln
2015-04-10 01:14:47 -07:00

148 lines
4.1 KiB
Go

/*
* Minimalist Object Storage, (C) 2014,2015 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"github.com/cheggaaa/pb"
"github.com/minio-io/cli"
"github.com/minio-io/mc/pkg/console"
"github.com/minio-io/minio/pkg/iodine"
"github.com/minio-io/minio/pkg/utils/log"
)
type message struct {
err error
}
func multiTargetGoroutine(targetURL string, md5Hex string, sourceSize int64, targetReader io.Reader, ch chan message) {
errParams := map[string]string{
"url": targetURL,
}
targetBucket, targetObject, err := url2Object(targetURL)
if err != nil {
ch <- message{err: iodine.New(err, errParams)}
}
targetClnt, err := getNewClient(globalDebugFlag, targetURL)
if err != nil {
ch <- message{err: iodine.New(err, errParams)}
}
if err := targetClnt.Put(targetBucket, targetObject, md5Hex, sourceSize, targetReader); err != nil {
ch <- message{err: iodine.New(err, errParams)}
}
ch <- message{err: nil}
close(ch)
}
func doPutMultiTarget(targetURLs []string, md5Hex string, sourceSize int64, targetReaders []io.Reader) <-chan message {
ch := make(chan message)
for i := 0; i < len(targetURLs); i++ {
go multiTargetGoroutine(targetURLs[i], md5Hex, sourceSize, targetReaders[i], ch)
}
return ch
}
// doCopyCmd copies objects into and from a bucket or between buckets
func multiCopy(targetURLs []string, sourceURL string) (err error) {
var targetBuffer bytes.Buffer
fmt.Fprint(&targetBuffer, targetURLs)
errParams := map[string]string{
"targetURLs": targetBuffer.String(),
"sourceURL": sourceURL,
}
numTargets := len(targetURLs)
// Parse URL to bucket and object names
sourceBucket, sourceObject, err := url2Object(sourceURL)
if err != nil {
return iodine.New(err, errParams)
}
// Initialize a new client object for the source
sourceClnt, err := getNewClient(globalDebugFlag, sourceURL)
if err != nil {
return iodine.New(err, errParams)
}
// Get a reader for the source object
sourceReader, sourceSize, md5Hex, err := sourceClnt.Get(sourceBucket, sourceObject)
if err != nil {
return iodine.New(err, errParams)
}
defer sourceReader.Close()
targetReaders := make([]io.Reader, numTargets)
targetWriters := make([]io.WriteCloser, numTargets)
for i := 0; i < numTargets; i++ {
targetReaders[i], targetWriters[i] = io.Pipe()
}
go func() {
var bar *pb.ProgressBar
if !globalQuietFlag {
bar = startBar(sourceSize)
bar.Start()
sourceReader = ioutil.NopCloser(io.TeeReader(sourceReader, bar))
}
// convert targetWriters to []io.Writer
multiWriters := make([]io.Writer, numTargets)
for i, writeCloser := range targetWriters {
defer writeCloser.Close()
multiWriters[i] = io.Writer(writeCloser)
}
io.CopyN(io.MultiWriter(multiWriters...), sourceReader, sourceSize)
if !globalQuietFlag {
bar.Finish()
}
}()
for msg := range doPutMultiTarget(targetURLs, md5Hex, sourceSize, targetReaders) {
if msg.err != nil {
log.Debug.Println(msg.err)
console.Fatalln(msg.err)
}
console.Infoln("Done")
}
return nil
}
// doCopyCmd copies objects into and from a bucket or between buckets
func doCopyCmd(ctx *cli.Context) {
if len(ctx.Args()) < 2 {
cli.ShowCommandHelpAndExit(ctx, "cp", 1) // last argument is exit code
}
// Convert arguments to URLs: expand alias, fix format...
urlList, err := parseURLs(ctx)
if err != nil {
log.Debug.Println(iodine.New(err, nil))
console.Fatalln(err)
}
sourceURL := urlList[0] // First arg is source
targetURLs := urlList[1:] // 1 or more targets
err = multiCopy(targetURLs, sourceURL)
if err != nil {
log.Debug.Println(iodine.New(err, nil))
console.Fatalln(err)
}
}