# Persistent predicates based on RocksDB

**URL:** <https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501>\
**Category:** Request For Comments\
**Created:** [June 16, 2022, 1:28pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501 "2022-06-16T13:28:32Z")\
**Posts on this page:** 20\
**Page:** 4

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [July 9, 2022, 4:13pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/64 "2022-07-09T16:13:33Z")

</div>

> [@peter.ludemann](#):
>
> I’ll add a comment to the README about `make`. It seems to be part of the base system for Debian, but it doesn’t hurt to do `sudo apt install make`.

Typically, you should be able to build most C based programs on Debian based systems after

```
 apt install build-essential

```

All the other deps @EricGT mentions from the build instructions are for SWI-Prolog and its core foreign language extensions. If you got SWI-Prolog itself as package you don’t need those.

On MacOS you need Xcode for compiling basic extensions.

On Windows, you need [MinGW-w64](https://www.mingw-w64.org/). Would be nice to have a good setup description for that.

For this package you also need `git` as it is downloaded using git.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 9, 2022, 4:19pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/65 "2022-07-09T16:19:22Z")

</div>

> [@jan](#):
>
> On Windows, you need [MinGW-w64](https://www.mingw-w64.org/). Would be nice to have a good setup description for that.

I am trying to move away from using [MinGW-w64](https://www.mingw-w64.org/) and [MSYS2](https://www.msys2.org/) as from what I have seen if one has a Linux based system installed under WSL 2 then they can leverage that instead. I have not done that for building SWI-Prolog for Windows but every day I work with RocksDB, it is one more day adding weight to that side of the scale to just do it.

If I do get it working I will surely post the instruction on this site.

* * *

**EDIT**

Found this set of instructions that look similar to what is needed for building on Windows using MinGW-64.

> **[Build](https://github.com/fastogt/fastonosql/wiki/Build)**
>
> FastoNoSQL is a crossplatform Redis, Memcached, SSDB, LevelDB, RocksDB, UnQLite, LMDB, ForestDB, Pika, Dynomite, KeyDB GUI management tool. - fastogt/fastonosql

I am slowing moving toward actually building SWI-Prolog for Windows on Windows.

> **Personal notes**
>
> For the instruction
> 
> > pacman -S base-devel git mingw-w64-x86\_64-toolchain mingw-w64-x86\_64-gcc mingw-w64-x86\_64-cmake mingw-w64-x86\_64-openssl mingw-w64-x86\_64-qt5 mingw-w64-x86\_64-ninja
> 
> [pacman](https://www.msys2.org/docs/package-management/) is a package management tool and is also a command.  
> Just copy the command as is and paste into the MSYS2 console.  
> Note that `Ctrl-V` does not work for pasting, instead use the middle mouse button which is mapped to paste.
> 
> In trying to build fastogt ran into error for instruction
> 
> > python3 build\_env.py
> 
> This GitLab repository might be needed.
> 
> [pyfastogt · master · FastoGT / pyfastogt · GitLab](https://gitlab.com/fastogt/pyfastogt/-/tree/master/pyfastogt)

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 9, 2022, 4:47pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/66 "2022-07-09T16:47:44Z")

</div>

> [@jan](#):
>
> `apt install build-essential`

I’ve added this to the README, and also the comments about MacOS and Windows (neither of which I can test).

---

<div class="post-metadata">

**Author:** ![drspro](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/drspro/32/3509_2.png) [@drspro](https://swi-prolog.discourse.group/u/drspro)\
**Post date:** [July 9, 2022, 5:12pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/67 "2022-07-09T17:12:14Z")

</div>

I copied 2 parts swi-prolog code from: 1 . example with file upload with multipart library, and  
2 - a simple webserver with odbc postgress

can the uploaded file be embedded in the SQL query so that it inserts it in Postgress to blob record? or else inserted in rockdb as blob

1:

```prolog
save_file(Request, Parts0, In, file(FileName, Path), Options) :-
    copy_term(Parts0, Parts),
    once(append(Parts, [], _)), % close the list
    debug(upload, 'Params so far: ~p', [Parts]),
    ( option(filename(FileName), Options),
        FileName \== blob
    -> true
    ; part(qqfilename, Parts, FileName)
    ),
    file_name_extension(_, Ext, FileName),
    part(qquuid, Parts, UUID),
    upload_file(UUID, Ext, Dir, Path),
    enforce_file_size_limit(Parts, FileName, Size),
    part_offset(Parts, Size, IsMulti, Offset),
    debug(upload, 'IsMulti = ~p, Offset = ~p', [IsMulti, Offset]),
    make_directory_path(Dir),
    setup_call_cleanup(
        open(Path, update, Out,
             [ type(binary)
             ]),
        ( seek(Out, Offset, bof, NewOffset),
            assertion(Offset == NewOffset),
            copy_stream_data(In, Out)
        ),
        close(Out)),
    ( IsMulti == false
    -> broadcast(file_upload(FileName, Path, Request))
    ; true
    ).

```

2:

```prolog
sql_escape_single_quotes(StringIn, StringOut) :-
  split_string(StringIn, "'", "", List),
  atomics_to_string(List, "''", StringOut).

db_insert(Title, Art) :-
  sql_escape_single_quotes(Title, ETitle),
  sql_escape_single_quotes(Art, EArt),  
  odbc_connect('blog', Connection, []),
  odbc_query(Connection, "INSERT INTO arts (title, art) VALUES ('~w', '~w')"-[ETitle, EArt]),
  odbc_disconnect(Connection).

```

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 9, 2022, 5:32pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/68 "2022-07-09T17:32:15Z")

</div>

> [@drspro](#):
>
> can the uploaded file be embedded in the SQL query so that it inserts it in Postgress to blob record? or else inserted in rockdb as blob

For (1), you should be able to replace the `open(Path,update,Out)` code by a `rocks_put/3` call. If you’re appending, then you’d need to first do `rocks_get/3` to get the existing blob. (And, of course, you’d need to have `rocks_open/3` and `rocks_close/1` at suitable places, similar to how you’d do a database connect.) The “merge” facility might help avoid the extra work when appending to a blob (I’ve only skimmed this; @jan can probably give better advice if it’s not clear from the documentation).

For (2), I think that the answer is “yes”. I’m not sure of the ODBC syntax … shouldn’t it use "?"s to avoid SQL injection? Also, you’d probably want to use a format like `~q` or `~k` to ensure round-trip of terms. In the case of using library(rocksdb), use the option option `value(term)`, which use an optimized read and write that’s faster and more compact than regular term reading and writing.

---

<div class="post-metadata">

**Author:** ![nobrowser](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/nobrowser/32/4269_2.png) [@nobrowser](https://swi-prolog.discourse.group/u/nobrowser)\
**Post date:** [July 10, 2022, 4:15pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/69 "2022-07-10T16:15:48Z")

</div>

> [@jan](#):
>
> On MacOS you need Xcode for compiling basic extensions.

I think this is slightly inaccurate. It’s _Xcode CLI tools_ one needs. It is in fact possible to have these and not Xcode itself, as my own system proves.

–  
Ian

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 10, 2022, 5:04pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/70 "2022-07-10T17:04:26Z")

</div>

@jan @peter.ludemann

Built a new Ubuntu machine from scratch, installed SWI-Prolog development via PPA and then ran [check\_installation/0](https://www.swi-prolog.org/pldoc/doc_for?object=check_installation%3Acheck_installation/0). As I always find with the PPA install, `tcmalloc` is not present. (Note that with a source build it is present)

Is `tcmalloc` needed/advantageous for using SWI-Prolog with #RocksDB?

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 10, 2022, 5:20pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/71 "2022-07-10T17:20:21Z")

</div>

> [@peter.ludemann](#):
>
> I’d need a clean machine to check what’s actually needed; but I’m too lazy to do that.

Built a new Ubuntu machine using PPA.  
Used Git clone to bring down the SWI-Prolog repository for RocksDB.

Tried  
`pack_rebuild(rocksdb).`  
which failed with `Error: program 'make' does not exist`

Installed build-essentials

```plaintext
sudo apt update
sudo apt install build-essential

```

Retired `pack_rebuild(rocksdb).`  
Error no longer appears.

🙂

* * *

Just to check which make commands are installed.

```plaintext
$ make -v
GNU Make 4.3
...

$ cmake -v
Command 'cmake' not found, but can be installed with: 
...

$ gmake -v
GNU Make 4.3
...

```

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 10, 2022, 5:29pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/72 "2022-07-10T17:29:25Z")

</div>

> [@EricGT](#):
>
> Is `tcmalloc` needed/advantageous for using [SWI-Prolog](https://www.swi-prolog.org/pldoc/doc_for?object=manual) with [#RocksDB](https://rocksdb.org/)?

The Makefile for pack(rocksdb) has  
`ROCKSENV=ROCKSDB_DISABLE_JEMALLOC=1 ROCKSDB_DISABLE_TCMALLOC=1`

@jan made a comment about the tcmalloc warning here:

> [@Installation fails with "No rule to make target \`man/archive'"](https://swi-prolog.discourse.group/t/installation-fails-with-no-rule-to-make-target-man-archive/602/23):
>
> You can do that also from the command line cmake -DLIBUUID\_INCLUDE\_DIR=/usr/include/ossp Normally the configuration is done using the utility uuid-config. Is that not present in the OpenSUSE version or is it installed somewhere else? That is normal. Maybe this should be suppressed. linking to tcmalloc must be done in the main program and is only done for swipl as the advantages are mostly relevant to multi threaded server applications. Standard glibc ptmalloc results in poor memory …

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 10, 2022, 5:43pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/73 "2022-07-10T17:43:27Z")

</div>

> [@peter.ludemann](#):
>
> `ROCKSENV=ROCKSDB_DISABLE_JEMALLOC=1 ROCKSDB_DISABLE_TCMALLOC=1`

I think I read a comment from @jan somewhere that enabling `tcmalloc` for RocksDB caused some problem (but I can’t find this comment) … as RocksDB is multi-threaded, it would be nice if it could use `tcmalloc` … but possibly its use of `tcmalloc` somehow conflicts with SWI-Prolog using it?

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 10, 2022, 6:15pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/74 "2022-07-10T18:15:01Z")

</div>

> [@peter.ludemann](#):
>
> I think I read a comment from @jan somewhere that enabling `tcmalloc` for RocksDB caused some problem (but I can’t find this comment)

I think the one you are referring to is the RocksDB pack [readme.md](https://github.com/JanWielemaker/rocksdb/blob/e253458069c7608e8d10a416c79c7e5ed5fac1d9/README.md).

Totally forgot about this and when reinstalling from scratch and double checking items read it again a few minutes ago.

> There are a number of issues with several pre-built versions of librocksdb:
> 
> - Shared objects are often linked to jemalloc or tcmalloc. This prevents lazy loading of the library, causing either problems loading or running the embedded rocksdb.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [July 10, 2022, 6:43pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/76 "2022-07-10T18:43:46Z")

</div>

> [@peter.ludemann](#):
>
> but possibly its use of `tcmalloc` somehow conflicts with [SWI-Prolog](https://www.swi-prolog.org/pldoc/doc_for?object=manual) using it?

AFAIK problems emerge if a shared object has tcmalloc as dependency while the main program has not. Some RocksDB packages are linked against jemalloc, so you have the main program loading tcmalloc or ptmalloc and then RocksDB using jemalloc. That does not work. The safe option is to not link RocksDB against a particular malloc library and leave the choice of allocator to the main program. It is possible that RocksDB actually uses the tcmalloc/jemalloc extension functions. That would be a pity as some optimizations may be lost. libswipl.so solves the tcmalloc dependency dynamically, i.e., it queries the linker to see whether tcmalloc is in use and, if so, uses the added functionality.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 10, 2022, 7:14pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/77 "2022-07-10T19:14:01Z")

</div>

> [@jan](#):
>
> It is possible that RocksDB actually uses the tcmalloc/jemalloc extension functions.

A scan of the RocksDB source doesn’t find `tcmalloc/malloc_extension.h` (or anything ending in `extension.h`), so presumably RocksDB doesn’t use the extension functions. And, as far as I can tell, the only references to tcmalloc are in build files.  
On my system, `rocksdb4pl.so` doesn’t have any tcmalloc dependencies (nor does 'libswipl.so`, so I should probably change my build options).

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [July 11, 2022, 7:01am UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/78 "2022-07-11T07:01:20Z")

</div>

> [@peter.ludemann](#):
>
> nor does 'libswipl.so`, so I should probably change my build options

No. For exactly the same reasons that cause problems when rocksdb.so depends on tcmalloc, libswipl.so doesn’t depend on it. The dependency is in swipl itself (the main program):

```prolog
> ldd src/swipl
	linux-vdso.so.1 (0x00007fffebf54000)
	libtcmalloc_minimal.so.4 => /lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4 (0x00007f58b1097000)
	libswipl.so.8 => /home/janw/src/swipl-devel/linux/src/libswipl.so.8 (0x00007f58b0ed9000)
    ...

```

SWI-Prolog does use the extensions, but libswipl.so discovers them dynamically such that the library works fine with any malloc implementation.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 11, 2022, 3:53pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/79 "2022-07-11T15:53:09Z")

</div>

Maybe someone will explain this while I am digging into the code to understand it.

Normally when accessing a resource such as a database via a connection, the access is maintained until the connection is closed then access is lost.

In using RocksDB that appears to not be the case. When using code as such

```prolog
load :-
    mrfiles_path(Mrfiles_data_path),
    rocksdb_directory(Rocksdb_directory),
    setup_call_cleanup(
        (
            open(Mrfiles_data_path,read,Files_data_stream),
			rdb_open(Rocksdb_directory,RocksDB)
        ),
        mrfiles_lines(Files_data_stream,RocksDB),
        (
			rdb_close(RocksDB),
            close(Files_data_stream)
        )
    ).

```

Note: mrfile\_lines/2 calls rdb\_assertz/1 for each record.

I was surprised to find that with a wrapper predicate like

```prolog
mrfile(A1,A2,A3,A4,A5,A6) :-
   rdb_clause(mrfile(A1,A2,A3,A4,A5,A6),true).

```

that the query worked from the top level. I was expecting that after load/0 successfully ran, calling rdb\_close/1 and then returning control back the top level that the RocksDB resource would not be accessible.

See: [rdb\_close not closing as expected. RocksDB can still be queried from top level after rdb\_close. · Issue #2 · JanWielemaker/rocks-predicates · GitHub](https://github.com/JanWielemaker/rocks-predicates/issues/2)

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 11, 2022, 4:05pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/80 "2022-07-11T16:05:52Z")

</div>

Feedback on predicates.

* * *

Item: 1

rdb\_assertz/2 will write duplicate entries.

When adding facts that should be unique in the DB it would be nice to have an option or different predicate that checked if the fact existed and did not add a duplicate and that also succeeded if the fact was a duplicate. 🙂 I would send a pull request but my Git skills are horrendous.

See: [New or option for rdb\_assertz/2 that does not create duplicate facts and succeeds if duplicate. · Issue #3 · JanWielemaker/rocks-predicates · GitHub](https://github.com/JanWielemaker/rocks-predicates/issues/3)

* * *

Item: 2

Using the most general query.

Retrieve first result.  
There are more valid results.  
Press enter instead of space bar.

Example:

```prolog
?- mrfile(A,B,C,D,E,F).
A = 'AMBIGLUI.RRF',
B = 'Ambiguous term identifiers',
C = ['LUI', 'CUI'],
D = 2,
E = 394198,
F = 7578465 .

ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [5] '$execute_goal2'('<garbage_collected>',['A'='AMBIGLUI.RRF',...|...],_2420)

```

See: [Most general query (goal) results in error if enter used to exit instead of space bar to continue. · Issue #5 · JanWielemaker/rocks-predicates · GitHub](https://github.com/JanWielemaker/rocks-predicates/issues/5)

* * *

Item: 3

It seems that information is being tabled; concern is that RAM is being used behind the scene and if millions, tens of millions of facts are asserted into RocksDB that the tabling could use up all of the RAM.

```prolog
?- current_table(M:H,Table),trie_property(Table,size(Bytes)).
M = rocks_preds,
H = rdb_clause_index(<rocksdb>(0x560f3641a570), umls:mrfile/6, _),
Table = <trie>(0x560f365231b0),
Bytes = 168 ;
false.

```

For now my take on this item is to just be aware that tabling is needed and that using the example code above one can check on the RAM used as needed. In other words if the sky is not falling no need to cause a panic.

See: [Reduce or remove need for tabiling to avoid using RAM. · Issue #4 · JanWielemaker/rocks-predicates · GitHub](https://github.com/JanWielemaker/rocks-predicates/issues/4)

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 11, 2022, 5:03pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/81 "2022-07-11T17:03:13Z")

</div>

Nice to know commands

For downloading packs via Git clone

> **Windows**
>
> On Windows (Work in progress)
> 
> ```prolog
> > cd %LOCALAPPDATA%\swi-prolog\pack
> > git clone https://github.com/JanWielemaker/rocksdb.git
> > git clone https://github.com/JanWielemaker/rocks-predicates.git
> > cd %USERPROFILE%
> 
> ```

On Ubuntu

```prolog
$ sudo apt install libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev libgflags-dev
$ mkdir -p ~/.local/share/swi-prolog/pack
$ cd ~/.local/share/swi-prolog/pack
$ git clone https://github.com/JanWielemaker/rocksdb.git
$ git clone https://github.com/JanWielemaker/rocks-predicates.git
$ cd rocksdb
$ git clone https://github.com/facebook/rocksdb.git

```

Nice to know queries.

Is the module rocksdb loaded?

```prolog
?- current_module(rocksdb).
true.

```

Load the rocksdb module.

```prolog
?- use_module(library(rocksdb)).
true.

```

  
For ther error: 

> ERROR: rocksdb4pl: cannot open shared object file: No such file or directory

If the RockDB pack was recently installed/built/rebuilt within SWI-Prolog try halt/0 then restart swipl and try the command again, it might resolve the error.

Is the module rocks\_preds loaded?

```prolog
?- current_module(rocks_preds).
true.

```

Load the rocks\_preds module.  
Note: This expects the the code to under the pack directory.  
Note: You will need to change the user name accordingly.

```prolog
?- assertz(user:file_search_path(library, '/home/groot/.local/share/swi-prolog/pack/rocks-predicates')).
true.
?- use_module(library(rocks_preds)).

```

What predicates are in module rocksdb?

```prolog
?- listing(rocksdb:P).
...

```

What predicates are in module rocks\_preds:P?

```prolog
?- listing(rocks_preds:P).
...

```

Is there currently a RocksDB?

```prolog
?- current_blob(Blob,rocksdb).
Blob = <rocksdb>(0x560f3641a570) ;
false.

```

Note: More than one RocksDB can be open at a time, e.g.

```prolog
?- current_blob(Blob,rocksdb).
Blob = <rocksdb>(0x557a667b1960) ;
Blob = <rocksdb>(0x557a66692920) ;
false.

```

What is the default RocksDB?  
Note: Identified by file directory.

```prolog
?- rocks_preds:default_db(Dir).
Dir = '/mnt/d/...'.

```

Note: If default\_db/1 returns `Dir = 'predicates.db'.` then no default RocksDB has been set. This helps to understand error messages like

```prolog
ERROR: rocksdb `'predicates.db'' does not exist

```

Note: `predicates.db` may actually be created, used and contain data. The parent directory at the time of creation will be the current working directory. So if you load up some data and then it seems to go missing look for the directory name `predicates.db` somewhere.

What is SWI-Prolog using for the current working directory?

```prolog
?- pwd.
% /home/groot/
true.

```

What predicates exist in the RocksDB?

```prolog
?- current_table(rocks_preds:H,_),H=rdb_clause_index(_,M:P/I,_).
H = rdb_clause_index(<rocksdb>(0x560f3641a570), umls:mrcol/8, '$VAR'('_')),
M = umls,
P = mrcol,
I = 8 ;
H = rdb_clause_index(<rocksdb>(0x560f3641a570), umls:mrfile/6, '$VAR'('_')),
M = umls,
P = mrfile,
I = 6 ;
H = rdb_clause_index(<rocksdb>(0x560f3641a570), '$VAR'('M'):'$VAR'('P')/'$VAR'('I'), '$VAR'('_')) ;
H = rdb_clause_index(<rocksdb>(0x560f3641a570), '$VAR'('M'):'$VAR'('P')/'$VAR'('I'), '$VAR'('_')) ;
false.

```

A variation that also reports the predicate with [predication](https://swi-prolog.discourse.group/t/what-is-the-difference-between-head-and-predication/4471).

```prolog
?- current_table(rocks_preds:H,_),H=rdb_clause_index(_,M:P/I,_),pi_head(M:P/I,Predication).
H = rdb_clause_index(<rocksdb>(0x55dff497bd10), issue_5:fact_01/9, _),
M = issue_5,
P = fact_01,
I = 9,
Predication = issue_5:fact_01(_, _, _, _, _, _, _, _, _) ;
false.

```

What are the properties for the predicates?

```prolog
?- rocks_preds:default_db(Dir),rocks_preds:rdb_predicate_property(Dir,umls:mrfile(_,_,_,_,_,_),Property).
Dir = '/mnt/d/...',
Property = database('/mnt/d/...') ;
Dir = '/mnt/d/...',
Property = defined ;
Dir = '/mnt/d/...',
Property = number_of_clauses(100).

```

```prolog
?- rocks_preds:default_db(Dir),rocks_preds:rdb_predicate_property(Dir,umls:mrcol(_,_,_,_,_,_,_,_),Property).
Dir = '/mnt/d/...',
Property = database('/mnt/d/...') ;
Dir = '/mnt/d/...',
Property = defined ;
Dir = '/mnt/d/...',
Property = number_of_clauses(329).

```

A variation using predication; since a predication is a most general query (goal) it can be executed as such.

```prolog
?- current_table(rocks_preds:H,_),H=rdb_clause_index(_,M:P/I,_),pi_head(M:P/I,Goal),Goal.
H = rdb_clause_index(<rocksdb>(0x55dff497bd10), issue_5:fact_01/9, _),
M = issue_5,
P = fact_01,
I = 9,
Goal = issue_5:fact_01('1', 'Mars 2MV-3 No.1', '04 Nov 1962', '25 Nov 1962', '890', -, -, 'Failed', 'Soviet Union') ;

...

```

* * *

When [issue 2](https://github.com/JanWielemaker/rocks-predicates/issues/2) is corrected the need to open the RocksDB and then run queries from the top-level will be desired. As noted the use of break/0 can accomplish this.

```prolog
interactive :-
    absolute_file_name(rocksdb('.'),Rocksdb_directory),
    setup_call_cleanup(
        rdb_open(Rocksdb_directory,RocksDB),
        break,
        rdb_close(RocksDB)
    ).

```

Example run:

```prolog
?- interactive.
% Break level 1
[1] ?- mars_lander(Sequence,Lander,Launch_date,Landing_date,Mass_kg,Landing_site,Region,Status,Country_of_origin).
Sequence = '1',
Lander = 'Mars 2MV-3 No.1',
Launch_date = '04 Nov 1962',
Landing_date = '25 Nov 1962',
Mass_kg = '890',
Landing_site = Region, Region = (-),
Status = 'Failed',
Country_of_origin = 'Soviet Union' .

...

Sequence = '21',
Lander = 'Tianwen-1',
Launch_date = '23 July 2020',
Landing_date = '14 May 2021',
Mass_kg = '240',
Landing_site = '109.7°E, 25.1°N',
Region = 'Utopia Planitia',
Status = 'Operational',
Country_of_origin = 'China'.

[1] ?- ^D
% Exit break level 1
true.

?-

```

Note: `^D` is the visualization of holding down the keyboard key `Ctrl` and pressing the key `D`.

It should be possible to use initialization/1 (which is only used as a Prolog directive) to open the RocksDB an thus enter top-level with the predicates loaded and use at\_halt/1 to close the RocksDB when SWI-Prolog halts; just not high on my priority list at present to work out the details.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 11, 2022, 5:34pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/82 "2022-07-11T17:34:02Z")

</div>

> [@EricGT](#):
>
> I was expecting that after load/0 successfully ran, calling rdb\_close/1 and then returning control back the top level that the RocksDB resource would not be accessible.

The rdb\_close/1 does a RocksDB close and then remove the entry from the dynamic predicate pred\_table/2. When another rdb\_open/2 is done, there’s no entry in the pred\_table/2, so the database is re-opened.

This doesn’t seem quite right … probably pred\_table/2 should store the options given to the initial rdb\_open/2. (Please open an issue on this and assign it to me, so that I don’t forget)

BTW, there are also the `alias(Name)` and `how(once)` options to rdb\_open/3.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 11, 2022, 5:37pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/83 "2022-07-11T17:37:28Z")

</div>

> [@peter.ludemann](#):
>
> The rdb\_close/1 does a RocksDB close and then remove the entry from the dynamic predicate pred\_table/2. When another rdb\_open/2 is done, there’s no entry in the pred\_table/2, so the database is re-opened.

Thanks.

I was actually hoping it was a feature and not a bug. 🥴

Now that I know it is a bug, I suspect that break/0 or something will be needed to keep the RocksDB session alive so that manual queries can be entered at the top level.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 11, 2022, 5:42pm UTC](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501/84 "2022-07-11T17:42:31Z")

</div>

> [@EricGT](#):
>
> rdb\_assertz/2 will write duplicate entries.

Right now, you’d need to check, using rdb\_clause/2. But this seems like a reasonable feature, and not difficult to implement, so please create an Issue for it. [Issues · JanWielemaker/rocks-predicates · GitHub](https://github.com/JanWielemaker/rocks-predicates/issues)

> [@EricGT](#):
>
> It seems that information is being tabled; concern is that RAM is being used behind the scene and if millions, tens of millions of facts are asserted into RocksDB that the tabling could use up all of the RAM.

That tabling might not be necessary … RocksDB has its own LRU cache of key/value pairs and its use of RAM can be controlled by options.

Again, please open an issue on this … I’ll have to think a bit about the ramifications.

> [@EricGT](#):
>
> Item: 2

Please file a bug with a reproducible example.  
I’m in the middle of some code clean-up, so it’ll be at least a few days before I can work on this.

[Previous page](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501.md?page=3)

[Next page](https://swi-prolog.discourse.group/t/persistent-predicates-based-on-rocksdb/5501.md?page=5)
