Skip to content

Commit

Permalink
Start of C++ client.
Browse files Browse the repository at this point in the history
  • Loading branch information
dacut committed Jun 12, 2016
1 parent 3e79ef8 commit 8e74257
Show file tree
Hide file tree
Showing 5 changed files with 387 additions and 0 deletions.
24 changes: 24 additions & 0 deletions client/ublkdev-c++/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
TARGETS = libublkdev.so ublkdev-s3
CPPFLAGS = -I. -I../../src
CXXFLAGS = -std=c++11 -fPIC

LIB_SRCS = ublkdev.cc
LIB_OBJS = $(LIB_SRCS:%.cc=%.o)
LIB_LD = g++
LIB_LDFLAGS = -shared

S3_SRCS = s3.cc
S3_OBJS = $(S3_SRCS:%.cc=%.o)
S3_LD = g++
S3_LDFLAGS = -L.
S3_LIBS = -lublkdev

all: $(TARGETS)
libublkdev.so: $(LIB_OBJS)
$(LIB_LD) $(LIB_LDFLAGS) -o $@ $(LIB_OBJS)

ublkdev-s3: $(S3_OBJS)
$(S3_LD) $(S3_LDFLAGS) -o $@ $(S3_OBJS) $(S3_LIBS)

%.o: %.c
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $<
43 changes: 43 additions & 0 deletions client/ublkdev-c++/s3.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <ublkdev.hh>
#include <aws/core/Aws.h>
#include "s3.hh"

UBDS3Volume::UBDS3Volume(
std::string const &bucket_name,
std::string const &devname,
std::string const &region,
uint32_t thread_count) :
m_ubd(NULL),
m_bucket_name(bucket_name),
m_devname(devname),
m_region(region),
m_thread_count(thread_count),
m_block_size(-1),
m_encryption(Aws::S3::Model::ServerSideEncryption::NOT_SET),
m_policy(Aws::S3::Model::ObjectCannedACL::private_),
m_storage_class(Aws::S3::Model::StorageClass::STANDARD),
m_suffix(),
m_size(0ull),
m_major(0),
m_stop_requested(false)
{
return;
}

UBDS3Volume::~UBDS3Volume() {
delete m_ubd;
return;
}

void UBDS3Volume::registerVolume() {
uint64_t n_sectors = m_size / 512;

m_ubd = new UserBlockDevice();
auto ui = m_ubd->registerEndpoint(m_devname.c_str(), n_sectors, false);
m_major = ui.ubd_major;
return;
}

void UBDS3Volume::readVolumeInfo() {

}
109 changes: 109 additions & 0 deletions client/ublkdev-c++/s3.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#pragma once
#include <stdint.h>
#include <string>

#include <aws/s3/S3Client.h>
#include <aws/s3/model/ObjectCannedACL.h>
#include <aws/s3/model/ServerSideEncryption.h>
#include <aws/s3/model/StorageClass.h>

class UBDS3Volume {
public:
UBDS3Volume(
std::string const &bucket_name,
std::string const &devname,
std::string const &region,
uint32_t thread_count);

virtual ~UBDS3Volume();

virtual void registerVolume();
virtual void run();
virtual void readVolumeInfo();
virtual void createVolume(
uint32_t blockSize,
Aws::S3::Model::ServerSideEncryption encryption =
Aws::S3::Model::ServerSideEncryption::NOT_SET,
Aws::S3::Model::ObjectCannedACL policy =
Aws::S3::Model::ObjectCannedACL::private_,
Aws::S3::Model::StorageClass storage_class =
Aws::S3::Model::StorageClass::STANDARD,
std::string const &suffix = "");
virtual void read(
uint64_t offset,
void *buffer /* OUT */,
uint32_t length);
virtual void write(
uint64_t offset,
void const *buffer,
uint32_t length);
virtual void trim(
uint64_t offset,
uint32_t length);

static std::string blockToPrefix(uint64_t block_index);

protected:
virtual void readBlock(
uint64_t block_id,
void *buffer);

virtual void writeBlock(
uint64_t block_id,
void *buffer);

virtual void trimBlock(
uint64_t block_id);

private:
UserBlockDevice *m_ubd;
std::string m_bucket_name;
std::string m_devname;
std::string m_region;
uint32_t m_thread_count;
uint32_t m_block_size;
Aws::S3::Model::ServerSideEncryption m_encryption;
Aws::S3::Model::ObjectCannedACL m_policy;
Aws::S3::Model::StorageClass m_storage_class;
std::string m_suffix;
uint64_t m_size;
uint32_t m_major;
volatile bool m_stop_requested;
};

class S3Pool;
class S3PoolConnection;

class S3Pool {
public:
S3Pool(
std::string region,
uint32_t size,
std::string bucket_name);

private:
Aws::S3::S3Client *getConnection();
void returnConnection(Aws::S3::S3Client *client);

Aws::Utils::Array<Aws::S3::S3Client *> m_connections;

friend class S3PoolConnection;
};

class S3PoolConnection {
public:
S3PoolConnection(S3Pool *pool) :
m_pool(pool),
m_client(pool->getConnection()) { }

~S3PoolConnection() {
m_pool->returnConnection(m_client);
}

Aws::S3::S3Client *operator ->() { return m_client; }

private:
S3Pool *m_pool;
Aws::S3::S3Client *m_client;
};

125 changes: 125 additions & 0 deletions client/ublkdev-c++/ublkdev.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#include <string>

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <ublkdev.hh>

using std::string;

UserBlockDevice::UserBlockDevice(
char const *control_endpoint)
{
m_control = open(control_endpoint, O_RDWR | O_SYNC | O_NONBLOCK);

if (m_control < 0) {
string msg("Unable to open ");

msg += control_endpoint;
msg += ": ";
msg += strerror(errno);

throw UBDError(msg, errno);
}

m_poll.fd = m_control;
m_poll.events = POLLIN;
return;
}

UserBlockDevice::~UserBlockDevice()
{
close(m_control);
return;
}

struct ubd_info UserBlockDevice::registerEndpoint(
const char *name,
ssize_t n_sectors,
bool read_only)
{
struct ubd_info ui;
strncpy(ui.ubd_name, name, UBD_DISK_NAME_LEN);
ui.ubd_flags = (read_only ? UBD_FL_READ_ONLY : 0u);
ui.ubd_major = 0u;
ui.ubd_nsectors = n_sectors;

if (ioctl(m_control, UBD_IOCREGISTER, &ui) != 0) {
throw UBDError(errno);
}

return ui;
}

void UserBlockDevice::unregisterEndpoint(
uint32_t major)
{
if (ioctl(m_control, UBD_IOCUNREGISTER, major) != 0) {
throw UBDError(errno);
}

return;
}

int UserBlockDevice::getCount() {
int result = ioctl(m_control, UBD_IOCGETCOUNT);
if (result < 0) {
throw UBDError(errno);
}

return result;
}

struct ubd_info UserBlockDevice::describe(
uint32_t index)
{
struct ubd_describe desc;
desc.ubd_index = index;

if (ioctl(m_control, UBD_IOCDESCRIBE, &desc) != 0) {
throw UBDError(errno);
}

return desc.ubd_info;
}

void UserBlockDevice::tie(
uint32_t major)
{
if (ioctl(m_control, UBD_IOCTIE, major) != 0) {
throw UBDError(errno);
}

return;
}

void UserBlockDevice::getRequest(
struct ubd_message *result)
{
if (ioctl(m_control, UBD_IOCGETREQUEST, result) != 0) {
throw UBDError(errno);
}

return;
}

void UserBlockDevice::putReply(
struct ubd_message const *reply)
{
if (ioctl(m_control, UBD_IOCPUTREPLY, reply) != 0) {
throw UBDError(errno);
}

return;
}

void UserBlockDevice::debug()
{
if (ioctl(m_control, UBD_IOCDEBUG) != 0) {
throw UBDError(errno);
}

return;
}
86 changes: 86 additions & 0 deletions client/ublkdev-c++/ublkdev.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#ifndef UBLKDEV_HH
#define UBLKDEV_HH

#include <cstring>
#include <stdexcept>
#include <string>

#include <poll.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>

extern "C" {
#include <ublkdev.h>
}

#ifndef UBD_IOC_MAGIC
#error No UBD_IOC_MAGIC defined
#endif

class UBDError : public std::runtime_error {
public:
inline UBDError(std::string const &what_arg) :
std::runtime_error(what_arg), m_error(0) { }

inline UBDError(std::string const &what_arg, int error) :
std::runtime_error(what_arg), m_error(error) { }

inline UBDError(int error) :
std::runtime_error(std::string(std::strerror(error))),
m_error(error) { }

#if __cplusplus >= 201103L /* C++11 */
inline UBDError(char const *what_arg) :
std::runtime_error(what_arg), m_error(0) { }

inline UBDError(char const *what_arg, int error) :
std::runtime_error(what_arg), m_error(error) { }
#endif /* C++11 */

inline int getError() { return m_error; }

private:
const int m_error;
};

class UserBlockDevice {
public:
explicit UserBlockDevice(
char const *control_endpoint="/dev/ubdctl");

virtual ~UserBlockDevice();

virtual struct ubd_info registerEndpoint(
const char *name,
ssize_t n_sectors,
bool read_only);

virtual void unregisterEndpoint(
uint32_t major);

virtual int getCount();

virtual struct ubd_info describe(
uint32_t index);

virtual void tie(
uint32_t major);

virtual void getRequest(
struct ubd_message *result /* IN/OUT */);

virtual void putReply(
struct ubd_message const *reply /* IN */);

virtual void debug();

private:
UserBlockDevice(UserBlockDevice const &);
UserBlockDevice operator = (UserBlockDevice const &);

int m_control;
struct pollfd m_poll;
};

#endif /* UBLKDEV_HH */

0 comments on commit 8e74257

Please sign in to comment.