1 #pragma once 2 3 #include "NVMeSensor.hpp" 4 5 #include <boost/asio/io_context.hpp> 6 #include <boost/asio/steady_timer.hpp> 7 8 #include <memory> 9 #include <stdexcept> 10 11 class NVMeContext : public std::enable_shared_from_this<NVMeContext> 12 { 13 public: NVMeContext(boost::asio::io_context & io,int rootBus)14 NVMeContext(boost::asio::io_context& io, int rootBus) : 15 scanTimer(io), rootBus(rootBus), pollCursor(sensors.end()) 16 { 17 if (rootBus < 0) 18 { 19 throw std::invalid_argument( 20 "Invalid root bus: Bus ID must not be negative"); 21 } 22 } 23 ~NVMeContext()24 virtual ~NVMeContext() 25 { 26 scanTimer.cancel(); 27 } 28 addSensor(const std::shared_ptr<NVMeSensor> & sensor)29 void addSensor(const std::shared_ptr<NVMeSensor>& sensor) 30 { 31 sensors.emplace_back(sensor); 32 } 33 34 std::optional<std::shared_ptr<NVMeSensor>> getSensorAtPath(const std::string & path)35 getSensorAtPath(const std::string& path) 36 { 37 for (auto& sensor : sensors) 38 { 39 if (sensor->configurationPath == path) 40 { 41 return sensor; 42 } 43 } 44 45 return std::nullopt; 46 } 47 48 // Post-condition: The sensor list does not contain the provided sensor 49 // Post-condition: pollCursor is a valid iterator for the sensor list removeSensor(const std::shared_ptr<NVMeSensor> & sensor)50 void removeSensor(const std::shared_ptr<NVMeSensor>& sensor) 51 { 52 // Locate the sensor that we're removing in the sensor list 53 auto found = std::find(sensors.begin(), sensors.end(), sensor); 54 55 // If we failed to find the sensor in the list the post-condition is 56 // already satisfied 57 if (found == sensors.end()) 58 { 59 return; 60 } 61 62 // We've found the sensor in the list 63 64 // If we're not actively polling the sensor list, then remove the sensor 65 if (pollCursor == sensors.end()) 66 { 67 sensors.erase(found); 68 return; 69 } 70 71 // We're actively polling the sensor list 72 73 // If we're not polling the specific sensor that has been removed, then 74 // remove the sensor 75 if (*pollCursor != *found) 76 { 77 sensors.erase(found); 78 return; 79 } 80 81 // We're polling the sensor that is being removed 82 83 // Remove the sensor and update the poll cursor so the cursor remains 84 // valid 85 pollCursor = sensors.erase(found); 86 } 87 close()88 virtual void close() 89 { 90 scanTimer.cancel(); 91 } 92 93 virtual void pollNVMeDevices() = 0; 94 95 virtual void readAndProcessNVMeSensor() = 0; 96 97 virtual void processResponse(std::shared_ptr<NVMeSensor>& sensor, void* msg, 98 size_t len) = 0; 99 100 protected: 101 boost::asio::steady_timer scanTimer; 102 int rootBus; // Root bus for this drive 103 std::list<std::shared_ptr<NVMeSensor>> sensors; 104 std::list<std::shared_ptr<NVMeSensor>>::iterator pollCursor; 105 }; 106 107 using NVMEMap = boost::container::flat_map<int, std::shared_ptr<NVMeContext>>; 108 109 NVMEMap& getNVMEMap(); 110