2017-05-15 21:51:50 +00:00
|
|
|
package odb
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
2017-05-16 21:29:03 +00:00
|
|
|
// memoryStorer is an implementation of the storer interface that holds data for
|
2017-05-15 21:51:50 +00:00
|
|
|
// the object database in memory.
|
2017-05-16 21:29:03 +00:00
|
|
|
type memoryStorer struct {
|
2017-05-15 21:51:50 +00:00
|
|
|
// mu guards reads and writes to the map "fs" below.
|
|
|
|
mu *sync.Mutex
|
|
|
|
// fs maps a hex-encoded SHA to a bytes.Buffer wrapped in a no-op closer
|
|
|
|
// type.
|
|
|
|
fs map[string]*bufCloser
|
|
|
|
}
|
|
|
|
|
2017-05-16 21:29:03 +00:00
|
|
|
var _ storer = (*memoryStorer)(nil)
|
2017-05-15 21:51:50 +00:00
|
|
|
|
2017-05-16 21:29:03 +00:00
|
|
|
// newMemoryStorer initializes a new memoryStorer instance with the given
|
2017-05-15 21:51:50 +00:00
|
|
|
// initial set.
|
|
|
|
//
|
|
|
|
// A value of "nil" is acceptable and indicates that no entries shall be added
|
|
|
|
// to the memory storer at/during construction time.
|
2017-05-16 21:29:03 +00:00
|
|
|
func newMemoryStorer(m map[string]io.ReadWriter) *memoryStorer {
|
2017-05-15 21:51:50 +00:00
|
|
|
fs := make(map[string]*bufCloser, len(m))
|
|
|
|
for n, rw := range m {
|
|
|
|
fs[n] = &bufCloser{rw}
|
|
|
|
}
|
|
|
|
|
2017-05-16 21:29:03 +00:00
|
|
|
return &memoryStorer{
|
2017-05-15 21:51:50 +00:00
|
|
|
mu: new(sync.Mutex),
|
|
|
|
fs: fs,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-16 21:29:03 +00:00
|
|
|
// Store implements the storer.Store function and copies the data given in "r"
|
2017-05-16 21:02:37 +00:00
|
|
|
// into an object entry in the memory. If an object given by that SHA "sha" is
|
|
|
|
// already indexed in the database, Store will panic().
|
2017-05-16 21:29:03 +00:00
|
|
|
func (ms *memoryStorer) Store(sha []byte, r io.Reader) (n int64, err error) {
|
2017-05-15 21:51:50 +00:00
|
|
|
ms.mu.Lock()
|
|
|
|
defer ms.mu.Unlock()
|
|
|
|
|
|
|
|
key := fmt.Sprintf("%x", sha)
|
|
|
|
if _, ok := ms.fs[key]; ok {
|
|
|
|
panic(fmt.Sprintf("git/odb: memory storage create %x, already exists", sha))
|
|
|
|
}
|
2017-05-16 21:02:37 +00:00
|
|
|
|
|
|
|
ms.fs[key] = &bufCloser{new(bytes.Buffer)}
|
|
|
|
return io.Copy(ms.fs[key], r)
|
2017-05-15 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
2017-05-16 21:29:03 +00:00
|
|
|
// Open implements the storer.Open function, and returns a io.ReadWriteCloser
|
2017-05-15 21:51:50 +00:00
|
|
|
// for the given SHA. If a reader for the given SHA does not exist an error will
|
|
|
|
// be returned.
|
2017-05-16 21:29:03 +00:00
|
|
|
func (ms *memoryStorer) Open(sha []byte) (f io.ReadWriteCloser, err error) {
|
2017-05-15 21:51:50 +00:00
|
|
|
ms.mu.Lock()
|
|
|
|
defer ms.mu.Unlock()
|
|
|
|
|
|
|
|
key := fmt.Sprintf("%x", sha)
|
|
|
|
if _, ok := ms.fs[key]; !ok {
|
|
|
|
panic(fmt.Sprintf("git/odb: memory storage cannot open %x, doesn't exist", sha))
|
|
|
|
}
|
|
|
|
return ms.fs[key], nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// bufCloser wraps a type satisfying the io.ReadWriter interface with a no-op
|
|
|
|
// Close() function, thus implementing the io.ReadWriteCloser composite
|
|
|
|
// interface.
|
|
|
|
type bufCloser struct {
|
|
|
|
io.ReadWriter
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ io.ReadWriteCloser = (*bufCloser)(nil)
|
|
|
|
|
|
|
|
// Close implements io.Closer, and returns nothing.
|
|
|
|
func (b *bufCloser) Close() error { return nil }
|