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.

132 lines
3.4 KiB

11 years ago
10 years ago
10 years ago
10 years ago
  1. package weed_server
  2. import (
  3. "math/rand"
  4. "net/http"
  5. "strconv"
  6. "sync"
  7. "time"
  8. "github.com/chrislusf/seaweedfs/weed/glog"
  9. "github.com/chrislusf/seaweedfs/weed/security"
  10. "github.com/chrislusf/seaweedfs/weed/storage"
  11. "github.com/chrislusf/seaweedfs/weed/util"
  12. "github.com/chrislusf/seaweedfs/weed/filer2"
  13. _ "github.com/chrislusf/seaweedfs/weed/filer2/leveldb"
  14. _ "github.com/chrislusf/seaweedfs/weed/filer2/memdb"
  15. _ "github.com/chrislusf/seaweedfs/weed/filer2/mysql"
  16. )
  17. type FilerServer struct {
  18. port string
  19. master string
  20. mnLock sync.RWMutex
  21. collection string
  22. defaultReplication string
  23. redirectOnRead bool
  24. disableDirListing bool
  25. secret security.Secret
  26. filer *filer2.Filer
  27. maxMB int
  28. masterNodes *storage.MasterNodes
  29. }
  30. func NewFilerServer(defaultMux, readonlyMux *http.ServeMux, ip string, port int, master string, collection string,
  31. replication string, redirectOnRead bool, disableDirListing bool,
  32. maxMB int,
  33. secret string,
  34. ) (fs *FilerServer, err error) {
  35. fs = &FilerServer{
  36. master: master,
  37. collection: collection,
  38. defaultReplication: replication,
  39. redirectOnRead: redirectOnRead,
  40. disableDirListing: disableDirListing,
  41. maxMB: maxMB,
  42. port: ip + ":" + strconv.Itoa(port),
  43. }
  44. fs.filer = filer2.NewFiler(master)
  45. fs.filer.LoadConfiguration()
  46. defaultMux.HandleFunc("/admin/register", fs.registerHandler)
  47. defaultMux.HandleFunc("/", fs.filerHandler)
  48. if defaultMux != readonlyMux {
  49. readonlyMux.HandleFunc("/", fs.readonlyFilerHandler)
  50. }
  51. go func() {
  52. connected := true
  53. fs.masterNodes = storage.NewMasterNodes(fs.master)
  54. glog.V(0).Infof("Filer server bootstraps with master %s", fs.getMasterNode())
  55. for {
  56. glog.V(4).Infof("Filer server sending to master %s", fs.getMasterNode())
  57. master, err := fs.detectHealthyMaster(fs.getMasterNode())
  58. if err == nil {
  59. if !connected {
  60. connected = true
  61. if fs.getMasterNode() != master {
  62. fs.setMasterNode(master)
  63. }
  64. glog.V(0).Infoln("Filer Server Connected with master at", master)
  65. }
  66. } else {
  67. glog.V(1).Infof("Filer Server Failed to talk with master %s: %v", fs.getMasterNode(), err)
  68. if connected {
  69. connected = false
  70. }
  71. }
  72. if connected {
  73. time.Sleep(time.Duration(float32(10*1e3)*(1+rand.Float32())) * time.Millisecond)
  74. } else {
  75. time.Sleep(time.Duration(float32(10*1e3)*0.25) * time.Millisecond)
  76. }
  77. }
  78. }()
  79. return fs, nil
  80. }
  81. func (fs *FilerServer) jwt(fileId string) security.EncodedJwt {
  82. return security.GenJwt(fs.secret, fileId)
  83. }
  84. func (fs *FilerServer) getMasterNode() string {
  85. fs.mnLock.RLock()
  86. defer fs.mnLock.RUnlock()
  87. return fs.master
  88. }
  89. func (fs *FilerServer) setMasterNode(masterNode string) {
  90. fs.mnLock.Lock()
  91. defer fs.mnLock.Unlock()
  92. fs.master = masterNode
  93. }
  94. func (fs *FilerServer) detectHealthyMaster(masterNode string) (master string, e error) {
  95. if e = checkMaster(masterNode); e != nil {
  96. fs.masterNodes.Reset()
  97. for i := 0; i <= 3; i++ {
  98. master, e = fs.masterNodes.FindMaster()
  99. if e != nil {
  100. continue
  101. } else {
  102. if e = checkMaster(master); e == nil {
  103. break
  104. }
  105. }
  106. }
  107. } else {
  108. master = masterNode
  109. }
  110. return
  111. }
  112. func checkMaster(masterNode string) error {
  113. statUrl := "http://" + masterNode + "/stats/health"
  114. glog.V(4).Infof("Connecting to %s ...", statUrl)
  115. _, e := util.Get(statUrl)
  116. return e
  117. }