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.

191 lines
5.3 KiB

11 years ago
10 years ago
10 years ago
10 years ago
  1. package weed_server
  2. import (
  3. "encoding/json"
  4. "math/rand"
  5. "net/http"
  6. "os"
  7. "strconv"
  8. "sync"
  9. "time"
  10. "github.com/chrislusf/seaweedfs/weed/filer/mysql_store"
  11. "github.com/chrislusf/seaweedfs/weed/filer/postgres_store"
  12. "github.com/chrislusf/seaweedfs/weed/glog"
  13. "github.com/chrislusf/seaweedfs/weed/security"
  14. "github.com/chrislusf/seaweedfs/weed/storage"
  15. "github.com/chrislusf/seaweedfs/weed/util"
  16. "github.com/chrislusf/seaweedfs/weed/filer2"
  17. "github.com/chrislusf/seaweedfs/weed/filer2/memdb"
  18. )
  19. type filerConf struct {
  20. MysqlConf []mysql_store.MySqlConf `json:"mysql"`
  21. mysql_store.ShardingConf
  22. PostgresConf *postgres_store.PostgresConf `json:"postgres"`
  23. }
  24. func parseConfFile(confPath string) (*filerConf, error) {
  25. var setting filerConf
  26. configFile, err := os.Open(confPath)
  27. defer configFile.Close()
  28. if err != nil {
  29. return nil, err
  30. }
  31. jsonParser := json.NewDecoder(configFile)
  32. if err = jsonParser.Decode(&setting); err != nil {
  33. return nil, err
  34. }
  35. return &setting, nil
  36. }
  37. type FilerServer struct {
  38. port string
  39. master string
  40. mnLock sync.RWMutex
  41. collection string
  42. defaultReplication string
  43. redirectOnRead bool
  44. disableDirListing bool
  45. secret security.Secret
  46. filer *filer2.Filer
  47. maxMB int
  48. masterNodes *storage.MasterNodes
  49. }
  50. func NewFilerServer(defaultMux, readonlyMux *http.ServeMux, ip string, port int, master string, dir string, collection string,
  51. replication string, redirectOnRead bool, disableDirListing bool,
  52. confFile string,
  53. maxMB int,
  54. secret string,
  55. cassandra_server string, cassandra_keyspace string,
  56. redis_server string, redis_password string, redis_database int,
  57. ) (fs *FilerServer, err error) {
  58. fs = &FilerServer{
  59. master: master,
  60. collection: collection,
  61. defaultReplication: replication,
  62. redirectOnRead: redirectOnRead,
  63. disableDirListing: disableDirListing,
  64. maxMB: maxMB,
  65. port: ip + ":" + strconv.Itoa(port),
  66. }
  67. var setting *filerConf
  68. if confFile != "" {
  69. setting, err = parseConfFile(confFile)
  70. if err != nil {
  71. return nil, err
  72. }
  73. } else {
  74. setting = new(filerConf)
  75. }
  76. if setting.MysqlConf != nil && len(setting.MysqlConf) != 0 {
  77. // mysql_store := mysql_store.NewMysqlStore(setting.MysqlConf, setting.IsSharding, setting.ShardCount)
  78. // fs.filer = flat_namespace.NewFlatNamespaceFiler(master, mysql_store)
  79. } else if setting.PostgresConf != nil {
  80. // fs.filer = postgres_store.NewPostgresStore(master, *setting.PostgresConf)
  81. } else if cassandra_server != "" {
  82. // cassandra_store, err := cassandra_store.NewCassandraStore(cassandra_keyspace, cassandra_server)
  83. // if err != nil {
  84. // glog.Fatalf("Can not connect to cassandra server %s with keyspace %s: %v", cassandra_server, cassandra_keyspace, err)
  85. // }
  86. // fs.filer = flat_namespace.NewFlatNamespaceFiler(master, cassandra_store)
  87. } else if redis_server != "" {
  88. // redis_store := redis_store.NewRedisStore(redis_server, redis_password, redis_database)
  89. // fs.filer = flat_namespace.NewFlatNamespaceFiler(master, redis_store)
  90. } else {
  91. /*
  92. if fs.filer, err = embedded_filer.NewFilerEmbedded(master, dir); err != nil {
  93. glog.Fatalf("Can not start filer in dir %s : %v", dir, err)
  94. return
  95. }
  96. */
  97. }
  98. fs.filer = filer2.NewFiler(master)
  99. fs.filer.SetStore(memdb.NewMemDbStore())
  100. defaultMux.HandleFunc("/admin/register", fs.registerHandler)
  101. defaultMux.HandleFunc("/", fs.filerHandler)
  102. if defaultMux != readonlyMux {
  103. readonlyMux.HandleFunc("/", fs.readonlyFilerHandler)
  104. }
  105. go func() {
  106. connected := true
  107. fs.masterNodes = storage.NewMasterNodes(fs.master)
  108. glog.V(0).Infof("Filer server bootstraps with master %s", fs.getMasterNode())
  109. for {
  110. glog.V(4).Infof("Filer server sending to master %s", fs.getMasterNode())
  111. master, err := fs.detectHealthyMaster(fs.getMasterNode())
  112. if err == nil {
  113. if !connected {
  114. connected = true
  115. if fs.getMasterNode() != master {
  116. fs.setMasterNode(master)
  117. }
  118. glog.V(0).Infoln("Filer Server Connected with master at", master)
  119. }
  120. } else {
  121. glog.V(1).Infof("Filer Server Failed to talk with master %s: %v", fs.getMasterNode(), err)
  122. if connected {
  123. connected = false
  124. }
  125. }
  126. if connected {
  127. time.Sleep(time.Duration(float32(10*1e3)*(1+rand.Float32())) * time.Millisecond)
  128. } else {
  129. time.Sleep(time.Duration(float32(10*1e3)*0.25) * time.Millisecond)
  130. }
  131. }
  132. }()
  133. return fs, nil
  134. }
  135. func (fs *FilerServer) jwt(fileId string) security.EncodedJwt {
  136. return security.GenJwt(fs.secret, fileId)
  137. }
  138. func (fs *FilerServer) getMasterNode() string {
  139. fs.mnLock.RLock()
  140. defer fs.mnLock.RUnlock()
  141. return fs.master
  142. }
  143. func (fs *FilerServer) setMasterNode(masterNode string) {
  144. fs.mnLock.Lock()
  145. defer fs.mnLock.Unlock()
  146. fs.master = masterNode
  147. }
  148. func (fs *FilerServer) detectHealthyMaster(masterNode string) (master string, e error) {
  149. if e = checkMaster(masterNode); e != nil {
  150. fs.masterNodes.Reset()
  151. for i := 0; i <= 3; i++ {
  152. master, e = fs.masterNodes.FindMaster()
  153. if e != nil {
  154. continue
  155. } else {
  156. if e = checkMaster(master); e == nil {
  157. break
  158. }
  159. }
  160. }
  161. } else {
  162. master = masterNode
  163. }
  164. return
  165. }
  166. func checkMaster(masterNode string) error {
  167. statUrl := "http://" + masterNode + "/stats/health"
  168. glog.V(4).Infof("Connecting to %s ...", statUrl)
  169. _, e := util.Get(statUrl)
  170. return e
  171. }