<commit_before>ZooKeeper C++
=============

A ZooKeeper client for C++.

Features include (but are not necessarily limited to):

- Simple

  - Connect with just a connection string
  - Clients should not require factories
  - Does not require *any* knowledge of the Java or C APIs

- Configurable

  - Use the parts you need
  - Change parts to fit in your application

- Safe

  - In the best case, illegal code should fail to compile
  - An illegal action should throw an exception
  - Utility functions have a `strong exception guarantee <http://www.gotw.ca/gotw/082.htm>`_

- Stable

  - Worry less about upgrading -- the API and ABI will not change out from under you

- Documented

  - Consumable by human beings
  - Answers questions you might actually ask

**NOTE**: This library is a work-in-progress.
All documentation you see here is subject to change and non-existence.

Usage
-----

Ultimately, the usage looks like this (assuming you have a ZooKeeper server running on your local host)::

    #include <zk/client.hpp>
    #include <zk/multi.hpp>

    #include <iostream>

    int main()
    {
        zk::client client("zk://127.0.0.1:2181");

        // foobar's type is zk::future<std::pair<zk::buffer, zk::stat>>
        auto foobar = client.get("/foo/bar");

        // children's type is zk::future<std::pair<std::vector<std::string>, zk::stat>>
        auto children = client.get_children("/foo");

        // set_res's type is zk::future<zk::stat>
        auto set_res = client.set("/foo/bar", "some data");
        auto foo_bar_version = set_res.get().data_version;

        // create_res's type is zk::future<std::string>
        auto create_res = client.create("/foo/baz", "more data");
        // More explicit: client.create("/foo/baz", "more data", zk::acls::all(), zk::create_flags::none);

        zk::multi ops =
        {
            zk::op::check("/foo", zk::version::any()),
            zk::op::check("/foo/baz", foo_bar_version),
            zk::op::create("/foo/bap", "hi", nullopt, zk::create_flags::sequential),
            zk::op::erase("/foo/bzr"),
        };
        // multi_res's type is zk::future<zk::multi_result>
        auto multi_res = client.commit(ops);
        multi_res.get();
    }

Value-Added Features
--------------------

The core library of ``libzkpp`` provides the primitives for connecting to and manipulating a ZooKeeper database.
This library also bundles a number of other features that are commonly required when working with a ZooKeeper cluster.

``zk/curator``
^^^^^^^^^^^^^^

Things in ``zk/curator`` have features found in the `Apache Curator <http://curator.apache.org/>`_ project.

* Elections

  * `Leader Latch <http://curator.apache.org/curator-recipes/leader-latch.html>`_
  * `Leader Election <http://curator.apache.org/curator-recipes/leader-election.html>`_

* Locks

  * `Shared Reentrant Lock <http://curator.apache.org/curator-recipes/shared-reentrant-lock.html>`_
  * `Shared Lock <http://curator.apache.org/curator-recipes/shared-lock.html>`_
  * `Shared Reentrant Read Write Lock <http://curator.apache.org/curator-recipes/shared-reentrant-read-write-lock.html>`_
  * `Shared Semaphore <http://curator.apache.org/curator-recipes/shared-semaphore.html>`_
  * `Multi Shared Lock <http://curator.apache.org/curator-recipes/multi-shared-lock.html>`_

* Barriers

  * `Barrier <http://curator.apache.org/curator-recipes/barrier.html>`_
  * `Double Barrier <http://curator.apache.org/curator-recipes/double-barrier.html>`_

* Counters

  * `Shared Counter <http://curator.apache.org/curator-recipes/shared-counter.html>`_
  * `Distributed Atomic Long <http://curator.apache.org/curator-recipes/distributed-atomic-long.html>`_

* Caches

  * `Path Cache <http://curator.apache.org/curator-recipes/path-cache.html>`_
  * `Node Cache <http://curator.apache.org/curator-recipes/node-cache.html>`_
  * `Tree Cache <http://curator.apache.org/curator-recipes/tree-cache.html>`_

* Nodes

  * `Persistent Node <http://curator.apache.org/curator-recipes/persistent-node.html>`_
  * `Persistent TTL Node <http://curator.apache.org/curator-recipes/persistent-ttl-node.html>`_
  * `Group Member <http://curator.apache.org/curator-recipes/group-member.html>`_

None of the queue types are planned to be implemented.
The `Curator Documentation (TN4) <https://cwiki.apache.org/confluence/display/CURATOR/TN4>`_ advises against their use,
claiming "it is a bad idea to use ZooKeeper as a Queue."
The authors of this library agree with this claim.

``zk/fake``
^^^^^^^^^^^

This library also provides a fake version of ZooKeeper which operates in-memory.
It is meant to be used in your unit testing, when fine-grained control of behavior of ZooKeeper is needed.
This allows for the injection of arbitrary behavior into ZK, allowing you to simulate some of the hard-to-reproduce
issues like ``zk::event_type::not_watching``, ``zk::marshalling_error``, or timing bugs.
It also allows for fast creation and teardown of entire databases, which is commonly done in unit testing.

It is connected to through using a connection string of the form::

    fake://{name}

To use this in unit tests link to ``libzkpp_fake`` and ``zk::fake::server``::

    TEST(my_test)
    {
        // The default constructor uses a randomly-generated unique name
        zk::fake::server server;<commit_msg>doc: Updates README links to issues instead of the Curator documentation.<commit_after>ZooKeeper C++
=============

A ZooKeeper client for C++.

Features include (but are not necessarily limited to):

- Simple

  - Connect with just a connection string
  - Clients should not require factories
  - Does not require *any* knowledge of the Java or C APIs

- Configurable

  - Use the parts you need
  - Change parts to fit in your application

- Safe

  - In the best case, illegal code should fail to compile
  - An illegal action should throw an exception
  - Utility functions have a `strong exception guarantee <http://www.gotw.ca/gotw/082.htm>`_

- Stable

  - Worry less about upgrading -- the API and ABI will not change out from under you

- Documented

  - Consumable by human beings
  - Answers questions you might actually ask

**NOTE**: This library is a work-in-progress.
All documentation you see here is subject to change and non-existence.

Usage
-----

Ultimately, the usage looks like this (assuming you have a ZooKeeper server running on your local host)::

    #include <zk/client.hpp>
    #include <zk/multi.hpp>

    #include <iostream>

    int main()
    {
        zk::client client("zk://127.0.0.1:2181");

        // foobar's type is zk::future<std::pair<zk::buffer, zk::stat>>
        auto foobar = client.get("/foo/bar");

        // children's type is zk::future<std::pair<std::vector<std::string>, zk::stat>>
        auto children = client.get_children("/foo");

        // set_res's type is zk::future<zk::stat>
        auto set_res = client.set("/foo/bar", "some data");
        auto foo_bar_version = set_res.get().data_version;

        // create_res's type is zk::future<std::string>
        auto create_res = client.create("/foo/baz", "more data");
        // More explicit: client.create("/foo/baz", "more data", zk::acls::all(), zk::create_flags::none);

        zk::multi ops =
        {
            zk::op::check("/foo", zk::version::any()),
            zk::op::check("/foo/baz", foo_bar_version),
            zk::op::create("/foo/bap", "hi", nullopt, zk::create_flags::sequential),
            zk::op::erase("/foo/bzr"),
        };
        // multi_res's type is zk::future<zk::multi_result>
        auto multi_res = client.commit(ops);
        multi_res.get();
    }

Value-Added Features
--------------------

The core library of ``libzkpp`` provides the primitives for connecting to and manipulating a ZooKeeper database.
This library also bundles a number of other features that are commonly required when working with a ZooKeeper cluster.

``zk/curator``
^^^^^^^^^^^^^^

Things in ``zk/curator`` have features found in the `Apache Curator <http://curator.apache.org/>`_ project.

* Elections

  * `Leader Latch <https://github.com/tgockel/zookeeper-cpp/issues/1>`_
  * `Leader Election <https://github.com/tgockel/zookeeper-cpp/issues/2>`_

* Locks

  * `Shared Reentrant Lock <https://github.com/tgockel/zookeeper-cpp/issues/3>`_
  * `Shared Lock <https://github.com/tgockel/zookeeper-cpp/issues/4>`_
  * `Shared Reentrant Read Write Lock <https://github.com/tgockel/zookeeper-cpp/issues/5>`_
  * `Shared Semaphore <https://github.com/tgockel/zookeeper-cpp/issues/6>`_
  * `Multi Shared Lock <https://github.com/tgockel/zookeeper-cpp/issues/7>`_

* Barriers

  * `Barrier <https://github.com/tgockel/zookeeper-cpp/issues/8>`_
  * `Double Barrier <https://github.com/tgockel/zookeeper-cpp/issues/9>`_

* Counters

  * `Shared Counter <https://github.com/tgockel/zookeeper-cpp/issues/10>`_
  * `Distributed Atomic Long <https://github.com/tgockel/zookeeper-cpp/issues/11>`_

* Caches

  * `Path Cache <https://github.com/tgockel/zookeeper-cpp/issues/12>`_
  * `Node Cache <https://github.com/tgockel/zookeeper-cpp/issues/13>`_
  * `Tree Cache <https://github.com/tgockel/zookeeper-cpp/issues/14>`_

* Nodes

  * `Persistent Node <https://github.com/tgockel/zookeeper-cpp/issues/15>`_
  * `Persistent TTL Node <https://github.com/tgockel/zookeeper-cpp/issues/16>`_
  * `Group Member <https://github.com/tgockel/zookeeper-cpp/issues/17>`_

None of the queue types are planned to be implemented.
The `Curator Documentation (TN4) <https://cwiki.apache.org/confluence/display/CURATOR/TN4>`_ advises against their use,
claiming "it is a bad idea to use ZooKeeper as a Queue."
The authors of this library agree with this claim.

``zk/fake``
^^^^^^^^^^^

This library also provides a fake version of ZooKeeper which operates in-memory.
It is meant to be used in your unit testing, when fine-grained control of behavior of ZooKeeper is needed.
This allows for the injection of arbitrary behavior into ZK, allowing you to simulate some of the hard-to-reproduce
issues like ``zk::event_type::not_watching``, ``zk::marshalling_error``, or timing bugs.
It also allows for fast creation and teardown of entire databases, which is commonly done in unit testing.

It is connected to through using a connection string of the form::

    fake://{name}

To use this in unit tests link to ``libzkpp_fake`` and ``zk::fake::server``::

    TEST(my_test)
    {
        // The default constructor uses a randomly-generated unique name
        zk::fake::server server;
{'fraction_non_alphanumeric': 0.13934270516717326, 'fraction_numerical': 0.005224164133738602, 'mean_word_length': 3.509207708779443, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 65, 'https://': 19, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2293812', 'n_tokens_mistral': 3480, 'n_tokens_neox': 3257, 'n_words': 959}