mirror of
https://github.com/HDT3213/godis.git
synced 2025-10-05 16:57:06 +08:00
Add the keyspace section of the info command
This commit is contained in:
@@ -136,7 +136,9 @@ func (cluster *Cluster) Exec(c redis.Connection, cmdLine [][]byte) (result redis
|
|||||||
}()
|
}()
|
||||||
cmdName := strings.ToLower(string(cmdLine[0]))
|
cmdName := strings.ToLower(string(cmdLine[0]))
|
||||||
if cmdName == "info" {
|
if cmdName == "info" {
|
||||||
return database2.Info(c, cmdLine)
|
if ser, ok := cluster.db.(*database2.Server); ok {
|
||||||
|
return database2.Info(ser, cmdLine[1:])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if cmdName == "auth" {
|
if cmdName == "auth" {
|
||||||
return database2.Auth(c, cmdLine[1:])
|
return database2.Auth(c, cmdLine[1:])
|
||||||
|
@@ -111,7 +111,7 @@ func (server *Server) Exec(c redis.Connection, cmdLine [][]byte) (result redis.R
|
|||||||
}
|
}
|
||||||
// info
|
// info
|
||||||
if cmdName == "info" {
|
if cmdName == "info" {
|
||||||
return Info(c, cmdLine)
|
return Info(server, cmdLine[1:])
|
||||||
}
|
}
|
||||||
if cmdName == "slaveof" {
|
if cmdName == "slaveof" {
|
||||||
if c != nil && c.InMultiState() {
|
if c != nil && c.InMultiState() {
|
||||||
@@ -388,3 +388,23 @@ func (server *Server) startReplCron() {
|
|||||||
}
|
}
|
||||||
}(server)
|
}(server)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAvgTTL Calculate the average expiration time of keys
|
||||||
|
func (server *Server) GetAvgTTL(dbIndex, randomKeyCount int) int64 {
|
||||||
|
var ttlCount int64
|
||||||
|
db := server.mustSelectDB(dbIndex)
|
||||||
|
keys := db.data.RandomKeys(randomKeyCount)
|
||||||
|
for _, k := range keys {
|
||||||
|
t := time.Now()
|
||||||
|
rawExpireTime, ok := db.ttlMap.Get(k)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
expireTime, _ := rawExpireTime.(time.Time)
|
||||||
|
// if the key has already reached its expiration time during calculation, ignore it
|
||||||
|
if expireTime.Sub(t).Microseconds() > 0 {
|
||||||
|
ttlCount += expireTime.Sub(t).Microseconds()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ttlCount / int64(len(keys))
|
||||||
|
}
|
||||||
|
@@ -24,30 +24,31 @@ func Ping(c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Info the information of the godis server returned by the INFO command
|
// Info the information of the godis server returned by the INFO command
|
||||||
func Info(c redis.Connection, args [][]byte) redis.Reply {
|
func Info(db *Server, args [][]byte) redis.Reply {
|
||||||
if len(args) == 1 {
|
if len(args) == 0 {
|
||||||
infoCommandList := [...]string{"server", "client", "cluster"}
|
infoCommandList := [...]string{"server", "client", "cluster", "keyspace"}
|
||||||
var allSection []byte
|
var allSection []byte
|
||||||
for _, s := range infoCommandList {
|
for _, s := range infoCommandList {
|
||||||
allSection = append(allSection, GenGodisInfoString(s)...)
|
allSection = append(allSection, GenGodisInfoString(s, db)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return protocol.MakeBulkReply(allSection)
|
return protocol.MakeBulkReply(allSection)
|
||||||
} else if len(args) == 2 {
|
} else if len(args) == 1 {
|
||||||
section := strings.ToLower(string(args[1]))
|
section := strings.ToLower(string(args[0]))
|
||||||
switch section {
|
switch section {
|
||||||
case "server":
|
case "server":
|
||||||
reply := GenGodisInfoString("server")
|
reply := GenGodisInfoString("server", db)
|
||||||
return protocol.MakeBulkReply(reply)
|
return protocol.MakeBulkReply(reply)
|
||||||
case "client":
|
case "client":
|
||||||
return protocol.MakeBulkReply(GenGodisInfoString("client"))
|
return protocol.MakeBulkReply(GenGodisInfoString("client", db))
|
||||||
case "cluster":
|
case "cluster":
|
||||||
return protocol.MakeBulkReply(GenGodisInfoString("cluster"))
|
return protocol.MakeBulkReply(GenGodisInfoString("cluster", db))
|
||||||
|
case "keyspace":
|
||||||
|
return protocol.MakeBulkReply(GenGodisInfoString("keyspace", db))
|
||||||
default:
|
default:
|
||||||
return protocol.MakeNullBulkReply()
|
return protocol.MakeErrReply("Invalid section for 'info' command")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return protocol.MakeErrReply("ERR wrong number of arguments for 'info' command")
|
return protocol.MakeArgNumErrReply("info")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth validate client's password
|
// Auth validate client's password
|
||||||
@@ -73,8 +74,8 @@ func isAuthenticated(c redis.Connection) bool {
|
|||||||
return c.GetPassword() == config.Properties.RequirePass
|
return c.GetPassword() == config.Properties.RequirePass
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenGodisInfoString(section string) []byte {
|
func GenGodisInfoString(section string, db *Server) []byte {
|
||||||
startUpTimeFromNow := getGodisRunningTime()
|
startUpTimeFromNow := getGodisRuninngTime()
|
||||||
switch section {
|
switch section {
|
||||||
case "server":
|
case "server":
|
||||||
s := fmt.Sprintf("# Server\r\n"+
|
s := fmt.Sprintf("# Server\r\n"+
|
||||||
@@ -139,8 +140,20 @@ func GenGodisInfoString(section string) []byte {
|
|||||||
)
|
)
|
||||||
return []byte(s)
|
return []byte(s)
|
||||||
}
|
}
|
||||||
|
case "keyspace":
|
||||||
|
dbCount := config.Properties.Databases
|
||||||
|
var serv []byte
|
||||||
|
for i := 0; i < dbCount; i++ {
|
||||||
|
keys, expiresKeys := db.GetDBSize(i)
|
||||||
|
if keys != 0 {
|
||||||
|
ttlSampleAverage := db.GetAvgTTL(i, 20)
|
||||||
|
serv = append(serv, getDbSize(i, keys, expiresKeys, ttlSampleAverage)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prefix := []byte("# Keyspace\r\n")
|
||||||
|
keyspaceInfo := append(prefix, serv...)
|
||||||
|
return keyspaceInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte("")
|
return []byte("")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +166,13 @@ func getGodisRunningMode() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getGodisRunningTime return the running time of godis
|
// getGodisRuninngTime return the running time of godis
|
||||||
func getGodisRunningTime() time.Duration {
|
func getGodisRuninngTime() time.Duration {
|
||||||
return time.Since(config.EachTimeServerInfo.StartUpTime) / time.Second
|
return time.Since(config.EachTimeServerInfo.StartUpTime) / time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDbSize(dbIndex, keys, expiresKeys int, ttl int64) []byte {
|
||||||
|
s := fmt.Sprintf("db%d:keys=%d,expires=%d,avg_ttl=%d\r\n",
|
||||||
|
dbIndex, keys, expiresKeys, ttl)
|
||||||
|
return []byte(s)
|
||||||
|
}
|
||||||
|
@@ -52,8 +52,10 @@ func TestInfo(t *testing.T) {
|
|||||||
asserts.AssertNotError(t, ret)
|
asserts.AssertNotError(t, ret)
|
||||||
ret = testServer.Exec(c, utils.ToCmdLine("iNFO", "SeRvEr"))
|
ret = testServer.Exec(c, utils.ToCmdLine("iNFO", "SeRvEr"))
|
||||||
asserts.AssertNotError(t, ret)
|
asserts.AssertNotError(t, ret)
|
||||||
|
ret = testServer.Exec(c, utils.ToCmdLine("INFO", "Keyspace"))
|
||||||
|
asserts.AssertNotError(t, ret)
|
||||||
ret = testServer.Exec(c, utils.ToCmdLine("iNFO", "abc", "bde"))
|
ret = testServer.Exec(c, utils.ToCmdLine("iNFO", "abc", "bde"))
|
||||||
asserts.AssertErrReply(t, ret, "ERR wrong number of arguments for 'info' command")
|
asserts.AssertErrReply(t, ret, "ERR wrong number of arguments for 'info' command")
|
||||||
ret = testServer.Exec(c, utils.ToCmdLine("INFO", "abc"))
|
ret = testServer.Exec(c, utils.ToCmdLine("INFO", "abc"))
|
||||||
asserts.AssertNullBulk(t, ret)
|
asserts.AssertErrReply(t, ret, "Invalid section for 'info' command")
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user