mirror of
https://github.com/HDT3213/godis.git
synced 2025-09-29 22:22:08 +08:00
184 lines
4.8 KiB
Go
184 lines
4.8 KiB
Go
package database
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/hdt3213/godis/config"
|
|
"github.com/hdt3213/godis/interface/redis"
|
|
"github.com/hdt3213/godis/redis/protocol"
|
|
"github.com/hdt3213/godis/tcp"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Ping the server
|
|
func Ping(c redis.Connection, args [][]byte) redis.Reply {
|
|
if len(args) == 0 {
|
|
return &protocol.PongReply{}
|
|
} else if len(args) == 1 {
|
|
return protocol.MakeStatusReply(string(args[0]))
|
|
} else {
|
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'ping' command")
|
|
}
|
|
}
|
|
|
|
// Info the information of the godis server returned by the INFO command
|
|
func Info(db *Server, args [][]byte) redis.Reply {
|
|
if len(args) == 0 {
|
|
infoCommandList := [...]string{"server", "client", "cluster", "keyspace"}
|
|
var allSection []byte
|
|
for _, s := range infoCommandList {
|
|
allSection = append(allSection, GenGodisInfoString(s, db)...)
|
|
}
|
|
return protocol.MakeBulkReply(allSection)
|
|
} else if len(args) == 1 {
|
|
section := strings.ToLower(string(args[0]))
|
|
switch section {
|
|
case "server":
|
|
reply := GenGodisInfoString("server", db)
|
|
return protocol.MakeBulkReply(reply)
|
|
case "client":
|
|
return protocol.MakeBulkReply(GenGodisInfoString("client", db))
|
|
case "cluster":
|
|
return protocol.MakeBulkReply(GenGodisInfoString("cluster", db))
|
|
case "keyspace":
|
|
return protocol.MakeBulkReply(GenGodisInfoString("keyspace", db))
|
|
default:
|
|
return protocol.MakeErrReply("Invalid section for 'info' command")
|
|
}
|
|
}
|
|
return protocol.MakeArgNumErrReply("info")
|
|
}
|
|
|
|
// Auth validate client's password
|
|
func Auth(c redis.Connection, args [][]byte) redis.Reply {
|
|
if len(args) != 1 {
|
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'auth' command")
|
|
}
|
|
if config.Properties.RequirePass == "" {
|
|
return protocol.MakeErrReply("ERR Client sent AUTH, but no password is set")
|
|
}
|
|
passwd := string(args[0])
|
|
c.SetPassword(passwd)
|
|
if config.Properties.RequirePass != passwd {
|
|
return protocol.MakeErrReply("ERR invalid password")
|
|
}
|
|
return &protocol.OkReply{}
|
|
}
|
|
|
|
func isAuthenticated(c redis.Connection) bool {
|
|
if config.Properties.RequirePass == "" {
|
|
return true
|
|
}
|
|
return c.GetPassword() == config.Properties.RequirePass
|
|
}
|
|
|
|
func DbSize(c redis.Connection, db *Server) redis.Reply {
|
|
keys, _ := db.GetDBSize(c.GetDBIndex())
|
|
return protocol.MakeIntReply(int64(keys))
|
|
}
|
|
|
|
func GenGodisInfoString(section string, db *Server) []byte {
|
|
startUpTimeFromNow := getGodisRuninngTime()
|
|
switch section {
|
|
case "server":
|
|
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)
|
|
case "client":
|
|
s := fmt.Sprintf("# Clients\r\n"+
|
|
"connected_clients:%d\r\n",
|
|
//"client_recent_max_input_buffer:%d\r\n"+
|
|
//"client_recent_max_output_buffer:%d\r\n"+
|
|
//"blocked_clients:%d\n",
|
|
tcp.ClientCounter,
|
|
//TODO,
|
|
//TODO,
|
|
//TODO,
|
|
)
|
|
return []byte(s)
|
|
case "cluster":
|
|
if getGodisRunningMode() == config.ClusterMode {
|
|
s := fmt.Sprintf("# Cluster\r\n"+
|
|
"cluster_enabled:%s\r\n",
|
|
"1",
|
|
)
|
|
return []byte(s)
|
|
} else {
|
|
s := fmt.Sprintf("# Cluster\r\n"+
|
|
"cluster_enabled:%s\r\n",
|
|
"0",
|
|
)
|
|
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("")
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
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)
|
|
}
|