コード例 #1
0
        // This not just a copy operation since the config manager takes care of construction the znode path to configsets
        public static async Task upConfig(SolrZkClient zkClient, string confPath, string confName, CancellationToken token)
        {
            ZkConfigManager manager = new ZkConfigManager(zkClient);

            // Try to download the configset
            await manager.uploadConfigDir(confPath, confName, token);
        }
コード例 #2
0
        /// <summary>
        /// Delete a path and all of its sub nodes
        /// yeah, it's recursive :(
        /// </summary>
        /// <param name="zkClient"></param>
        /// <param name="path"></param>
        /// <param name="filter">For node to be deleted</param>
        /// <returns></returns>
        public static async Task clean(SolrZkClient zkClient, string path, CancellationToken token, Predicate <string> filter = null)
        {
            var paths = new List <string>();

            await traverseZkTree(zkClient, path, VISIT_ORDER.VISIT_POST, znode =>
            {
                if (!znode.Equals("/") && (filter?.Invoke(znode) ?? true))
                {
                    paths.Add(znode);
                }
            });

            foreach (var subpath in paths.OrderByDescending(s => s.Length))
            {
                if (!subpath.Equals("/"))
                {
                    try
                    {
                        token.ThrowIfCancellationRequested();
                        await zkClient.delete(subpath, -1, true);
                    }
                    catch (Exception ex)
                    {
                        if (ex is KeeperException.NotEmptyException || ex is KeeperException.NoNodeException)
                        {
                            //expected
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            }
        }
コード例 #3
0
        public static async Task moveZnode(SolrZkClient zkClient, string src, string dst, CancellationToken token)
        {
            String destName = normalizeDest(src, dst, true, true);

            // Special handling if the source has no children, i.e. copying just a single file.
            if (!(await zkClient.getChildren(src, null, true)).Any())
            {
                await zkClient.makePath(destName, false, true);

                await zkClient.setData(destName, await zkClient.getData(src, null, null, true), true);
            }
            else
            {
                await traverseZkTree(zkClient, src, VISIT_ORDER.VISIT_PRE, async path =>
                {
                    var finalDestination = dst;
                    if (path.Equals(src) == false)
                    {
                        finalDestination += "/" + path.Substring(src.Length + 1);
                    }
                    await zkClient.makePath(finalDestination, false, true);
                    await zkClient.setData(finalDestination, await zkClient.getData(path, null, null, true), true);
                });
            }

            // Insure all source znodes are present in dest before deleting the source.
            // throws error if not all there so the source is left intact. Throws error if source and dest don't match.
            await checkAllZnodesThere(zkClient, src, destName);

            await clean(zkClient, src, token);
        }
コード例 #4
0
        public static async Task uploadToZK(SolrZkClient zkClient, string fromPath, string zkPath, Regex filenameExclusions, CancellationToken token)
        {
            var path = fromPath;

            if (path.EndsWith("*"))
            {
                path = path.Substring(0, path.Length - 1);
            }

            var rootPath = path;

            if (!Directory.Exists(rootPath))
            {
                if (!File.Exists(rootPath))
                {
                    throw new IOException("Path " + rootPath + " does not exist");
                }
                var filePath = path;
                token.ThrowIfCancellationRequested();
                await uploadFileToZk(zkClient, zkPath, filePath, filenameExclusions);
            }

            WalkFileTree(rootPath, async(file) =>
            {
                var zkNode = createZkNodeName(zkPath, rootPath, file);
                await uploadFileToZk(zkClient, zkNode, file, filenameExclusions);
            }, token);
        }
コード例 #5
0
        private static async Task uploadFileToZk(SolrZkClient zkClient, string zkNode, string file, Regex filenameExclusions)
        {
            var fielName = Path.GetFileName(file);

            if (filenameExclusions != null && filenameExclusions.Match(fielName ?? throw new InvalidOperationException("File name is empty")).Success)
            {
                //TODO: Log here
                //log.info("uploadToZK skipping '{}' due to filenameExclusions '{}'", filename, filenameExclusions);
                return;
            }
            try
            {
                // if the path exists (and presumably we're uploading data to it) just set its data
                if (Path.GetFileName(file).Equals(ZKNODE_DATA_FILE) && (await zkClient.exists(zkNode, true)))
                {
                    await zkClient.setData(zkNode, file, true);
                }
                else
                {
                    //Can't work async because it will try to create same path
                    zkClient.makePath(zkNode, file, false, true).Wait();
                }
            }
            catch (KeeperException ex)
            {
                throw new Exception("Error uploading file " + file + " to zookeeper path " + zkNode, SolrZkClient.checkInterrupted(ex));
            }
        }
コード例 #6
0
        public static async Task downloadFromZK(SolrZkClient zkClient, string zkPath, string filePath, CancellationToken token)
        {
            try
            {
                token.ThrowIfCancellationRequested();
                var children = await zkClient.getChildren(zkPath, null, true);

                // If it has no children, it's a leaf node, write the associated data from the ZNode.
                // Otherwise, continue recursing, but write the associated data to a special file if any
                if (!children.Any())
                {
                    // If we didn't copy data down, then we also didn't create the file. But we still need a marker on the local
                    // disk so create an empty file.
                    if (await copyDataDown(zkClient, zkPath, filePath) == 0)
                    {
                        Debug.WriteLine("Download: " + filePath);
                        File.Create(filePath);
                    }
                }
                else
                {
                    Directory.CreateDirectory(filePath); // Make parent dir.
                                                         // ZK nodes, whether leaf or not can have data. If it's a non-leaf node and
                                                         // has associated data write it into the special file.
                    token.ThrowIfCancellationRequested();
                    Debug.WriteLine("Download: " + filePath);
                    await copyDataDown(zkClient, zkPath, Path.Combine(filePath, ZKNODE_DATA_FILE));

                    foreach (var child in children)
                    {
                        var zkChild = zkPath;
                        if (zkChild.EndsWith("/") == false)
                        {
                            zkChild += "/";
                        }
                        zkChild += child;
                        if (await isEphemeral(zkClient, zkChild))
                        {
                            // Don't copy ephemeral nodes
                            continue;
                        }
                        // Go deeper into the tree now
                        await downloadFromZK(zkClient, zkChild, Path.Combine(filePath, child), token);
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex is KeeperException || ex is ThreadInterruptedException)
                {
                    throw new IOException("Error downloading files from zookeeper path " + zkPath + " to " + filePath,
                                          SolrZkClient.checkInterrupted(ex));
                }
                throw;
            }
        }
コード例 #7
0
 // Insure that all the nodes in one path match the nodes in the other as a safety check before removing
 // the source in a 'mv' command.
 private static async Task checkAllZnodesThere(SolrZkClient zkClient, string src, string dst)
 {
     foreach (var node in await zkClient.getChildren(src, null, true))
     {
         if (await zkClient.exists(dst + "/" + node, true) == false)
         {
             throw new Exception("mv command did not move node " + dst + "/" + node + " source left intact");
         }
         await checkAllZnodesThere(zkClient, src + "/" + node, dst + "/" + node);
     }
 }
コード例 #8
0
        public static async Task <int> copyDataDown(SolrZkClient zkClient, string zkPath, string filePath)
        {
            var data = await zkClient.getData(zkPath, null, null, true);

            if (data == null || data.Length <= 1)
            {
                return(0); // There are apparently basically empty ZNodes.
            }
            //TODO: Log here
            //log.info("Writing file {}", file.toString());
            File.WriteAllBytes(filePath, data);
            return(data.Length);
        }
コード例 #9
0
        //TODO: Check if works
        #region CHECK IF WORKS

        /// <summary>
        /// Lists a ZNode child and (optionally) the znodes of all the children. No data is dumped
        /// </summary>
        /// <param name="zkClient"></param>
        /// <param name="path">The node to remove on Zookeeper</param>
        /// <param name="recurse">Whether to remove children</param>
        /// <returns>An indented list of the znodes suitable for display</returns>
        /// <exception cref="KeeperException"> Could not perform the Zookeeper operation</exception>
        public static async Task <string> listZnode(SolrZkClient zkClient, string path, bool recurse)
        {
            var root = path;

            if (path.ToLower(CultureInfo.InvariantCulture).StartsWith("zk:"))
            {
                root = path.Substring(3);
            }
            if (root.Equals("/") == false && root.EndsWith("/"))
            {
                root = root.Substring(0, root.Length - 1);
            }

            var sb = new StringBuilder();

            if (recurse == false)
            {
                foreach (var node in await zkClient.getChildren(root, null, true))
                {
                    if (node.Equals("zookeeper") == false)
                    {
                        sb.Append(node).Append(Environment.NewLine);
                    }
                }
                return(sb.ToString());
            }

            await traverseZkTree(zkClient, root, VISIT_ORDER.VISIT_PRE, znode =>
            {
                if (znode.StartsWith("/zookeeper"))
                {
                    return;                                 // can't do anything with this node!
                }
                int iPos = znode.LastIndexOf("/");
                if (iPos > 0)
                {
                    for (int idx = 0; idx < iPos; ++idx)
                    {
                        sb.Append(" ");
                    }
                    sb.Append(znode.Substring(iPos + 1)).Append(Environment.NewLine);
                }
                else
                {
                    sb.Append(znode).Append(Environment.NewLine);
                }
            });

            return(sb.ToString());
        }
コード例 #10
0
 /// <summary>
 /// Check whether a config exists in Zookeeper
 /// </summary>
 /// <param name="configName">The config to check existance on</param>
 /// <returns>Whether the config exists or not</returns>
 /// <exception cref="IOException">If an I/O error occurs</exception>
 public async Task <bool> configExists(string configName)
 {
     try
     {
         return(await zkClient.exists(ConfigsZKnode + "/" + configName, true));
     }
     catch (Exception ex)
     {
         if (ex is KeeperException || ex is ThreadInterruptedException)
         {
             throw new IOException("Error checking whether config exists", SolrZkClient.checkInterrupted(ex));
         }
         throw;
     }
 }
コード例 #11
0
 /// <summary>
 /// Delete a config in ZooKeeper
 /// </summary>
 /// <param name="configName">The config to delete</param>
 /// <param name="token"></param>
 /// <exception cref="IOException">If an I/O error occurs</exception>
 public async Task deleteConfigDir(string configName, CancellationToken token)
 {
     try
     {
         await zkClient.clean(ConfigsZKnode + "/" + configName, token);
     }
     catch (Exception ex)
     {
         if (ex is KeeperException || ex is ThreadInterruptedException)
         {
             throw new IOException("Error checking whether config exists", SolrZkClient.checkInterrupted(ex));
         }
         throw;
     }
 }
コード例 #12
0
 public async Task <List <string> > listConfigs()
 {
     try
     {
         return(await zkClient.getChildren(ConfigsZKnode, null, true));
     }
     catch (KeeperException.NoNodeException)
     {
         return(new List <string>());
     }
     catch (Exception ex)
     {
         if (ex is KeeperException || ex is ThreadInterruptedException)
         {
             throw new IOException("Error listing configs", SolrZkClient.checkInterrupted(ex));
         }
         throw;
     }
 }
コード例 #13
0
        public static async Task <IEnumerable <string> > GetTree(SolrZkClient zkCnxn, string zooPath = "/")
        {
            var children = (await zkCnxn.getChildren(zooPath, null, false));
            var nodes    = new List <string>();

            if (!children.Any())
            {
                return(nodes);
            }
            if (zooPath.Last() != '/')
            {
                zooPath += "/";
            }
            foreach (var child in children)
            {
                nodes.Add(zooPath + child);
                nodes.AddRange(await GetTree(zkCnxn, zooPath + child));
            }
            return(nodes);
        }
コード例 #14
0
        /// <summary>
        /// Recursively visit a zk tree rooted at path and apply the given visitor to each path. Exists as a separate method
        /// because some of the logic can get nuanced.
        /// </summary>
        /// <param name="zkClient"></param>
        /// <param name="path">The path to start from</param>
        /// <param name="visitOrder">Whether to call the visitor at the at the ending or beginning of the run.</param>
        /// <param name="visitor">The operation to perform on each path</param>
        public static async Task traverseZkTree(SolrZkClient zkClient, string path, VISIT_ORDER visitOrder, Action <string> visitor)
        {
            if (visitOrder == VISIT_ORDER.VISIT_PRE)
            {
                visitor.Invoke(path);
            }
            List <string> children;

            try
            {
                children = await zkClient.getChildren(path, null, true);
            }
            catch (KeeperException.NoNodeException)
            {
                return;
            }
            foreach (var child in children)
            {
                // we can't do anything to the built-in zookeeper node
                if (path.Equals("/") && child.Equals("zookeeper"))
                {
                    continue;
                }
                if (path.StartsWith("/zookeeper"))
                {
                    continue;
                }
                if (path.Equals("/"))
                {
                    await traverseZkTree(zkClient, path + child, visitOrder, visitor);
                }
                else
                {
                    await traverseZkTree(zkClient, path + "/" + child, visitOrder, visitor);
                }
            }
            if (visitOrder == VISIT_ORDER.VISIT_POST)
            {
                visitor.Invoke(path);
            }
        }
コード例 #15
0
 public async void EnsureExists(string path, byte[] data, CreateMode createMode, SolrZkClient zkClient, int skipPathParts)
 {
     if (await zkClient.exists(path, true))
     {
         return;
     }
     try
     {
         await zkClient.makePath(path, data, createMode, null, true, true, skipPathParts);
     }
     catch (KeeperException.NodeExistsException ex)
     {
         // it's okay if another beats us creating the node
     }
 }
コード例 #16
0
 public void EnsureExists(string path, byte[] data, CreateMode createMode, SolrZkClient zkClient)
 {
     EnsureExists(path, data, createMode, zkClient, 0);
 }
コード例 #17
0
 public void EnsureExists(string path, byte[] data, SolrZkClient zkClient)
 {
     EnsureExists(path, data, CreateMode.PERSISTENT, zkClient, 0);
 }
コード例 #18
0
 public void EnsureExists(string path, SolrZkClient zkClient)
 {
     EnsureExists(path, null, CreateMode.PERSISTENT, zkClient, 0);
 }
コード例 #19
0
        /// <summary>
        /// Copy between local file system and Zookeeper, or from one Zookeeper node to another, optionally copying recursively.
        /// </summary>
        /// <param name="zkClient"></param>
        /// <param name="src">Source to copy from. Both src and dst may be Znodes. However, both may NOT be local</param>
        /// <param name="srcIsZk"></param>
        /// <param name="dst">The place to copy the files too. Both src and dst may be Znodes. However both may NOT be local</param>
        /// <param name="dstIsZk"></param>
        /// <param name="recurse">If the source is a directory, reccursively copy the contents iff this is true.</param>
        /// <exception cref="ArgumentException">Explanatory exception due to bad params, failed operation, etc.</exception>
        public static async Task zkTransfer(SolrZkClient zkClient, string src, bool srcIsZk, string dst, bool dstIsZk, bool recurse, CancellationToken token)
        {
            if (srcIsZk == false && dstIsZk == false)
            {
                throw new Exception("One or both of source or destination must specify ZK nodes.");
            }

            // Make sure -recurse is specified if the source has children.
            if (recurse == false)
            {
                if (srcIsZk)
                {
                    if ((await zkClient.getChildren(src, null, true)).Any())
                    {
                        throw new ArgumentException("Zookeeper node " + src + " has children and recurse is false");
                    }
                }
                else if (IsDirectory(src))
                {
                    throw new ArgumentException("Local path " + src + " is a directory and recurse is false");
                }
            }

            if (dstIsZk && dst.Length == 0)
            {
                dst = "/"; // for consistency, one can copy from zk: and send to zk:/
            }
            dst = normalizeDest(src, dst, srcIsZk, dstIsZk);

            // ZK -> ZK copy.
            if (srcIsZk && dstIsZk)
            {
                await traverseZkTree(zkClient, src, VISIT_ORDER.VISIT_PRE, async path =>
                {
                    var finalDestination = dst;
                    if (path.Equals(src) == false)
                    {
                        finalDestination += "/" + path.Substring(src.Length + 1);
                    }
                    await zkClient.makePath(finalDestination, false, true);
                    await zkClient.setData(finalDestination, await zkClient.getData(path, null, null, true), true);
                });

                return;
            }

            //local -> ZK copy
            if (dstIsZk)
            {
                await uploadToZK(zkClient, src, dst, null, token);

                return;
            }

            // Copying individual files from ZK requires special handling since downloadFromZK assumes the node has children.
            // This is kind of a weak test for the notion of "directory" on Zookeeper.
            // ZK -> local copy where ZK is a parent node
            if ((await zkClient.getChildren(src, null, true)).Any())
            {
                await downloadFromZK(zkClient, src, dst, token);

                return;
            }

            // Single file ZK -> local copy where ZK is a leaf node
            if (IsDirectory(dst))
            {
                if (dst.EndsWith(Path.DirectorySeparatorChar.ToString()) == false)
                {
                    dst += Path.DirectorySeparatorChar;
                }
                dst = normalizeDest(src, dst, srcIsZk, dstIsZk);
            }
            byte[] data = await zkClient.getData(src, null, null, true);

            Directory.CreateDirectory(Path.GetDirectoryName(dst));
            //TODO: Log here
            //log.info("Writing file {}", filename);
            File.WriteAllBytes(dst, data);
        }
コード例 #20
0
 /// <summary>
 /// Creates a new ZkConfigManager
 /// </summary>
 /// <param name="zkClient">zkClient the SolrZkClient to use</param>
 public ZkConfigManager(SolrZkClient zkClient)
 {
     this.zkClient = zkClient;
 }
コード例 #21
0
        public static async Task <bool> isEphemeral(SolrZkClient zkClient, string zkPath)
        {
            var znodeStat = await zkClient.exists(zkPath, null, true);

            return(znodeStat.getEphemeralOwner() != 0);
        }
コード例 #22
0
        private async Task copyConfigDirFromZk(string fromZkPath, string toZkPath, ISet <string> copiedToZkPaths = null)
        {
            try
            {
                var files = await zkClient.getChildren(fromZkPath, null, true);

                foreach (var file in files)
                {
                    var children = await zkClient.getChildren(fromZkPath + "/" + file, null, true);

                    if (!children.Any())
                    {
                        var toZkFilePath = toZkPath + "/" + file;
                        //TODO: Log here
                        //logger.info("Copying zk node {} to {}",fromZkPath + "/" + file, toZkFilePath);
                        var data = await zkClient.getData(fromZkPath + "/" + file, null, null, true);

                        //Take care it fails on Exists
                        await zkClient.makePath(toZkFilePath, data, true);

                        copiedToZkPaths?.Add(toZkFilePath);
                    }
                    else
                    {
                        await copyConfigDirFromZk(fromZkPath + "/" + file, toZkPath + "/" + file, copiedToZkPaths);
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex is KeeperException || ex is ThreadInterruptedException)
                {
                    throw new IOException("Error copying nodes from zookeeper path " + fromZkPath + " to " + toZkPath, SolrZkClient.checkInterrupted(ex));
                }
                throw;
            }
        }