// PruneActionLogs prunes old actionlog entries. Returns how many // entries were purged (even if there was an error). // // There is a chance some processes might still be waiting for action // results, but it is very very small. func (zkts *Server) PruneActionLogs(zkActionLogPath string, keepCount int) (prunedCount int, err error) { if path.Base(zkActionLogPath) != "actionlog" { return 0, fmt.Errorf("not actionlog path: %v", zkActionLogPath) } // get sorted list of children children, _, err := zkts.zconn.Children(zkActionLogPath) if err != nil { return 0, err } sort.Strings(children) // see if nothing to do if len(children) <= keepCount { return 0, nil } for i := 0; i < len(children)-keepCount; i++ { actionPath := path.Join(zkActionLogPath, children[i]) err = zk.DeleteRecursive(zkts.zconn, actionPath, -1) if err != nil { return prunedCount, fmt.Errorf("purge action err: %v", err) } prunedCount++ } return prunedCount, nil }
// PurgeActions removes all queued actions, leaving the action node // itself in place. // // This inherently breaks the locking mechanism of the action queue, // so this is a rare cleanup action, not a normal part of the flow. // // This can be used for tablets, shards and keyspaces. func (zkts *Server) PurgeActions(zkActionPath string, canBePurged func(data string) bool) error { if path.Base(zkActionPath) != "action" { return fmt.Errorf("not action path: %v", zkActionPath) } children, _, err := zkts.zconn.Children(zkActionPath) if err != nil { return err } sort.Strings(children) // Purge newer items first so the action queues don't try to process something. for i := len(children) - 1; i >= 0; i-- { actionPath := path.Join(zkActionPath, children[i]) data, _, err := zkts.zconn.Get(actionPath) if err != nil && !zookeeper.IsError(err, zookeeper.ZNONODE) { return fmt.Errorf("PurgeActions(%v) err: %v", zkActionPath, err) } if !canBePurged(data) { continue } err = zk.DeleteRecursive(zkts.zconn, actionPath, -1) if err != nil && !zookeeper.IsError(err, zookeeper.ZNONODE) { return fmt.Errorf("PurgeActions(%v) err: %v", zkActionPath, err) } } return nil }
func (zkts *Server) DeleteTablet(alias topo.TabletAlias) error { // We need to find out the keyspace and shard names because those are required // in the TabletChange event. ti, tiErr := zkts.GetTablet(alias) zkTabletPath := TabletPathForAlias(alias) err := zk.DeleteRecursive(zkts.zconn, zkTabletPath, -1) if err != nil { if zookeeper.IsError(err, zookeeper.ZNONODE) { err = topo.ErrNoNode } return err } // Only try to log if we have the required information. if tiErr == nil { // We only want to copy the identity info for the tablet (alias, etc.). // The rest has just been deleted, so it should be blank. event.Dispatch(&events.TabletChange{ Tablet: topo.Tablet{ Alias: ti.Tablet.Alias, Keyspace: ti.Tablet.Keyspace, Shard: ti.Tablet.Shard, }, Status: "deleted", }) } return nil }
func (zkts *Server) unlockForAction(lockPath, results string) error { // Write the data to the actionlog actionLogPath := strings.Replace(lockPath, "/action/", "/actionlog/", 1) if _, err := zk.CreateRecursive(zkts.zconn, actionLogPath, results, 0, zookeeper.WorldACL(zookeeper.PERM_ALL)); err != nil { log.Warningf("Cannot create actionlog path %v (check the permissions with 'zk stat'), will keep the lock, use 'zk rm' to clear the lock", actionLogPath) return err } // and delete the action return zk.DeleteRecursive(zkts.zconn, lockPath, -1) }
func (zkts *Server) DeleteKeyspaceShards(keyspace string) error { shardsPath := path.Join(globalKeyspacesPath, keyspace, "shards") if err := zk.DeleteRecursive(zkts.zconn, shardsPath, -1); err != nil && !zookeeper.IsError(err, zookeeper.ZNONODE) { return err } event.Dispatch(&events.KeyspaceChange{ KeyspaceInfo: *topo.NewKeyspaceInfo(keyspace, nil, -1), Status: "deleted all shards", }) return nil }
func cmdRm(subFlags *flag.FlagSet, args []string) { var ( force = subFlags.Bool("f", false, "no warning on nonexistent node") recursiveDelete = subFlags.Bool("r", false, "recursive delete") forceAndRecursive = subFlags.Bool("rf", false, "shorthand for -r -f") ) subFlags.Parse(args) *force = *force || *forceAndRecursive *recursiveDelete = *recursiveDelete || *forceAndRecursive if subFlags.NArg() == 0 { log.Fatal("rm: no path specified") } if *recursiveDelete { for _, arg := range subFlags.Args() { zkPath := fixZkPath(arg) if strings.Count(zkPath, "/") < 4 { log.Fatalf("rm: overly general path: %v", zkPath) } } } resolved, err := zk.ResolveWildcards(zconn, subFlags.Args()) if err != nil { log.Fatalf("rm: invalid wildcards: %v", err) } if len(resolved) == 0 { // the wildcards didn't result in anything, we're done return } hasError := false for _, arg := range resolved { zkPath := fixZkPath(arg) var err error if *recursiveDelete { err = zk.DeleteRecursive(zconn, zkPath, -1) } else { err = zconn.Delete(zkPath, -1) } if err != nil && (!*force || !zookeeper.IsError(err, zookeeper.ZNONODE)) { hasError = true log.Warningf("rm: cannot delete %v: %v", zkPath, err) } } if hasError { // to be consistent with the command line 'rm -f', return // 0 if using 'zk rm -f' and the file doesn't exist. os.Exit(1) } }
func (zkts *Server) DeleteShard(keyspace, shard string) error { shardPath := path.Join(globalKeyspacesPath, keyspace, "shards", shard) err := zk.DeleteRecursive(zkts.zconn, shardPath, -1) if err != nil { if zookeeper.IsError(err, zookeeper.ZNONODE) { err = topo.ErrNoNode } return err } event.Dispatch(&events.ShardChange{ ShardInfo: *topo.NewShardInfo(keyspace, shard, nil, -1), Status: "deleted", }) return nil }