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.

264 lines
7.5 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. if n.HasName() {
  88. util.Uint8toBytes(header[0:1], n.NameSize)
  89. if _, err = w.Write(header[0:1]); err != nil {
  90. return
  91. }
  92. if _, err = w.Write(n.Name); err != nil {
  93. return
  94. }
  95. }
  96. if n.HasMime() {
  97. util.Uint8toBytes(header[0:1], n.MimeSize)
  98. if _, err = w.Write(header[0:1]); err != nil {
  99. return
  100. }
  101. if _, err = w.Write(n.Mime); err != nil {
  102. return
  103. }
  104. }
  105. if n.HasLastModifiedDate() {
  106. util.Uint64toBytes(header[0:8], n.LastModified)
  107. if _, err = w.Write(header[8-LastModifiedBytesLength : 8]); err != nil {
  108. return
  109. }
  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. newChecksum := NewCRC(n.Data)
  130. if checksum != newChecksum.Value() {
  131. return 0, errors.New("CRC error! Data On Disk Corrupted!")
  132. }
  133. n.Checksum = newChecksum
  134. return
  135. case Version2:
  136. if size == 0 {
  137. return 0, nil
  138. }
  139. bytes := make([]byte, NeedleHeaderSize+size+NeedleChecksumSize)
  140. if ret, err = r.Read(bytes); err != nil {
  141. return
  142. }
  143. if ret != int(NeedleHeaderSize+size+NeedleChecksumSize) {
  144. return 0, errors.New("File Entry Not Found!")
  145. }
  146. n.readNeedleHeader(bytes)
  147. if n.Size != size {
  148. return 0, fmt.Errorf("File Entry Not Found! Needle %d Memory %d", n.Size, size)
  149. }
  150. n.readNeedleDataVersion2(bytes[NeedleHeaderSize : NeedleHeaderSize+int(n.Size)])
  151. checksum := util.BytesToUint32(bytes[NeedleHeaderSize+n.Size : NeedleHeaderSize+n.Size+NeedleChecksumSize])
  152. newChecksum := NewCRC(n.Data)
  153. if checksum != newChecksum.Value() {
  154. return 0, errors.New("CRC error! Data On Disk Corrupted!")
  155. }
  156. n.Checksum = newChecksum
  157. return
  158. }
  159. return 0, fmt.Errorf("Unsupported Version! (%d)", version)
  160. }
  161. func (n *Needle) readNeedleHeader(bytes []byte) {
  162. n.Cookie = util.BytesToUint32(bytes[0:4])
  163. n.Id = util.BytesToUint64(bytes[4:12])
  164. n.Size = util.BytesToUint32(bytes[12:NeedleHeaderSize])
  165. }
  166. func (n *Needle) readNeedleDataVersion2(bytes []byte) {
  167. index, lenBytes := 0, len(bytes)
  168. if index < lenBytes {
  169. n.DataSize = util.BytesToUint32(bytes[index : index+4])
  170. index = index + 4
  171. n.Data = bytes[index : index+int(n.DataSize)]
  172. index = index + int(n.DataSize)
  173. n.Flags = bytes[index]
  174. index = index + 1
  175. }
  176. if index < lenBytes && n.HasName() {
  177. n.NameSize = uint8(bytes[index])
  178. index = index + 1
  179. n.Name = bytes[index : index+int(n.NameSize)]
  180. index = index + int(n.NameSize)
  181. }
  182. if index < lenBytes && n.HasMime() {
  183. n.MimeSize = uint8(bytes[index])
  184. index = index + 1
  185. n.Mime = bytes[index : index+int(n.MimeSize)]
  186. index = index + int(n.MimeSize)
  187. }
  188. if index < lenBytes && n.HasLastModifiedDate() {
  189. n.LastModified = util.BytesToUint64(bytes[index : index+LastModifiedBytesLength])
  190. index = index + LastModifiedBytesLength
  191. }
  192. }
  193. func ReadNeedleHeader(r *os.File, version Version) (n *Needle, bodyLength uint32, err error) {
  194. n = new(Needle)
  195. if version == Version1 || version == Version2 {
  196. bytes := make([]byte, NeedleHeaderSize)
  197. var count int
  198. count, err = r.Read(bytes)
  199. if count <= 0 || err != nil {
  200. return nil, 0, err
  201. }
  202. n.readNeedleHeader(bytes)
  203. padding := NeedlePaddingSize - ((n.Size + NeedleHeaderSize + NeedleChecksumSize) % NeedlePaddingSize)
  204. bodyLength = n.Size + NeedleChecksumSize + padding
  205. }
  206. return
  207. }
  208. //n should be a needle already read the header
  209. //the input stream will read until next file entry
  210. func (n *Needle) ReadNeedleBody(r *os.File, version Version, bodyLength uint32) (err error) {
  211. if bodyLength <= 0 {
  212. return nil
  213. }
  214. switch version {
  215. case Version1:
  216. bytes := make([]byte, bodyLength)
  217. if _, err = r.Read(bytes); err != nil {
  218. return
  219. }
  220. n.Data = bytes[:n.Size]
  221. n.Checksum = NewCRC(n.Data)
  222. case Version2:
  223. bytes := make([]byte, bodyLength)
  224. if _, err = r.Read(bytes); err != nil {
  225. return
  226. }
  227. n.readNeedleDataVersion2(bytes[0:n.Size])
  228. n.Checksum = NewCRC(n.Data)
  229. default:
  230. err = fmt.Errorf("Unsupported Version! (%d)", version)
  231. }
  232. return
  233. }
  234. func (n *Needle) IsGzipped() bool {
  235. return n.Flags&FlagGzip > 0
  236. }
  237. func (n *Needle) SetGzipped() {
  238. n.Flags = n.Flags | FlagGzip
  239. }
  240. func (n *Needle) HasName() bool {
  241. return n.Flags&FlagHasName > 0
  242. }
  243. func (n *Needle) SetHasName() {
  244. n.Flags = n.Flags | FlagHasName
  245. }
  246. func (n *Needle) HasMime() bool {
  247. return n.Flags&FlagHasMime > 0
  248. }
  249. func (n *Needle) SetHasMime() {
  250. n.Flags = n.Flags | FlagHasMime
  251. }
  252. func (n *Needle) HasLastModifiedDate() bool {
  253. return n.Flags&FlagHasLastModifiedDate > 0
  254. }
  255. func (n *Needle) SetHasLastModifiedDate() {
  256. n.Flags = n.Flags | FlagHasLastModifiedDate
  257. }