本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

366 lines
7.3KB

  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. package afero
  14. import (
  15. "fmt"
  16. "log"
  17. "os"
  18. "path/filepath"
  19. "strings"
  20. "sync"
  21. "time"
  22. "github.com/spf13/afero/mem"
  23. )
  24. type MemMapFs struct {
  25. mu sync.RWMutex
  26. data map[string]*mem.FileData
  27. init sync.Once
  28. }
  29. func NewMemMapFs() Fs {
  30. return &MemMapFs{}
  31. }
  32. func (m *MemMapFs) getData() map[string]*mem.FileData {
  33. m.init.Do(func() {
  34. m.data = make(map[string]*mem.FileData)
  35. // Root should always exist, right?
  36. // TODO: what about windows?
  37. m.data[FilePathSeparator] = mem.CreateDir(FilePathSeparator)
  38. })
  39. return m.data
  40. }
  41. func (*MemMapFs) Name() string { return "MemMapFS" }
  42. func (m *MemMapFs) Create(name string) (File, error) {
  43. name = normalizePath(name)
  44. m.mu.Lock()
  45. file := mem.CreateFile(name)
  46. m.getData()[name] = file
  47. m.registerWithParent(file)
  48. m.mu.Unlock()
  49. return mem.NewFileHandle(file), nil
  50. }
  51. func (m *MemMapFs) unRegisterWithParent(fileName string) error {
  52. f, err := m.lockfreeOpen(fileName)
  53. if err != nil {
  54. return err
  55. }
  56. parent := m.findParent(f)
  57. if parent == nil {
  58. log.Panic("parent of ", f.Name(), " is nil")
  59. }
  60. parent.Lock()
  61. mem.RemoveFromMemDir(parent, f)
  62. parent.Unlock()
  63. return nil
  64. }
  65. func (m *MemMapFs) findParent(f *mem.FileData) *mem.FileData {
  66. pdir, _ := filepath.Split(f.Name())
  67. pdir = filepath.Clean(pdir)
  68. pfile, err := m.lockfreeOpen(pdir)
  69. if err != nil {
  70. return nil
  71. }
  72. return pfile
  73. }
  74. func (m *MemMapFs) registerWithParent(f *mem.FileData) {
  75. if f == nil {
  76. return
  77. }
  78. parent := m.findParent(f)
  79. if parent == nil {
  80. pdir := filepath.Dir(filepath.Clean(f.Name()))
  81. err := m.lockfreeMkdir(pdir, 0777)
  82. if err != nil {
  83. //log.Println("Mkdir error:", err)
  84. return
  85. }
  86. parent, err = m.lockfreeOpen(pdir)
  87. if err != nil {
  88. //log.Println("Open after Mkdir error:", err)
  89. return
  90. }
  91. }
  92. parent.Lock()
  93. mem.InitializeDir(parent)
  94. mem.AddToMemDir(parent, f)
  95. parent.Unlock()
  96. }
  97. func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
  98. name = normalizePath(name)
  99. x, ok := m.getData()[name]
  100. if ok {
  101. // Only return ErrFileExists if it's a file, not a directory.
  102. i := mem.FileInfo{FileData: x}
  103. if !i.IsDir() {
  104. return ErrFileExists
  105. }
  106. } else {
  107. item := mem.CreateDir(name)
  108. m.getData()[name] = item
  109. m.registerWithParent(item)
  110. }
  111. return nil
  112. }
  113. func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
  114. name = normalizePath(name)
  115. m.mu.RLock()
  116. _, ok := m.getData()[name]
  117. m.mu.RUnlock()
  118. if ok {
  119. return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
  120. }
  121. m.mu.Lock()
  122. item := mem.CreateDir(name)
  123. m.getData()[name] = item
  124. m.registerWithParent(item)
  125. m.mu.Unlock()
  126. m.Chmod(name, perm|os.ModeDir)
  127. return nil
  128. }
  129. func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
  130. err := m.Mkdir(path, perm)
  131. if err != nil {
  132. if err.(*os.PathError).Err == ErrFileExists {
  133. return nil
  134. }
  135. return err
  136. }
  137. return nil
  138. }
  139. // Handle some relative paths
  140. func normalizePath(path string) string {
  141. path = filepath.Clean(path)
  142. switch path {
  143. case ".":
  144. return FilePathSeparator
  145. case "..":
  146. return FilePathSeparator
  147. default:
  148. return path
  149. }
  150. }
  151. func (m *MemMapFs) Open(name string) (File, error) {
  152. f, err := m.open(name)
  153. if f != nil {
  154. return mem.NewReadOnlyFileHandle(f), err
  155. }
  156. return nil, err
  157. }
  158. func (m *MemMapFs) openWrite(name string) (File, error) {
  159. f, err := m.open(name)
  160. if f != nil {
  161. return mem.NewFileHandle(f), err
  162. }
  163. return nil, err
  164. }
  165. func (m *MemMapFs) open(name string) (*mem.FileData, error) {
  166. name = normalizePath(name)
  167. m.mu.RLock()
  168. f, ok := m.getData()[name]
  169. m.mu.RUnlock()
  170. if !ok {
  171. return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileNotFound}
  172. }
  173. return f, nil
  174. }
  175. func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) {
  176. name = normalizePath(name)
  177. f, ok := m.getData()[name]
  178. if ok {
  179. return f, nil
  180. } else {
  181. return nil, ErrFileNotFound
  182. }
  183. }
  184. func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
  185. chmod := false
  186. file, err := m.openWrite(name)
  187. if os.IsNotExist(err) && (flag&os.O_CREATE > 0) {
  188. file, err = m.Create(name)
  189. chmod = true
  190. }
  191. if err != nil {
  192. return nil, err
  193. }
  194. if flag == os.O_RDONLY {
  195. file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data())
  196. }
  197. if flag&os.O_APPEND > 0 {
  198. _, err = file.Seek(0, os.SEEK_END)
  199. if err != nil {
  200. file.Close()
  201. return nil, err
  202. }
  203. }
  204. if flag&os.O_TRUNC > 0 && flag&(os.O_RDWR|os.O_WRONLY) > 0 {
  205. err = file.Truncate(0)
  206. if err != nil {
  207. file.Close()
  208. return nil, err
  209. }
  210. }
  211. if chmod {
  212. m.Chmod(name, perm)
  213. }
  214. return file, nil
  215. }
  216. func (m *MemMapFs) Remove(name string) error {
  217. name = normalizePath(name)
  218. m.mu.Lock()
  219. defer m.mu.Unlock()
  220. if _, ok := m.getData()[name]; ok {
  221. err := m.unRegisterWithParent(name)
  222. if err != nil {
  223. return &os.PathError{Op: "remove", Path: name, Err: err}
  224. }
  225. delete(m.getData(), name)
  226. } else {
  227. return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist}
  228. }
  229. return nil
  230. }
  231. func (m *MemMapFs) RemoveAll(path string) error {
  232. path = normalizePath(path)
  233. m.mu.Lock()
  234. m.unRegisterWithParent(path)
  235. m.mu.Unlock()
  236. m.mu.RLock()
  237. defer m.mu.RUnlock()
  238. for p, _ := range m.getData() {
  239. if strings.HasPrefix(p, path) {
  240. m.mu.RUnlock()
  241. m.mu.Lock()
  242. delete(m.getData(), p)
  243. m.mu.Unlock()
  244. m.mu.RLock()
  245. }
  246. }
  247. return nil
  248. }
  249. func (m *MemMapFs) Rename(oldname, newname string) error {
  250. oldname = normalizePath(oldname)
  251. newname = normalizePath(newname)
  252. if oldname == newname {
  253. return nil
  254. }
  255. m.mu.RLock()
  256. defer m.mu.RUnlock()
  257. if _, ok := m.getData()[oldname]; ok {
  258. m.mu.RUnlock()
  259. m.mu.Lock()
  260. m.unRegisterWithParent(oldname)
  261. fileData := m.getData()[oldname]
  262. delete(m.getData(), oldname)
  263. mem.ChangeFileName(fileData, newname)
  264. m.getData()[newname] = fileData
  265. m.registerWithParent(fileData)
  266. m.mu.Unlock()
  267. m.mu.RLock()
  268. } else {
  269. return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
  270. }
  271. return nil
  272. }
  273. func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
  274. f, err := m.Open(name)
  275. if err != nil {
  276. return nil, err
  277. }
  278. fi := mem.GetFileInfo(f.(*mem.File).Data())
  279. return fi, nil
  280. }
  281. func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
  282. name = normalizePath(name)
  283. m.mu.RLock()
  284. f, ok := m.getData()[name]
  285. m.mu.RUnlock()
  286. if !ok {
  287. return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
  288. }
  289. m.mu.Lock()
  290. mem.SetMode(f, mode)
  291. m.mu.Unlock()
  292. return nil
  293. }
  294. func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
  295. name = normalizePath(name)
  296. m.mu.RLock()
  297. f, ok := m.getData()[name]
  298. m.mu.RUnlock()
  299. if !ok {
  300. return &os.PathError{Op: "chtimes", Path: name, Err: ErrFileNotFound}
  301. }
  302. m.mu.Lock()
  303. mem.SetModTime(f, mtime)
  304. m.mu.Unlock()
  305. return nil
  306. }
  307. func (m *MemMapFs) List() {
  308. for _, x := range m.data {
  309. y := mem.FileInfo{FileData: x}
  310. fmt.Println(x.Name(), y.Size())
  311. }
  312. }
  313. // func debugMemMapList(fs Fs) {
  314. // if x, ok := fs.(*MemMapFs); ok {
  315. // x.List()
  316. // }
  317. // }
上海开阖软件有限公司 沪ICP备12045867号-1