mirror of
https://github.com/HDT3213/godis.git
synced 2025-10-06 01:07:06 +08:00
Add info command (#141)
* Generate a new runid for each start of godis * Add info command * Add info command * Generate a new runid for each start of godis * Add unittests for the info command
This commit is contained in:
@@ -2,17 +2,26 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ClusterMode = "cluster"
|
||||||
|
StandaloneMode = "standalone"
|
||||||
|
)
|
||||||
|
|
||||||
// ServerProperties defines global config properties
|
// ServerProperties defines global config properties
|
||||||
type ServerProperties struct {
|
type ServerProperties struct {
|
||||||
|
// for Public configuration
|
||||||
|
RunID string `cfg:"runid"` // runID always different at every exec.
|
||||||
Bind string `cfg:"bind"`
|
Bind string `cfg:"bind"`
|
||||||
Port int `cfg:"port"`
|
Port int `cfg:"port"`
|
||||||
AppendOnly bool `cfg:"appendonly"`
|
AppendOnly bool `cfg:"appendonly"`
|
||||||
@@ -27,19 +36,36 @@ type ServerProperties struct {
|
|||||||
SlaveAnnounceIP string `cfg:"slave-announce-ip"`
|
SlaveAnnounceIP string `cfg:"slave-announce-ip"`
|
||||||
ReplTimeout int `cfg:"repl-timeout"`
|
ReplTimeout int `cfg:"repl-timeout"`
|
||||||
|
|
||||||
Peers []string `cfg:"peers"`
|
// for cluster mode configuration
|
||||||
Self string `cfg:"self"`
|
ClusterEnabled string `cfg:"cluster-enabled"` // Not used at present.
|
||||||
|
Peers []string `cfg:"peers"`
|
||||||
|
Self string `cfg:"self"`
|
||||||
|
|
||||||
|
// config file path
|
||||||
|
CfPath string `cfg:"cf,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerInfo struct {
|
||||||
|
StartUpTime time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// Properties holds global config properties
|
// Properties holds global config properties
|
||||||
var Properties *ServerProperties
|
var Properties *ServerProperties
|
||||||
|
|
||||||
|
var EachTimeServerInfo *ServerInfo
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
// A few stats we don't want to reset: server startup time, and peak mem.
|
||||||
|
EachTimeServerInfo = &ServerInfo{
|
||||||
|
StartUpTime: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
// default config
|
// default config
|
||||||
Properties = &ServerProperties{
|
Properties = &ServerProperties{
|
||||||
Bind: "127.0.0.1",
|
Bind: "127.0.0.1",
|
||||||
Port: 6379,
|
Port: 6379,
|
||||||
AppendOnly: false,
|
AppendOnly: false,
|
||||||
|
RunID: utils.RandString(40),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,4 +135,5 @@ func SetupConfig(configFilename string) {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
Properties = parse(file)
|
Properties = parse(file)
|
||||||
|
Properties.RunID = utils.RandString(40)
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var godisVersion = "1.2.8" // do not modify
|
||||||
|
|
||||||
// Server is a redis-server with full capabilities including multiple database, rdb loader, replication
|
// Server is a redis-server with full capabilities including multiple database, rdb loader, replication
|
||||||
type Server struct {
|
type Server struct {
|
||||||
dbSet []*atomic.Value // *DB
|
dbSet []*atomic.Value // *DB
|
||||||
@@ -90,6 +92,10 @@ func (server *Server) Exec(c redis.Connection, cmdLine [][]byte) (result redis.R
|
|||||||
if cmdName == "auth" {
|
if cmdName == "auth" {
|
||||||
return Auth(c, cmdLine[1:])
|
return Auth(c, cmdLine[1:])
|
||||||
}
|
}
|
||||||
|
// info
|
||||||
|
if cmdName == "info" {
|
||||||
|
return Info(c, cmdLine)
|
||||||
|
}
|
||||||
if !isAuthenticated(c) {
|
if !isAuthenticated(c) {
|
||||||
return protocol.MakeErrReply("NOAUTH Authentication required")
|
return protocol.MakeErrReply("NOAUTH Authentication required")
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,14 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/hdt3213/godis/config"
|
"github.com/hdt3213/godis/config"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/redis/protocol"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ping the server
|
// Ping the server
|
||||||
@@ -17,6 +22,24 @@ func Ping(c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info the information of the godis server returned by the INFO command
|
||||||
|
func Info(c redis.Connection, args [][]byte) redis.Reply {
|
||||||
|
if len(args) == 1 {
|
||||||
|
return protocol.MakeBulkReply(GenGodisInfoString())
|
||||||
|
} else if len(args) == 2 {
|
||||||
|
section := strings.ToLower(string(args[1]))
|
||||||
|
switch section {
|
||||||
|
case "server":
|
||||||
|
reply := GenGodisInfoString()
|
||||||
|
return protocol.MakeBulkReply(reply)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'info' command")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &protocol.NullBulkReply{}
|
||||||
|
}
|
||||||
|
|
||||||
// Auth validate client's password
|
// Auth validate client's password
|
||||||
func Auth(c redis.Connection, args [][]byte) redis.Reply {
|
func Auth(c redis.Connection, args [][]byte) redis.Reply {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
@@ -39,3 +62,57 @@ func isAuthenticated(c redis.Connection) bool {
|
|||||||
}
|
}
|
||||||
return c.GetPassword() == config.Properties.RequirePass
|
return c.GetPassword() == config.Properties.RequirePass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GenGodisInfoString() []byte {
|
||||||
|
startUpTimeFromNow := getGodisRuninngTime()
|
||||||
|
s := fmt.Sprintf("# Server\r\n"+
|
||||||
|
"godis_version:%s\r\n"+
|
||||||
|
//"godis_git_sha1:%s\r\n"+
|
||||||
|
//"godis_git_dirty:%d\r\n"+
|
||||||
|
//"godis_build_id:%s\r\n"+
|
||||||
|
"godis_mode:%s\r\n"+
|
||||||
|
"os:%s %s\r\n"+
|
||||||
|
"arch_bits:%d\r\n"+
|
||||||
|
//"multiplexing_api:%s\r\n"+
|
||||||
|
"go_version:%s\r\n"+
|
||||||
|
"process_id:%d\r\n"+
|
||||||
|
"run_id:%s\r\n"+
|
||||||
|
"tcp_port:%d\r\n"+
|
||||||
|
"uptime_in_seconds:%d\r\n"+
|
||||||
|
"uptime_in_days:%d\r\n"+
|
||||||
|
//"hz:%d\r\n"+
|
||||||
|
//"lru_clock:%d\r\n"+
|
||||||
|
"config_file:%s\r\n",
|
||||||
|
godisVersion,
|
||||||
|
//TODO,
|
||||||
|
//TODO,
|
||||||
|
//TODO,
|
||||||
|
getGodisRunningMode(),
|
||||||
|
runtime.GOOS, runtime.GOARCH,
|
||||||
|
32<<(^uint(0)>>63),
|
||||||
|
//TODO,
|
||||||
|
runtime.Version(),
|
||||||
|
os.Getpid(),
|
||||||
|
config.Properties.RunID,
|
||||||
|
config.Properties.Port,
|
||||||
|
startUpTimeFromNow,
|
||||||
|
startUpTimeFromNow/time.Duration(3600*24),
|
||||||
|
//TODO,
|
||||||
|
//TODO,
|
||||||
|
config.Properties.CfPath)
|
||||||
|
return []byte(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getGodisRunningMode return godis running mode
|
||||||
|
func getGodisRunningMode() string {
|
||||||
|
if config.Properties.ClusterEnabled == "yes" {
|
||||||
|
return config.ClusterMode
|
||||||
|
} else {
|
||||||
|
return config.StandaloneMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getGodisRuninngTime return the running time of godis
|
||||||
|
func getGodisRuninngTime() time.Duration {
|
||||||
|
return time.Since(config.EachTimeServerInfo.StartUpTime) / time.Second
|
||||||
|
}
|
||||||
|
@@ -39,3 +39,17 @@ func TestAuth(t *testing.T) {
|
|||||||
asserts.AssertStatusReply(t, ret, "OK")
|
asserts.AssertStatusReply(t, ret, "OK")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInfo(t *testing.T) {
|
||||||
|
c := connection.NewFakeConn()
|
||||||
|
ret := testServer.Exec(c, utils.ToCmdLine("INFO"))
|
||||||
|
asserts.AssertNotError(t, ret)
|
||||||
|
ret = testServer.Exec(c, utils.ToCmdLine("INFO", "server"))
|
||||||
|
asserts.AssertNotError(t, ret)
|
||||||
|
ret = testServer.Exec(c, utils.ToCmdLine("iNFO", "SeRvEr"))
|
||||||
|
asserts.AssertNotError(t, ret)
|
||||||
|
ret = testServer.Exec(c, utils.ToCmdLine("iNFO", "abc", "bde"))
|
||||||
|
asserts.AssertErrReply(t, ret, "ERR wrong number of arguments for 'info' command")
|
||||||
|
ret = testServer.Exec(c, utils.ToCmdLine("INFO", "abc"))
|
||||||
|
asserts.AssertNullBulk(t, ret)
|
||||||
|
}
|
||||||
|
2
main.go
2
main.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hdt3213/godis/config"
|
"github.com/hdt3213/godis/config"
|
||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
RedisServer "github.com/hdt3213/godis/redis/server"
|
RedisServer "github.com/hdt3213/godis/redis/server"
|
||||||
"github.com/hdt3213/godis/tcp"
|
"github.com/hdt3213/godis/tcp"
|
||||||
"os"
|
"os"
|
||||||
@@ -23,6 +24,7 @@ var defaultProperties = &config.ServerProperties{
|
|||||||
AppendOnly: false,
|
AppendOnly: false,
|
||||||
AppendFilename: "",
|
AppendFilename: "",
|
||||||
MaxClients: 1000,
|
MaxClients: 1000,
|
||||||
|
RunID: utils.RandString(40),
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileExists(filename string) bool {
|
func fileExists(filename string) bool {
|
||||||
|
Reference in New Issue
Block a user