Facts are triples in the form {subject, relation, object}.
They are stored in a database. To create an empty database
call Facts.database(). To query the environment database
(global database with all program symbols and operators) use
Facts.env_db().
Use Facts.add_tags to add a triple to a database and
Facts.remove_tags to remove a triple from a database.
Facts can be queried in order from queries in triples.
If you only need one triple you can use Facts.with_tags or
Facts.collect_with_tags. If you need a join query you can
use Facts.with or Facts.collect_with to query multiple triples
at the same time. These functions initialize internally an iterator
for the query and then call the iterator in a loop calling a callback
function or evaluating the passed block for _macro variants.
You can achieve persistence by calling just one function.
Facts.open takes a database and a pathname as arguments and
replays the dump and the log in the file and opens the file for
appending for logging all transactions.
Transactions make their content atomic. A transaction either end in success or error. In the latter case, the already applied parts of the transaction are rolled back in reverse order. The database is locked read/write during a transaction. Transactions can be nested and are multithread ready with pthread support.
Create a database and add and remove triples and do a full query (?, ?, ?) :
ikc3> db = Facts.database()
(Ptr) 0x12345678
ikc3> Facts.add_tags(db, "Blade Runner", :is_a, :movie)
true
ikc3> Facts.add_tags(db, "Snow White", :is_a, :movie)
true
ikc3> Facts.remove_tags(db, "Blade Runner", :is_a, :movie)
true
ikc3> Facts.with_tags(db, ?, ?, ?, fn (fact) { puts(inspect(fact)) })
{"Snow White", :is_a, :movie}
Query operators from the global environment :
ikc3> Facts.with(Facts.env_db(), [[op = ?, :is_a, :op],
ikc3> [op, :op_sym, sym = ?]], fn (fact) {
ikc3> puts("#{inspect(sym)} #{inspect(op)}")
ikc3> })
The config module from an HTTPd instance has an example of persistence, this way the database is loaded when the module is loaded :
defmodule Config do
def db = Facts.database()
Facts.open(db, "db/app.facts")
end
Facts databases support network replication. When connections are established between databases, all add and remove operations are automatically broadcast to connected peers. This works independently of on-disk persistence (the log).
Use Facts.connect to connect to a remote facts server:
ikc3> db = Facts.database()
ikc3> Facts.connect(db, "192.168.1.100", "9000")
true
The connection runs a background thread that receives facts from the remote peer and applies them to the local database.
To accept incoming connections, first create a TCP server socket using
the Socket module, then use Facts.accept:
ikc3> require Socket
ikc3> db = Facts.database()
ikc3> server = Socket.listen("0.0.0.0", "9000")
ikc3> Facts.accept(db, server)
true
Each accepted connection spawns a background thread for receiving facts.
To close all connections on a database:
ikc3> Facts.close_all(db)
This gracefully shuts down all connection threads and closes the sockets.
Top : KC3 documentation
Previous : 1.24 Variable
Next : 1.26 Named block