Line data Source code
1 : // Copyright 2023 The LevelDB-Go and Pebble Authors. All rights reserved. Use
2 : // of this source code is governed by a BSD-style license that can be found in
3 : // the LICENSE file.
4 :
5 : package remote
6 :
7 : import (
8 : "bytes"
9 : "context"
10 : "io"
11 : "os"
12 : "strings"
13 : "sync"
14 : )
15 :
16 : // NewInMem returns an in-memory implementation of the remote.Storage
17 : // interface (for testing).
18 1 : func NewInMem() Storage {
19 1 : store := &inMemStore{}
20 1 : store.mu.objects = make(map[string]*inMemObj)
21 1 : return store
22 1 : }
23 :
24 : // inMemStore is an in-memory implementation of the remote.Storage interface
25 : // (for testing).
26 : type inMemStore struct {
27 : mu struct {
28 : sync.Mutex
29 : objects map[string]*inMemObj
30 : }
31 : }
32 :
33 : var _ Storage = (*inMemStore)(nil)
34 :
35 : type inMemObj struct {
36 : name string
37 : data []byte
38 : }
39 :
40 0 : func (s *inMemStore) Close() error {
41 0 : *s = inMemStore{}
42 0 : return nil
43 0 : }
44 :
45 : func (s *inMemStore) ReadObject(
46 : ctx context.Context, objName string,
47 1 : ) (_ ObjectReader, objSize int64, _ error) {
48 1 : obj, err := s.getObj(objName)
49 1 : if err != nil {
50 0 : return nil, 0, err
51 0 : }
52 1 : return &inMemReader{data: obj.data}, int64(len(obj.data)), nil
53 : }
54 :
55 : type inMemReader struct {
56 : data []byte
57 : }
58 :
59 : var _ ObjectReader = (*inMemReader)(nil)
60 :
61 1 : func (r *inMemReader) ReadAt(ctx context.Context, p []byte, offset int64) error {
62 1 : if offset+int64(len(p)) > int64(len(r.data)) {
63 0 : return io.EOF
64 0 : }
65 1 : copy(p, r.data[offset:])
66 1 : return nil
67 : }
68 :
69 1 : func (r *inMemReader) Close() error {
70 1 : r.data = nil
71 1 : return nil
72 1 : }
73 :
74 1 : func (s *inMemStore) CreateObject(objName string) (io.WriteCloser, error) {
75 1 : return &inMemWriter{
76 1 : store: s,
77 1 : name: objName,
78 1 : }, nil
79 1 : }
80 :
81 : type inMemWriter struct {
82 : store *inMemStore
83 : name string
84 : buf bytes.Buffer
85 : }
86 :
87 : var _ io.WriteCloser = (*inMemWriter)(nil)
88 :
89 1 : func (o *inMemWriter) Write(p []byte) (n int, err error) {
90 1 : if o.store == nil {
91 0 : panic("Write after Close")
92 : }
93 1 : return o.buf.Write(p)
94 : }
95 :
96 1 : func (o *inMemWriter) Close() error {
97 1 : if o.store != nil {
98 1 : o.store.addObj(&inMemObj{
99 1 : name: o.name,
100 1 : data: o.buf.Bytes(),
101 1 : })
102 1 : o.store = nil
103 1 : }
104 1 : return nil
105 : }
106 :
107 1 : func (s *inMemStore) List(prefix, delimiter string) ([]string, error) {
108 1 : if delimiter != "" {
109 0 : panic("delimiter unimplemented")
110 : }
111 :
112 1 : s.mu.Lock()
113 1 : defer s.mu.Unlock()
114 1 : res := make([]string, 0, len(s.mu.objects))
115 1 : for name := range s.mu.objects {
116 1 : if strings.HasPrefix(name, prefix) {
117 1 : res = append(res, name)
118 1 : }
119 : }
120 1 : return res, nil
121 : }
122 :
123 1 : func (s *inMemStore) Delete(objName string) error {
124 1 : s.rmObj(objName)
125 1 : return nil
126 1 : }
127 :
128 : // Size returns the length of the named object in bytesWritten.
129 1 : func (s *inMemStore) Size(objName string) (int64, error) {
130 1 : obj, err := s.getObj(objName)
131 1 : if err != nil {
132 0 : return 0, err
133 0 : }
134 1 : return int64(len(obj.data)), nil
135 : }
136 :
137 0 : func (s *inMemStore) IsNotExistError(err error) bool {
138 0 : return err == os.ErrNotExist
139 0 : }
140 :
141 1 : func (s *inMemStore) getObj(name string) (*inMemObj, error) {
142 1 : s.mu.Lock()
143 1 : defer s.mu.Unlock()
144 1 : obj, ok := s.mu.objects[name]
145 1 : if !ok {
146 0 : return nil, os.ErrNotExist
147 0 : }
148 1 : return obj, nil
149 : }
150 :
151 1 : func (s *inMemStore) addObj(o *inMemObj) {
152 1 : s.mu.Lock()
153 1 : defer s.mu.Unlock()
154 1 : s.mu.objects[o.name] = o
155 1 : }
156 :
157 1 : func (s *inMemStore) rmObj(name string) {
158 1 : s.mu.Lock()
159 1 : defer s.mu.Unlock()
160 1 : delete(s.mu.objects, name)
161 1 : }
|