blob: f1e7ee798a0ce8cde225c2556b086b80e7635071 [file] [log] [blame]
#include "example/example.hpp"
#include <phosphor-logging/log.hpp>
#include <algorithm>
#include <cstring>
#include <memory>
#include <string>
#include <vector>
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<std::string> 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<uint8_t> ExampleBlobHandler::read(uint16_t session, uint32_t offset,
uint32_t requestedSize)
{
ExampleBlob* sess = getSession(session);
if (!sess)
{
return std::vector<uint8_t>();
}
/* Is the offset beyond the array? */
if (offset >= sizeof(sess->buffer))
{
return std::vector<uint8_t>();
}
/* 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<uint8_t> result(numBytes);
std::memcpy(result.data(), &sess->buffer[offset], numBytes);
return result;
}
bool ExampleBlobHandler::write(uint16_t session, uint32_t offset,
const std::vector<uint8_t>& 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<std::vector<uint8_t>::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<uint8_t>&)
{
/* Not supported. */
return false;
}
bool ExampleBlobHandler::commit(uint16_t session, const std::vector<uint8_t>&)
{
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<blobs::GenericBlobInterface> createHandler()
{
return std::make_unique<blobs::ExampleBlobHandler>();
}