# Atomic operations on Broker store

**URL:** <https://community.zeek.org/t/atomic-operations-on-broker-store/4949>\
**Category:** Zeek\
**Created:** [July 18, 2017, 9:56am UTC](https://community.zeek.org/t/atomic-operations-on-broker-store/4949 "2017-07-18T09:56:53Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bencteux\_Jeffrey](https://avatars.discourse-cdn.com/v4/letter/b/f17d59/32.png) [@Bencteux\_Jeffrey](https://community.zeek.org/u/Bencteux_Jeffrey)\
**Post date:** [July 18, 2017, 9:56am UTC](https://community.zeek.org/t/atomic-operations-on-broker-store/4949/1 "2017-07-18T09:56:53Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA256

Hi all,

I am playing around with Broker framework and I am having some trouble  
trying to share elements such as set or table between multiple instances  
of Bro.

What I am doing follows :

\* A master store script creates a table and add it to the store  
\* A frontend store script retreive the table, add elements to it and  
push it back to the store

I got strange results doing that such as only one element I was trying  
to add was added (never the same) so I suspected the problem was  
concurrency and that my operations were not atomic. Indeed, what happens  
it that every call to my function in the slave script do not retreive an  
up-to-date table. Retreiving and adding a new element to a table is not  
an atomic operation and no function in the API is defined to do it in  
one call.

If I do the same test with Broker::add\_to\_set() with a set instead of a  
table it works. And it seems that it is because it is implemented as an  
atomic operation in aux/broker/src/store/frontend.cc.

Any idea how to that with a table with existing functions? Or does it  
needs further developments? If so, any hints on how to implement that?

Here is the Bro scripts I used (debug prints removed) :

master.bro:

@load base/frameworks/broker  
@load broker\_wrapper

const broker\_port: port = 6666/tcp &redef;  
redef exit\_only\_after\_terminate = T;

global h: opaque of Broker::Handle;

event bro\_init()  
{  
&nbsp;&nbsp;&nbsp;&nbsp;Broker::enable();  
&nbsp;&nbsp;&nbsp;&nbsp;Broker::listen(broker\_port, "127.0.0.1");

&nbsp;&nbsp;&nbsp;&nbsp;h = Broker::create\_master("test\_store");

&nbsp;&nbsp;&nbsp;&nbsp;WRAPPER::broker\_table\_create(h, "test");  
}

event Broker::incoming\_connection\_established(peer\_name: string)  
{  
&nbsp;&nbsp;&nbsp;&nbsp;print "Conn established: ", peer\_name;  
}

frontend.bro:

@load base/frameworks/broker  
@load broker\_wrapper

const broker\_port: port = 6666/tcp &redef;  
redef exit\_only\_after\_terminate = T;

global h: opaque of Broker::Handle;

event bro\_init()  
{  
&nbsp;&nbsp;&nbsp;&nbsp;Broker::enable();  
&nbsp;&nbsp;&nbsp;&nbsp;Broker::connect("127.0.0.1", broker\_port, 1secs);  
}

event Broker::outgoing\_connection\_established(peer\_address: string,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;peer\_port: port,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;peer\_name: string)  
{  
&nbsp;&nbsp;&nbsp;&nbsp;print "Conn established: ", peer\_address, peer\_port, peer\_name;

&nbsp;&nbsp;&nbsp;&nbsp;h = Broker::create\_clone("test\_store");

&nbsp;&nbsp;&nbsp;&nbsp;WRAPPER::broker\_table\_insert(h, "test", Broker::data("one"),  
Broker::data("this"));  
&nbsp;&nbsp;&nbsp;&nbsp;WRAPPER::broker\_table\_insert(h, "test", Broker::data("two"),  
Broker::data("is"));  
&nbsp;&nbsp;&nbsp;&nbsp;WRAPPER::broker\_table\_insert(h, "test", Broker::data("three"),  
Broker::data("sparta"));  
}

event Broker::outgoing\_connection\_broken(peer\_name: string, peer\_port: port)  
{  
&nbsp;&nbsp;&nbsp;&nbsp;print "Connection closed by remote peer";  
&nbsp;&nbsp;&nbsp;&nbsp;terminate();  
}

broker\_wrapper.bro:

module WRAPPER;

export {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;global broker\_table\_create: function(h: opaque of Broker::Handle,  
name: string);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;global broker\_table\_insert: function(h: opaque of Broker::Handle,  
name: string, key: Broker::Data, val: Broker::Data);  
}

function broker\_table\_create(h: opaque of Broker::Handle,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name: string)  
{  
&nbsp;&nbsp;&nbsp;&nbsp;local tab = Broker::table\_create();  
&nbsp;&nbsp;&nbsp;&nbsp;Broker::insert(h, Broker::data(name), tab);  
}

function broker\_table\_insert(h: opaque of Broker::Handle,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name: string,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key: Broker::Data,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val: Broker::Data)  
{  
&nbsp;&nbsp;&nbsp;&nbsp;# look for table with name 'name'  
&nbsp;&nbsp;&nbsp;&nbsp;when (local res = Broker::lookup(h, Broker::data(name)))  
&nbsp;&nbsp;&nbsp;&nbsp;{  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# insert element "key" = "value" into table  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local status = Broker::table\_insert(res$result,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print res$result;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# insert table back into store  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Broker::insert(h, Broker::data(name), res$result);  
&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;timeout 10sec  
&nbsp;&nbsp;&nbsp;&nbsp;{  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print fmt("timeout broker\_table\_insert: %s key: %s val: %s",  
name, key, val);  
&nbsp;&nbsp;&nbsp;&nbsp;}  
}

I also did a second test:

If I try to add an element to a set, then test its existence in it with  
Broker::set\_contains() and it appears not to be in in the set. Any idea why?

Any help is welcome!

- --  
Jeffrey BENCTEUX  
ANSSI/COSSI/DTO/BSD

---

<div class="post-metadata">

**Author:** ![robin](https://yyz1.discourse-cdn.com/flex011/user_avatar/community.zeek.org/robin/32/599_2.png) [@robin](https://community.zeek.org/u/robin)\
**Post date:** [July 22, 2017, 2:43pm UTC](https://community.zeek.org/t/atomic-operations-on-broker-store/4949/2 "2017-07-22T14:43:08Z")

</div>

Hi Bencteux,

You are exactly right: the table operations aren't atomic currently  
(i.e., they don't happen server-side). Set manipulations are. The main  
difference is that for sets there are explicit store operations for  
inserting/removing elements, whereas for tables there are not.

I don't think there's a particular reason that Broker doesn't offer  
table operations. We are working on a 2nd-gen Broker API currently  
which simplifies usage quite a bit overall. It doesn't have table  
operations either yet (nor set operations in fact) but I'm planing on  
adding them shortly. If you want to track progress there, it's in the  
topic/actor-framework branch. This work shouldn't take very long  
anymore to get ready.

Robin

---

<div class="post-metadata">

**Author:** ![robin](https://yyz1.discourse-cdn.com/flex011/user_avatar/community.zeek.org/robin/32/599_2.png) [@robin](https://community.zeek.org/u/robin)\
**Post date:** [July 26, 2017, 12:30am UTC](https://community.zeek.org/t/atomic-operations-on-broker-store/4949/3 "2017-07-26T00:30:22Z")

</div>

I stand corrected: it actually did have them already, the API just  
made it easy to miss. I've now added explicit methods for  
set/table/vector manipulations to the store API in that branch branch  
(Note that they aren't accessible from the Bro side yet, that'll come  
shortly).

Robin

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex011/uploads/zeek/original/1X/f09d732bc2cc7c7cc7e35db67cf4e1d5233ce7a7.png) [@system](https://community.zeek.org/u/system)\
**Post date:** [May 6, 2022, 3:45pm UTC](https://community.zeek.org/t/atomic-operations-on-broker-store/4949/4 "2022-05-06T15:45:08Z")

</div>


