#include "example/example.hpp" #include #include #include #include #include #include namespace blobs { using namespace phosphor::logging; constexpr char ExampleBlobHandler::supportedPath[]; ExampleBlob* ExampleBlobHandler::getSession(uint16_t id) { auto search = sessions.find(id); if (search == sessions.end()) { return nullptr; } /* Not thread-safe, however, the blob handler deliberately assumes serial * execution. */ return &search->second; } bool ExampleBlobHandler::canHandleBlob(const std::string& path) { return (path == supportedPath); } std::vector ExampleBlobHandler::getBlobIds() { return {supportedPath}; } bool ExampleBlobHandler::deleteBlob(const std::string&) { return false; } bool ExampleBlobHandler::stat(const std::string&, BlobMeta*) { return false; } bool ExampleBlobHandler::open(uint16_t session, uint16_t flags, const std::string& path) { if (!canHandleBlob(path)) { return false; } auto findSess = sessions.find(session); if (findSess != sessions.end()) { /* This session is already active. */ return false; } sessions[session] = ExampleBlob(session, flags); return true; } std::vector ExampleBlobHandler::read(uint16_t session, uint32_t offset, uint32_t requestedSize) { ExampleBlob* sess = getSession(session); if (!sess) { return std::vector(); } /* Is the offset beyond the array? */ if (offset >= sizeof(sess->buffer)) { return std::vector(); } /* Determine how many bytes we can read from the offset. * In this case, if they read beyond "size" we allow it. */ uint32_t remain = sizeof(sess->buffer) - offset; uint32_t numBytes = std::min(remain, requestedSize); /* Copy the bytes! */ std::vector result(numBytes); std::memcpy(result.data(), &sess->buffer[offset], numBytes); return result; } bool ExampleBlobHandler::write(uint16_t session, uint32_t offset, const std::vector& data) { ExampleBlob* sess = getSession(session); if (!sess) { return false; } /* Is the offset beyond the array? */ if (offset >= sizeof(sess->buffer)) { return false; } /* Determine whether all their bytes will fit. */ uint32_t remain = sizeof(sess->buffer) - offset; if (data.size() > remain) { return false; } sess->length = std::max(offset + data.size(), static_cast::size_type>(sess->length)); std::memcpy(&sess->buffer[offset], data.data(), data.size()); return true; } bool ExampleBlobHandler::writeMeta(uint16_t, uint32_t, const std::vector&) { /* Not supported. */ return false; } bool ExampleBlobHandler::commit(uint16_t session, const std::vector&) { ExampleBlob* sess = getSession(session); if (!sess) { return false; } /* Do something with the staged data!. */ return false; } bool ExampleBlobHandler::close(uint16_t session) { ExampleBlob* sess = getSession(session); if (!sess) { return false; } sessions.erase(session); return true; } bool ExampleBlobHandler::stat(uint16_t session, BlobMeta* meta) { ExampleBlob* sess = getSession(session); if (!sess) { return false; } if (!meta) { return false; } meta->size = sess->length; meta->blobState = sess->state; return true; } bool ExampleBlobHandler::expire(uint16_t session) { ExampleBlob* sess = getSession(session); if (!sess) { return false; } /* TODO: implement session expiration behavior. */ return false; } void setupExampleHandler() __attribute__((constructor)); void setupExampleHandler() { // You don't need to do anything in the constructor. } } // namespace blobs /** * This method is required by the blob manager. * * It is called to grab a handler for registering the blob handler instance. */ std::unique_ptr createHandler() { return std::make_unique(); }