schema: start of more efficient/aggressive file reading

Change-Id: I027881c9844b0df3d70c1e05da69b04d853da883
This commit is contained in:
Brad Fitzpatrick 2013-01-04 18:11:40 -08:00
parent 75a0361165
commit e8ab934464
2 changed files with 59 additions and 0 deletions

37
pkg/atomics/atomics.go Normal file
View File

@ -0,0 +1,37 @@
/*
Copyright 2012 Google 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 atomics
import (
"sync/atomic"
)
type Bool struct {
v uint32 // 0 or 1, atomically
}
func (b *Bool) Get() bool {
return atomic.LoadUint32(&b.v) != 0
}
func (b *Bool) Set(v bool) {
if v {
atomic.StoreUint32(&b.v, 1)
return
}
atomic.StoreUint32(&b.v, 0)
}

View File

@ -25,6 +25,7 @@ import (
"os"
"strings"
"camlistore.org/pkg/atomics"
"camlistore.org/pkg/blobref"
)
@ -42,6 +43,8 @@ type FileReader struct {
ss *Superset
size int64 // total number of bytes
readAll atomics.Bool // whether to preload aggressively
}
// NewFileReader returns a new FileReader reading the contents of fileBlobRef,
@ -75,6 +78,14 @@ func NewFileReader(fetcher blobref.SeekFetcher, fileBlobRef *blobref.BlobRef) (*
return fr, nil
}
// NewFileReader returns a new FileReader, reading bytes and blobs
// from the provided fetcher.
//
// NewFileReader does no fetch operation on the fetcher itself. The
// fetcher is only used in subsequent read operations.
//
// An error is only returned if the type of the Superset is not either
// "file" or "bytes".
func (ss *Superset) NewFileReader(fetcher blobref.SeekFetcher) (*FileReader, error) {
if ss.Type != "file" && ss.Type != "bytes" {
return nil, fmt.Errorf("schema/filereader: Superset not of type \"file\" or \"bytes\"")
@ -139,6 +150,17 @@ func (fr *FileReader) ReadAt(p []byte, offset int64) (n int, err error) {
return n, err
}
func (fr *FileReader) WriteTo(w io.Writer) (n int64, err error) {
// WriteTo is called by io.Copy. Use this as a signal that we're going to want
// to read the rest of the file and go into an aggressive read-ahead mode.
fr.readAll.Set(true)
// TODO: actually use readAll somehow.
// Now just do a normal copy, but hide fr's WriteTo method from io.Copy:
return io.Copy(w, struct{ io.Reader }{fr})
}
type sliceWriter struct {
dst []byte
}