file_io.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. package rpl
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "github.com/edsrzf/mmap-go"
  7. "github.com/siddontang/go/log"
  8. )
  9. //like leveldb or rocksdb file interface, haha!
  10. type writeFile interface {
  11. Sync() error
  12. Write(b []byte) (n int, err error)
  13. Close() error
  14. ReadAt(buf []byte, offset int64) (int, error)
  15. Truncate(size int64) error
  16. SetOffset(o int64)
  17. Name() string
  18. Size() int
  19. Offset() int64
  20. }
  21. type readFile interface {
  22. ReadAt(buf []byte, offset int64) (int, error)
  23. Close() error
  24. Size() int
  25. Name() string
  26. }
  27. type rawWriteFile struct {
  28. writeFile
  29. f *os.File
  30. offset int64
  31. name string
  32. }
  33. func newRawWriteFile(name string, size int64) (writeFile, error) {
  34. m := new(rawWriteFile)
  35. var err error
  36. m.name = name
  37. m.f, err = os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0644)
  38. if err != nil {
  39. return nil, err
  40. }
  41. return m, nil
  42. }
  43. func (m *rawWriteFile) Close() error {
  44. if err := m.f.Truncate(m.offset); err != nil {
  45. return fmt.Errorf("close truncate %s error %s", m.name, err.Error())
  46. }
  47. if err := m.f.Close(); err != nil {
  48. return fmt.Errorf("close %s error %s", m.name, err.Error())
  49. }
  50. return nil
  51. }
  52. func (m *rawWriteFile) Sync() error {
  53. return m.f.Sync()
  54. }
  55. func (m *rawWriteFile) Write(b []byte) (n int, err error) {
  56. n, err = m.f.WriteAt(b, m.offset)
  57. if err != nil {
  58. return
  59. } else if n != len(b) {
  60. err = io.ErrShortWrite
  61. return
  62. }
  63. m.offset += int64(n)
  64. return
  65. }
  66. func (m *rawWriteFile) ReadAt(buf []byte, offset int64) (int, error) {
  67. return m.f.ReadAt(buf, offset)
  68. }
  69. func (m *rawWriteFile) Truncate(size int64) error {
  70. var err error
  71. if err = m.f.Truncate(size); err != nil {
  72. return err
  73. }
  74. if m.offset > size {
  75. m.offset = size
  76. }
  77. return nil
  78. }
  79. func (m *rawWriteFile) SetOffset(o int64) {
  80. m.offset = o
  81. }
  82. func (m *rawWriteFile) Offset() int64 {
  83. return m.offset
  84. }
  85. func (m *rawWriteFile) Name() string {
  86. return m.name
  87. }
  88. func (m *rawWriteFile) Size() int {
  89. st, _ := m.f.Stat()
  90. return int(st.Size())
  91. }
  92. type rawReadFile struct {
  93. readFile
  94. f *os.File
  95. name string
  96. }
  97. func newRawReadFile(name string) (readFile, error) {
  98. m := new(rawReadFile)
  99. var err error
  100. m.f, err = os.Open(name)
  101. m.name = name
  102. if err != nil {
  103. return nil, err
  104. }
  105. return m, err
  106. }
  107. func (m *rawReadFile) Close() error {
  108. return m.f.Close()
  109. }
  110. func (m *rawReadFile) Size() int {
  111. st, _ := m.f.Stat()
  112. return int(st.Size())
  113. }
  114. func (m *rawReadFile) ReadAt(b []byte, offset int64) (int, error) {
  115. return m.f.ReadAt(b, offset)
  116. }
  117. func (m *rawReadFile) Name() string {
  118. return m.name
  119. }
  120. /////////////////////////////////////////////////
  121. type mmapWriteFile struct {
  122. writeFile
  123. f *os.File
  124. m mmap.MMap
  125. name string
  126. size int64
  127. offset int64
  128. }
  129. func newMmapWriteFile(name string, size int64) (writeFile, error) {
  130. m := new(mmapWriteFile)
  131. m.name = name
  132. var err error
  133. m.f, err = os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0644)
  134. if err != nil {
  135. return nil, err
  136. }
  137. if size == 0 {
  138. st, _ := m.f.Stat()
  139. size = st.Size()
  140. }
  141. if err = m.f.Truncate(size); err != nil {
  142. return nil, err
  143. }
  144. if m.m, err = mmap.Map(m.f, mmap.RDWR, 0); err != nil {
  145. return nil, err
  146. }
  147. m.size = size
  148. m.offset = 0
  149. return m, nil
  150. }
  151. func (m *mmapWriteFile) Size() int {
  152. return int(m.size)
  153. }
  154. func (m *mmapWriteFile) Sync() error {
  155. return m.m.Flush()
  156. }
  157. func (m *mmapWriteFile) Close() error {
  158. if err := m.m.Unmap(); err != nil {
  159. return fmt.Errorf("unmap %s error %s", m.name, err.Error())
  160. }
  161. if err := m.f.Truncate(m.offset); err != nil {
  162. return fmt.Errorf("close truncate %s error %s", m.name, err.Error())
  163. }
  164. if err := m.f.Close(); err != nil {
  165. return fmt.Errorf("close %s error %s", m.name, err.Error())
  166. }
  167. return nil
  168. }
  169. func (m *mmapWriteFile) Write(b []byte) (n int, err error) {
  170. extra := int64(len(b)) - (m.size - m.offset)
  171. if extra > 0 {
  172. newSize := m.size + extra + m.size/10
  173. if err = m.Truncate(newSize); err != nil {
  174. return
  175. }
  176. m.size = newSize
  177. }
  178. n = copy(m.m[m.offset:], b)
  179. if n != len(b) {
  180. return 0, io.ErrShortWrite
  181. }
  182. m.offset += int64(len(b))
  183. return len(b), nil
  184. }
  185. func (m *mmapWriteFile) ReadAt(buf []byte, offset int64) (int, error) {
  186. if offset > m.offset {
  187. return 0, fmt.Errorf("invalid offset %d", offset)
  188. }
  189. n := copy(buf, m.m[offset:m.offset])
  190. if n != len(buf) {
  191. return n, io.ErrUnexpectedEOF
  192. }
  193. return n, nil
  194. }
  195. func (m *mmapWriteFile) Truncate(size int64) error {
  196. var err error
  197. if err = m.m.Unmap(); err != nil {
  198. return err
  199. }
  200. if err = m.f.Truncate(size); err != nil {
  201. return err
  202. }
  203. if m.m, err = mmap.Map(m.f, mmap.RDWR, 0); err != nil {
  204. return err
  205. }
  206. m.size = size
  207. if m.offset > m.size {
  208. m.offset = m.size
  209. }
  210. return nil
  211. }
  212. func (m *mmapWriteFile) SetOffset(o int64) {
  213. m.offset = o
  214. }
  215. func (m *mmapWriteFile) Offset() int64 {
  216. return m.offset
  217. }
  218. func (m *mmapWriteFile) Name() string {
  219. return m.name
  220. }
  221. type mmapReadFile struct {
  222. readFile
  223. f *os.File
  224. m mmap.MMap
  225. name string
  226. }
  227. func newMmapReadFile(name string) (readFile, error) {
  228. m := new(mmapReadFile)
  229. m.name = name
  230. var err error
  231. m.f, err = os.Open(name)
  232. if err != nil {
  233. return nil, err
  234. }
  235. m.m, err = mmap.Map(m.f, mmap.RDONLY, 0)
  236. return m, err
  237. }
  238. func (m *mmapReadFile) ReadAt(buf []byte, offset int64) (int, error) {
  239. if int64(offset) > int64(len(m.m)) {
  240. return 0, fmt.Errorf("invalid offset %d", offset)
  241. }
  242. n := copy(buf, m.m[offset:])
  243. if n != len(buf) {
  244. return n, io.ErrUnexpectedEOF
  245. }
  246. return n, nil
  247. }
  248. func (m *mmapReadFile) Close() error {
  249. if m.m != nil {
  250. if err := m.m.Unmap(); err != nil {
  251. log.Errorf("unmap %s error %s", m.name, err.Error())
  252. }
  253. m.m = nil
  254. }
  255. if m.f != nil {
  256. if err := m.f.Close(); err != nil {
  257. log.Errorf("close %s error %s", m.name, err.Error())
  258. }
  259. m.f = nil
  260. }
  261. return nil
  262. }
  263. func (m *mmapReadFile) Size() int {
  264. return len(m.m)
  265. }
  266. func (m *mmapReadFile) Name() string {
  267. return m.name
  268. }
  269. /////////////////////////////////////
  270. func newWriteFile(useMmap bool, name string, size int64) (writeFile, error) {
  271. if useMmap {
  272. return newMmapWriteFile(name, size)
  273. } else {
  274. return newRawWriteFile(name, size)
  275. }
  276. }
  277. func newReadFile(useMmap bool, name string) (readFile, error) {
  278. if useMmap {
  279. return newMmapReadFile(name)
  280. } else {
  281. return newRawReadFile(name)
  282. }
  283. }