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.

260 lines
7.4 KiB

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