func (entry *localFileEntry) GetStat() (os.FileInfo, error) {
	return os.Stat(entry.GetPath())
}
GetStat returns a FileInfo describing the named file.
package base
import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"github.com/uber/makisu/lib/storage/metadata"
	"github.com/uber/makisu/lib/utils/stringset"
)
var (
	ErrFilePersisted = errors.New("file is persisted")
)
type FileState struct {
	directory string
}
func NewFileState(directory string) FileState {
	return FileState{directory}
}
func (s FileState) GetDirectory() string {
	return s.directory
}
type FileEntryFactory interface {
	Create(name string, state FileState) FileEntry
	GetRelativePath(name string) string
}
type FileEntry interface {
	GetState() FileState
	GetName() string
	GetPath() string
	GetStat() (os.FileInfo, error)
	Create(targetState FileState, len int64) error
	Reload() error
	MoveFrom(targetState FileState, sourcePath string) error
	Move(targetState FileState) error
	LinkTo(targetPath string) error
	Delete() error
	GetReader() (FileReader, error)
	GetReadWriter() (FileReadWriter, error)
	AddMetadata(md metadata.Metadata) error
	GetMetadata(md metadata.Metadata) error
	SetMetadata(md metadata.Metadata) (bool, error)
	SetMetadataAt(md metadata.Metadata, b []byte, offset int64) (updated bool, err error)
	GetOrSetMetadata(md metadata.Metadata) error
	DeleteMetadata(md metadata.Metadata) error
	RangeMetadata(f func(md metadata.Metadata) error) error
}
var _ FileEntryFactory = (*localFileEntryFactory)(nil)
var _ FileEntryFactory = (*casFileEntryFactory)(nil)
var _ FileEntry = (*localFileEntry)(nil)
type localFileEntryFactory struct{}
func NewLocalFileEntryFactory() FileEntryFactory {
	return &localFileEntryFactory{}
}
func (f *localFileEntryFactory) Create(name string, state FileState) FileEntry {
	return newLocalFileEntry(state, name, f.GetRelativePath(name))
}
func (f *localFileEntryFactory) GetRelativePath(name string) string {
	return filepath.Join(name, DefaultDataFileName)
}
type casFileEntryFactory struct{}
func NewCASFileEntryFactory() FileEntryFactory {
	return &casFileEntryFactory{}
}
func (f *casFileEntryFactory) Create(name string, state FileState) FileEntry {
	return newLocalFileEntry(state, name, f.GetRelativePath(name))
}
func (f *casFileEntryFactory) GetRelativePath(name string) string {
	filePath := ""
	for i := 0; i < int(DefaultShardIDLength) && i < len(name)/2; i++ {
		dirName := name[i*2 : i*2+2]
		filePath = filepath.Join(filePath, dirName)
	}
	return filepath.Join(filePath, name, DefaultDataFileName)
}
type localFileEntry struct {
	sync.RWMutex
	state            FileState
	name             string
	relativeDataPath string         
	metadata         stringset.Set  
}
func newLocalFileEntry(
	state FileState,
	name string,
	relativeDataPath string,
) *localFileEntry {
	return &localFileEntry{
		state:            state,
		name:             name,
		relativeDataPath: relativeDataPath,
		metadata:         make(stringset.Set),
	}
}
func (entry *localFileEntry) GetState() FileState {
	return entry.state
}
func (entry *localFileEntry) GetName() string {
	return entry.name
}
func (entry *localFileEntry) GetPath() string {
	return filepath.Join(entry.state.GetDirectory(), entry.relativeDataPath)
}