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.

89 lines
2.2 KiB

  1. package sequence
  2. import (
  3. "bytes"
  4. "code.google.com/p/weed-fs/go/glog"
  5. "code.google.com/p/weed-fs/go/metastore"
  6. "encoding/gob"
  7. "sync"
  8. )
  9. const (
  10. FileIdSaveInterval = 10000
  11. )
  12. type Sequencer interface {
  13. NextFileId(count int) (uint64, int)
  14. }
  15. type SequencerImpl struct {
  16. fileFullPath string
  17. volumeLock sync.Mutex
  18. sequenceLock sync.Mutex
  19. FileIdSequence uint64
  20. fileIdCounter uint64
  21. metaStore *metastore.MetaStore
  22. }
  23. func NewFileSequencer(filepath string) (m *SequencerImpl) {
  24. m = &SequencerImpl{fileFullPath: filepath}
  25. m.metaStore = &metastore.MetaStore{metastore.NewMetaStoreFileBacking()}
  26. m.initilize()
  27. return
  28. }
  29. func (m *SequencerImpl) initilize() {
  30. if !m.metaStore.Has(m.fileFullPath) {
  31. m.FileIdSequence = FileIdSaveInterval
  32. glog.V(0).Infoln("Setting file id sequence", m.FileIdSequence)
  33. } else {
  34. var err error
  35. if m.FileIdSequence, err = m.metaStore.GetUint64(m.fileFullPath); err != nil {
  36. if data, err := m.metaStore.Get(m.fileFullPath); err == nil {
  37. m.FileIdSequence = decode(data)
  38. glog.V(0).Infoln("Decoding old version of FileIdSequence", m.FileIdSequence)
  39. } else {
  40. glog.V(0).Infof("No existing FileIdSequence: %s", err)
  41. }
  42. } else {
  43. glog.V(0).Infoln("Loading file id sequence", m.FileIdSequence)
  44. }
  45. //in case the server stops between intervals
  46. }
  47. return
  48. }
  49. //count should be 1 or more
  50. func (m *SequencerImpl) NextFileId(count int) (uint64, int) {
  51. if count <= 0 {
  52. return 0, 0
  53. }
  54. m.sequenceLock.Lock()
  55. defer m.sequenceLock.Unlock()
  56. if m.fileIdCounter < uint64(count) {
  57. m.fileIdCounter = FileIdSaveInterval
  58. m.FileIdSequence += FileIdSaveInterval
  59. m.saveSequence()
  60. }
  61. m.fileIdCounter = m.fileIdCounter - uint64(count)
  62. return m.FileIdSequence - m.fileIdCounter - uint64(count), count
  63. }
  64. func (m *SequencerImpl) saveSequence() {
  65. glog.V(0).Infoln("Saving file id sequence", m.FileIdSequence, "to", m.fileFullPath)
  66. if e := m.metaStore.SetUint64(m.fileFullPath, m.FileIdSequence); e != nil {
  67. glog.Fatalf("Sequence id Save [ERROR] %s", e)
  68. }
  69. }
  70. //decode are for backward compatible purpose
  71. func decode(input string) uint64 {
  72. var x uint64
  73. b := bytes.NewReader([]byte(input))
  74. decoder := gob.NewDecoder(b)
  75. if e := decoder.Decode(&x); e == nil {
  76. return x
  77. }
  78. return 0
  79. }