C · Graphs

Graphs

#include <ustore/graph.h> 1.0.0-rc.1 · d6d40961

A graph collection stores edges as triplets of a source, a target and an edge identifier, indexed from both ends. The graph calls address a collection created with ustore_modality_graph_k, which the in-memory engine keeps apart from every collection of values. Several edges between the same two vertices need distinct edge identifiers, and an edge without one gets ustore_edge_id_default_k.

  • ustore_graph_write_edges adds edges together with their vertices.
  • ustore_graph_write_vertices adds vertices without edges.
  • ustore_graph_read_edges exports the degree and the edges of every requested vertex in the requested role.
  • ustore_graph_remove_edges removes edges and keeps their vertices.
  • ustore_graph_remove_vertices removes vertices together with all their edges.
  • ustore_graph_scan_vertices lists the vertices, those without edges included, as ustore_blobs_scan lists keys; a missing vertex reads with the degree ustore_vertex_degree_missing_k.
typedef struct triplet_t {
    ustore_key_t source;
    ustore_key_t target;
    ustore_key_t edge;
} triplet_t;

ustore_collection_id_t graph = {0};
ustore_collection_create(&(ustore_collection_create_t){
    .database = database,
    .outcome = &outcome,
    .modality = ustore_modality_graph_k,
    .collection = &graph,
});

triplet_t const triplets[2] = {
    {{.uuid.bytes[15] = 1}, {.uuid.bytes[15] = 2}, {.uuid.bytes[15] = 9}},
    {{.uuid.bytes[15] = 2}, {.uuid.bytes[15] = 3}, {.uuid.bytes[15] = 10}},
};
ustore_graph_write_edges(&(ustore_graph_write_edges_t){
    .database = database,
    .outcome = &outcome,
    .count = 2,
    .collections = {&graph, 0},
    .edges = {&triplets[0].edge, sizeof(triplet_t)},
    .sources = {&triplets[0].source, sizeof(triplet_t)},
    .targets = {&triplets[0].target, sizeof(triplet_t)},
});

ustore_key_t vertex = {.uuid.bytes[15] = 2};
ustore_vertex_role_t const role = ustore_vertex_role_any_k;
ustore_vertex_degree_t const* degrees = NULL;
ustore_length_t const* edges_offsets = NULL;
ustore_key_t const* edges = NULL;
ustore_graph_read_edges(&(ustore_graph_read_edges_t){
    .database = database,
    .outcome = &outcome,
    .count = 1,
    .collections = {&graph, 0},
    .vertices = {&vertex, sizeof(ustore_key_t)},
    .roles = {&role, 0},
    .degrees_per_vertex = &degrees,
    .edges_offsets = &edges_offsets,
    .edges_per_vertex = &edges,
    .arena = arena,
});

Every found edge takes three keys of edges: its source, its target and its identifier. The edges of vertex i span from edge edges_offsets[i] up to edge edges_offsets[i + 1], so a missing vertex spans none, and edges_offsets is required whenever edges_per_vertex is asked for. Outgoing edges come first, sorted by target, then incoming edges, sorted by source, and a missing vertex has the degree ustore_vertex_degree_missing_k. Roles matter only in directed graphs, where ustore_vertex_role_source_k and ustore_vertex_role_target_k select one direction, and roles with NULL data stand for ustore_vertex_role_any_k.

API

Types

ustore_vertex_role_tThe role a vertex plays in an edge, where undirected graphs use ustore_vertex_role_any_k.
graph.h:31 ↗
enum ustore_vertex_role_t

In a joining graph the members of each collection must stay either sources or targets.

Values

ustore_vertex_role_unknown_k0No role.
ustore_vertex_role_source_k1The vertex an edge leaves.
ustore_vertex_role_target_k2The vertex an edge enters.
ustore_vertex_role_any_k3Either end of an edge.

Spellings

char const * ustore_vertex_role_name(ustore_vertex_role_t vertex_role);
ustore_vertex_role_t ustore_vertex_role_from_name(
    ustore_bytes_view_t name);
ustore_vertex_roles_view_tA strided run of roles, one per task, where NULL data stands for ustore_vertex_role_any_k.
graph.h:54 ↗
struct ustore_vertex_roles_view_t

Fields

dataustore_vertex_role_t const *First role of the run.
strideustore_size_tBytes between consecutive roles, where zero repeats the first one.
ustore_vertex_degree_tThe number of edges a vertex connects to.
graph.h:65 ↗
typedef uint32_t ustore_vertex_degree_t;
ustore_graph_vertices_cursor_tAn opaque handle to a walk over the vertex keys of one collection, which every pull resumes past the last key the pull before it handed out, as ustore_blobs_cursor_t walks.
graph.h:503 ↗
typedef struct ustore_graph_vertices_cursor_handle_t * ustore_graph_vertices_cursor_t;

It holds its database open, and the transaction or snapshot it reads through, until ustore_graph_vertices_cursor_free, and serves one pull at a time, so a second pull naming it finishes ustore_status_contended_k.

Functions

ustore_graph_read_edgesReads the edges connected to a batch of vertices.
graph.h:145 ↗
void ustore_graph_read_edges(ustore_graph_read_edges_t *arguments);

Parameters

databaseustore_database_tAn open database.
executorustore_executor_tExecutor that runs the call, where NULL runs it on the calling thread.
outcomeustore_outcome_t *Output for the outcome, final once its status leaves ustore_status_deferred_k.
completionustore_completion_tWhether the call returns final, the default, or once submitted.
viewustore_view_tWhat the call sees, where NULL is the head.
countustore_size_tNumber of vertices.
collectionsustore_collections_view_tGraph collections.
verticesustore_keys_view_tVertices whose edges are read.
rolesustore_vertex_roles_view_tRoles the vertices play in the wanted edges.
degrees_per_vertexustore_vertex_degree_t const **Output for the degree of every vertex, with ustore_vertex_degree_missing_k for missing ones, inside arena.
edges_offsetsustore_length_t const **Optional output for count plus one offsets into edges_per_vertex, counted in edges, where a missing vertex spans none, inside arena; required with edges_per_vertex.
edges_per_vertexustore_key_t const **Optional output for the tape of edges, three keys per edge, inside arena.
arenaustore_arena_tRewound by this call, then holding every output it writes; NULL is refused.

Statuses

ustore_status_invalid_argument_k means the arena, collections, vertices or degrees output is missing, the edges are asked without their offsets, the view was made by neither view constructor or belongs to another engine, a watching read goes through a staged transaction, or a collection holds another modality.

ustore_graph_write_edgesWrites a batch of edges between existing or new vertices.
graph.h:211 ↗
void ustore_graph_write_edges(ustore_graph_write_edges_t *arguments);

Parameters

databaseustore_database_tAn open database.
executorustore_executor_tExecutor that runs the call, where NULL runs it on the calling thread.
outcomeustore_outcome_t *Output for the outcome, final once its status leaves ustore_status_deferred_k.
completionustore_completion_tWhether the call returns final, the default, or once submitted.
transactionustore_transaction_tTransaction the edits join, where NULL writes to the head.
countustore_size_tNumber of edges.
collectionsustore_collections_view_tGraph collections.
edgesustore_keys_view_tIdentifiers of the edges, where NULL data gives each ustore_edge_id_default_k.
sourcesustore_keys_view_tSources of the edges.
targetsustore_keys_view_tTargets of the edges.
durabilityustore_durability_tHow durable the edits are once the call finishes at the head; a transaction's commit decides its own.
watchustore_watch_tWhether the transaction records the vertices it reads and writes for conflicts.

Statuses

ustore_graph_remove_edgesRemoves a batch of edges.
graph.h:277 ↗
void ustore_graph_remove_edges(ustore_graph_remove_edges_t *arguments);

Parameters

databaseustore_database_tAn open database.
executorustore_executor_tExecutor that runs the call, where NULL runs it on the calling thread.
outcomeustore_outcome_t *Output for the outcome, final once its status leaves ustore_status_deferred_k.
completionustore_completion_tWhether the call returns final, the default, or once submitted.
transactionustore_transaction_tTransaction the edits join, where NULL writes to the head.
countustore_size_tNumber of edges.
collectionsustore_collections_view_tGraph collections.
edgesustore_keys_view_tIdentifiers of the edges, where NULL data gives each ustore_edge_id_default_k.
sourcesustore_keys_view_tSources of the edges.
targetsustore_keys_view_tTargets of the edges.
durabilityustore_durability_tHow durable the edits are once the call finishes at the head; a transaction's commit decides its own.
watchustore_watch_tWhether the transaction records the vertices it reads and writes for conflicts.

Statuses

ustore_graph_write_verticesWrites a batch of vertices without edges, keeping those already present.
graph.h:338 ↗
void ustore_graph_write_vertices(
    ustore_graph_write_vertices_t *arguments);

ustore_status_invalid_argument_k means the collections or vertices are missing, the transaction belongs to another engine or is staged, the durability or watch is unknown, a flushed write names a transaction, ustore_watch_none_k comes without one on RocksDB and LevelDB, or a collection holds another modality.

Parameters

databaseustore_database_tAn open database.
executorustore_executor_tExecutor that runs the call, where NULL runs it on the calling thread.
outcomeustore_outcome_t *Output for the outcome, final once its status leaves ustore_status_deferred_k.
completionustore_completion_tWhether the call returns final, the default, or once submitted.
transactionustore_transaction_tTransaction the edits join, where NULL writes to the head.
countustore_size_tNumber of vertices.
collectionsustore_collections_view_tGraph collections.
verticesustore_keys_view_tVertices to insert unless present.
durabilityustore_durability_tHow durable the edits are once the call finishes at the head; a transaction's commit decides its own.
watchustore_watch_tWhether the transaction records the vertices it reads and writes for conflicts.

Statuses

ustore_graph_remove_verticesRemoves a batch of vertices together with every edge they belong to.
graph.h:407 ↗
void ustore_graph_remove_vertices(
    ustore_graph_remove_vertices_t *arguments);

ustore_status_invalid_argument_k means the collections or vertices are missing, the transaction belongs to another engine or is staged, the durability or watch is unknown, a flushed remove names a transaction, ustore_watch_none_k comes without one on RocksDB and LevelDB, or a collection holds another modality.

Parameters

databaseustore_database_tAn open database.
executorustore_executor_tExecutor that runs the call, where NULL runs it on the calling thread.
outcomeustore_outcome_t *Output for the outcome, final once its status leaves ustore_status_deferred_k.
completionustore_completion_tWhether the call returns final, the default, or once submitted.
transactionustore_transaction_tTransaction the edits join, where NULL writes to the head.
countustore_size_tNumber of vertices.
collectionsustore_collections_view_tGraph collections.
verticesustore_keys_view_tVertices to remove, or the inclusive starts of ranges when end_vertices is given.
end_verticesustore_keys_view_tExclusive ends of the ranges of vertices to remove with their edges, or a zeroed view to remove vertices alone.
rolesustore_vertex_roles_view_tRoles of the vertices, needed only by joining graphs.
durabilityustore_durability_tHow durable the edits are once the call finishes at the head; a transaction's commit decides its own.
watchustore_watch_tWhether the transaction records the vertices it reads and writes for conflicts.

Statuses

ustore_graph_scan_verticesScans a batch of vertex ranges.
graph.h:493 ↗
void ustore_graph_scan_vertices(
    ustore_graph_scan_vertices_t *arguments);

Parameters

databaseustore_database_tAn open database.
executorustore_executor_tExecutor that runs the call, where NULL runs it on the calling thread.
outcomeustore_outcome_t *Output for the outcome, final once its status leaves ustore_status_deferred_k.
completionustore_completion_tWhether the call returns final, the default, or once submitted.
viewustore_view_tWhat the call sees, where NULL is the head.
countustore_size_tNumber of scans.
collectionsustore_collections_view_tGraph collections.
start_keysustore_keys_view_tVertex every scan starts from, inclusive, where NULL data starts at the first vertex in the direction.
end_keysustore_keys_view_tKey every scan stops before, exclusive, or a zeroed view for no bound.
directionustore_scan_direction_tAscending, the default, or descending from the start key.
predicateustore_predicate_tOptional verdict on the listed vertices, asked on the host once per page as its cost says.
offsetsustore_length_t const **Output for count plus one offsets into keys, the last one closing the final scan, inside arena.
keysustore_key_t const **Output for the found vertices, scan after scan, inside arena.
arenaustore_arena_tRewound by this call, then holding every output it writes; NULL is refused.
wantedustore_size_tMost vertices every scan returns.
modeustore_scan_mode_tIn what order the vertices come.
progressustore_progress_callback_tOptional callback reporting the scans finished.
progress_statevoid *Opaque pointer passed to progress.

Statuses

ustore_status_invalid_argument_k means the arena, collections or an output is missing, the mode, direction or a predicate cost is unknown, the view was made by neither view constructor or belongs to another engine, a watching scan goes through a staged transaction, or a collection holds another modality.

ustore_graph_vertices_cursor_initOpens a walk over the vertex keys of one collection, reading nothing until its first pull.
graph.h:552 ↗
void ustore_graph_vertices_cursor_init(
    ustore_graph_vertices_cursor_init_t *arguments);

Parameters

cursorustore_graph_vertices_cursor_t *Output for the new cursor, which the caller frees with ustore_graph_vertices_cursor_free, or NULL on failure.
databaseustore_database_tAn open database.
executorustore_executor_tExecutor of the kind every pull runs on, which picks the side the walk computes on, where NULL walks on host executors; a pull on another kind of executor reports ustore_status_device_k.
outcomeustore_outcome_t *Output for the outcome, final on return.
viewustore_view_tWhat the walk sees, where NULL is the head, read pull by pull.
collectionustore_collection_id_tGraph collection whose vertices to walk.
start_keyustore_key_tKey the walk starts from, inclusive.
end_keyustore_key_t const *Key the walk stops before, exclusive, or NULL for no bound.
directionustore_scan_direction_tAscending, the default, or descending from the start key.
predicateustore_predicate_tOptional verdict on the keys of every page, asked as its cost says; host executors only.

Statuses

ustore_graph_vertices_cursor_nextPulls the next page of a walk.
graph.h:610 ↗
void ustore_graph_vertices_cursor_next(
    ustore_graph_vertices_cursor_next_t *arguments);

Parameters

databaseustore_database_tThe database the cursor was opened on.
executorustore_executor_tExecutor that runs the call, where NULL runs it on the calling thread.
outcomeustore_outcome_t *Output for the outcome, final once its status leaves ustore_status_deferred_k.
completionustore_completion_tWhether the call returns final, the default, or once submitted.
cursorustore_graph_vertices_cursor_tThe cursor to advance, which a pull that fails or is cancelled leaves where it was.
keysustore_key_t const **Output for the keys of the page in their order, inside arena.
writtenustore_size_t *Output for the keys written, zero once the walk is exhausted; zeroed on failure.
arenaustore_arena_tRewound by this call, then holding every output it writes; NULL is refused.
wantedustore_size_tMost keys the page holds, where a page of fewer exhausts the walk.
progressustore_progress_callback_tOptional callback reporting the one pull, which may cancel it before the cursor advances.
progress_statevoid *Opaque pointer passed to progress.

Statuses

  • ustore_status_invalid_argument_k The cursor, the arena or the written output is NULL, the cursor walks another database, a watching pull goes through a staged transaction, or the collection holds another modality.
  • ustore_status_device_k The arena lives where another executor computes, a cursor opened for a device is pulled on host threads, or a host cursor is pulled on a device.
  • ustore_status_contended_k The arena, the cursor or the transaction it reads through serves another call, the executor's deferred table is full, a callback blocks on the executor running it, or an NVMe value keeps changing size across reads.
  • ustore_status_uninitialized_k The database is NULL or an NVMe transfer was cancelled.
  • ustore_status_not_found_k The collection does not exist or was dropped meanwhile.
  • ustore_status_capacity_exhausted_k Every shared NVMe channel is taken.
ustore_graph_vertices_cursor_freeWaits until every deferred call naming the cursor finishes, then frees it, giving back the holds it kept on its database and on the transaction or snapshot it reads through.
graph.h:617 ↗
void ustore_graph_vertices_cursor_free(
    ustore_graph_vertices_cursor_t cursor);

Parameters

cursorinoutThe cursor to be freed; NULL is safe.
ustore_graph_sample_verticesSamples vertices from a batch of collections.
graph.h:675 ↗
void ustore_graph_sample_vertices(
    ustore_graph_sample_vertices_t *arguments);

Parameters

databaseustore_database_tAn open database.
executorustore_executor_tExecutor that runs the call, where NULL runs it on the calling thread.
outcomeustore_outcome_t *Output for the outcome, final once its status leaves ustore_status_deferred_k.
completionustore_completion_tWhether the call returns final, the default, or once submitted.
viewustore_view_tWhat the call sees, where NULL is the head.
countustore_size_tNumber of samples.
collectionsustore_collections_view_tCollections to sample.
offsetsustore_length_t const **Output in arena for count plus one offsets into keys, the last closing them.
keysustore_key_t const **Output for the sampled keys, sample after sample, inside arena.
arenaustore_arena_tRewound by this call, then holding every output it writes; NULL is refused.
wantedustore_size_tMost keys every sample draws.

Statuses

ustore_graph_measure_verticesEstimates the vertices and the space inside a batch of key ranges.
graph.h:753 ↗
void ustore_graph_measure_vertices(
    ustore_graph_measure_vertices_t *arguments);

ustore_status_invalid_argument_k means the arena or the collections are missing, the direction is unknown, the view was made by neither view constructor or belongs to another engine, a watching measure goes through a staged transaction, or a collection holds another modality.

Parameters

databaseustore_database_tAn open database.
executorustore_executor_tExecutor that runs the call, where NULL runs it on the calling thread.
outcomeustore_outcome_t *Output for the outcome, final once its status leaves ustore_status_deferred_k.
completionustore_completion_tWhether the call returns final, the default, or once submitted.
viewustore_view_tWhat the call sees, where NULL is the head.
countustore_size_tNumber of measured ranges.
collectionsustore_collections_view_tCollections to measure.
start_keysustore_keys_view_tInclusive start of every range, NULL data starting at the first key in direction.
end_keysustore_keys_view_tKey every range stops before, exclusive, or a zeroed view for no bound.
directionustore_scan_direction_tAscending, the default, or descending from the start key.
min_cardinalitiesustore_size_t const **Optional output for the lower bound on the vertices in every range, inside arena.
max_cardinalitiesustore_size_t const **Optional output for the upper bound on the vertices in every range, inside arena.
min_value_bytesustore_size_t const **Optional output for the lower bound on the value bytes in every range, inside arena.
max_value_bytesustore_size_t const **Optional output for the upper bound on the value bytes in every range, inside arena.
min_space_usagesustore_size_t const **Optional output for the lower bound on the disk space every range takes, inside arena.
max_space_usagesustore_size_t const **Optional output for the upper bound on the disk space every range takes, inside arena.
arenaustore_arena_tRewound by this call, then holding every output it writes; NULL is refused.

Statuses

Constants

ustore_edge_id_default_kThe edge identifier of an edge that was given none, every bit of it set like ustore_key_unknown_k.
graph.h:26 ↗
ustore_key_t const ustore_edge_id_default_k;
ustore_vertex_degree_missing_kThe degree reported for a missing vertex.
graph.h:68 ↗
ustore_vertex_degree_t const ustore_vertex_degree_missing_k;