98 lines
2.2 KiB
Go
98 lines
2.2 KiB
Go
// Copyright 2023 The LevelDB-Go and Pebble Authors. All rights reserved. Use
|
|
// of this source code is governed by a BSD-style license that can be found in
|
|
// the LICENSE file.
|
|
|
|
package objstorage
|
|
|
|
import (
|
|
"io"
|
|
|
|
"github.com/cockroachdb/pebble/objstorage/shared"
|
|
)
|
|
|
|
// sharedReadable is a very simple implementation of Readable on top of the
|
|
// ReadCloser returned by shared.Storage.CreateObject.
|
|
type sharedReadable struct {
|
|
storage shared.Storage
|
|
objName string
|
|
size int64
|
|
|
|
// rh is used for direct ReadAt calls without a read handle.
|
|
rh sharedReadHandle
|
|
}
|
|
|
|
var _ Readable = (*sharedReadable)(nil)
|
|
|
|
func newSharedReadable(storage shared.Storage, objName string, size int64) *sharedReadable {
|
|
r := &sharedReadable{
|
|
storage: storage,
|
|
objName: objName,
|
|
size: size,
|
|
}
|
|
r.rh.readable = r
|
|
return r
|
|
}
|
|
|
|
func (r *sharedReadable) ReadAt(p []byte, offset int64) (n int, err error) {
|
|
return r.rh.ReadAt(p, offset)
|
|
}
|
|
|
|
func (r *sharedReadable) Close() error {
|
|
err := r.rh.Close()
|
|
r.storage = nil
|
|
return err
|
|
}
|
|
|
|
func (r *sharedReadable) Size() int64 {
|
|
return r.size
|
|
}
|
|
|
|
func (r *sharedReadable) NewReadHandle() ReadHandle {
|
|
// TODO(radu): use a pool.
|
|
return &sharedReadHandle{readable: r}
|
|
}
|
|
|
|
type sharedReadHandle struct {
|
|
readable *sharedReadable
|
|
lastReader io.ReadCloser
|
|
lastOffset int64
|
|
}
|
|
|
|
var _ ReadHandle = (*sharedReadHandle)(nil)
|
|
|
|
func (r *sharedReadHandle) ReadAt(p []byte, offset int64) (n int, err error) {
|
|
// See if this continues the previous read so that we can reuse the last reader.
|
|
if r.lastReader == nil || r.lastOffset != offset {
|
|
// We need to create a new reader.
|
|
if r.lastReader != nil {
|
|
if err := r.lastReader.Close(); err != nil {
|
|
return 0, err
|
|
}
|
|
r.lastReader = nil
|
|
}
|
|
reader, _, err := r.readable.storage.ReadObjectAt(r.readable.objName, offset)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
r.lastReader = reader
|
|
r.lastOffset = offset
|
|
}
|
|
n, err = io.ReadFull(r.lastReader, p)
|
|
r.lastOffset += int64(n)
|
|
return n, err
|
|
}
|
|
|
|
func (r *sharedReadHandle) Close() error {
|
|
var err error
|
|
if r.lastReader != nil {
|
|
err = r.lastReader.Close()
|
|
r.lastReader = nil
|
|
}
|
|
r.readable = nil
|
|
return err
|
|
}
|
|
|
|
func (r *sharedReadHandle) MaxReadahead() {}
|
|
|
|
func (r *sharedReadHandle) RecordCacheHit(offset, size int64) {}
|