// WalkWithChildrenFilter traverses a filesystem defined within driver, // starting from the given path, calling f on each file. Given filter will be // called on a list of directory children before being recursively processed. func WalkWithChildrenFilter(ctx context.Context, driver storageDriver.StorageDriver, from string, filter WalkChildrenFilter, f WalkFn) error { children, err := driver.List(ctx, from) if err != nil { return err } filter(children) for _, child := range children { // TODO(stevvooe): Calling driver.Stat for every entry is quite // expensive when running against backends with a slow Stat // implementation, such as s3. This is very likely a serious // performance bottleneck. fileInfo, err := driver.Stat(ctx, child) if err != nil { return err } err = f(fileInfo) skipDir := (err == ErrSkipDir) if err != nil && !skipDir { return err } if fileInfo.IsDir() && !skipDir { if err := WalkWithChildrenFilter(ctx, driver, child, filter, f); err != nil { return err } } } return nil }
// Walk traverses a filesystem defined within driver, starting // from the given path, calling f on each file func Walk(driver storageDriver.StorageDriver, from string, f WalkFn) error { children, err := driver.List(from) if err != nil { return err } for _, child := range children { fileInfo, err := driver.Stat(child) if err != nil { return err } err = f(fileInfo) skipDir := (err == ErrSkipDir) if err != nil && !skipDir { return err } if fileInfo.IsDir() && !skipDir { Walk(driver, child, f) } } return nil }
// handleRequest handles storagedriver.StorageDriver method requests as defined in client.go // Responds to requests using the Request.ResponseChannel func handleRequest(driver storagedriver.StorageDriver, request Request) { switch request.Type { case "Version": err := request.ResponseChannel.Send(&VersionResponse{Version: storagedriver.CurrentVersion}) if err != nil { panic(err) } case "GetContent": path, _ := request.Parameters["Path"].(string) content, err := driver.GetContent(path) var response ReadStreamResponse if err != nil { response = ReadStreamResponse{Error: WrapError(err)} } else { response = ReadStreamResponse{Reader: ioutil.NopCloser(bytes.NewReader(content))} } err = request.ResponseChannel.Send(&response) if err != nil { panic(err) } case "PutContent": path, _ := request.Parameters["Path"].(string) reader, _ := request.Parameters["Reader"].(io.ReadCloser) contents, err := ioutil.ReadAll(reader) defer reader.Close() if err == nil { err = driver.PutContent(path, contents) } response := WriteStreamResponse{ Error: WrapError(err), } err = request.ResponseChannel.Send(&response) if err != nil { panic(err) } case "ReadStream": path, _ := request.Parameters["Path"].(string) // Depending on serialization method, Offset may be converted to any int/uint type offset := reflect.ValueOf(request.Parameters["Offset"]).Convert(reflect.TypeOf(int64(0))).Int() reader, err := driver.ReadStream(path, offset) var response ReadStreamResponse if err != nil { response = ReadStreamResponse{Error: WrapError(err)} } else { response = ReadStreamResponse{Reader: reader} } err = request.ResponseChannel.Send(&response) if err != nil { panic(err) } case "WriteStream": path, _ := request.Parameters["Path"].(string) // Depending on serialization method, Offset may be converted to any int/uint type offset := reflect.ValueOf(request.Parameters["Offset"]).Convert(reflect.TypeOf(int64(0))).Int() // Depending on serialization method, Size may be converted to any int/uint type size := reflect.ValueOf(request.Parameters["Size"]).Convert(reflect.TypeOf(int64(0))).Int() reader, _ := request.Parameters["Reader"].(io.ReadCloser) err := driver.WriteStream(path, offset, size, reader) response := WriteStreamResponse{ Error: WrapError(err), } err = request.ResponseChannel.Send(&response) if err != nil { panic(err) } case "CurrentSize": path, _ := request.Parameters["Path"].(string) position, err := driver.CurrentSize(path) response := CurrentSizeResponse{ Position: position, Error: WrapError(err), } err = request.ResponseChannel.Send(&response) if err != nil { panic(err) } case "List": path, _ := request.Parameters["Path"].(string) keys, err := driver.List(path) response := ListResponse{ Keys: keys, Error: WrapError(err), } err = request.ResponseChannel.Send(&response) if err != nil { panic(err) } case "Move": sourcePath, _ := request.Parameters["SourcePath"].(string) destPath, _ := request.Parameters["DestPath"].(string) err := driver.Move(sourcePath, destPath) response := MoveResponse{ Error: WrapError(err), } err = request.ResponseChannel.Send(&response) if err != nil { panic(err) } case "Delete": path, _ := request.Parameters["Path"].(string) err := driver.Delete(path) response := DeleteResponse{ Error: WrapError(err), } err = request.ResponseChannel.Send(&response) if err != nil { panic(err) } default: panic(request) } }