summaryrefslogtreecommitdiffstats
path: root/occ_errors.hpp
blob: 12ae9255c771a7d5da2b49f3f4cc202888c1cf75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#pragma once

#include <unistd.h>
#include <functional>
#include <experimental/filesystem>
#include "occ_events.hpp"
#include "config.h"
namespace open_power
{
namespace occ
{

namespace fs = std::experimental::filesystem;

/** @class Error
 *  @brief Monitors for OCC device error condition
 */
class Error
{
    public:
        Error() = delete;
        Error(const Error&) = delete;
        Error& operator=(const Error&) = delete;
        Error(Error&&) = default;
        Error& operator=(Error&&) = default;

        /** @brief Constructs the Error object
         *
         *  @param[in] event    - reference to sd_event unique_ptr
         *  @param[in] file     - File used by driver to communicate errors
         *  @param[in] callBack - Optional function callback on error condition
         */
        Error(EventPtr& event,
              const fs::path& file,
              std::function<void(bool)> callBack = nullptr) :
            event(event),
            file(fs::path(DEV_PATH) / file),
            callBack(callBack)
        {
            // Nothing to do here.
        }

        ~Error()
        {
            if (fd>= 0)
            {
                close(fd);
            }
        }

        /** @brief Starts to monitor for error conditions */
        void addWatch();

        /** @brief Removes error watch */
        void removeWatch();

    private:
        /** @brief sd_event wrapped in unique_ptr */
        EventPtr& event;

        /** @brief event source wrapped in unique_ptr */
        EventSourcePtr eventSource;

        /** @brief Current state of error watching */
        bool watching = false;

        /** @brief attaches FD to events and sets up callback handler */
        void registerCallBack();

        /** @brief Opens the file and populates fd */
        void openFile();

        /** @brief Callback handler when the FD has some activity on it
         *
         *  @param[in] es       - Populated event source
         *  @param[in] fd       - Associated File descriptor
         *  @param[in] revents  - Type of event
         *  @param[in] userData - User data that was passed during registration
         *
         *  @return             - 0 or positive number on success and negative
         *                        errno otherwise
         */
        static int processEvents(sd_event_source* es, int fd,
                                 uint32_t revents, void* userData);

        /** @brief When the error event is received, analyzes it
         *         and makes a callback to error handler if the
         *         content denotes an error condition
         */
        virtual void analyzeEvent();

    protected:
        /** @brief File descriptor to watch for errors */
        int fd = -1;

        /** Error file */
        const fs::path file;

        /** @brief Optional function to call on error scenario */
        std::function<void(bool)> callBack;

        /** @brief Reads file data
         *
         *  @return data read. Since its a /sysfs entry,
         *          it would be a string
         */
        std::string readFile(int) const;
};

} // namespace occ
} // namespace open_power
OpenPOWER on IntegriCloud