43 return std::string(DataDir) +
"/base/" + std::to_string(db_oid) +
"/" + filename;
70 auto [idx, created] =
mapping.add(token);
81 &&
gates[idx].nb_children == 0;
82 bool real_create = type !=
gate_input || !children.empty();
83 if(placeholder && real_create) {
84 gates[idx].type = type;
85 gates[idx].nb_children =
static_cast<unsigned>(children.size());
87 for(
const auto &c: children)
89 for(
const auto &c: children) {
90 auto [child_idx, child_created] =
mapping.add(c);
98 gates.add({type,
static_cast<unsigned>(children.size()),
wires.nbElements()});
99 for(
const auto &c: children)
102 for(
const auto &c: children) {
103 auto [child_idx, child_created] =
mapping.add(c);
115 return gates[idx].type;
120 std::vector<pg_uuid_t> result;
125 result.push_back(
wires[k]);
132 auto [idx, created] =
mapping.add(token);
136 gates[idx].prob = prob;
149 return gates[idx].prob;
156 gates[idx].info1=info1;
157 gates[idx].info2=info2;
168 gates[idx].extra_len=s.size();
176 return std::make_pair(0, 0);
189 for(
unsigned long start=
gates[idx].extra_idx, k=start, end=start+
gates[idx].extra_len; k<end; ++k)
207#ifdef PROVSQL_INPROCESS_STORE
221 std::vector<pg_uuid_t>{root,
event});
234 unsigned nb_children;
239 std::vector<pg_uuid_t> children(nb_children);
240 for(
unsigned i=0; i<nb_children; ++i)
256 bool ok = circuit->
setProb(token, prob);
257 char return_value = ok?
static_cast<char>(1):0;
259 if(!
WRITEB(&return_value,
char))
260 provsql_error(
"Cannot write response to pipe (message type P)");
267 unsigned info1, info2;
272 circuit->
setInfos(token, info1, info2);
285 char *data =
new char[len];
289 circuit->
setExtra(token, std::string(data, len));
305 provsql_error(
"Cannot write response to pipe (message type t)");
313 if(!
WRITEB(&nb,
unsigned long))
314 provsql_error(
"Cannot write response to pipe (message type n)");
326 unsigned nb_children = children.size();
327 if(!
WRITEB(&nb_children,
unsigned))
328 provsql_error(
"Cannot write response to pipe (message type c)");
331 provsql_error(
"Cannot write response to pipe (message type c)");
342 double prob = circuit->
getProb(token);
344 if(!
WRITEB(&prob,
double))
345 provsql_error(
"Cannot write response to pipe (message type p)");
356 auto infos = circuit->
getInfos(token);
358 if(!
WRITEB(&infos.first,
unsigned) || !
WRITEB(&infos.second,
unsigned))
359 provsql_error(
"Cannot write response to pipe (message type i)");
370 auto str = circuit->
getExtra(token);
371 unsigned len = str.size();
374 provsql_error(
"Cannot write response to pipe (message type e)");
385#ifdef PROVSQL_INPROCESS_STORE
388 provsql_error(
"message type g is not used by the in-process store");
390 std::stringstream ss;
391 boost::archive::binary_oarchive oa(ss);
394 ss.seekg(0, std::ios::end);
395 unsigned long size = ss.tellg();
396 ss.seekg(0, std::ios::beg);
425 if(!
READM(relid, Oid))
435 if(!
READM(relid, Oid))
438 char found = circuit->
getTableInfo(relid, info) ? 1 : 0;
440 provsql_error(
"Cannot write response to pipe (message type s)");
443 provsql_error(
"Cannot write response to pipe (message type s)");
446 provsql_error(
"Cannot write response to pipe (message type s)");
457 if(!
READM(relid, Oid) || !
READM(ancestor_n, uint16_t))
464 for(uint16_t i=0; i<ancestor_n; ++i)
465 if(!
READM(ancestors[i], Oid))
475 if(!
READM(relid, Oid))
485 if(!
READM(relid, Oid))
488 char found = circuit->
getTableInfo(relid, info) ? 1 : 0;
490 provsql_error(
"Cannot write response to pipe (message type a)");
493 provsql_error(
"Cannot write response to pipe (message type a)");
496 provsql_error(
"Cannot write response to pipe (message type a)");
509 if(!
READM(nb_roots,
unsigned))
512 std::vector<pg_uuid_t> roots(nb_roots);
513 for(
unsigned i=0; i<nb_roots; ++i)
517#ifdef PROVSQL_INPROCESS_STORE
520 provsql_error(
"message type j is not used by the in-process store");
522 std::stringstream ss;
523 boost::archive::binary_oarchive oa(ss);
526 ss.seekg(0, std::ios::end);
527 unsigned long size = ss.tellg();
528 ss.seekg(0, std::ios::beg);
541#ifndef PROVSQL_INPROCESS_STORE
546 while(
READM(c,
char)) {
548 if(!
READM(db_oid, Oid))
589 unsigned long n =
tableInfo.nbElements();
590 for(
unsigned long i=0; i<n; ++i) {
600 if(tombstone < 0 &&
tableInfo[i].relid == InvalidOid)
601 tombstone =
static_cast<long>(i);
613 const Oid *ancestors)
615 if(relid == InvalidOid)
619 unsigned long n =
tableInfo.nbElements();
620 for(
unsigned long i=0; i<n; ++i) {
624 memcpy(updated.
ancestors, ancestors, ancestor_n *
sizeof(Oid));
638 if(relid == InvalidOid)
640 unsigned long n =
tableInfo.nbElements();
641 for(
unsigned long i=0; i<n; ++i) {
651 if(relid == InvalidOid)
653 unsigned long n =
tableInfo.nbElements();
654 for(
unsigned long i=0; i<n; ++i) {
664 if(relid == InvalidOid)
666 for(
unsigned long i=0; i<
tableInfo.nbElements(); ++i) {
683 return memcmp(&a, &b,
sizeof(
pg_uuid_t))<0;
692 const std::vector<pg_uuid_t> &roots)
const
700 std::set<pg_uuid_t> to_process, processed;
701 for(
const auto &r : roots)
702 to_process.insert(r);
706 while(!to_process.empty()) {
708 to_process.erase(to_process.begin());
709 processed.insert(uuid);
715 if(!std::isnan(prob))
718 std::vector<pg_uuid_t> children =
getChildren(uuid);
719 for(
unsigned i=0; i<children.size(); ++i) {
723 if(processed.find(children[i])==processed.end())
724 to_process.insert(children[i]);
729 auto [info1, info2] =
getInfos(uuid);
735 auto [info1, info2] =
getInfos(uuid);
736 if(info1 != 0 || info2 != 0)
gate_t
Strongly-typed gate identifier.
Out-of-line template method implementations for Circuit<gateType>.
Semiring-agnostic in-memory provenance circuit.
void provsql_mmap_dispatch(char c, Oid db_oid)
Handle a single IPC message: read its payload and write its reply.
static std::map< Oid, MMappedCircuit * > circuits
Per-database mmap-backed provenance circuits, keyed by database OID.
void destroy_provsql_mmap()
Unmap and close the mmap files.
bool operator<(const pg_uuid_t a, const pg_uuid_t b)
Lexicographic less-than comparison for pg_uuid_t.
void provsql_mmap_main_loop()
Main processing loop of the mmap background worker.
void initialize_provsql_mmap()
Open (or create) the mmap files and initialise the circuit store.
static MMappedCircuit * getCircuit(Oid db_oid)
Return (creating lazily if needed) the circuit for db_oid.
Persistent, mmap-backed storage for the full provenance circuit.
#define PROVSQL_TABLE_INFO_MAX_BLOCK_KEY
Cap on the number of block-key columns recorded per relation.
#define PROVSQL_TABLE_INFO_MAX_ANCESTORS
Cap on the number of base ancestors recorded per relation.
void addWire(gate_t f, gate_t t)
Add a directed wire from gate f (parent) to gate t (child).
gate_t getGate(const uuid &u)
Return (or create) the gate associated with UUID u.
In-memory provenance circuit with semiring-generic evaluation.
void setInfos(gate_t g, unsigned info1, unsigned info2)
Set the integer annotation pair for gate g.
gate_t setGate(gate_type type) override
Allocate a new gate with type type and no UUID.
void setExtra(gate_t g, const std::string &ex)
Attach a string extra to gate g.
void setProb(gate_t g, double p)
Set the probability for gate g.
Persistent mmap-backed representation of the provenance circuit.
void setTableAncestry(Oid relid, uint16_t ancestor_n, const Oid *ancestors)
Insert or update the ancestor set of a per-table metadata record, preserving any existing kind / bloc...
void setExtra(pg_uuid_t token, const std::string &s)
Attach a variable-length string annotation to a gate.
void setTableInfo(const ProvenanceTableInfo &info)
Insert or update the kind / block_key half of a per-table metadata record, preserving any existing an...
void removeTableInfo(Oid relid)
Remove a per-table metadata entry (both halves).
MMappedUUIDHashTable mapping
UUID → gate-index hash table.
void createGate(pg_uuid_t token, gate_type type, const std::vector< pg_uuid_t > &children)
Persist a new gate to the mmap store.
std::string getExtra(pg_uuid_t token) const
Return the variable-length string annotation for gate token.
unsigned long getNbGates() const
Return the total number of gates stored in the circuit.
static constexpr const char * GATES_FILENAME
Backing file for gates.
gate_type getGateType(pg_uuid_t token) const
Return the type of the gate identified by token.
static constexpr const char * TABLE_INFO_FILENAME
Backing file for tableInfo.
void removeTableAncestry(Oid relid)
Clear just the ancestor set of a per-table metadata record, preserving kind / block_key.
void sync()
Flush all backing files to disk with msync().
MMappedVector< ProvenanceTableInfo > tableInfo
Per-relation TID/BID metadata (safe-query optimisation).
static constexpr const char * WIRES_FILENAME
Backing file for wires.
GenericCircuit createGenericCircuit(pg_uuid_t token) const
Build an in-memory GenericCircuit rooted at token.
static std::string makePath(Oid db_oid, const char *filename)
Build the full path for a mmap file under $PGDATA/base/<db_oid>/.
bool setProb(pg_uuid_t token, double prob)
Set the probability associated with a gate.
static constexpr const char * EXTRA_FILENAME
Backing file for extra.
static constexpr const char * MAPPING_FILENAME
Backing file for mapping.
bool getTableInfo(Oid relid, ProvenanceTableInfo &out) const
Look up the full per-table metadata record (both halves).
MMappedVector< char > extra
Variable-length string data.
double getProb(pg_uuid_t token) const
Return the probability stored for the gate identified by token.
std::vector< pg_uuid_t > getChildren(pg_uuid_t token) const
Return the child UUIDs of the gate identified by token.
MMappedVector< GateInformation > gates
Gate metadata array.
MMappedVector< pg_uuid_t > wires
Flattened child UUID array.
void setInfos(pg_uuid_t token, unsigned info1, unsigned info2)
Update the info1 / info2 annotations of a gate.
MMappedCircuit(const std::string &mp, const std::string &gp, const std::string &wp, const std::string &ep, const std::string &tp, bool read_only)
Delegating constructor that accepts pre-built paths.
std::pair< unsigned, unsigned > getInfos(pg_uuid_t token) const
Return the info1 / info2 pair for the gate token.
static constexpr unsigned long NOTHING
Sentinel returned by operator[]() when the UUID is not present.
#define provsql_error(fmt,...)
Report a fatal ProvSQL error and abort the current transaction.
Background worker and IPC primitives for mmap-backed circuit storage.
#define WRITEB_BYTES(ptr, n)
Write n reply bytes to the main-to-background pipe.
#define READM(var, type)
Read one value of type from the background-to-main pipe.
#define WRITEB(pvar, type)
Write one value of type to the main-to-background pipe.
#define READM_BYTES(ptr, n)
Read exactly n bytes of a request from the background-to-main pipe.
Shared-memory segment and inter-process pipe management.
@ gate_rv
Continuous random-variable leaf (extra encodes distribution).
@ gate_annotation
Transparent single-child wrapper carrying a query-level annotation in extra (inversion-free certifica...
@ gate_mobius
Signed Möbius combination: a MEASURE-only gate carrying one integer coefficient per child (in extra,...
@ gate_arith
n-ary arithmetic gate over scalar-valued children (info1 holds operator tag)
@ gate_assumed
Structural marker over a single child whose sub-circuit was computed under a Boolean-provenance assum...
string uuid2string(pg_uuid_t uuid)
Format a pg_uuid_t as a std::string.
C++ utility functions for UUID manipulation.
Per-relation metadata for the safe-query optimisation.
Oid relid
pg_class OID of the relation (primary key)
AttrNumber block_key[PROVSQL_TABLE_INFO_MAX_BLOCK_KEY]
Block-key column numbers.
uint16_t block_key_n
Number of valid entries in block_key.
Oid ancestors[PROVSQL_TABLE_INFO_MAX_ANCESTORS]
Sorted, deduplicated base-relation OIDs.
uint8_t kind
One of provsql_table_kind.
uint16_t ancestor_n
Number of valid entries in ancestors (0 = no registry info).