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.

287 lines
8.2 KiB

12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
  1. package storage
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "os"
  7. "github.com/chrislusf/weed-fs/go/glog"
  8. "github.com/chrislusf/weed-fs/go/util"
  9. )
  10. const (
  11. FlagGzip = 0x01
  12. FlagHasName = 0x02
  13. FlagHasMime = 0x04
  14. FlagHasLastModifiedDate = 0x08
  15. FlagHasTtl = 0x10
  16. LastModifiedBytesLength = 5
  17. TtlBytesLength = 2
  18. )
  19. func (n *Needle) DiskSize() int64 {
  20. padding := NeedlePaddingSize - ((NeedleHeaderSize + int64(n.Size) + NeedleChecksumSize) % NeedlePaddingSize)
  21. return NeedleHeaderSize + int64(n.Size) + padding + NeedleChecksumSize
  22. }
  23. func (n *Needle) Append(w io.Writer, version Version) (size uint32, err error) {
  24. if s, ok := w.(io.Seeker); ok {
  25. if end, e := s.Seek(0, 1); e == nil {
  26. defer func(s io.Seeker, off int64) {
  27. if err != nil {
  28. if _, e = s.Seek(off, 0); e != nil {
  29. glog.V(0).Infof("Failed to seek %s back to %d with error: %v", w, off, e)
  30. }
  31. }
  32. }(s, end)
  33. } else {
  34. err = fmt.Errorf("Cannot Read Current Volume Position: %v", e)
  35. return
  36. }
  37. }
  38. switch version {
  39. case Version1:
  40. header := make([]byte, NeedleHeaderSize)
  41. util.Uint32toBytes(header[0:4], n.Cookie)
  42. util.Uint64toBytes(header[4:12], n.Id)
  43. n.Size = uint32(len(n.Data))
  44. size = n.Size
  45. util.Uint32toBytes(header[12:16], n.Size)
  46. if _, err = w.Write(header); err != nil {
  47. return
  48. }
  49. if _, err = w.Write(n.Data); err != nil {
  50. return
  51. }
  52. padding := NeedlePaddingSize - ((NeedleHeaderSize + n.Size + NeedleChecksumSize) % NeedlePaddingSize)
  53. util.Uint32toBytes(header[0:NeedleChecksumSize], n.Checksum.Value())
  54. _, err = w.Write(header[0 : NeedleChecksumSize+padding])
  55. return
  56. case Version2:
  57. header := make([]byte, NeedleHeaderSize)
  58. util.Uint32toBytes(header[0:4], n.Cookie)
  59. util.Uint64toBytes(header[4:12], n.Id)
  60. n.DataSize, n.NameSize, n.MimeSize = uint32(len(n.Data)), uint8(len(n.Name)), uint8(len(n.Mime))
  61. if n.DataSize > 0 {
  62. n.Size = 4 + n.DataSize + 1
  63. if n.HasName() {
  64. n.Size = n.Size + 1 + uint32(n.NameSize)
  65. }
  66. if n.HasMime() {
  67. n.Size = n.Size + 1 + uint32(n.MimeSize)
  68. }
  69. if n.HasLastModifiedDate() {
  70. n.Size = n.Size + LastModifiedBytesLength
  71. }
  72. if n.HasTtl() {
  73. n.Size = n.Size + TtlBytesLength
  74. }
  75. }
  76. size = n.DataSize
  77. util.Uint32toBytes(header[12:16], n.Size)
  78. if _, err = w.Write(header); err != nil {
  79. return
  80. }
  81. if n.DataSize > 0 {
  82. util.Uint32toBytes(header[0:4], n.DataSize)
  83. if _, err = w.Write(header[0:4]); err != nil {
  84. return
  85. }
  86. if _, err = w.Write(n.Data); err != nil {
  87. return
  88. }
  89. util.Uint8toBytes(header[0:1], n.Flags)
  90. if _, err = w.Write(header[0:1]); err != nil {
  91. return
  92. }
  93. if n.HasName() {
  94. util.Uint8toBytes(header[0:1], n.NameSize)
  95. if _, err = w.Write(header[0:1]); err != nil {
  96. return
  97. }
  98. if _, err = w.Write(n.Name); err != nil {
  99. return
  100. }
  101. }
  102. if n.HasMime() {
  103. util.Uint8toBytes(header[0:1], n.MimeSize)
  104. if _, err = w.Write(header[0:1]); err != nil {
  105. return
  106. }
  107. if _, err = w.Write(n.Mime); err != nil {
  108. return
  109. }
  110. }
  111. if n.HasLastModifiedDate() {
  112. util.Uint64toBytes(header[0:8], n.LastModified)
  113. if _, err = w.Write(header[8-LastModifiedBytesLength : 8]); err != nil {
  114. return
  115. }
  116. }
  117. if n.HasTtl() {
  118. n.Ttl.ToBytes(header[0:TtlBytesLength])
  119. if _, err = w.Write(header[0:TtlBytesLength]); err != nil {
  120. return
  121. }
  122. }
  123. }
  124. padding := NeedlePaddingSize - ((NeedleHeaderSize + n.Size + NeedleChecksumSize) % NeedlePaddingSize)
  125. util.Uint32toBytes(header[0:NeedleChecksumSize], n.Checksum.Value())
  126. _, err = w.Write(header[0 : NeedleChecksumSize+padding])
  127. return n.DataSize, err
  128. }
  129. return 0, fmt.Errorf("Unsupported Version! (%d)", version)
  130. }
  131. func (n *Needle) Read(r *os.File, offset int64, size uint32, version Version) (ret int, err error) {
  132. switch version {
  133. case Version1:
  134. bytes := make([]byte, NeedleHeaderSize+size+NeedleChecksumSize)
  135. if ret, err = r.ReadAt(bytes, offset); err != nil {
  136. return
  137. }
  138. n.readNeedleHeader(bytes)
  139. n.Data = bytes[NeedleHeaderSize : NeedleHeaderSize+size]
  140. checksum := util.BytesToUint32(bytes[NeedleHeaderSize+size : NeedleHeaderSize+size+NeedleChecksumSize])
  141. newChecksum := NewCRC(n.Data)
  142. if checksum != newChecksum.Value() {
  143. return 0, errors.New("CRC error! Data On Disk Corrupted!")
  144. }
  145. n.Checksum = newChecksum
  146. return
  147. case Version2:
  148. if size == 0 {
  149. return 0, nil
  150. }
  151. bytes := make([]byte, NeedleHeaderSize+size+NeedleChecksumSize)
  152. if ret, err = r.ReadAt(bytes, offset); err != nil {
  153. return
  154. }
  155. if ret != int(NeedleHeaderSize+size+NeedleChecksumSize) {
  156. return 0, errors.New("File Entry Not Found!")
  157. }
  158. n.readNeedleHeader(bytes)
  159. if n.Size != size {
  160. return 0, fmt.Errorf("File Entry Not Found! Needle %d Memory %d", n.Size, size)
  161. }
  162. n.readNeedleDataVersion2(bytes[NeedleHeaderSize : NeedleHeaderSize+int(n.Size)])
  163. checksum := util.BytesToUint32(bytes[NeedleHeaderSize+n.Size : NeedleHeaderSize+n.Size+NeedleChecksumSize])
  164. newChecksum := NewCRC(n.Data)
  165. if checksum != newChecksum.Value() {
  166. return 0, errors.New("CRC error! Data On Disk Corrupted!")
  167. }
  168. n.Checksum = newChecksum
  169. return
  170. }
  171. return 0, fmt.Errorf("Unsupported Version! (%d)", version)
  172. }
  173. func (n *Needle) readNeedleHeader(bytes []byte) {
  174. n.Cookie = util.BytesToUint32(bytes[0:4])
  175. n.Id = util.BytesToUint64(bytes[4:12])
  176. n.Size = util.BytesToUint32(bytes[12:NeedleHeaderSize])
  177. }
  178. func (n *Needle) readNeedleDataVersion2(bytes []byte) {
  179. index, lenBytes := 0, len(bytes)
  180. if index < lenBytes {
  181. n.DataSize = util.BytesToUint32(bytes[index : index+4])
  182. index = index + 4
  183. n.Data = bytes[index : index+int(n.DataSize)]
  184. index = index + int(n.DataSize)
  185. n.Flags = bytes[index]
  186. index = index + 1
  187. }
  188. if index < lenBytes && n.HasName() {
  189. n.NameSize = uint8(bytes[index])
  190. index = index + 1
  191. n.Name = bytes[index : index+int(n.NameSize)]
  192. index = index + int(n.NameSize)
  193. }
  194. if index < lenBytes && n.HasMime() {
  195. n.MimeSize = uint8(bytes[index])
  196. index = index + 1
  197. n.Mime = bytes[index : index+int(n.MimeSize)]
  198. index = index + int(n.MimeSize)
  199. }
  200. if index < lenBytes && n.HasLastModifiedDate() {
  201. n.LastModified = util.BytesToUint64(bytes[index : index+LastModifiedBytesLength])
  202. index = index + LastModifiedBytesLength
  203. }
  204. if index < lenBytes && n.HasTtl() {
  205. n.Ttl = LoadTTLFromBytes(bytes[index : index+TtlBytesLength])
  206. index = index + TtlBytesLength
  207. }
  208. }
  209. func ReadNeedleHeader(r *os.File, version Version, offset int64) (n *Needle, bodyLength uint32, err error) {
  210. n = new(Needle)
  211. if version == Version1 || version == Version2 {
  212. bytes := make([]byte, NeedleHeaderSize)
  213. var count int
  214. count, err = r.ReadAt(bytes, offset)
  215. if count <= 0 || err != nil {
  216. return nil, 0, err
  217. }
  218. n.readNeedleHeader(bytes)
  219. padding := NeedlePaddingSize - ((n.Size + NeedleHeaderSize + NeedleChecksumSize) % NeedlePaddingSize)
  220. bodyLength = n.Size + NeedleChecksumSize + padding
  221. }
  222. return
  223. }
  224. //n should be a needle already read the header
  225. //the input stream will read until next file entry
  226. func (n *Needle) ReadNeedleBody(r *os.File, version Version, offset int64, bodyLength uint32) (err error) {
  227. if bodyLength <= 0 {
  228. return nil
  229. }
  230. switch version {
  231. case Version1:
  232. bytes := make([]byte, bodyLength)
  233. if _, err = r.ReadAt(bytes, offset); err != nil {
  234. return
  235. }
  236. n.Data = bytes[:n.Size]
  237. n.Checksum = NewCRC(n.Data)
  238. case Version2:
  239. bytes := make([]byte, bodyLength)
  240. if _, err = r.ReadAt(bytes, offset); err != nil {
  241. return
  242. }
  243. n.readNeedleDataVersion2(bytes[0:n.Size])
  244. n.Checksum = NewCRC(n.Data)
  245. default:
  246. err = fmt.Errorf("Unsupported Version! (%d)", version)
  247. }
  248. return
  249. }
  250. func (n *Needle) IsGzipped() bool {
  251. return n.Flags&FlagGzip > 0
  252. }
  253. func (n *Needle) SetGzipped() {
  254. n.Flags = n.Flags | FlagGzip
  255. }
  256. func (n *Needle) HasName() bool {
  257. return n.Flags&FlagHasName > 0
  258. }
  259. func (n *Needle) SetHasName() {
  260. n.Flags = n.Flags | FlagHasName
  261. }
  262. func (n *Needle) HasMime() bool {
  263. return n.Flags&FlagHasMime > 0
  264. }
  265. func (n *Needle) SetHasMime() {
  266. n.Flags = n.Flags | FlagHasMime
  267. }
  268. func (n *Needle) HasLastModifiedDate() bool {
  269. return n.Flags&FlagHasLastModifiedDate > 0
  270. }
  271. func (n *Needle) SetHasLastModifiedDate() {
  272. n.Flags = n.Flags | FlagHasLastModifiedDate
  273. }
  274. func (n *Needle) HasTtl() bool {
  275. return n.Flags&FlagHasTtl > 0
  276. }
  277. func (n *Needle) SetHasTtl() {
  278. n.Flags = n.Flags | FlagHasTtl
  279. }