1 #pragma once
2 
3 #include "config.h"
4 
5 #include "occ_events.hpp"
6 
7 #include <unistd.h>
8 
9 #include <experimental/filesystem>
10 #include <functional>
11 namespace open_power
12 {
13 namespace occ
14 {
15 
16 namespace fs = std::experimental::filesystem;
17 
18 /** @class Error
19  *  @brief Monitors for OCC device error condition
20  */
21 class Error
22 {
23   public:
24     Error() = delete;
25     Error(const Error&) = delete;
26     Error& operator=(const Error&) = delete;
27     Error(Error&&) = default;
28     Error& operator=(Error&&) = default;
29 
30     /** @brief Constructs the Error object
31      *
32      *  @param[in] event    - reference to sd_event unique_ptr
33      *  @param[in] file     - File used by driver to communicate errors
34      *  @param[in] callBack - Optional function callback on error condition
35      */
36     Error(EventPtr& event, const fs::path& file,
37           std::function<void(bool)> callBack = nullptr) :
38         event(event),
39         file(file), callBack(callBack)
40     {
41         // Nothing to do here.
42     }
43 
44     ~Error()
45     {
46         if (fd >= 0)
47         {
48             close(fd);
49         }
50     }
51 
52     /** @brief Starts to monitor for error conditions
53      *
54      *  @param[in] poll - Indicates whether or not the error file should
55      *                    actually be polled for changes. Disabling polling is
56      *                    necessary for error files that don't support the poll
57      *                    file operation.
58      */
59     void addWatch(bool poll = true);
60 
61     /** @brief Removes error watch */
62     void removeWatch();
63 
64     inline void setFile(const fs::path& f)
65     {
66         file = f;
67     }
68 
69   private:
70     /** @brief sd_event wrapped in unique_ptr */
71     EventPtr& event;
72 
73     /** @brief event source wrapped in unique_ptr */
74     EventSourcePtr eventSource;
75 
76     /** @brief Current state of error watching */
77     bool watching = false;
78 
79     /** @brief attaches FD to events and sets up callback handler */
80     void registerCallBack();
81 
82     /** @brief Opens the file and populates fd */
83     void openFile();
84 
85     /** @brief Callback handler when the FD has some activity on it
86      *
87      *  @param[in] es       - Populated event source
88      *  @param[in] fd       - Associated File descriptor
89      *  @param[in] revents  - Type of event
90      *  @param[in] userData - User data that was passed during registration
91      *
92      *  @return             - 0 or positive number on success and negative
93      *                        errno otherwise
94      */
95     static int processEvents(sd_event_source* es, int fd, uint32_t revents,
96                              void* userData);
97 
98     /** @brief When the error event is received, analyzes it
99      *         and makes a callback to error handler if the
100      *         content denotes an error condition
101      */
102     virtual void analyzeEvent();
103 
104   protected:
105     /** @brief File descriptor to watch for errors */
106     int fd = -1;
107 
108     /** Error file */
109     fs::path file;
110 
111     /** @brief Optional function to call on error scenario */
112     std::function<void(bool)> callBack;
113 
114     /** @brief Reads file data
115      *
116      *  @return data read. Since its a /sysfs entry,
117      *          it would be a string
118      */
119     std::string readFile(int) const;
120 };
121 
122 } // namespace occ
123 } // namespace open_power
124