[Bro-Dev] Broker data store API

Matthias Vallentin vallentin at icir.org
Fri Jul 22 12:26:10 PDT 2016


  - Does anyone use Broker's RocksDB backend?
  - Brief overview of the revamped data store frontend API

I've been working on the Broker data store API a bit, trying to come
with the smallest denominator possible for an initial release. So far I
have ported the in-memory SQLite backend over. This made me wonder: did
anyone ever use (or wanted to use) the RocksDB in production? I wonder
if we can keep it out for Bro 2.5.

Regarding the API, here's a snippet that illustrates the user-facing

  // Setup an endpoint.
  context ctx;
  auto ep = ctx.spawn<blocking>();

  // Attach a master datastore with backend. The semantics of
  // "attaching" are open-or-create: if a master exists under the
  // given name, use it, otherwise create it.
  backend_options opts;
  opts["path"] = "/tmp/test.db";
  auto ds = ep.attach<master, sqlite>("foo", std::move(opts));
  if (!ds)

  // Perform some asynchronous operations.
  ds->put("foo", 4.2);
  ds->put(42, set{"x", "y", "z"});
  ds->remove(42, "z"); // data at key 42 is now {"x", "y"}
  ds->increment("foo", 1.7); // data at key "foo" is now 5.7

  // Add a value that expires after 10 seconds.
  ds->put("bar", 4.2, time::now() + std::chrono::seconds(10));

  // Get data in a blocking fashion.
  auto x = ds->get<blocking>("foo"); // Equivalent to: get("foo"), the
                                     // blocking API is the default.

  // Get data in a non-blocking fashion. The function then() returns
  // immediately and one MUST NOT capture any variables on the stack by
  // reference in the callback. The runtime invokes the callback as soon
  // as the result has arrived.
    [=](const data& d) {
      cout << "data at key 'foo': " << d << endl;
    [=](const error& e) {
      if (e == ec::no_such_key)
          cout << "no such key: foo" << endl;

Here's another setup with two peering endpoints, one having a master and
one a clone (directly taken from the unit tests). This illustrates how
data stores and peering go hand in hand.

  context ctx;
  auto ep0 = ctx.spawn<blocking>();
  auto ep1 = ctx.spawn<blocking>();
  auto m = ep0.attach<master, memory>("flaka");
  auto c = ep1.attach<clone>("flaka");
  c->put("foo", 4.2);
  std::this_thread::sleep_for(propagation_delay); // master -> clone
  auto v = c->get("foo");
  CHECK_EQUAL(v, data{4.2});
  c->decrement("foo", 0.2);
  std::this_thread::sleep_for(propagation_delay); // master -> clone
  v = c->get("foo");
  CHECK_EQUAL(v, data{4.0});

I think this API covers the most common use cases. It's always easy to
add functionality later, so my goal is to find the smallest common


More information about the bro-dev mailing list