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.

194 lines
5.2 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"
  11. "github.com/chrislusf/seaweedfs/weed/filer/cassandra_store"
  12. "github.com/chrislusf/seaweedfs/weed/filer/embedded_filer"
  13. "github.com/chrislusf/seaweedfs/weed/filer/flat_namespace"
  14. "github.com/chrislusf/seaweedfs/weed/filer/mysql_store"
  15. "github.com/chrislusf/seaweedfs/weed/filer/redis_store"
  16. "github.com/chrislusf/seaweedfs/weed/glog"
  17. "github.com/chrislusf/seaweedfs/weed/security"
  18. "github.com/chrislusf/seaweedfs/weed/storage"
  19. "github.com/chrislusf/seaweedfs/weed/util"
  20. )
  21. type filerConf struct {
  22. MysqlConf []mysql_store.MySqlConf `json:"mysql"`
  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 filer.Filer
  47. maxMB int
  48. masterNodes *storage.MasterNodes
  49. }
  50. func NewFilerServer(r *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)
  78. fs.filer = flat_namespace.NewFlatNamespaceFiler(master, mysql_store)
  79. } else if cassandra_server != "" {
  80. cassandra_store, err := cassandra_store.NewCassandraStore(cassandra_keyspace, cassandra_server)
  81. if err != nil {
  82. glog.Fatalf("Can not connect to cassandra server %s with keyspace %s: %v", cassandra_server, cassandra_keyspace, err)
  83. }
  84. fs.filer = flat_namespace.NewFlatNamespaceFiler(master, cassandra_store)
  85. } else if redis_server != "" {
  86. redis_store := redis_store.NewRedisStore(redis_server, redis_password, redis_database)
  87. fs.filer = flat_namespace.NewFlatNamespaceFiler(master, redis_store)
  88. } else {
  89. if fs.filer, err = embedded_filer.NewFilerEmbedded(master, dir); err != nil {
  90. glog.Fatalf("Can not start filer in dir %s : %v", dir, err)
  91. return
  92. }
  93. r.HandleFunc("/admin/mv", fs.moveHandler)
  94. r.HandleFunc("/admin/register", fs.registerHandler)
  95. }
  96. r.HandleFunc("/", fs.filerHandler)
  97. go func() {
  98. connected := true
  99. fs.masterNodes = storage.NewMasterNodes(fs.master)
  100. glog.V(0).Infof("Filer server bootstraps with master %s", fs.getMasterNode())
  101. //force initialize with all available master nodes
  102. for {
  103. _, err := fs.masterNodes.FindMaster()
  104. if err != nil {
  105. glog.Infof("filer server failed to get master cluster info:%s", err.Error())
  106. time.Sleep(3 * time.Second)
  107. } else {
  108. break
  109. }
  110. }
  111. for {
  112. glog.V(4).Infof("Filer server sending to master %s", fs.getMasterNode())
  113. master, err := fs.detectHealthyMaster(fs.getMasterNode())
  114. if err == nil {
  115. if !connected {
  116. connected = true
  117. if fs.getMasterNode() != master {
  118. fs.setMasterNode(master)
  119. }
  120. glog.V(0).Infoln("Filer Server Connected with master at", master)
  121. }
  122. } else {
  123. glog.V(1).Infof("Filer Server Failed to talk with master %s: %v", fs.getMasterNode(), err)
  124. if connected {
  125. connected = false
  126. }
  127. }
  128. if connected {
  129. time.Sleep(time.Duration(float32(10*1e3)*(1+rand.Float32())) * time.Millisecond)
  130. } else {
  131. time.Sleep(time.Duration(float32(10*1e3)*0.25) * time.Millisecond)
  132. }
  133. }
  134. }()
  135. return fs, nil
  136. }
  137. func (fs *FilerServer) jwt(fileId string) security.EncodedJwt {
  138. return security.GenJwt(fs.secret, fileId)
  139. }
  140. func (fs *FilerServer) getMasterNode() string {
  141. fs.mnLock.RLock()
  142. defer fs.mnLock.RUnlock()
  143. return fs.master
  144. }
  145. func (fs *FilerServer) setMasterNode(masterNode string) {
  146. fs.mnLock.Lock()
  147. defer fs.mnLock.Unlock()
  148. fs.master = masterNode
  149. }
  150. func (fs *FilerServer) detectHealthyMaster(masterNode string) (master string, e error) {
  151. if e = checkMaster(masterNode); e != nil {
  152. fs.masterNodes.Reset()
  153. for i := 0; i <= 3; i++ {
  154. master, e = fs.masterNodes.FindMaster()
  155. if e != nil {
  156. continue
  157. } else {
  158. if e = checkMaster(master); e == nil {
  159. break
  160. }
  161. }
  162. }
  163. } else {
  164. master = masterNode
  165. }
  166. return
  167. }
  168. func checkMaster(masterNode string) error {
  169. statUrl := "http://" + masterNode + "/stats"
  170. glog.V(4).Infof("Connecting to %s ...", statUrl)
  171. _, e := util.Get(statUrl)
  172. return e
  173. }