blob: d6c7b0f23b986e4ffe190e30e88a9cd508eeb3d0 [file]
/** @file
A brief file description
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/****************************************************************************
Store.h
****************************************************************************/
#pragma once
#include "tscore/List.h"
#include "tscore/Result.h"
#define STORE_BLOCK_SIZE 8192
#define STORE_BLOCK_SHIFT 13
#define DEFAULT_HW_SECTOR_SIZE 512
enum span_error_t {
SPAN_ERROR_OK,
SPAN_ERROR_UNKNOWN,
SPAN_ERROR_NOT_FOUND,
SPAN_ERROR_NO_ACCESS,
SPAN_ERROR_MISSING_SIZE,
SPAN_ERROR_UNSUPPORTED_DEVTYPE,
SPAN_ERROR_MEDIA_PROBE,
};
struct span_diskid_t {
int64_t id[2];
bool
operator<(const span_diskid_t &rhs) const
{
return id[0] < rhs.id[0] && id[1] < rhs.id[1];
}
bool
operator==(const span_diskid_t &rhs) const
{
return id[0] == rhs.id[0] && id[1] == rhs.id[1];
}
int64_t &
operator[](unsigned i)
{
return id[i];
}
};
//
// A Store is a place to store data.
// Those on the same disk should be in a linked list.
//
struct Span {
int64_t blocks = 0; // in STORE_BLOCK_SIZE blocks
int64_t offset = 0; // used only if (file == true); in bytes
unsigned hw_sector_size = DEFAULT_HW_SECTOR_SIZE;
unsigned alignment = 0;
span_diskid_t disk_id;
bool file_pathname = false; // the pathname is a file
// v- used as a magic location for copy constructor.
// we memcpy everything before this member and do explicit assignment for the rest.
ats_scoped_str name;
ats_scoped_str pathname;
ats_scoped_str hash_base_string; ///< Used to seed the stripe assignment hash.
SLINK(Span, link);
int64_t
size() const
{
return blocks * STORE_BLOCK_SIZE;
}
int64_t
end() const
{
return offset + blocks;
}
const char *init(const char *name, const char *path, int64_t size);
/// Set the hash seed string.
void hash_base_string_set(const char *s);
/// Set the volume number.
void volume_number_set(int n);
Span() { disk_id[0] = disk_id[1] = 0; }
/// Copy constructor.
/// @internal Prior to this implementation handling the char* pointers was done manually
/// at every call site. We also need this because we have @c ats_scoped_str members and need
/// to make copies.
Span(Span const &that)
{
/* I looked at simplifying this by changing the @c ats_scoped_str instances to @c std::string
* but that actually makes it worse. The copy constructor @b must be overridden to get the
* internal link (@a link.next) correct. Given that, changing to @c std::string means doing
* explicit assignment for every member, which has its own problems.
*/
memcpy(static_cast<void *>(this), &that, reinterpret_cast<intptr_t>(&(static_cast<Span *>(nullptr)->pathname)));
if (that.name) {
name = ats_strdup(that.name);
}
if (that.pathname) {
pathname = ats_strdup(that.pathname);
}
if (that.hash_base_string) {
hash_base_string = ats_strdup(that.hash_base_string);
}
link.next = nullptr;
}
~Span();
static const char *errorstr(span_error_t serr);
};
struct Store {
void sort();
void
extend(unsigned i)
{
if (i > n_spans) {
spans = static_cast<Span **>(ats_realloc(spans, i * sizeof(Span *)));
for (unsigned j = n_spans; j < i; j++) {
spans[j] = nullptr;
}
n_spans = i;
}
}
void delete_all();
Store(){};
~Store();
unsigned n_spans_in_config = 0; ///< The number of disks/paths defined in storage.yaml
unsigned n_spans = 0; ///< The number of disks/paths we could actually read and parse
Span **spans = nullptr;
Result read_config();
int write_config_data(int fd) const;
};
// store either free or in the cache, can be stolen for reconfiguration
void stealStore(Store &s, int blocks);