From 36643ff986a50b523c96c5f1d29ac415980e8b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Gul=C3=A1csi?= Date: Mon, 9 Dec 2013 12:48:15 +0100 Subject: [PATCH] Fix Fetch -> FetchStreaming conversion As blob.fetcherToSeekerWrapper.Fetch erroneously asserts that FetchStreaming returns a ReadSeekCloser everytime, it had to be changed. Move MaxBlobSize from blobserver to constants (new package). Change-Id: I4b4f22c302cbec84d77d21454e0c9e8aebdf73e5 --- pkg/blob/fetcher.go | 23 +++++++++++++++++++++-- pkg/blobserver/interface.go | 7 ++----- pkg/constants/constants.go | 27 +++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 pkg/constants/constants.go diff --git a/pkg/blob/fetcher.go b/pkg/blob/fetcher.go index 748b5acf4..fb01c355d 100644 --- a/pkg/blob/fetcher.go +++ b/pkg/blob/fetcher.go @@ -27,6 +27,7 @@ import ( "strings" "sync" + "camlistore.org/pkg/constants" "camlistore.org/pkg/osutil" "camlistore.org/pkg/types" ) @@ -64,8 +65,26 @@ func (w *fetcherToSeekerWrapper) Fetch(r Ref) (file types.ReadSeekCloser, size i if err != nil { return } - file = rc.(types.ReadSeekCloser) - return + file, ok := rc.(types.ReadSeekCloser) + if ok { + return + } + // we must make it seekable + var slurp bytes.Buffer + n, err := io.CopyN(&slurp, rc, constants.MaxBlobSize+1) + if err != nil && err != io.EOF { + return nil, 0, err + } + if n > constants.MaxBlobSize { + return nil, 0, fmt.Errorf("blob %v too big", r) + } + return struct { + io.ReadSeeker + io.Closer + }{ + bytes.NewReader(slurp.Bytes()), + ioutil.NopCloser(nil), + }, n, err } // StreamingFetcher is the minimal interface for retrieving a blob from storage. diff --git a/pkg/blobserver/interface.go b/pkg/blobserver/interface.go index 662c82460..fd9650c9d 100644 --- a/pkg/blobserver/interface.go +++ b/pkg/blobserver/interface.go @@ -24,15 +24,12 @@ import ( "time" "camlistore.org/pkg/blob" + "camlistore.org/pkg/constants" "camlistore.org/pkg/context" ) // MaxBlobSize is the size of a single blob in Camlistore. -// -// TODO: formalize this in the specs. This value of 16 MB is less than -// App Engine's 32 MB request limit, much more than Venti's limit, and -// much more than the ~64 KB & 256 KB chunks that the FileWriter make -const MaxBlobSize = 16 << 20 +const MaxBlobSize = constants.MaxBlobSize var ErrCorruptBlob = errors.New("corrupt blob; digest doesn't match") diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go new file mode 100644 index 000000000..b07ea8c76 --- /dev/null +++ b/pkg/constants/constants.go @@ -0,0 +1,27 @@ +/* +Copyright 2014 the Camlistore authors. + +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 constants contains Camlistore constants. +// +// This is a leaf package, without dependencies. +package constants + +// MaxBlobSize is the size of a single blob in Camlistore. +// +// TODO: formalize this in the specs. This value of 16 MB is less than +// App Engine's 32 MB request limit, much more than Venti's limit, and +// much more than the ~64 KB & 256 KB chunks that the FileWriter make +const MaxBlobSize = 16 << 20