Browse Source

[4297] Hooks documentation updated.

Tomek Mrugalski 9 years ago
parent
commit
07e75c55e0
1 changed files with 133 additions and 0 deletions
  1. 133 0
      src/lib/hooks/hooks_user.dox

+ 133 - 0
src/lib/hooks/hooks_user.dox

@@ -1271,4 +1271,137 @@ int load() {
 
 
 }
 }
 @endcode
 @endcode
+
+@subsection hooksdgHooksConfig Configuring Hooks Libraries
+
+Sometimes it is useful for the hook library to have some configuration parameters.
+This capability was introduced in Kea 1.1. This is often convenient to follow
+generic Kea configuration approach rather than invent your own configuration
+logic. Consider the following example:
+
+@code
+"hooks-libraries": [
+    {
+        "library": "/opt/first.so"
+    },
+    {
+        "library": "/opt/second.so",
+        "parameters": {
+        }
+    },
+    {
+        "library": "/opt/third.so",
+        "parameters": {
+            "mail": "spam@example.com",
+            "floor": 13,
+            "debug": false,
+            "users": [ "alice", "bob", "charlie" ],
+            "languages": {
+                "french": "bonjour",
+                "klingon": "yl'el"
+            }
+        }
+    }
+]
+@endcode
+
+This example has three hook libraries configured. The first and and second have
+no parameters. Note that parameters map is optional, but it's perfectly ok to
+specify it as an empty map. The third library is more interesting. It has five
+parameters specified. The first one called 'mail' is a string. The second one
+is an integer and the third one is boolean. Fourth and fifth parameters are
+slightly more complicated as they are a list and a map respectively. JSON
+structures can be nested if necessary, e.g. you can have a list, which contains
+maps, maps that contain maps that contain other maps etc. Any valid JSON
+structure can be repesented. One important limitation here is that the top
+level "parameters" structure must either be a map or not present at all.
+
+Those parameters can be accessed in load() method. Passed isc::hooks::LibraryHandle
+object has a method called getParameter that returns an instance of
+isc::data::ConstElementPtr or NULL if there was no parameter specified. This pointer
+will point to an object derived from isc::data::Element class. For detailed
+explanation how to use those objects, see isc::data::Element class.
+
+Here's a brief overview of how to use those elements:
+
+ - x = getParameter("mail") will return instance of isc::data::StringElement. The content
+   can be accessed with x->stringValue() and will return std::string.
+ - x = getParameter("floor") will return an instance of isc::data::IntElement.
+   The content can be accessed with x->intValue() and will return int.
+ - x = getParameter("debug") will return an instance of isc::data::BoolElement.
+   Its value can be accessed with x->boolValue() and will return bool.
+ - x = getParameter("users") will return an instance of isc::data::ListElement.
+   Its content can be accessed with the following methods:
+   x->size(), x->get(index)
+ - x = getParameter("watch-list") will return an instance of isc::data::MapElement.
+   Its content can be accessed with the following methods:
+   x->find("klingon"), x->contains("french"), x->size()
+
+Keep in mind that the user can structure his config file incorrectly.
+Remember to check if the structure has expected type before using type specific
+method. For example calling stringValue on IntElement will throw an exception.
+You can do this by calling isc::data::Element::getType.
+
+Here's an example that obtains all of the parameters specified above.
+If you want to get nested elemented, Element::get(index) and Element::find(name)
+will return ElementPtr, which can be iterated in similar manner.
+
+@code
+int load(LibraryHandle& handle) {
+    ConstElementPtr mail  = handle.getParameter("mail");
+    ConstElementPtr floor = handle.getParameter("floor");
+    ConstElementPtr debug = handle.getParameter("debug");
+    ConstElementPtr users = handle.getParameter("users");
+    ConstElementPtr lang  = handle.getParameter("languages");
+
+    // String handling example
+    if (!mail) {
+        // Handle missing 'mail' parameter here.
+        return (1);
+    }
+    if (mail->getType() != Element::string) {
+        // Handle incorrect 'mail' parameter here.
+        return (1);
+    }
+    std::string mail_str = mail->stringValue();
+
+    // In the following examples safety checks are omitted for clarity.
+    // Make sure you do it properly similar to mail example above
+    // or you risk dereferencing NULL pointer or at least throwing
+    // an exception!
+
+    // Integer handling example
+    int floor_num = floor->intValue();
+
+    // Boolean handling example
+    bool debug_flag = debug->boolValue();
+
+    // List handling example
+    std::cout << "There are " << users->size() << " users defined." << std::endl;
+    for (int i = 0; i < users->size(); i++) {
+        ConstElementPtr user = users->get(i);
+        std::cout << "User " << user->stringValue() << std::endl;
+    }
+
+    // Map handling example
+    std::cout << "There are " << lang->size() << " languages defined." << std::endl;
+    if (lang->contains("french")) {
+       std::cout << "One of them is French!" << std::endl;
+    }
+    ConstElementPtr greeting = lang->find("klingon");
+    if (greeting) {
+       std::cout << "Lt. Worf says " << greeting->stringValue() << std::endl;
+    }
+
+    // All validation steps were successful. The library has all the parameters
+    // it needs, so we should report a success.
+    return (0);
+}
+@endcode
+
+A good sources of examples could be unit-tests in file src/lib/cc/tests/data_unittests.cc
+which are dedicated to isc::data::Element testing and src/lib/hooks/tests/callout_params_library.cc,
+which is an example library used in testing. This library expects exactly 3 parameters:
+svalue (which is a string), ivalue (which is an integer) and bvalue (which is a boolean).
+
 */
 */