1 /************************************************************************** 2 Copyright: 3 (C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com> 4 License: See LICENSE_gsmartcontrol.txt 5 ***************************************************************************/ 6 /// \file 7 /// \author Alexander Shaduri 8 /// \ingroup applib 9 /// \weakgroup applib 10 /// @{ 11 12 #ifndef SELFTEST_H 13 #define SELFTEST_H 14 15 #include <glibmm.h> 16 #include <string> 17 18 #include "hz/cstdint.h" 19 #include "hz/intrusive_ptr.h" 20 21 #include "storage_device.h" 22 #include "cmdex_sync.h" 23 24 25 26 /// SMART self-test runner. 27 class SelfTest : public hz::intrusive_ptr_referenced { 28 public: 29 30 /// Test type 31 enum test_t { 32 type_ioffline, ///< Immediate offline, not supported 33 type_short, ///< Short self-test 34 type_long, ///< Extended (a.k.a. long) self-test 35 type_conveyance ///< Conveyance self-test 36 }; 37 38 39 /// Get displayable name for a test type get_test_name(test_t t)40 static std::string get_test_name(test_t t) 41 { 42 switch (t) { 43 case type_ioffline: return "Immediate Offline Test"; 44 case type_short: return "Short Self-test"; 45 case type_long: return "Extended Self-test"; 46 case type_conveyance: return "Conveyance Self-test"; 47 }; 48 return "[error]"; 49 } 50 51 52 /// Constructor. \c drive must have the capabilities present in its properties. SelfTest(StorageDeviceRefPtr drive,test_t type)53 SelfTest(StorageDeviceRefPtr drive, test_t type) 54 : drive_(drive), type_(type) 55 { 56 clear(); 57 } 58 59 60 /// Clear results of previous test clear()61 void clear() 62 { 63 status_ = StorageSelftestEntry::status_unknown; 64 remaining_percent_ = -1; 65 last_seen_percent_ = -1; 66 total_duration_ = -1; 67 poll_in_seconds_ = -1; 68 } 69 70 71 /// Check if the test is currently active is_active()72 bool is_active() const 73 { 74 return (status_ == StorageSelftestEntry::status_in_progress); 75 } 76 77 78 /// Get remaining time percent until the test completion. 79 /// \return -1 if N/A or unknown. get_remaining_percent()80 int8_t get_remaining_percent() const 81 { 82 return remaining_percent_; 83 } 84 85 86 /// Get estimated time of completion for the test. 87 /// \return -1 if N/A or unknown. Note that 0 is a valid value. 88 int64_t get_remaining_seconds() const; 89 90 91 /// Get test type get_test_type()92 test_t get_test_type() const 93 { 94 return type_; 95 } 96 97 98 /// Get test status get_status()99 StorageSelftestEntry::status_t get_status() const 100 { 101 return status_; 102 } 103 104 105 /// Get the number of seconds after which the caller should call update(). get_poll_in_seconds()106 int64_t get_poll_in_seconds() const 107 { 108 return poll_in_seconds_; 109 } 110 111 112 /// Get a constant "test duration during idle" capability drive's stored capabilities. -1 if N/A. 113 int64_t get_min_duration_seconds() const; 114 115 116 /// Gets the current test type support status from drive's stored capabilities. 117 bool is_supported() const; 118 119 120 /// Start the test. 121 /// \return error message on error, empty string on success. 122 std::string start(hz::intrusive_ptr<CmdexSync> smartctl_ex = 0); 123 124 125 /// Abort the running test. 126 /// \return error message on error, empty string on success. 127 std::string force_stop(hz::intrusive_ptr<CmdexSync> smartctl_ex = 0); 128 129 130 /// Update status variables. The user should call this every get_poll_in_seconds() seconds. 131 /// \return error message on error, empty string on success. 132 std::string update(hz::intrusive_ptr<CmdexSync> smartctl_ex = 0); 133 134 135 private: 136 137 StorageDeviceRefPtr drive_; ///< Drive to run the tests on 138 test_t type_; ///< Test type 139 140 // status variables: 141 StorageSelftestEntry::status_t status_; ///< Current status of the test as reported by the drive 142 int8_t remaining_percent_; ///< Remaining %. 0 means unknown, -1 means N/A. This is set to 100 on start. 143 int8_t last_seen_percent_; ///< Last reported %, to detect changes in percentage (needed for timer update). 144 mutable int64_t total_duration_; ///< Total duration needed for the test, as reported by the drive. Constant. This variable acts as a cache. 145 int64_t poll_in_seconds_; ///< The user is asked to poll after this much seconds have passed. 146 147 Glib::Timer timer_; ///< Counts time since the last percent change 148 149 }; 150 151 152 153 /// A reference-counting pointer to SelfTest 154 typedef hz::intrusive_ptr<SelfTest> SelfTestPtr; 155 156 157 158 159 #endif 160 161 /// @} 162