OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / spf13 / afero / memmap.go
1 // Copyright © 2014 Steve Francia <spf@spf13.com>.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package afero
15
16 import (
17         "fmt"
18         "log"
19         "os"
20         "path/filepath"
21         "strings"
22         "sync"
23         "time"
24
25         "github.com/spf13/afero/mem"
26 )
27
28 type MemMapFs struct {
29         mu   sync.RWMutex
30         data map[string]*mem.FileData
31         init sync.Once
32 }
33
34 func NewMemMapFs() Fs {
35         return &MemMapFs{}
36 }
37
38 func (m *MemMapFs) getData() map[string]*mem.FileData {
39         m.init.Do(func() {
40                 m.data = make(map[string]*mem.FileData)
41                 // Root should always exist, right?
42                 // TODO: what about windows?
43                 m.data[FilePathSeparator] = mem.CreateDir(FilePathSeparator)
44         })
45         return m.data
46 }
47
48 func (*MemMapFs) Name() string { return "MemMapFS" }
49
50 func (m *MemMapFs) Create(name string) (File, error) {
51         name = normalizePath(name)
52         m.mu.Lock()
53         file := mem.CreateFile(name)
54         m.getData()[name] = file
55         m.registerWithParent(file)
56         m.mu.Unlock()
57         return mem.NewFileHandle(file), nil
58 }
59
60 func (m *MemMapFs) unRegisterWithParent(fileName string) error {
61         f, err := m.lockfreeOpen(fileName)
62         if err != nil {
63                 return err
64         }
65         parent := m.findParent(f)
66         if parent == nil {
67                 log.Panic("parent of ", f.Name(), " is nil")
68         }
69
70         parent.Lock()
71         mem.RemoveFromMemDir(parent, f)
72         parent.Unlock()
73         return nil
74 }
75
76 func (m *MemMapFs) findParent(f *mem.FileData) *mem.FileData {
77         pdir, _ := filepath.Split(f.Name())
78         pdir = filepath.Clean(pdir)
79         pfile, err := m.lockfreeOpen(pdir)
80         if err != nil {
81                 return nil
82         }
83         return pfile
84 }
85
86 func (m *MemMapFs) registerWithParent(f *mem.FileData) {
87         if f == nil {
88                 return
89         }
90         parent := m.findParent(f)
91         if parent == nil {
92                 pdir := filepath.Dir(filepath.Clean(f.Name()))
93                 err := m.lockfreeMkdir(pdir, 0777)
94                 if err != nil {
95                         //log.Println("Mkdir error:", err)
96                         return
97                 }
98                 parent, err = m.lockfreeOpen(pdir)
99                 if err != nil {
100                         //log.Println("Open after Mkdir error:", err)
101                         return
102                 }
103         }
104
105         parent.Lock()
106         mem.InitializeDir(parent)
107         mem.AddToMemDir(parent, f)
108         parent.Unlock()
109 }
110
111 func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
112         name = normalizePath(name)
113         x, ok := m.getData()[name]
114         if ok {
115                 // Only return ErrFileExists if it's a file, not a directory.
116                 i := mem.FileInfo{FileData: x}
117                 if !i.IsDir() {
118                         return ErrFileExists
119                 }
120         } else {
121                 item := mem.CreateDir(name)
122                 m.getData()[name] = item
123                 m.registerWithParent(item)
124         }
125         return nil
126 }
127
128 func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
129         name = normalizePath(name)
130
131         m.mu.RLock()
132         _, ok := m.getData()[name]
133         m.mu.RUnlock()
134         if ok {
135                 return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
136         }
137
138         m.mu.Lock()
139         item := mem.CreateDir(name)
140         m.getData()[name] = item
141         m.registerWithParent(item)
142         m.mu.Unlock()
143
144         m.Chmod(name, perm|os.ModeDir)
145
146         return nil
147 }
148
149 func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
150         err := m.Mkdir(path, perm)
151         if err != nil {
152                 if err.(*os.PathError).Err == ErrFileExists {
153                         return nil
154                 }
155                 return err
156         }
157         return nil
158 }
159
160 // Handle some relative paths
161 func normalizePath(path string) string {
162         path = filepath.Clean(path)
163
164         switch path {
165         case ".":
166                 return FilePathSeparator
167         case "..":
168                 return FilePathSeparator
169         default:
170                 return path
171         }
172 }
173
174 func (m *MemMapFs) Open(name string) (File, error) {
175         f, err := m.open(name)
176         if f != nil {
177                 return mem.NewReadOnlyFileHandle(f), err
178         }
179         return nil, err
180 }
181
182 func (m *MemMapFs) openWrite(name string) (File, error) {
183         f, err := m.open(name)
184         if f != nil {
185                 return mem.NewFileHandle(f), err
186         }
187         return nil, err
188 }
189
190 func (m *MemMapFs) open(name string) (*mem.FileData, error) {
191         name = normalizePath(name)
192
193         m.mu.RLock()
194         f, ok := m.getData()[name]
195         m.mu.RUnlock()
196         if !ok {
197                 return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileNotFound}
198         }
199         return f, nil
200 }
201
202 func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) {
203         name = normalizePath(name)
204         f, ok := m.getData()[name]
205         if ok {
206                 return f, nil
207         } else {
208                 return nil, ErrFileNotFound
209         }
210 }
211
212 func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
213         chmod := false
214         file, err := m.openWrite(name)
215         if os.IsNotExist(err) && (flag&os.O_CREATE > 0) {
216                 file, err = m.Create(name)
217                 chmod = true
218         }
219         if err != nil {
220                 return nil, err
221         }
222         if flag == os.O_RDONLY {
223                 file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data())
224         }
225         if flag&os.O_APPEND > 0 {
226                 _, err = file.Seek(0, os.SEEK_END)
227                 if err != nil {
228                         file.Close()
229                         return nil, err
230                 }
231         }
232         if flag&os.O_TRUNC > 0 && flag&(os.O_RDWR|os.O_WRONLY) > 0 {
233                 err = file.Truncate(0)
234                 if err != nil {
235                         file.Close()
236                         return nil, err
237                 }
238         }
239         if chmod {
240                 m.Chmod(name, perm)
241         }
242         return file, nil
243 }
244
245 func (m *MemMapFs) Remove(name string) error {
246         name = normalizePath(name)
247
248         m.mu.Lock()
249         defer m.mu.Unlock()
250
251         if _, ok := m.getData()[name]; ok {
252                 err := m.unRegisterWithParent(name)
253                 if err != nil {
254                         return &os.PathError{Op: "remove", Path: name, Err: err}
255                 }
256                 delete(m.getData(), name)
257         } else {
258                 return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist}
259         }
260         return nil
261 }
262
263 func (m *MemMapFs) RemoveAll(path string) error {
264         path = normalizePath(path)
265         m.mu.Lock()
266         m.unRegisterWithParent(path)
267         m.mu.Unlock()
268
269         m.mu.RLock()
270         defer m.mu.RUnlock()
271
272         for p, _ := range m.getData() {
273                 if strings.HasPrefix(p, path) {
274                         m.mu.RUnlock()
275                         m.mu.Lock()
276                         delete(m.getData(), p)
277                         m.mu.Unlock()
278                         m.mu.RLock()
279                 }
280         }
281         return nil
282 }
283
284 func (m *MemMapFs) Rename(oldname, newname string) error {
285         oldname = normalizePath(oldname)
286         newname = normalizePath(newname)
287
288         if oldname == newname {
289                 return nil
290         }
291
292         m.mu.RLock()
293         defer m.mu.RUnlock()
294         if _, ok := m.getData()[oldname]; ok {
295                 m.mu.RUnlock()
296                 m.mu.Lock()
297                 m.unRegisterWithParent(oldname)
298                 fileData := m.getData()[oldname]
299                 delete(m.getData(), oldname)
300                 mem.ChangeFileName(fileData, newname)
301                 m.getData()[newname] = fileData
302                 m.registerWithParent(fileData)
303                 m.mu.Unlock()
304                 m.mu.RLock()
305         } else {
306                 return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
307         }
308         return nil
309 }
310
311 func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
312         f, err := m.Open(name)
313         if err != nil {
314                 return nil, err
315         }
316         fi := mem.GetFileInfo(f.(*mem.File).Data())
317         return fi, nil
318 }
319
320 func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
321         name = normalizePath(name)
322
323         m.mu.RLock()
324         f, ok := m.getData()[name]
325         m.mu.RUnlock()
326         if !ok {
327                 return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
328         }
329
330         m.mu.Lock()
331         mem.SetMode(f, mode)
332         m.mu.Unlock()
333
334         return nil
335 }
336
337 func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
338         name = normalizePath(name)
339
340         m.mu.RLock()
341         f, ok := m.getData()[name]
342         m.mu.RUnlock()
343         if !ok {
344                 return &os.PathError{Op: "chtimes", Path: name, Err: ErrFileNotFound}
345         }
346
347         m.mu.Lock()
348         mem.SetModTime(f, mtime)
349         m.mu.Unlock()
350
351         return nil
352 }
353
354 func (m *MemMapFs) List() {
355         for _, x := range m.data {
356                 y := mem.FileInfo{FileData: x}
357                 fmt.Println(x.Name(), y.Size())
358         }
359 }
360
361 // func debugMemMapList(fs Fs) {
362 //      if x, ok := fs.(*MemMapFs); ok {
363 //              x.List()
364 //      }
365 // }