Add RecordVal::AssignField() and use it in supervisor code

This is a convenience method to assign a known record field value by
field name.  May also be useful to reduce warnings from static analysis
(e.g. Coverity) about not checking for negative return values before
assigning since that now flows through a [[noreturn]] error path.
This commit is contained in:
Jon Siwek 2021-03-26 18:57:42 -07:00
parent 7bf885b0b8
commit 2855df63ce
3 changed files with 33 additions and 22 deletions

View file

@ -1152,6 +1152,19 @@ public:
void Assign(int field, String* new_val) void Assign(int field, String* new_val)
{ Assign(field, new StringVal(new_val)); } { Assign(field, new StringVal(new_val)); }
/**
* Assign a value of type @c T to a record field of the given name.
* A fatal error occurs if the no such field name exists.
*/
template <class T>
void AssignField(const char* field_name, T&& val)
{
int idx = GetType()->AsRecordType()->FieldOffset(field_name);
if ( idx < 0 )
reporter->InternalError("missing record field: %s", field_name);
Assign(idx, std::forward<T>(val));
}
/** /**
* Appends a value to the record's fields. The caller is responsible * Appends a value to the record's fields. The caller is responsible
* for ensuring that fields are appended in the correct order and * for ensuring that fields are appended in the correct order and

View file

@ -1348,22 +1348,22 @@ RecordValPtr Supervisor::NodeConfig::ToRecord() const
{ {
const auto& rt = BifType::Record::Supervisor::NodeConfig; const auto& rt = BifType::Record::Supervisor::NodeConfig;
auto rval = make_intrusive<RecordVal>(rt); auto rval = make_intrusive<RecordVal>(rt);
rval->Assign(rt->FieldOffset("name"), name); rval->AssignField("name", name);
if ( interface ) if ( interface )
rval->Assign(rt->FieldOffset("interface"), *interface); rval->AssignField("interface", *interface);
if ( directory ) if ( directory )
rval->Assign(rt->FieldOffset("directory"), *directory); rval->AssignField("directory", *directory);
if ( stdout_file ) if ( stdout_file )
rval->Assign(rt->FieldOffset("stdout_file"), *stdout_file); rval->AssignField("stdout_file", *stdout_file);
if ( stderr_file ) if ( stderr_file )
rval->Assign(rt->FieldOffset("stderr_file"), *stderr_file); rval->AssignField("stderr_file", *stderr_file);
if ( cpu_affinity ) if ( cpu_affinity )
rval->Assign(rt->FieldOffset("cpu_affinity"), *cpu_affinity); rval->AssignField("cpu_affinity", *cpu_affinity);
auto st = rt->GetFieldType<VectorType>("scripts"); auto st = rt->GetFieldType<VectorType>("scripts");
auto scripts_val = make_intrusive<VectorVal>(std::move(st)); auto scripts_val = make_intrusive<VectorVal>(std::move(st));
@ -1371,11 +1371,11 @@ RecordValPtr Supervisor::NodeConfig::ToRecord() const
for ( const auto& s : scripts ) for ( const auto& s : scripts )
scripts_val->Assign(scripts_val->Size(), make_intrusive<StringVal>(s)); scripts_val->Assign(scripts_val->Size(), make_intrusive<StringVal>(s));
rval->Assign(rt->FieldOffset("scripts"), std::move(scripts_val)); rval->AssignField("scripts", std::move(scripts_val));
auto tt = rt->GetFieldType<TableType>("cluster"); auto tt = rt->GetFieldType<TableType>("cluster");
auto cluster_val = make_intrusive<TableVal>(std::move(tt)); auto cluster_val = make_intrusive<TableVal>(std::move(tt));
rval->Assign(rt->FieldOffset("cluster"), cluster_val); rval->AssignField("cluster", cluster_val);
for ( const auto& e : cluster ) for ( const auto& e : cluster )
{ {
@ -1385,12 +1385,12 @@ RecordValPtr Supervisor::NodeConfig::ToRecord() const
const auto& ept = BifType::Record::Supervisor::ClusterEndpoint; const auto& ept = BifType::Record::Supervisor::ClusterEndpoint;
auto val = make_intrusive<RecordVal>(ept); auto val = make_intrusive<RecordVal>(ept);
val->Assign(ept->FieldOffset("role"), BifType::Enum::Supervisor::ClusterRole->GetEnumVal(ep.role)); val->AssignField("role", BifType::Enum::Supervisor::ClusterRole->GetEnumVal(ep.role));
val->Assign(ept->FieldOffset("host"), make_intrusive<AddrVal>(ep.host)); val->AssignField("host", make_intrusive<AddrVal>(ep.host));
val->Assign(ept->FieldOffset("p"), val_mgr->Port(ep.port, TRANSPORT_TCP)); val->AssignField("p", val_mgr->Port(ep.port, TRANSPORT_TCP));
if ( ep.interface ) if ( ep.interface )
val->Assign(ept->FieldOffset("interface"), *ep.interface); val->AssignField("interface", *ep.interface);
cluster_val->Assign(std::move(key), std::move(val)); cluster_val->Assign(std::move(key), std::move(val));
} }
@ -1403,10 +1403,10 @@ RecordValPtr SupervisorNode::ToRecord() const
const auto& rt = BifType::Record::Supervisor::NodeStatus; const auto& rt = BifType::Record::Supervisor::NodeStatus;
auto rval = make_intrusive<RecordVal>(rt); auto rval = make_intrusive<RecordVal>(rt);
rval->Assign(rt->FieldOffset("node"), config.ToRecord()); rval->AssignField("node", config.ToRecord());
if ( pid ) if ( pid )
rval->Assign(rt->FieldOffset("pid"), pid); rval->AssignField("pid", pid);
return rval; return rval;
} }
@ -1458,17 +1458,15 @@ bool SupervisedNode::InitCluster() const
auto val = make_intrusive<RecordVal>(cluster_node_type); auto val = make_intrusive<RecordVal>(cluster_node_type);
auto node_type = supervisor_role_to_cluster_node_type(ep.role); auto node_type = supervisor_role_to_cluster_node_type(ep.role);
val->Assign(cluster_node_type->FieldOffset("node_type"), std::move(node_type)); val->AssignField("node_type", std::move(node_type));
val->Assign(cluster_node_type->FieldOffset("ip"), make_intrusive<AddrVal>(ep.host)); val->AssignField("ip", make_intrusive<AddrVal>(ep.host));
val->Assign(cluster_node_type->FieldOffset("p"), val_mgr->Port(ep.port, TRANSPORT_TCP)); val->AssignField("p", val_mgr->Port(ep.port, TRANSPORT_TCP));
if ( ep.interface ) if ( ep.interface )
val->Assign(cluster_node_type->FieldOffset("interface"), val->AssignField("interface", *ep.interface);
*ep.interface);
if ( manager_name && ep.role != BifEnum::Supervisor::MANAGER ) if ( manager_name && ep.role != BifEnum::Supervisor::MANAGER )
val->Assign(cluster_node_type->FieldOffset("manager"), val->AssignField("manager", *manager_name);
*manager_name);
cluster_nodes->Assign(std::move(key), std::move(val)); cluster_nodes->Assign(std::move(key), std::move(val));
} }

View file

@ -86,7 +86,7 @@ function Supervisor::__node%(%): Supervisor::NodeConfig
zeek::emit_builtin_error("not a supervised process"); zeek::emit_builtin_error("not a supervised process");
const auto& rt = zeek::BifType::Record::Supervisor::NodeConfig; const auto& rt = zeek::BifType::Record::Supervisor::NodeConfig;
auto rval = zeek::make_intrusive<zeek::RecordVal>(rt); auto rval = zeek::make_intrusive<zeek::RecordVal>(rt);
rval->Assign(rt->FieldOffset("name"), "<invalid>"); rval->AssignField("name", "<invalid>");
return rval; return rval;
} }