mirror of https://github.com/tidwall/tile38.git
Merge pull request #404 from tidwall/Adding-more-replication-data-to-INFO-response
Adding more replication data to INFO response
This commit is contained in:
commit
bfa35d5db9
|
@ -17,6 +17,7 @@ import (
|
||||||
// Client is an remote connection into to Tile38
|
// Client is an remote connection into to Tile38
|
||||||
type Client struct {
|
type Client struct {
|
||||||
id int // unique id
|
id int // unique id
|
||||||
|
replPort int // the known replication port for follower connections
|
||||||
authd bool // client has been authenticated
|
authd bool // client has been authenticated
|
||||||
outputType Type // Null, JSON, or RESP
|
outputType Type // Null, JSON, or RESP
|
||||||
remoteAddr string // original remote address
|
remoteAddr string // original remote address
|
||||||
|
|
|
@ -96,6 +96,41 @@ func (c *Server) cmdFollow(msg *Message) (res resp.Value, err error) {
|
||||||
return OKMessage(msg, start), nil
|
return OKMessage(msg, start), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cmdReplConf is a command handler that sets replication configuration info
|
||||||
|
func (c *Server) cmdReplConf(msg *Message, client *Client) (res resp.Value, err error) {
|
||||||
|
start := time.Now()
|
||||||
|
vs := msg.Args[1:]
|
||||||
|
var ok bool
|
||||||
|
var cmd, val string
|
||||||
|
|
||||||
|
// Parse the message
|
||||||
|
if vs, cmd, ok = tokenval(vs); !ok || cmd == "" {
|
||||||
|
return NOMessage, errInvalidNumberOfArguments
|
||||||
|
}
|
||||||
|
if vs, val, ok = tokenval(vs); !ok || val == "" {
|
||||||
|
return NOMessage, errInvalidNumberOfArguments
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch on the command received
|
||||||
|
switch cmd {
|
||||||
|
case "listening-port":
|
||||||
|
// Parse the port as an integer
|
||||||
|
port, err := strconv.Atoi(val)
|
||||||
|
if err != nil {
|
||||||
|
return NOMessage, errInvalidArgument(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the replication port to the client and return
|
||||||
|
for _, c := range c.conns {
|
||||||
|
if c.remoteAddr == client.remoteAddr {
|
||||||
|
c.replPort = port
|
||||||
|
return OKMessage(msg, start), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOMessage, fmt.Errorf("cannot find follower")
|
||||||
|
}
|
||||||
|
|
||||||
func doServer(conn *RESPConn) (map[string]string, error) {
|
func doServer(conn *RESPConn) (map[string]string, error) {
|
||||||
v, err := conn.Do("server")
|
v, err := conn.Do("server")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -191,7 +226,22 @@ func (c *Server) followStep(host string, port int, followc int) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := conn.Do("aof", pos)
|
// Send the replication port to the leader
|
||||||
|
v, err := conn.Do("replconf", "listening-port", c.port)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if v.Error() != nil {
|
||||||
|
return v.Error()
|
||||||
|
}
|
||||||
|
if v.String() != "OK" {
|
||||||
|
return errors.New("invalid response to replconf request")
|
||||||
|
}
|
||||||
|
if core.ShowDebugMessages {
|
||||||
|
log.Debug("follow:", addr, ":replconf")
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err = conn.Do("aof", pos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -970,7 +970,7 @@ func (server *Server) handleInputCommand(client *Client, msg *Message) error {
|
||||||
if server.config.followHost() != "" && !server.fcuponce {
|
if server.config.followHost() != "" && !server.fcuponce {
|
||||||
return writeErr("catching up to leader")
|
return writeErr("catching up to leader")
|
||||||
}
|
}
|
||||||
case "follow", "readonly", "config":
|
case "follow", "slaveof", "replconf", "readonly", "config":
|
||||||
// system operations
|
// system operations
|
||||||
// does not write to aof, but requires a write lock.
|
// does not write to aof, but requires a write lock.
|
||||||
server.mu.Lock()
|
server.mu.Lock()
|
||||||
|
@ -1081,7 +1081,6 @@ func (server *Server) command(msg *Message, client *Client) (
|
||||||
res, d, err = server.cmdRename(msg, false)
|
res, d, err = server.cmdRename(msg, false)
|
||||||
case "renamenx":
|
case "renamenx":
|
||||||
res, d, err = server.cmdRename(msg, true)
|
res, d, err = server.cmdRename(msg, true)
|
||||||
|
|
||||||
case "sethook":
|
case "sethook":
|
||||||
res, d, err = server.cmdSetHook(msg, false)
|
res, d, err = server.cmdSetHook(msg, false)
|
||||||
case "delhook":
|
case "delhook":
|
||||||
|
@ -1090,7 +1089,6 @@ func (server *Server) command(msg *Message, client *Client) (
|
||||||
res, d, err = server.cmdPDelHook(msg, false)
|
res, d, err = server.cmdPDelHook(msg, false)
|
||||||
case "hooks":
|
case "hooks":
|
||||||
res, err = server.cmdHooks(msg, false)
|
res, err = server.cmdHooks(msg, false)
|
||||||
|
|
||||||
case "setchan":
|
case "setchan":
|
||||||
res, d, err = server.cmdSetHook(msg, true)
|
res, d, err = server.cmdSetHook(msg, true)
|
||||||
case "delchan":
|
case "delchan":
|
||||||
|
@ -1099,7 +1097,6 @@ func (server *Server) command(msg *Message, client *Client) (
|
||||||
res, d, err = server.cmdPDelHook(msg, true)
|
res, d, err = server.cmdPDelHook(msg, true)
|
||||||
case "chans":
|
case "chans":
|
||||||
res, err = server.cmdHooks(msg, true)
|
res, err = server.cmdHooks(msg, true)
|
||||||
|
|
||||||
case "expire":
|
case "expire":
|
||||||
res, d, err = server.cmdExpire(msg)
|
res, d, err = server.cmdExpire(msg)
|
||||||
case "persist":
|
case "persist":
|
||||||
|
@ -1124,8 +1121,10 @@ func (server *Server) command(msg *Message, client *Client) (
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
res, err = server.cmdSleep(msg)
|
res, err = server.cmdSleep(msg)
|
||||||
case "follow":
|
case "follow", "slaveof":
|
||||||
res, err = server.cmdFollow(msg)
|
res, err = server.cmdFollow(msg)
|
||||||
|
case "replconf":
|
||||||
|
res, err = server.cmdReplConf(msg, client)
|
||||||
case "readonly":
|
case "readonly":
|
||||||
res, err = server.cmdReadOnly(msg)
|
res, err = server.cmdReadOnly(msg)
|
||||||
case "stats":
|
case "stats":
|
||||||
|
|
|
@ -352,9 +352,27 @@ func (c *Server) writeInfoStats(w *bytes.Buffer) {
|
||||||
fmt.Fprintf(w, "total_commands_processed:%d\r\n", c.statsTotalCommands.get()) // Total number of commands processed by the server
|
fmt.Fprintf(w, "total_commands_processed:%d\r\n", c.statsTotalCommands.get()) // Total number of commands processed by the server
|
||||||
fmt.Fprintf(w, "expired_keys:%d\r\n", c.statsExpired.get()) // Total number of key expiration events
|
fmt.Fprintf(w, "expired_keys:%d\r\n", c.statsExpired.get()) // Total number of key expiration events
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeInfoReplication writes all replication data to the 'info' response
|
||||||
func (c *Server) writeInfoReplication(w *bytes.Buffer) {
|
func (c *Server) writeInfoReplication(w *bytes.Buffer) {
|
||||||
|
if c.config.followHost() != "" {
|
||||||
|
fmt.Fprintf(w, "role:slave\r\n")
|
||||||
|
fmt.Fprintf(w, "master_host:%s\r\n", c.config.followHost())
|
||||||
|
fmt.Fprintf(w, "master_port:%v\r\n", c.config.followPort())
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "role:master\r\n")
|
||||||
|
var i int
|
||||||
|
for _, cc := range c.conns {
|
||||||
|
if cc.replPort != 0 {
|
||||||
|
fmt.Fprintf(w, "slave%v:ip=%s,port=%v,state=online\r\n", i,
|
||||||
|
strings.Split(cc.remoteAddr, ":")[0], cc.replPort)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
fmt.Fprintf(w, "connected_slaves:%d\r\n", len(c.aofconnM)) // Number of connected slaves
|
fmt.Fprintf(w, "connected_slaves:%d\r\n", len(c.aofconnM)) // Number of connected slaves
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Server) writeInfoCluster(w *bytes.Buffer) {
|
func (c *Server) writeInfoCluster(w *bytes.Buffer) {
|
||||||
fmt.Fprintf(w, "cluster_enabled:0\r\n")
|
fmt.Fprintf(w, "cluster_enabled:0\r\n")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue