2019-11-03 01:34:29 +03:00
|
|
|
#pragma once
|
|
|
|
|
2019-11-12 13:52:27 +03:00
|
|
|
#ifndef _LARGEFILE64_SOURCE
|
2019-11-03 01:34:29 +03:00
|
|
|
#define _LARGEFILE64_SOURCE
|
2019-11-12 13:52:27 +03:00
|
|
|
#endif
|
2019-12-15 14:49:10 +03:00
|
|
|
|
2019-11-03 01:34:29 +03:00
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include <map>
|
2019-12-15 14:49:10 +03:00
|
|
|
#include <unordered_map>
|
2019-11-03 01:34:29 +03:00
|
|
|
#include <functional>
|
|
|
|
|
2019-11-05 02:43:21 +03:00
|
|
|
#include "ringloop.h"
|
|
|
|
|
2019-12-02 02:44:56 +03:00
|
|
|
// Default block size is 128 KB, current allowed range is 4K - 128M
|
2019-11-03 01:34:29 +03:00
|
|
|
#define DEFAULT_ORDER 17
|
2019-12-02 02:44:56 +03:00
|
|
|
#define MIN_BLOCK_SIZE 4*1024
|
2019-11-03 01:34:29 +03:00
|
|
|
#define MAX_BLOCK_SIZE 128*1024*1024
|
|
|
|
#define DISK_ALIGNMENT 512
|
|
|
|
|
|
|
|
// 16 bytes per object/stripe id
|
|
|
|
// stripe includes replica number in 4 least significant bits
|
|
|
|
struct __attribute__((__packed__)) object_id
|
|
|
|
{
|
|
|
|
uint64_t inode;
|
|
|
|
uint64_t stripe;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline bool operator == (const object_id & a, const object_id & b)
|
|
|
|
{
|
2019-11-08 00:19:17 +03:00
|
|
|
return a.inode == b.inode && a.stripe == b.stripe;
|
|
|
|
}
|
|
|
|
|
2019-11-15 13:58:35 +03:00
|
|
|
inline bool operator != (const object_id & a, const object_id & b)
|
|
|
|
{
|
|
|
|
return a.inode != b.inode || a.stripe != b.stripe;
|
|
|
|
}
|
|
|
|
|
2019-11-08 00:19:17 +03:00
|
|
|
inline bool operator < (const object_id & a, const object_id & b)
|
|
|
|
{
|
|
|
|
return a.inode < b.inode || a.inode == b.inode && a.stripe < b.stripe;
|
2019-11-03 01:34:29 +03:00
|
|
|
}
|
|
|
|
|
2019-11-14 21:15:59 +03:00
|
|
|
// 56 = 24 + 32 bytes per dirty entry in memory (obj_ver_id => dirty_entry)
|
2019-11-08 00:19:17 +03:00
|
|
|
struct __attribute__((__packed__)) obj_ver_id
|
2019-11-03 01:34:29 +03:00
|
|
|
{
|
2019-11-08 00:19:17 +03:00
|
|
|
object_id oid;
|
2019-11-03 01:34:29 +03:00
|
|
|
uint64_t version;
|
2019-11-08 00:19:17 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
inline bool operator < (const obj_ver_id & a, const obj_ver_id & b)
|
|
|
|
{
|
|
|
|
return a.oid < b.oid || a.oid == b.oid && a.version < b.version;
|
|
|
|
}
|
|
|
|
|
2019-12-15 14:54:00 +03:00
|
|
|
namespace std
|
2019-11-03 01:34:29 +03:00
|
|
|
{
|
2019-12-15 14:54:00 +03:00
|
|
|
template<> struct hash<object_id>
|
2019-11-03 01:34:29 +03:00
|
|
|
{
|
2019-12-15 14:54:00 +03:00
|
|
|
inline size_t operator()(const object_id &s) const
|
|
|
|
{
|
|
|
|
size_t seed = 0;
|
|
|
|
// Copy-pasted from spp::hash_combine()
|
|
|
|
seed ^= (s.inode + 0xc6a4a7935bd1e995 + (seed << 6) + (seed >> 2));
|
|
|
|
seed ^= (s.stripe + 0xc6a4a7935bd1e995 + (seed << 6) + (seed >> 2));
|
|
|
|
return seed;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2019-11-03 01:34:29 +03:00
|
|
|
|
|
|
|
#define OP_READ 1
|
2019-11-10 13:26:56 +03:00
|
|
|
#define OP_WRITE 2
|
|
|
|
#define OP_SYNC 3
|
|
|
|
#define OP_STABLE 4
|
|
|
|
#define OP_DELETE 5
|
2019-11-05 14:10:23 +03:00
|
|
|
#define OP_TYPE_MASK 0x7
|
2019-11-03 01:34:29 +03:00
|
|
|
|
2019-12-15 14:49:10 +03:00
|
|
|
#define BS_OP_PRIVATE_DATA_SIZE 256
|
2019-12-03 12:09:30 +03:00
|
|
|
|
2019-12-15 14:11:03 +03:00
|
|
|
struct blockstore_op_t
|
2019-11-03 01:34:29 +03:00
|
|
|
{
|
2019-11-11 14:10:23 +03:00
|
|
|
// flags contain operation type and possibly other flags
|
2019-11-12 18:16:03 +03:00
|
|
|
uint64_t flags;
|
|
|
|
// finish callback
|
2019-12-15 14:11:03 +03:00
|
|
|
std::function<void (blockstore_op_t*)> callback;
|
2019-11-11 14:10:23 +03:00
|
|
|
// For reads, writes & deletes: oid is the requested object
|
2019-11-03 01:34:29 +03:00
|
|
|
object_id oid;
|
2019-11-10 13:26:56 +03:00
|
|
|
// For reads: version=0 -> last stable, version=UINT64_MAX -> last unstable, version=X -> specific version
|
2019-11-11 14:10:23 +03:00
|
|
|
// For writes & deletes: a new version is assigned automatically
|
2019-11-03 01:34:29 +03:00
|
|
|
uint64_t version;
|
2019-11-11 14:10:23 +03:00
|
|
|
// For reads & writes: offset & len are the requested part of the object, buf is the buffer
|
2019-11-03 01:34:29 +03:00
|
|
|
uint32_t offset;
|
2019-11-11 14:10:23 +03:00
|
|
|
// For stabilize requests: buf contains <len> obj_ver_id's to stabilize
|
2019-11-03 01:34:29 +03:00
|
|
|
uint32_t len;
|
2019-11-26 00:02:54 +03:00
|
|
|
void *buf;
|
2019-11-05 14:10:23 +03:00
|
|
|
int retval;
|
2019-11-03 01:34:29 +03:00
|
|
|
|
2019-12-15 14:49:10 +03:00
|
|
|
uint8_t private_data[BS_OP_PRIVATE_DATA_SIZE];
|
2019-11-03 01:34:29 +03:00
|
|
|
};
|
|
|
|
|
2019-12-15 14:49:10 +03:00
|
|
|
typedef std::unordered_map<std::string, std::string> blockstore_config_t;
|
2019-11-13 17:45:37 +03:00
|
|
|
|
2019-12-15 14:49:10 +03:00
|
|
|
class blockstore_impl_t;
|
2019-11-28 00:50:52 +03:00
|
|
|
|
2019-12-15 14:49:10 +03:00
|
|
|
class blockstore_t
|
2019-11-03 01:34:29 +03:00
|
|
|
{
|
2019-12-15 14:49:10 +03:00
|
|
|
blockstore_impl_t *impl;
|
2019-11-10 01:40:48 +03:00
|
|
|
public:
|
2019-12-15 14:49:10 +03:00
|
|
|
blockstore_t(blockstore_config_t & config, ring_loop_t *ringloop);
|
|
|
|
~blockstore_t();
|
2019-11-10 01:40:48 +03:00
|
|
|
|
|
|
|
// Event loop
|
|
|
|
void loop();
|
|
|
|
|
2019-11-25 01:29:07 +03:00
|
|
|
// Returns true when blockstore is ready to process operations
|
|
|
|
// (Although you're free to enqueue them before that)
|
2019-11-18 02:36:53 +03:00
|
|
|
bool is_started();
|
|
|
|
|
2019-11-11 21:22:28 +03:00
|
|
|
// Returns true when it's safe to destroy the instance. If destroying the instance
|
|
|
|
// requires to purge some queues, starts that process. Should be called in the event
|
|
|
|
// loop until it returns true.
|
2019-11-25 01:29:07 +03:00
|
|
|
bool is_safe_to_stop();
|
2019-11-11 21:22:28 +03:00
|
|
|
|
2019-11-10 01:40:48 +03:00
|
|
|
// Submission
|
2019-12-15 14:11:03 +03:00
|
|
|
void enqueue_op(blockstore_op_t *op);
|
2019-11-26 00:02:54 +03:00
|
|
|
|
2019-12-10 00:13:57 +03:00
|
|
|
// Unstable writes are added here (map of object_id -> version)
|
2019-12-15 14:49:10 +03:00
|
|
|
std::map<object_id, uint64_t> & get_unstable_writes();
|
2019-12-10 00:13:57 +03:00
|
|
|
|
2019-12-15 14:49:10 +03:00
|
|
|
uint32_t get_block_size();
|
|
|
|
uint32_t get_block_order();
|
|
|
|
uint64_t get_block_count();
|
2019-11-03 01:34:29 +03:00
|
|
|
};
|