Bootstrap method: view
The “view” bootstrap method allows you to initialize a Flock group from a pre-constructed group view. This is useful when you have a known set of members that have coordinated between themselves ahead of initializing flock, and want to initialize their flock provider with the same view of the group.
When to use
Use the “view” bootstrap method when:
You have a predetermined list of group members, and you already know their address
You want to programmatically construct a group view
You’re initializing multiple processes with a shared view
You need fine-grained control over the initial group membership
Configuration
In a Bedrock configuration, you can’t directly specify the view bootstrap method because views must be constructed programmatically.
In C code
To use the view bootstrap method programmatically, you can load a view from a file:
Bootstrapping from a view assumes that you have a way of creating a consistent view
across members beforehand. Here is an example where such a view is provided in a JSON
file, read using flock_group_view_init_from_file.
/*
* (C) 2024 The University of Chicago
*
* See COPYRIGHT in top-level directory.
*/
#include <assert.h>
#include <stdio.h>
#include <margo.h>
#include <flock/flock-server.h>
#include <flock/flock-bootstrap.h>
int main(int argc, char** argv)
{
if(argc != 2) {
fprintf(stderr, "Usage: %s <view_file>\n", argv[0]);
return -1;
}
const char* view_file = argv[1];
// Initialize Margo
margo_instance_id mid = margo_init("na+sm", MARGO_SERVER_MODE, 0, 0);
assert(mid);
// Initialize provider args
struct flock_provider_args args = FLOCK_PROVIDER_ARGS_INIT;
flock_group_view_t initial_view = FLOCK_GROUP_VIEW_INITIALIZER;
args.initial_view = &initial_view;
// Bootstrap from view file
uint16_t provider_id = 42;
int ret = flock_group_view_init_from_file(view_file, &initial_view);
if(ret != FLOCK_SUCCESS) {
fprintf(stderr, "Failed to initialize view from file: %s\n", view_file);
margo_finalize(mid);
return -1;
}
printf("Bootstrapped group from view file: %s\n", view_file);
printf("Group size: %zu\n", initial_view.members.size);
// Print all members
for(size_t i = 0; i < initial_view.members.size; i++) {
printf(" Member %zu: %s (provider_id=%u)\n",
i,
initial_view.members.data[i].address,
initial_view.members.data[i].provider_id);
}
// Configure with static backend
const char* config = "{ \"group\":{ \"type\":\"static\", \"config\":{} } }";
// Register provider
flock_provider_t provider;
ret = flock_provider_register(mid, provider_id, config, &args, &provider);
assert(ret == FLOCK_SUCCESS);
printf("Flock provider registered\n");
// Wait for finalize
margo_wait_for_finalize(mid);
return 0;
}
Sharing views between processes
Once you have a group view, you can:
Serialize to JSON: Convert the view to JSON format for easy sharing
Write to file: Save the view to a file that other processes can read
Send via RPC: Transmit the view to other processes using Mercury RPC
Other processes can then use the “file” bootstrap method to initialize from this view.
View operations
The group view API provides several operations:
flock_group_view_add_member: Add a member to the viewflock_group_view_add_metadata: Add metadata key-value pairflock_group_view_serialize: Convert view to JSON stringflock_group_view_deserialize: Parse view from JSON stringflock_group_view_clear: Free view resourcesflock_group_view_copy: Create a copy of a view