added a new method to list all active actions in shard

This commit is contained in:
Mike Solomon 2012-11-11 21:25:21 -08:00
Родитель b131ab75a1
Коммит 845d28598a
4 изменённых файлов: 130 добавлений и 29 удалений

Просмотреть файл

@ -18,6 +18,7 @@ import (
"sort"
"strconv"
"strings"
"sync"
"time"
"code.google.com/p/vitess/go/relog"
@ -96,8 +97,9 @@ Tablets:
ExecuteHook <zk tablet path> <hook name> [<param1=value1> <param2=value2> ...]
This runs the specified hook on the given tablet.
Shards:
RebuildShardGraph <zk shard path>
RebuildShardGraph <zk shard path> (/zk/global/vt/keyspaces/<keyspace>/shards/<shard>)
Rebuild the replication graph and shard serving data in zk.
This may trigger an update to all connected clients
@ -111,12 +113,18 @@ Shards:
ShardReplicationPositions <zk shard path> (/zk/global/vt/keyspaces/<keyspace>/shards/<shard>)
Show slave status on all machines in the shard graph.
ListShardTablets <zk shard path> (/zk/global/vt/keyspaces/<keyspace>/shards/<shard>)
list all tablets in a given shard
ListShardActions <zk shard path> (/zk/global/vt/keyspaces/<keyspace>/shards/<shard>)
list all active actions in a given shard
Keyspaces:
CreateKeyspace <zk keyspaces path>/<name> <shard count>
e.g. CreateKeyspace /zk/global/vt/keyspaces/my_keyspace 4
RebuildKeyspaceGraph <zk keyspace path>
RebuildKeyspaceGraph <zk keyspace path> (/zk/global/vt/keyspaces/<keyspace>)
Rebuild the serving data for all shards in this keyspace.
This may trigger an update to all connected clients
@ -125,10 +133,10 @@ Keyspaces:
Generic:
PurgeActions <zk action path>
PurgeActions <zk action path> (/zk/global/vt/keyspaces/<keyspace>/shards/<shard>/action)
remove all actions - be careful, this is powerful cleanup magic
WaitForAction <zk action path>
WaitForAction <zk action path> (/zk/global/vt/keyspaces/<keyspace>/shards/<shard>/action/<action id>)
watch an action node, printing updates, until the action is complete
Resolve <keyspace>.<shard>.<db type>
@ -138,7 +146,7 @@ Generic:
validate all nodes reachable from global replication graph and all
tablets in all discoverable cells are consistent
ExportZkns <zk local vt path> (/zk/<cell>/vt)
ExportZkns <zk local vt path> (/zk/<cell>/vt) DEPRECATED
export the serving graph entries to the legacy zkns format
ExportZknsForKeyspace <zk global keyspace path> (/zk/global/vt/keyspaces/<keyspace>)
@ -151,23 +159,20 @@ Generic:
data to recover the replication graph, at which point further
auditing with Validate can reveal any remaining issues.
ListIdle <zk local vt path>
ListIdle <zk local vt path> (/zk/<cell>/vt) DEPRECATED - ListAllTablets + awk
list all idle tablet paths
ListScrap <zk local vt path>
ListScrap <zk local vt path> (/zk/<cell>/vt) DEPRECATED - ListAllTablets + awk
list all scrap tablet paths
ListShardTablets <zk shard path>
list all tablets paths in a given shard
ListAllTablets <zk local vt path>
ListAllTablets <zk local vt path> (/zk/<cell>/vt)
list all tablets in an awk-friendly way
ListTablets <zk tablet path> ...
ListTablets <zk tablet path> ... (/zk/<cell>/vt/tablets/<tablet uid> ...)
list specified tablets in an awk-friendly way
Schema:
Schema: (beta)
GetSchema <zk tablet path>
display the full schema for a tablet
@ -349,16 +354,101 @@ func listTabletsByType(zconn zk.Conn, zkVtPath string, dbType tm.TabletType) err
return nil
}
func listTabletsByShard(zconn zk.Conn, zkShardPath string) error {
tabletAliases, err := tm.FindAllTabletAliasesInShard(zconn, zkShardPath)
func getFirstAction(zconn zk.Conn, actionPath string) (*tm.ActionNode, error) {
actions, _, err := zconn.Children(actionPath)
if err != nil {
return nil, fmt.Errorf("getFirstAction: %v %v", actionPath, err)
}
if len(actions) == 0 {
return nil, nil
}
actionNodePath := path.Join(actionPath, actions[0])
data, _, err := zconn.Get(actionNodePath)
if err != nil {
return nil, fmt.Errorf("getFirstAction: %v %v", actionNodePath, err)
}
actionNode, err := tm.ActionNodeFromJson(data, actionNodePath)
if err != nil {
return nil, fmt.Errorf("getFirstAction: %v %v", actionNodePath, err)
}
return actionNode, nil
}
func listActionsByShard(zconn zk.Conn, zkShardPath string) error {
tabletPaths, err := tabletPathsForShard(zconn, zkShardPath)
if err != nil {
return err
}
wg := sync.WaitGroup{}
mu := sync.Mutex{}
actionMap := make(map[string]*tm.ActionNode)
f := func(actionPath string) {
defer wg.Done()
actionNode, err := getFirstAction(zconn, actionPath)
if err != nil {
relog.Warning("listActionsByShard %v", err)
return
}
if actionNode != nil {
mu.Lock()
actionMap[actionNode.Path()] = actionNode
mu.Unlock()
}
}
shardActionNode, err := getFirstAction(zconn, tm.ShardActionPath(zkShardPath))
if err != nil {
relog.Warning("listActionsByShard %v", err)
}
for _, tabletPath := range tabletPaths {
actionPath := tm.TabletActionPath(tabletPath)
wg.Add(1)
go f(actionPath)
}
wg.Wait()
mu.Lock()
defer mu.Unlock()
keys := wr.CopyMapKeys(actionMap, []string{}).([]string)
sort.Strings(keys)
if shardActionNode != nil {
fmt.Println(fmtAction(shardActionNode))
}
for _, key := range keys {
action := actionMap[key]
if action == nil {
fmt.Fprintf(os.Stderr, "ERROR: %v\n", key)
} else {
fmt.Println(fmtAction(action))
}
}
return nil
}
func fmtAction(action *tm.ActionNode) string {
return fmt.Sprintf("%v %v %v %v %v", action.Path(), action.Action, action.State, action.ActionGuid, action.Error)
}
func listTabletsByShard(zconn zk.Conn, zkShardPath string) error {
tabletPaths, err := tabletPathsForShard(zconn, zkShardPath)
if err != nil {
return err
}
return dumpTablets(zconn, tabletPaths)
}
func tabletPathsForShard(zconn zk.Conn, zkShardPath string) ([]string, error) {
tabletAliases, err := tm.FindAllTabletAliasesInShard(zconn, zkShardPath)
if err != nil {
return nil, err
}
tabletPaths := make([]string, len(tabletAliases))
for i, alias := range tabletAliases {
tabletPaths[i] = tm.TabletPathForAlias(alias)
}
return dumpTablets(zconn, tabletPaths)
return tabletPaths, nil
}
func dumpAllTablets(zconn zk.Conn, zkVtPath string) error {
@ -754,7 +844,6 @@ func main() {
lines = append(lines, fmtTabletAwkable(ti)+fmt.Sprintf(" %v:%010d %v:%010d %v", pos.MasterLogFile, pos.MasterLogPosition, pos.MasterLogFileIo, pos.MasterLogPositionIo, pos.SecondsBehindMaster))
}
}
// sort.Strings(lines)
for _, l := range lines {
fmt.Println(l)
}
@ -773,6 +862,11 @@ func main() {
relog.Fatal("action %v requires <zk shard path>", args[0])
}
err = listTabletsByShard(zconn, args[1])
case "ListShardActions":
if len(args) != 2 {
relog.Fatal("action %v requires <zk shard path>", args[0])
}
err = listActionsByShard(zconn, args[1])
case "ListAllTablets":
if len(args) != 2 {
relog.Fatal("action %v requires <zk vt path>", args[0])

Просмотреть файл

@ -68,7 +68,7 @@ type ActionNode struct {
Error string
State ActionState
Args map[string]string
path string // path in zookeeper representing this action
path string // path in zookeeper representing this action, don't serialize
}
func ActionNodeFromJson(data, path string) (*ActionNode, error) {
@ -81,6 +81,10 @@ func ActionNodeFromJson(data, path string) (*ActionNode, error) {
return node, nil
}
func (n *ActionNode) Path() string {
return n.path
}
func ActionNodeToJson(n *ActionNode) string {
return jscfg.ToJson(n)
}

Просмотреть файл

@ -49,7 +49,7 @@ func NewActionInitiator(zconn zk.Conn) *ActionInitiator {
}
func actionGuid() string {
now := time.Now().Unix()
now := time.Now().Format(time.RFC3339)
username := "unknown"
if u, err := user.Current(); err == nil {
username = u.Username

Просмотреть файл

@ -89,20 +89,23 @@ func GetAllTablets(zconn zk.Conn, zkVtPath string) ([]*tm.TabletInfo, error) {
return tablets, nil
}
// copy keys from from map m into slice s - types must match.
func CopyMapKeys(s, m interface{}) {
keys := reflect.ValueOf(s)
// Copy keys from from map m into a new slice with the type specified
// by typeHint. Reflection can't make a new slice type just based on
// the key type AFAICT.
func CopyMapKeys(m interface{}, typeHint interface{}) interface{} {
mapVal := reflect.ValueOf(m)
for _, kv := range mapVal.MapKeys() {
keys = reflect.AppendSlice(keys, kv)
keys := reflect.MakeSlice(reflect.TypeOf(typeHint), 0, mapVal.Len())
for _, k := range mapVal.MapKeys() {
keys = reflect.Append(keys, k)
}
return keys.Interface()
}
// copy values from from map m into slice s - types must match.
func CopyMapValues(s, m interface{}) {
keys := reflect.ValueOf(s)
func CopyMapValues(m interface{}, typeHint interface{}) interface{} {
mapVal := reflect.ValueOf(m)
for _, kv := range mapVal.MapKeys() {
keys = reflect.AppendSlice(keys, mapVal.MapIndex(kv))
vals := reflect.MakeSlice(reflect.TypeOf(typeHint), 0, mapVal.Len())
for _, k := range mapVal.MapKeys() {
vals = reflect.Append(vals, mapVal.MapIndex(k))
}
return vals.Interface()
}