예제 #1
0
파일: main.go 프로젝트: slowfranklin/rqlite
func main() {
	flag.Parse()

	// Set up profiling, if requested.
	if cpuprofile != "" {
		log.Info("Profiling enabled")
		f, err := os.Create(cpuprofile)
		if err != nil {
			log.Errorf("Unable to create path: %s", err.Error())
		}
		defer closeFile(f)

		err = pprof.StartCPUProfile(f)
		if err != nil {
			log.Errorf("Unable to start CPU Profile: %s", err.Error())
		}

		defer pprof.StopCPUProfile()
	}

	// Set logging
	log.SetLevel(logLevel)
	if logFile != "stdout" {
		f := createFile(logFile)
		defer closeFile(f)

		log.Infof("Redirecting logging to %s", logFile)
		log.SetOutput(f)
	}

	// Set the data directory.
	if flag.NArg() == 0 {
		flag.Usage()
		println("Data path argument required")
		log.Error("No data path supplied -- aborting")
		os.Exit(1)
	}

	dataPath := flag.Arg(0)
	createDir(dataPath)

	s := server.NewServer(dataPath, dbfile, snapAfter, host, port)
	go func() {
		log.Error(s.ListenAndServe(join).Error())
	}()

	if !disableReporting {
		reportLaunch()
	}

	terminate := make(chan os.Signal, 1)
	signal.Notify(terminate, os.Interrupt)
	<-terminate
	log.Info("rqlite server stopped")
}
예제 #2
0
파일: db.go 프로젝트: slowfranklin/rqlite
// Open an existing database, creating it if it does not exist.
func Open(dbPath string) *DB {
	log.Tracef("Opening SQLite database path at %s", dbPath)
	dbc, err := sql.Open("sqlite3", dbPath)
	if err != nil {
		log.Error(err.Error())
		return nil
	}
	return &DB{
		dbConn: dbc,
	}
}
예제 #3
0
// serveStatistics returns the statistics for the program
func (s *Server) serveStatistics(w http.ResponseWriter, req *http.Request) {
	statistics := make(map[string]interface{})
	resources := map[string]interfaces.Statistics{"server": s}
	for k, v := range resources {
		s, err := v.GetStatistics()
		if err != nil {
			log.Error("failed to get " + k + " stats")
			http.Error(w, "failed to get "+k+" stats", http.StatusInternalServerError)
			return
		}
		statistics[k] = s
	}

	_, err := w.Write(ensurePrettyPrint(req, statistics))
	if err != nil {
		log.Error("failed to serve stats")
		http.Error(w, "failed to serve stats", http.StatusInternalServerError)
		return
	}
}
예제 #4
0
// serveRaftInfo returns information about the underlying Raft server
func (s *Server) serveRaftInfo(w http.ResponseWriter, req *http.Request) {
	var peers []interface{}
	for _, v := range s.raftServer.Peers() {
		peers = append(peers, v)
	}

	info := make(map[string]interface{})
	info["name"] = s.raftServer.Name()
	info["state"] = s.raftServer.State()
	info["leader"] = s.raftServer.Leader()
	info["peers"] = peers

	_, err := w.Write(ensurePrettyPrint(req, info))
	if err != nil {
		log.Error("failed to serve raft info")
		http.Error(w, "failed to serve raft info", http.StatusInternalServerError)
		return
	}
}
예제 #5
0
// serveDiagnostics returns basic server diagnostics
func (s *Server) serveDiagnostics(w http.ResponseWriter, req *http.Request) {
	diagnostics := make(map[string]interface{})
	diagnostics["started"] = s.diagnostics.startTime.String()
	diagnostics["uptime"] = time.Since(s.diagnostics.startTime).String()
	diagnostics["host"] = s.host
	diagnostics["port"] = s.port
	diagnostics["data"] = s.path
	diagnostics["database"] = s.dbPath
	diagnostics["connection"] = s.connectionString()
	diagnostics["snapafter"] = s.snapConf.snapshotAfter
	diagnostics["snapindex"] = s.snapConf.lastIndex

	_, err := w.Write(ensurePrettyPrint(req, diagnostics))
	if err != nil {
		log.Error("failed to serve diagnostics")
		http.Error(w, "failed to serve diagnostics", http.StatusInternalServerError)
		return
	}
}
예제 #6
0
// leaderRedirect returns a 307 Temporary Redirect, with the full path
// to the leader.
func (s *Server) leaderRedirect(w http.ResponseWriter, r *http.Request) {
	peers := s.raftServer.Peers()
	leader := peers[s.raftServer.Leader()]

	if leader == nil {
		// No leader available, give up.
		log.Error("attempted leader redirection, but no leader available")
		w.WriteHeader(http.StatusServiceUnavailable)
		w.Write([]byte("no leader available"))
		return
	}

	var u string
	for _, p := range peers {
		if p.Name == leader.Name {
			u = p.ConnectionString
			break
		}
	}
	http.Redirect(w, r, u+r.URL.Path, http.StatusTemporaryRedirect)
}
예제 #7
0
// ListenAndServe starts the server.
func (s *Server) ListenAndServe(leader string) error {
	var err error

	log.Infof("Initializing Raft Server: %s", s.path)

	// Initialize and start Raft server.
	transporter := raft.NewHTTPTransporter("/raft", 200*time.Millisecond)
	stateMachine := NewDbStateMachine(s.dbPath)
	s.raftServer, err = raft.NewServer(s.name, s.path, transporter, stateMachine, s.db, "")
	if err != nil {
		log.Errorf("Failed to create new Raft server: %s", err.Error())
		return err
	}

	log.Info("Loading latest snapshot, if any, from disk")
	if err := s.raftServer.LoadSnapshot(); err != nil && os.IsNotExist(err) {
		log.Info("no snapshot found")
	} else if err != nil {
		log.Errorf("Error loading snapshot: %s", err.Error())
	}

	transporter.Install(s.raftServer, s)
	if err := s.raftServer.Start(); err != nil {
		log.Errorf("Error starting raft server: %s", err.Error())
	}

	if leader != "" {
		// Join to leader if specified.

		log.Infof("Attempting to join leader at %s", leader)

		if !s.raftServer.IsLogEmpty() {
			log.Error("Cannot join with an existing log")
			return errors.New("Cannot join with an existing log")
		}
		if err := s.Join(leader); err != nil {
			log.Errorf("Failed to join leader: %s", err.Error())
			return err
		}

	} else if s.raftServer.IsLogEmpty() {
		// Initialize the server by joining itself.

		log.Info("Initializing new cluster")

		_, err := s.raftServer.Do(&raft.DefaultJoinCommand{
			Name:             s.raftServer.Name(),
			ConnectionString: s.connectionString(),
		})
		if err != nil {
			log.Errorf("Failed to join to self: %s", err.Error())
		}

	} else {
		log.Info("Recovered from log")
	}

	log.Info("Initializing HTTP server")

	// Initialize and start HTTP server.
	s.httpServer = &http.Server{
		Addr:    fmt.Sprintf(":%d", s.port),
		Handler: s.router,
	}

	s.router.HandleFunc("/statistics", s.serveStatistics).Methods("GET")
	s.router.HandleFunc("/diagnostics", s.serveDiagnostics).Methods("GET")
	s.router.HandleFunc("/raft", s.serveRaftInfo).Methods("GET")
	s.router.HandleFunc("/db", s.readHandler).Methods("GET")
	s.router.HandleFunc("/db", s.writeHandler).Methods("POST")
	s.router.HandleFunc("/join", s.joinHandler).Methods("POST")

	log.Infof("Listening at %s", s.connectionString())

	return s.httpServer.ListenAndServe()
}