blob: fc119129a593055f774d4f72626dcf82b25d890d [file] [log] [blame]
/* Copyright 2018 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef RUNTIME_PROBE_PROBE_FUNCTION_H_
#define RUNTIME_PROBE_PROBE_FUNCTION_H_
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <variant>
#include <vector>
#include <base/json/json_writer.h>
#include <base/values.h>
#include <base/strings/string_util.h>
#include "runtime_probe/probe_function_argument.h"
namespace runtime_probe {
class ProbeFunction {
/*
* Formally, a probe function will be represented as following structure::
* {
* <function_name:string>: <args:ArgsType>
* }
*
* where the top layer dictionary should have one and only one key. For
* example::
* {
* "sysfs": {
* "dir_path": "/sys/class/cool/device/dev*",
* "keys": ["key_1", "key_2"],
* "optional_keys": ["opt_key_1"]
* }
* }
*
* TODO(stimim): implement the following syntax.
*
* Alternative Syntax::
* 1. single string ("<function_name:string>"), this is equivalent to::
* {
* <function_name:string>: {}
* }
*
* 2. single string ("<function_name:string>:<arg:string>"), this is
* equivalent to::
* {
* <function_name:string>: {
* "__only_required_argument": {
* <arg:string>
* }
* }
* }
*/
public:
typedef std::vector<base::DictionaryValue> DataType;
/* Convert |value| to ProbeFunction. Returns nullptr on failure.
*/
static std::unique_ptr<ProbeFunction> FromValue(const base::Value& value) {
std::unique_ptr<ProbeFunction> retval;
if (value.is_dict()) {
const base::DictionaryValue* dict_value;
value.GetAsDictionary(&dict_value);
retval = FromDictionaryValue(*dict_value);
}
if (retval == nullptr) {
LOG(ERROR) << "Failed to parse " << value << " as ProbeFunction";
}
return retval;
}
/* Evaluates this probe function.
*
* Output will be a list of base::DictionaryValue.
*/
virtual DataType Eval() const = 0;
/* Function prototype of |FromDictionaryValue| that should be implemented by
* each derived class. See `functions/sysfs.h` about how to implement this
* function.
*/
typedef std::function<std::unique_ptr<ProbeFunction>(
const base::DictionaryValue&)>
FactoryFunctionType;
/* Mapping from |function_name| to |FromDictionaryValue| of each derived
* classes.
*/
static std::unordered_map<std::string_view, FactoryFunctionType>
REGISTERED_FUNCTIONS;
template <class T>
struct Register {
Register() {
static_assert(std::is_base_of<ProbeFunction, T>::value,
"Registered type must inherit ProbeFunction");
REGISTERED_FUNCTIONS[T::function_name] = T::FromDictionaryValue;
}
};
virtual ~ProbeFunction() = default;
protected:
ProbeFunction() = default;
private:
static std::unique_ptr<ProbeFunction> FromDictionaryValue(
const base::DictionaryValue& dict_value);
/*
* Each probe function must define their own args type.
*/
};
#ifdef _RUNTIME_PROBE_GENERATE_PROBE_FUNCTIONS
/* _RUNTIME_PROBE_GENERATE_PROBE_FUNCTIONS should only be defined by
* `all_functions.cc`. So the following initialization will only have one
* instance.
*/
std::unordered_map<std::string_view, ProbeFunction::FactoryFunctionType>
ProbeFunction::REGISTERED_FUNCTIONS{};
#define REGISTER_PROBE_FUNCTION(T) ProbeFunction::Register<T> T::register_
#else
#define REGISTER_PROBE_FUNCTION(T)
#endif
} // namespace runtime_probe
#endif // RUNTIME_PROBE_PROBE_FUNCTION_H_