1 #include "example/example.hpp" 2 3 #include <algorithm> 4 #include <cstring> 5 #include <memory> 6 #include <phosphor-logging/log.hpp> 7 #include <string> 8 #include <vector> 9 10 namespace blobs 11 { 12 13 using namespace phosphor::logging; 14 15 constexpr char ExampleBlobHandler::supportedPath[]; 16 17 ExampleBlob* ExampleBlobHandler::getSession(uint16_t id) 18 { 19 auto search = sessions.find(id); 20 if (search == sessions.end()) 21 { 22 return nullptr; 23 } 24 /* Not thread-safe, however, the blob handler deliberately assumes serial 25 * execution. */ 26 return &search->second; 27 } 28 29 bool ExampleBlobHandler::canHandleBlob(const std::string& path) 30 { 31 return (path == supportedPath); 32 } 33 34 std::vector<std::string> ExampleBlobHandler::getBlobIds() 35 { 36 return {supportedPath}; 37 } 38 39 bool ExampleBlobHandler::deleteBlob(const std::string&) 40 { 41 return false; 42 } 43 44 bool ExampleBlobHandler::stat(const std::string&, BlobMeta*) 45 { 46 return false; 47 } 48 49 bool ExampleBlobHandler::open(uint16_t session, uint16_t flags, 50 const std::string& path) 51 { 52 if (!canHandleBlob(path)) 53 { 54 return false; 55 } 56 57 auto findSess = sessions.find(session); 58 if (findSess != sessions.end()) 59 { 60 /* This session is already active. */ 61 return false; 62 } 63 sessions[session] = ExampleBlob(session, flags); 64 return true; 65 } 66 67 std::vector<uint8_t> ExampleBlobHandler::read(uint16_t session, uint32_t offset, 68 uint32_t requestedSize) 69 { 70 ExampleBlob* sess = getSession(session); 71 if (!sess) 72 { 73 return std::vector<uint8_t>(); 74 } 75 76 /* Is the offset beyond the array? */ 77 if (offset >= sizeof(sess->buffer)) 78 { 79 return std::vector<uint8_t>(); 80 } 81 82 /* Determine how many bytes we can read from the offset. 83 * In this case, if they read beyond "size" we allow it. 84 */ 85 uint32_t remain = sizeof(sess->buffer) - offset; 86 uint32_t numBytes = std::min(remain, requestedSize); 87 /* Copy the bytes! */ 88 std::vector<uint8_t> result(numBytes); 89 std::memcpy(result.data(), &sess->buffer[offset], numBytes); 90 return result; 91 } 92 93 bool ExampleBlobHandler::write(uint16_t session, uint32_t offset, 94 const std::vector<uint8_t>& data) 95 { 96 ExampleBlob* sess = getSession(session); 97 if (!sess) 98 { 99 return false; 100 } 101 /* Is the offset beyond the array? */ 102 if (offset >= sizeof(sess->buffer)) 103 { 104 return false; 105 } 106 /* Determine whether all their bytes will fit. */ 107 uint32_t remain = sizeof(sess->buffer) - offset; 108 if (data.size() > remain) 109 { 110 return false; 111 } 112 sess->length = 113 std::max(offset + data.size(), 114 static_cast<std::vector<uint8_t>::size_type>(sess->length)); 115 std::memcpy(&sess->buffer[offset], data.data(), data.size()); 116 return true; 117 } 118 119 bool ExampleBlobHandler::writeMeta(uint16_t, uint32_t, 120 const std::vector<uint8_t>&) 121 { 122 /* Not supported. */ 123 return false; 124 } 125 126 bool ExampleBlobHandler::commit(uint16_t session, const std::vector<uint8_t>&) 127 { 128 ExampleBlob* sess = getSession(session); 129 if (!sess) 130 { 131 return false; 132 } 133 134 /* Do something with the staged data!. */ 135 136 return false; 137 } 138 139 bool ExampleBlobHandler::close(uint16_t session) 140 { 141 ExampleBlob* sess = getSession(session); 142 if (!sess) 143 { 144 return false; 145 } 146 147 sessions.erase(session); 148 return true; 149 } 150 151 bool ExampleBlobHandler::stat(uint16_t session, BlobMeta* meta) 152 { 153 ExampleBlob* sess = getSession(session); 154 if (!sess) 155 { 156 return false; 157 } 158 if (!meta) 159 { 160 return false; 161 } 162 meta->size = sess->length; 163 meta->blobState = sess->state; 164 return true; 165 } 166 167 bool ExampleBlobHandler::expire(uint16_t session) 168 { 169 ExampleBlob* sess = getSession(session); 170 if (!sess) 171 { 172 return false; 173 } 174 /* TODO: implement session expiration behavior. */ 175 return false; 176 } 177 178 void setupExampleHandler() __attribute__((constructor)); 179 180 void setupExampleHandler() 181 { 182 // You don't need to do anything in the constructor. 183 } 184 185 } // namespace blobs 186 187 /** 188 * This method is required by the blob manager. 189 * 190 * It is called to grab a handler for registering the blob handler instance. 191 */ 192 std::unique_ptr<blobs::GenericBlobInterface> createHandler() 193 { 194 return std::make_unique<blobs::ExampleBlobHandler>(); 195 } 196