From fe415e64520cdce5a262cb3c49b6c3495bc91fbf Mon Sep 17 00:00:00 2001 From: Philip O'Toole Date: Sat, 28 Mar 2015 11:25:20 -0700 Subject: [PATCH] Revert "Merge pull request #25 from oscillatingworks/deprecate-log4go" This reverts commit f2de6cc26e9bc056f95af68b547f553883a93f4c, reversing changes made to cdc6021ae745471bca6b3e02cc1bbb1c2999abbf. The change causes a panic when the server is started like so: $GOPATH/bin/rqlite ~/node.1 --- command/execute_command.go | 31 ++++--- db/db.go | 49 ++++++----- interfaces/interfaces.go | 1 - log/log.go | 103 ----------------------- log/log_test.go | 131 ------------------------------ main.go | 114 ++++++++++++-------------- server/server.go | 153 ++++++++++++++--------------------- server/single_server_test.go | 10 +-- server/statemachine.go | 17 ++-- 9 files changed, 162 insertions(+), 447 deletions(-) delete mode 100644 log/log.go delete mode 100644 log/log_test.go diff --git a/command/execute_command.go b/command/execute_command.go index b0e09ede..b667fb1c 100644 --- a/command/execute_command.go +++ b/command/execute_command.go @@ -4,10 +4,10 @@ import ( "github.com/goraft/raft" "github.com/otoolep/rqlite/db" - "github.com/otoolep/rqlite/log" + log "code.google.com/p/log4go" ) -// ExecuteCommand encapsulates a sqlite statement. +// This command encapsulates a sqlite statement. type ExecuteCommand struct { Stmt string `json:"stmt"` } @@ -19,19 +19,19 @@ func NewExecuteCommand(stmt string) *ExecuteCommand { } } -// CommandName of the ExecuteCommand in the log. +// The name of the ExecuteCommand in the log. func (c *ExecuteCommand) CommandName() string { return "execute" } // Apply executes an sqlite statement. func (c *ExecuteCommand) Apply(server raft.Server) (interface{}, error) { - log.Tracef("Applying ExecuteCommand: '%s'", c.Stmt) + log.Trace("Applying ExecuteCommand: '%s'", c.Stmt) db := server.Context().(*db.DB) return nil, db.Execute(c.Stmt) } -// TransactionExecuteCommandSet encapsulates a set of sqlite statement, which are executed +// This command encapsulates a set of sqlite statement, which are executed // within a transaction. type TransactionExecuteCommandSet struct { Stmts []string `json:"stmts"` @@ -45,7 +45,7 @@ func NewTransactionExecuteCommandSet(stmts []string) *TransactionExecuteCommandS } } -// CommandName of the TransactionExecute command in the log. +// The name of the TransactionExecute command in the log. func (c *TransactionExecuteCommandSet) CommandName() string { return "transaction_execute" } @@ -53,7 +53,7 @@ func (c *TransactionExecuteCommandSet) CommandName() string { // Apply executes a set of sqlite statements, within a transaction. All statements // will take effect, or none. func (c *TransactionExecuteCommandSet) Apply(server raft.Server) (interface{}, error) { - log.Tracef("Applying TransactionExecuteCommandSet of size %d", len(c.Stmts)) + log.Trace("Applying TransactionExecuteCommandSet of size %d", len(c.Stmts)) commitSuccess := false db := server.Context().(*db.DB) @@ -61,30 +61,29 @@ func (c *TransactionExecuteCommandSet) Apply(server raft.Server) (interface{}, e if !commitSuccess { err := db.RollbackTransaction() if err != nil { - log.Errorf("Failed to rollback transaction: %s", err.Error()) + log.Error("Failed to rollback transaction: %s", err.Error) } } }() err := db.StartTransaction() if err != nil { - log.Errorf("Failed to start transaction: %s", err.Error()) + log.Error("Failed to start transaction:", err.Error()) return nil, err } - for i := range c.Stmts { err = db.Execute(c.Stmts[i]) if err != nil { - log.Errorf("Failed to execute statement within transaction: %s", err.Error()) + log.Error("Failed to execute statement within transaction", err.Error()) return nil, err } } - - if err = db.CommitTransaction(); err != nil { - log.Errorf("Failed to commit transaction: %s", err.Error()) + err = db.CommitTransaction() + if err != nil { + log.Error("Failed to commit transaction:", err.Error()) return nil, err + } else { + commitSuccess = true } - - commitSuccess = true return nil, nil } diff --git a/db/db.go b/db/db.go index d33e49f0..49019668 100644 --- a/db/db.go +++ b/db/db.go @@ -6,34 +6,37 @@ import ( "os" "strings" - _ "github.com/mattn/go-sqlite3" // required blank import - "github.com/otoolep/rqlite/log" + _ "github.com/mattn/go-sqlite3" + + log "code.google.com/p/log4go" +) + +const ( + dbName = "db.sqlite" ) -// DB is the SQL database. +// The SQL database. type DB struct { dbConn *sql.DB } -// RowResult is the result type. +// Query result types type RowResult map[string]string - -// RowResults is the list of results. type RowResults []map[string]string // New creates a new database. Deletes any existing database. func New(dbPath string) *DB { - log.Tracef("Removing any existing SQLite database at %s", dbPath) - _ = os.Remove(dbPath) + log.Trace("Removing any existing SQLite database at %s", dbPath) + os.Remove(dbPath) return Open(dbPath) } // 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) + log.Trace("Opening SQLite database path at %s", dbPath) dbc, err := sql.Open("sqlite3", dbPath) if err != nil { - log.Error(err.Error()) + log.Error(err) return nil } return &DB{ @@ -50,33 +53,28 @@ func (db *DB) Close() error { // RowResults. func (db *DB) Query(query string) (RowResults, error) { if !strings.HasPrefix(strings.ToUpper(query), "SELECT ") { - log.Warnf("Query \"%s\" may modify the database", query) + log.Warn("Query \"%s\" may modify the database", query) } rows, err := db.dbConn.Query(query) if err != nil { - log.Errorf("failed to execute SQLite query: %s", err.Error()) + log.Error("failed to execute SQLite query", err.Error()) return nil, err } - defer func() { - err = rows.Close() - if err != nil { - log.Errorf("failed to close rows: %s", err.Error()) - } - }() + defer rows.Close() results := make(RowResults, 0) columns, _ := rows.Columns() rawResult := make([][]byte, len(columns)) dest := make([]interface{}, len(columns)) - for i := range rawResult { + for i, _ := range rawResult { dest[i] = &rawResult[i] // Pointers to each string in the interface slice } for rows.Next() { err = rows.Scan(dest...) if err != nil { - log.Errorf("failed to scan SQLite row: %s", err.Error()) + log.Error("failed to scan SQLite row", err.Error()) return nil, err } @@ -90,7 +88,7 @@ func (db *DB) Query(query string) (RowResults, error) { } results = append(results, r) } - log.Debugf("Executed query successfully: %s", query) + log.Debug(func() string { return "Executed query successfully: " + query }) return results, nil } @@ -102,8 +100,7 @@ func (db *DB) Execute(stmt string) error { return fmt.Sprintf("Error executing \"%s\", error: %s", stmt, err.Error()) } return fmt.Sprintf("Successfully executed \"%s\"", stmt) - }()) - + }) return err } @@ -115,7 +112,7 @@ func (db *DB) StartTransaction() error { return "Error starting transaction" } return "Successfully started transaction" - }()) + }) return err } @@ -127,7 +124,7 @@ func (db *DB) CommitTransaction() error { return "Error ending transaction" } return "Successfully ended transaction" - }()) + }) return err } @@ -140,6 +137,6 @@ func (db *DB) RollbackTransaction() error { return "Error rolling back transaction" } return "Successfully rolled back transaction" - }()) + }) return err } diff --git a/interfaces/interfaces.go b/interfaces/interfaces.go index 6b85b993..4638002a 100644 --- a/interfaces/interfaces.go +++ b/interfaces/interfaces.go @@ -2,7 +2,6 @@ package interfaces import "github.com/rcrowley/go-metrics" -// Statistics is an interface for metrics statistics type Statistics interface { GetStatistics() (metrics.Registry, error) } diff --git a/log/log.go b/log/log.go deleted file mode 100644 index 2067ee37..00000000 --- a/log/log.go +++ /dev/null @@ -1,103 +0,0 @@ -package log - -import ( - "io" - "log" -) - -// Log levels -const ( - TRACE = iota // 0 - DEBUG = iota // 1 - INFO = iota // 2 - WARN = iota // 3 - ERROR = iota // 4 -) - -// Level set for logs -var Level = TRACE - -// SetLevel sets the log level -// given a string -func SetLevel(level string) { - switch level { - case "TRACE": - Level = TRACE - case "DEBUG": - Level = DEBUG - case "INFO": - Level = INFO - case "WARN": - Level = WARN - case "ERROR": - Level = ERROR - default: - Level = TRACE - } -} - -// SetOutput set the output destination -// of logs -func SetOutput(w io.Writer) { - log.SetOutput(w) -} - -// Tracef writes a formatted log on TRACE level -func Tracef(format string, v ...interface{}) { - if Level <= TRACE { - log.Printf("[TRACE] "+format, v...) - } -} - -// Trace writes a log on TRACE level -func Trace(s string) { - Tracef(s) -} - -// Debugf writes a formatted log on DEBUG level -func Debugf(format string, v ...interface{}) { - if Level <= DEBUG { - log.Printf("[DEBUG] "+format, v...) - } -} - -// Debug writes a log on DEBUG level -func Debug(s string) { - Debugf(s) -} - -// Infof writes a formatted log on INFO level -func Infof(format string, v ...interface{}) { - if Level <= INFO { - log.Printf("[INFO ] "+format, v...) - } -} - -// Info write a log on INFO level -func Info(s string) { - Infof(s) -} - -// Warnf writes a formatted log on WARN level -func Warnf(format string, v ...interface{}) { - if Level <= WARN { - log.Printf("[WARN ] "+format, v...) - } -} - -// Warn write a log on WARN level -func Warn(s string) { - Warnf(s) -} - -// Errorf writes a formatted log on ERROR level -func Errorf(format string, v ...interface{}) { - if Level <= ERROR { - log.Printf("[ERROR] "+format, v...) - } -} - -// Error write a log on ERROR level -func Error(s string) { - Errorf(s) -} diff --git a/log/log_test.go b/log/log_test.go deleted file mode 100644 index a9587432..00000000 --- a/log/log_test.go +++ /dev/null @@ -1,131 +0,0 @@ -package log - -import ( - "bytes" - "io" - "os" - "testing" - - . "gopkg.in/check.v1" -) - -// Hook up gocheck into the "go test" runner. -func Test(t *testing.T) { - TestingT(t) -} - -type LogSuite struct{} - -var _ = Suite(&LogSuite{}) - -func (s *LogSuite) TestSetLevel(c *C) { - SetLevel("DEBUG") - c.Assert(Level, Equals, DEBUG) - - SetLevel("INFO") - c.Assert(Level, Equals, INFO) - - SetLevel("WARN") - c.Assert(Level, Equals, WARN) - - SetLevel("ERROR") - c.Assert(Level, Equals, ERROR) - - SetLevel("TRACE") - c.Assert(Level, Equals, TRACE) -} - -func (s *LogSuite) TestLog(c *C) { - logFile, err := os.OpenFile("tmptestfile.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) - c.Check(err, IsNil) - defer logFile.Close() - defer os.Remove("tmptestfile.txt") - - SetOutput(logFile) - - num, err := lineCounter(logFile) - c.Check(num, Equals, 0) - c.Check(err, IsNil) - - tmpFile, _ := os.Open("tmptestfile.txt") - Level = ERROR - Trace("a") - Debug("a") - Info("a") - Warn("a") - Error("a") - num, err = lineCounter(tmpFile) - c.Check(num, Equals, 1) - c.Check(err, IsNil) - tmpFile.Close() - - tmpFile, _ = os.Open("tmptestfile.txt") - Level = WARN - Trace("a") - Debug("a") - Info("a") - Warn("a") - Error("a") - num, err = lineCounter(tmpFile) - c.Check(num, Equals, 3) - c.Check(err, IsNil) - tmpFile.Close() - - tmpFile, _ = os.Open("tmptestfile.txt") - Level = INFO - Trace("a") - Debug("a") - Info("a") - Warn("a") - Error("a") - num, err = lineCounter(tmpFile) - c.Check(num, Equals, 6) - c.Check(err, IsNil) - tmpFile.Close() - - tmpFile, _ = os.Open("tmptestfile.txt") - Level = DEBUG - Trace("a") - Debug("a") - Info("a") - Warn("a") - Error("a") - num, err = lineCounter(tmpFile) - c.Check(num, Equals, 10) - c.Check(err, IsNil) - tmpFile.Close() - - tmpFile, _ = os.Open("tmptestfile.txt") - Level = TRACE - Trace("a") - Debug("a") - Info("a") - Warn("a") - Error("a") - num, err = lineCounter(tmpFile) - c.Check(num, Equals, 15) - c.Check(err, IsNil) - tmpFile.Close() -} - -// Taken from http://stackoverflow.com/a/24563853/1187471 -func lineCounter(r io.Reader) (int, error) { - buf := make([]byte, 8196) - count := 0 - lineSep := []byte{'\n'} - - for { - c, err := r.Read(buf) - if err != nil && err != io.EOF { - return count, err - } - - count += bytes.Count(buf[:c], lineSep) - - if err == io.EOF { - break - } - } - - return count, nil -} diff --git a/main.go b/main.go index 04b7c721..aca8d4b2 100644 --- a/main.go +++ b/main.go @@ -16,15 +16,14 @@ import ( "net/http" "os" "os/signal" - "os/user" "path/filepath" "runtime" "runtime/pprof" - "strings" "time" - "github.com/otoolep/rqlite/log" "github.com/otoolep/rqlite/server" + + log "code.google.com/p/log4go" ) var host string @@ -53,6 +52,44 @@ func init() { } } +func setupLogging(loggingLevel, logFile string) { + level := log.DEBUG + switch loggingLevel { + case "TRACE": + level = log.TRACE + case "DEBUG": + level = log.DEBUG + case "INFO": + level = log.INFO + case "WARN": + level = log.WARNING + case "ERROR": + level = log.ERROR + } + + log.Global = make(map[string]*log.Filter) + + if logFile == "stdout" { + flw := log.NewConsoleLogWriter() + log.AddFilter("stdout", level, flw) + + } else { + logFileDir := filepath.Dir(logFile) + os.MkdirAll(logFileDir, 0744) + + flw := log.NewFileLogWriter(logFile, false) + log.AddFilter("file", level, flw) + + flw.SetFormat("[%D %T] [%L] (%S) %M") + flw.SetRotate(true) + flw.SetRotateSize(0) + flw.SetRotateLines(0) + flw.SetRotateDaily(true) + } + + log.Info("Redirectoring logging to %s", logFile) +} + func main() { flag.Parse() @@ -61,27 +98,14 @@ func main() { 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()) + log.Error("Unable to create path: %s", err.Error()) } + defer f.Close() + pprof.StartCPUProfile(f) 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) - } + setupLogging(logLevel, logFile) // Set the data directory. if flag.NArg() == 0 { @@ -90,13 +114,14 @@ func main() { log.Error("No data path supplied -- aborting") os.Exit(1) } + path := flag.Arg(0) + if err := os.MkdirAll(path, 0744); err != nil { + log.Error("Unable to create path: %s", err.Error()) + } - dataPath := flag.Arg(0) - createFile(dataPath) - - s := server.NewServer(dataPath, dbfile, snapAfter, host, port) + s := server.NewServer(path, dbfile, snapAfter, host, port) go func() { - log.Error(s.ListenAndServe(join).Error()) + log.Error(s.ListenAndServe(join)) }() if !disableReporting { @@ -109,45 +134,10 @@ func main() { log.Info("rqlite server stopped") } -func closeFile(f *os.File) { - if err := f.Close(); err != nil { - log.Errorf("Unable to close file: %s", err.Error()) - os.Exit(1) - } -} - -func createFile(path string) *os.File { - usr, _ := user.Current() - dir := usr.HomeDir - - // Check in case of paths like "/something/~/something/" - if path[:2] == "~/" { - path = strings.Replace(path, "~/", dir+"/", 1) - } - - if err := os.MkdirAll(filepath.Dir(path), 0744); err != nil { - log.Errorf("Unable to create path: %s", err.Error()) - os.Exit(1) - } - - f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) - if err != nil && !strings.Contains(err.Error(), "is a directory") { - log.Errorf("Unable to open file: %s", err.Error()) - os.Exit(1) - } - - return f -} - func reportLaunch() { json := fmt.Sprintf(`{"os": "%s", "arch": "%s", "app": "rqlite"}`, runtime.GOOS, runtime.GOARCH) data := bytes.NewBufferString(json) client := http.Client{Timeout: time.Duration(5 * time.Second)} - go func() { - _, err := client.Post("https://logs-01.loggly.com/inputs/8a0edd84-92ba-46e4-ada8-c529d0f105af/tag/reporting/", - "application/json", data) - if err != nil { - log.Errorf("Report launch failed: %s", err.Error()) - } - }() + go client.Post("https://logs-01.loggly.com/inputs/8a0edd84-92ba-46e4-ada8-c529d0f105af/tag/reporting/", + "application/json", data) } diff --git a/server/server.go b/server/server.go index 2574d29c..4e4c23a8 100644 --- a/server/server.go +++ b/server/server.go @@ -20,32 +20,28 @@ import ( "github.com/otoolep/rqlite/command" "github.com/otoolep/rqlite/db" "github.com/otoolep/rqlite/interfaces" - "github.com/otoolep/rqlite/log" "github.com/rcrowley/go-metrics" + + log "code.google.com/p/log4go" ) -// FailedSqlStmt contains a SQL query and an error. type FailedSqlStmt struct { Sql string `json:"sql"` Error string `json:"error"` } -// StmtResponse contains a date and a list of failed -// SQL statements. type StmtResponse struct { Time string `json:"time"` Failures []FailedSqlStmt `json:"failures"` } -// QueryResponse contains the response to a query. type QueryResponse struct { Time string `json:"time"` Failures []FailedSqlStmt `json:"failures"` Rows db.RowResults `json:"rows"` } -// Metrics are the server metrics user for statistics. -type Metrics struct { +type ServerMetrics struct { registry metrics.Registry joinSuccess metrics.Counter joinFail metrics.Counter @@ -59,13 +55,10 @@ type Metrics struct { snapshotCreated metrics.Counter } -// Diagnostics contains a start time of the server. -type Diagnostics struct { +type ServerDiagnostics struct { startTime time.Time } -// SnapshotConf contains the index when the last snapshot happened -// and a threshold for index entries since the last snapshot. type SnapshotConf struct { // The index when the last snapshot happened lastIndex uint64 @@ -75,8 +68,9 @@ type SnapshotConf struct { snapshotAfter uint64 } -// Server is is a combination of the Raft server and an HTTP +// The raftd server is a combination of the Raft server and an HTTP // server which acts as the transport. + type Server struct { name string host string @@ -88,8 +82,8 @@ type Server struct { dbPath string db *db.DB snapConf *SnapshotConf - metrics *Metrics - diagnostics *Diagnostics + metrics *ServerMetrics + diagnostics *ServerDiagnostics mutex sync.Mutex } @@ -129,9 +123,9 @@ func isTransaction(req *http.Request) (bool, error) { return queryParam(req, "transaction") } -// NewMetrics creates a new Metrics object. -func NewMetrics() *Metrics { - m := &Metrics{ +// NewServerMetrics creates a new ServerMetrics object. +func NewServerMetrics() *ServerMetrics { + m := &ServerMetrics{ registry: metrics.NewRegistry(), joinSuccess: metrics.NewCounter(), joinFail: metrics.NewCounter(), @@ -145,22 +139,22 @@ func NewMetrics() *Metrics { snapshotCreated: metrics.NewCounter(), } - _ = m.registry.Register("join.success", m.joinSuccess) - _ = m.registry.Register("join.fail", m.joinFail) - _ = m.registry.Register("query.Received", m.queryReceived) - _ = m.registry.Register("query.success", m.querySuccess) - _ = m.registry.Register("query.fail", m.queryFail) - _ = m.registry.Register("execute.Received", m.executeReceived) - _ = m.registry.Register("execute.tx.received", m.executeTxReceived) - _ = m.registry.Register("execute.success", m.executeSuccess) - _ = m.registry.Register("execute.fail", m.executeFail) - _ = m.registry.Register("snapshot.created", m.snapshotCreated) + m.registry.Register("join.success", m.joinSuccess) + m.registry.Register("join.fail", m.joinFail) + m.registry.Register("query.Received", m.queryReceived) + m.registry.Register("query.success", m.querySuccess) + m.registry.Register("query.fail", m.queryFail) + m.registry.Register("execute.Received", m.executeReceived) + m.registry.Register("execute.tx.received", m.executeTxReceived) + m.registry.Register("execute.success", m.executeSuccess) + m.registry.Register("execute.fail", m.executeFail) + m.registry.Register("snapshot.created", m.snapshotCreated) return m } -// NewDiagnostics creates a new Diagnostics object. -func NewDiagnostics() *Diagnostics { - d := &Diagnostics{ +// NewServerDiagnostics creates a new ServerDiagnostics object. +func NewServerDiagnostics() *ServerDiagnostics { + d := &ServerDiagnostics{ startTime: time.Now(), } return d @@ -186,8 +180,8 @@ func NewServer(dataDir string, dbfile string, snapAfter int, host string, port i dbPath: dbPath, db: db.New(dbPath), snapConf: &SnapshotConf{snapshotAfter: uint64(snapAfter)}, - metrics: NewMetrics(), - diagnostics: NewDiagnostics(), + metrics: NewServerMetrics(), + diagnostics: NewServerDiagnostics(), router: mux.NewRouter(), } @@ -217,11 +211,11 @@ func (s *Server) connectionString() string { // logSnapshot logs about the snapshot that was taken. func (s *Server) logSnapshot(err error, currentIndex, count uint64) { - info := fmt.Sprintf("%s: snapshot of %d events at index %d", s.connectionString(), count, currentIndex) + info := fmt.Sprintf("%s: snapshot of %d events at index %d", s.connectionString, count, currentIndex) if err != nil { - log.Infof("%s attempted and failed: %v", info, err) + log.Info("%s attempted and failed: %v", info, err) } else { - log.Infof("%s completed", info) + log.Info("%s completed", info) } } @@ -229,38 +223,37 @@ func (s *Server) logSnapshot(err error, currentIndex, count uint64) { func (s *Server) ListenAndServe(leader string) error { var err error - log.Infof("Initializing Raft Server: %s", s.path) + log.Info("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()) + log.Error("Failed to create new Raft server", err.Error()) return err } log.Info("Loading latest snapshot, if any, from disk") - if err := s.raftServer.LoadSnapshot(); err != nil { - log.Errorf("Error loading snapshot: %s", err.Error()) + err = s.raftServer.LoadSnapshot() + if err != nil { + log.Error("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()) - } + s.raftServer.Start() if leader != "" { // Join to leader if specified. - log.Infof("Attempting to join leader at %s", leader) + log.Info("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()) + log.Error("Failed to join leader", err.Error()) return err } @@ -274,7 +267,7 @@ func (s *Server) ListenAndServe(leader string) error { ConnectionString: s.connectionString(), }) if err != nil { - log.Errorf("Failed to join to self: %s", err.Error()) + log.Error("Failed to join to self", err.Error()) } } else { @@ -296,18 +289,18 @@ func (s *Server) ListenAndServe(leader string) error { s.router.HandleFunc("/db", s.writeHandler).Methods("POST") s.router.HandleFunc("/join", s.joinHandler).Methods("POST") - log.Infof("Listening at %s", s.connectionString()) + log.Info("Listening at %s", s.connectionString()) return s.httpServer.ListenAndServe() } -// HandleFunc is a hack around Gorilla mux not providing the correct net/http +// This is a hack around Gorilla mux not providing the correct net/http // HandleFunc() interface. func (s *Server) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) { s.router.HandleFunc(pattern, handler) } -// Join joins to the leader of an existing cluster. +// Joins to the leader of an existing cluster. func (s *Server) Join(leader string) error { command := &raft.DefaultJoinCommand{ Name: s.raftServer.Name(), @@ -315,17 +308,12 @@ func (s *Server) Join(leader string) error { } var b bytes.Buffer - if err := json.NewEncoder(&b).Encode(command); err != nil { - return nil - } - + json.NewEncoder(&b).Encode(command) resp, err := http.Post(fmt.Sprintf("http://%s/join", leader), "application/json", &b) if err != nil { return err } - defer func() { - _ = resp.Body.Close() - }() + defer resp.Body.Close() // Look for redirect. if resp.StatusCode == http.StatusTemporaryRedirect { @@ -337,7 +325,7 @@ func (s *Server) Join(leader string) error { if err != nil { return errors.New("Failed to parse redirect location") } - log.Infof("Redirecting to leader at %s", u.Host) + log.Info("Redirecting to leader at %s", u.Host) return s.Join(u.Host) } @@ -369,14 +357,14 @@ func (s *Server) joinHandler(w http.ResponseWriter, req *http.Request) { } func (s *Server) readHandler(w http.ResponseWriter, req *http.Request) { - log.Tracef("readHandler for URL: %s", req.URL) + log.Trace("readHandler for URL: %s", req.URL) s.metrics.queryReceived.Inc(1) var failures = make([]FailedSqlStmt, 0) b, err := ioutil.ReadAll(req.Body) if err != nil { - log.Tracef("Bad HTTP request: %s", err.Error()) + log.Trace("Bad HTTP request", err.Error()) w.WriteHeader(http.StatusBadRequest) s.metrics.queryFail.Inc(1) return @@ -386,7 +374,7 @@ func (s *Server) readHandler(w http.ResponseWriter, req *http.Request) { startTime := time.Now() r, err := s.db.Query(stmt) if err != nil { - log.Tracef("Bad SQL statement: %s", err.Error()) + log.Trace("Bad SQL statement", err.Error()) s.metrics.queryFail.Inc(1) failures = append(failures, FailedSqlStmt{stmt, err.Error()}) } else { @@ -402,13 +390,10 @@ func (s *Server) readHandler(w http.ResponseWriter, req *http.Request) { b, err = json.Marshal(rr) } if err != nil { - log.Tracef("Failed to marshal JSON data: %s", err.Error()) + log.Trace("Failed to marshal JSON data", err.Error()) http.Error(w, err.Error(), http.StatusBadRequest) // Internal error actually } else { - _, err = w.Write([]byte(b)) - if err != nil { - log.Errorf("Error writting JSON data: %s", err.Error()) - } + w.Write([]byte(b)) } } @@ -421,7 +406,7 @@ func (s *Server) execute(tx bool, stmts []string) ([]FailedSqlStmt, error) { _, err := s.raftServer.Do(command.NewTransactionExecuteCommandSet(stmts)) if err != nil { - log.Tracef("Transaction failed: %s", err.Error()) + log.Trace("Transaction failed: %s", err.Error()) s.metrics.executeFail.Inc(1) failures = append(failures, FailedSqlStmt{stmts[0], err.Error()}) } else { @@ -432,7 +417,7 @@ func (s *Server) execute(tx bool, stmts []string) ([]FailedSqlStmt, error) { for i := range stmts { _, err := s.raftServer.Do(command.NewExecuteCommand(stmts[i])) if err != nil { - log.Tracef("Execute statement %s failed: %s", stmts[i], err.Error()) + log.Trace("Execute statement %s failed: %s", stmts[i], err.Error()) s.metrics.executeFail.Inc(1) failures = append(failures, FailedSqlStmt{stmts[i], err.Error()}) } else { @@ -454,7 +439,7 @@ func (s *Server) writeHandler(w http.ResponseWriter, req *http.Request) { return } - log.Tracef("writeHandler for URL: %s", req.URL) + log.Trace("writeHandler for URL: %s", req.URL) s.metrics.executeReceived.Inc(1) currentIndex := s.raftServer.CommitIndex() @@ -472,7 +457,7 @@ func (s *Server) writeHandler(w http.ResponseWriter, req *http.Request) { // Read the value from the POST body. b, err := ioutil.ReadAll(req.Body) if err != nil { - log.Tracef("Bad HTTP request: %s", err.Error()) + log.Trace("Bad HTTP request", err.Error()) s.metrics.executeFail.Inc(1) w.WriteHeader(http.StatusBadRequest) return @@ -482,7 +467,7 @@ func (s *Server) writeHandler(w http.ResponseWriter, req *http.Request) { stmts = stmts[:len(stmts)-1] } - log.Tracef("Execute statement contains %d commands", len(stmts)) + log.Trace("Execute statement contains %d commands", len(stmts)) if len(stmts) == 0 { log.Trace("No database execute commands supplied") s.metrics.executeFail.Inc(1) @@ -494,7 +479,7 @@ func (s *Server) writeHandler(w http.ResponseWriter, req *http.Request) { startTime = time.Now() failures, err := s.execute(transaction, stmts) if err != nil { - log.Errorf("Database mutation failed: %s", err.Error()) + log.Error("Database mutation failed: %s", err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -510,10 +495,7 @@ func (s *Server) writeHandler(w http.ResponseWriter, req *http.Request) { if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } else { - _, err = w.Write([]byte(b)) - if err != nil { - log.Errorf("Error writting JSON data: %s", err.Error()) - } + w.Write([]byte(b)) } } @@ -531,12 +513,7 @@ func (s *Server) serveStatistics(w http.ResponseWriter, req *http.Request) { 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 - } + w.Write(ensurePrettyPrint(req, statistics)) } // serveDiagnostics returns basic server diagnostics @@ -551,13 +528,7 @@ func (s *Server) serveDiagnostics(w http.ResponseWriter, req *http.Request) { 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 - } + w.Write(ensurePrettyPrint(req, diagnostics)) } // serveRaftInfo returns information about the underlying Raft server @@ -568,13 +539,7 @@ func (s *Server) serveRaftInfo(w http.ResponseWriter, req *http.Request) { 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 - } + w.Write(ensurePrettyPrint(req, info)) } // leaderRedirect returns a 307 Temporary Redirect, with the full path diff --git a/server/single_server_test.go b/server/single_server_test.go index 70c8f8f0..6e065882 100644 --- a/server/single_server_test.go +++ b/server/single_server_test.go @@ -54,7 +54,7 @@ func postEndpoint(endpoint string, body string) (*http.Response, error) { return client.Do(req) } -func isJSONBody(res *http.Response) bool { +func isJsonBody(res *http.Response) bool { b, err := ioutil.ReadAll(res.Body) if err != nil { return false @@ -87,17 +87,17 @@ func (s *SingleServerSuite) Test_SingleServer(c *C) { res, err = getEndpoint("/statistics") c.Assert(err, IsNil) c.Assert(res.StatusCode, Equals, 200) - c.Assert(isJSONBody(res), Equals, true) + c.Assert(isJsonBody(res), Equals, true) res, err = getEndpoint("/diagnostics") c.Assert(err, IsNil) c.Assert(res.StatusCode, Equals, 200) - c.Assert(isJSONBody(res), Equals, true) + c.Assert(isJsonBody(res), Equals, true) res, err = getEndpoint("/raft") c.Assert(err, IsNil) c.Assert(res.StatusCode, Equals, 200) - c.Assert(isJSONBody(res), Equals, true) + c.Assert(isJsonBody(res), Equals, true) // Create a database. res, err = postEndpoint("/db", "CREATE TABLE foo (id integer not null primary key, name text)") @@ -113,5 +113,5 @@ func (s *SingleServerSuite) Test_SingleServer(c *C) { res, err = getEndpointBody("/db", "SELECT * from foo") c.Assert(err, IsNil) c.Assert(res.StatusCode, Equals, 200) - c.Assert(isJSONBody(res), Equals, true) + c.Assert(isJsonBody(res), Equals, true) } diff --git a/server/statemachine.go b/server/statemachine.go index 5f2586b8..32716a1a 100644 --- a/server/statemachine.go +++ b/server/statemachine.go @@ -4,10 +4,9 @@ import ( "io/ioutil" "os" - "github.com/otoolep/rqlite/log" + log "code.google.com/p/log4go" ) -// DbStateMachine contains the DB path. type DbStateMachine struct { dbpath string } @@ -18,7 +17,7 @@ func NewDbStateMachine(path string) *DbStateMachine { d := &DbStateMachine{ dbpath: path, } - log.Tracef("New DB state machine created with path: %s", path) + log.Trace("New DB state machine created with path: %s", path) return d } @@ -28,24 +27,24 @@ func NewDbStateMachine(path string) *DbStateMachine { // http://sqlite.org/howtocorrupt.html states it is safe to do this // as long as no transaction is in progress. func (d *DbStateMachine) Save() ([]byte, error) { - log.Tracef("Capturing database state from path: %s", d.dbpath) + log.Trace("Capturing database state from path: %s", d.dbpath) b, err := ioutil.ReadFile(d.dbpath) if err != nil { - log.Errorf("Failed to save state: %s", err.Error()) + log.Error("Failed to save state: ", err.Error()) return nil, err } - log.Tracef("Database state successfully saved to %s", d.dbpath) + log.Trace("Database state successfully saved to %s", d.dbpath) return b, nil } // Recovery restores the state of the database using the given data. func (d *DbStateMachine) Recovery(b []byte) error { - log.Tracef("Restoring database state to path: %s", d.dbpath) + log.Trace("Restoring database state to path: %s", d.dbpath) err := ioutil.WriteFile(d.dbpath, b, os.ModePerm) if err != nil { - log.Errorf("Failed to recover state: %s", err.Error()) + log.Error("Failed to recover state: ", err.Error()) return err } - log.Tracef("Database restored successfully to %s", d.dbpath) + log.Trace("Database restored successfully to %s", d.dbpath) return nil }