mirror of https://gitee.com/bigwinds/arangodb
[3.4] fix ASAN issues in arangosearch (#7027)
* update iresearch * update iresearch
This commit is contained in:
parent
168755f377
commit
0c6cf212e3
|
@ -657,6 +657,10 @@ install:
|
|||
- eval "${SET_ENV}"
|
||||
- which bison
|
||||
- bison --version
|
||||
- which ${CC}
|
||||
- ${CC} --version
|
||||
- which ${CXX}
|
||||
- ${CXX} --version
|
||||
|
||||
############################################################################
|
||||
# All the dependencies are installed in ${TRAVIS_BUILD_DIR}/deps/
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "shared.hpp"
|
||||
#include "token_streams.hpp"
|
||||
#include "utils/bit_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
NS_LOCAL
|
||||
|
||||
|
@ -134,25 +135,25 @@ bytes_ref numeric_token_stream::numeric_term::value(
|
|||
switch (type) {
|
||||
case NT_LONG: {
|
||||
typedef numeric_utils::numeric_traits<int64_t> traits_t;
|
||||
oversize(buf, traits_t::size());
|
||||
string_utils::oversize(buf, traits_t::size());
|
||||
|
||||
return bytes_ref(&(buf[0]), traits_t::encode(val.i64, &(buf[0]), shift));
|
||||
}
|
||||
case NT_DBL: {
|
||||
typedef numeric_utils::numeric_traits<double_t> traits_t;
|
||||
oversize(buf, traits_t::size());
|
||||
string_utils::oversize(buf, traits_t::size());
|
||||
|
||||
return bytes_ref(&(buf[0]), traits_t::encode(val.i64, &(buf[0]), shift));
|
||||
}
|
||||
case NT_INT: {
|
||||
typedef numeric_utils::numeric_traits<int32_t> traits_t;
|
||||
oversize(buf, traits_t::size());
|
||||
string_utils::oversize(buf, traits_t::size());
|
||||
|
||||
return bytes_ref(&(buf[0]), traits_t::encode(val.i32, &(buf[0]), shift));
|
||||
}
|
||||
case NT_FLOAT: {
|
||||
typedef numeric_utils::numeric_traits<float_t> traits_t;
|
||||
oversize(buf, traits_t::size());
|
||||
string_utils::oversize(buf, traits_t::size());
|
||||
|
||||
return bytes_ref(&(buf[0]), traits_t::encode(val.i32, &(buf[0]), shift));
|
||||
}
|
||||
|
|
|
@ -62,21 +62,10 @@ struct IRESEARCH_API error_base: std::exception {
|
|||
// -----------------------------------------------------------------------------
|
||||
class IRESEARCH_API detailed_error_base: public error_base {
|
||||
public:
|
||||
explicit detailed_error_base(const char* error): error_(error) {}
|
||||
explicit detailed_error_base(std::string&& error) NOEXCEPT
|
||||
: error_(std::move(error)) {
|
||||
}
|
||||
|
||||
detailed_error_base(const detailed_error_base& other)
|
||||
: error_(other.error_) {
|
||||
}
|
||||
|
||||
detailed_error_base(detailed_error_base&& other) NOEXCEPT
|
||||
: error_(std::move(other.error_)) {
|
||||
}
|
||||
|
||||
detailed_error_base& operator=(const detailed_error_base& other) = delete;
|
||||
detailed_error_base& operator=(detailed_error_base&& other) NOEXCEPT = delete;
|
||||
|
||||
virtual const char* what() const NOEXCEPT final { return error_.c_str(); }
|
||||
|
||||
private:
|
||||
|
@ -117,11 +106,9 @@ struct IRESEARCH_API eof_error: io_error {
|
|||
// ----------------------------------------------------------------------------
|
||||
struct IRESEARCH_API detailed_io_error: public detailed_error_base {
|
||||
public:
|
||||
explicit detailed_io_error(std::string&& error)
|
||||
: detailed_error_base(std::move(error)) {
|
||||
}
|
||||
|
||||
DECLARE_ERROR_CODE(io_error);
|
||||
template<typename T>
|
||||
detailed_io_error(T&& error): detailed_error_base(std::forward<T>(error)) {}
|
||||
virtual ErrorCode code() const NOEXCEPT override { return CODE; }
|
||||
};
|
||||
|
||||
|
@ -168,11 +155,9 @@ struct IRESEARCH_API index_not_found: error_base {
|
|||
// index_error
|
||||
// ----------------------------------------------------------------------------
|
||||
struct IRESEARCH_API index_error: detailed_error_base {
|
||||
explicit index_error(std::string&& error)
|
||||
: detailed_error_base(std::move(error)) {
|
||||
}
|
||||
|
||||
DECLARE_ERROR_CODE(index_error);
|
||||
template<typename T>
|
||||
index_error(T&& error): detailed_error_base(std::forward<T>(error)) {}
|
||||
virtual ErrorCode code() const NOEXCEPT override { return CODE; }
|
||||
};
|
||||
|
||||
|
@ -205,4 +190,4 @@ struct IRESEARCH_API illegal_state: error_base {
|
|||
|
||||
NS_END
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -28,33 +28,34 @@
|
|||
|
||||
#include "formats/formats.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
NS_ROOT
|
||||
|
||||
void validate_footer(iresearch::index_input& in) {
|
||||
const int64_t remain = in.length() - in.file_pointer();
|
||||
|
||||
if (remain != format_utils::FOOTER_LEN) {
|
||||
throw index_error(
|
||||
std::string("while validating footer, error: invalid position '") + std::to_string(remain) + "'"
|
||||
);
|
||||
throw index_error(string_utils::to_string(
|
||||
"while validating footer, error: invalid position '%ld'",
|
||||
remain
|
||||
));
|
||||
}
|
||||
|
||||
const int32_t magic = in.read_int();
|
||||
|
||||
if (magic != format_utils::FOOTER_MAGIC) {
|
||||
throw index_error(
|
||||
std::string("while validating footer, error: invalid magic number '") + std::to_string(magic) + "'"
|
||||
);
|
||||
throw index_error(string_utils::to_string(
|
||||
"while validating footer, error: invalid magic number '%d'",
|
||||
magic
|
||||
));
|
||||
}
|
||||
|
||||
const int32_t alg_id = in.read_int();
|
||||
|
||||
if (alg_id != 0) {
|
||||
throw index_error(
|
||||
std::string("while validating footer, error: invalid algorithm '") + std::to_string(alg_id) + "'"
|
||||
);
|
||||
throw index_error(string_utils::to_string(
|
||||
"while validating footer, error: invalid algorithm '%d'",
|
||||
alg_id
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,27 +80,28 @@ int32_t check_header(
|
|||
const int32_t magic = in.read_int();
|
||||
|
||||
if (FORMAT_MAGIC != magic) {
|
||||
throw irs::index_error(
|
||||
std::string("while checking header, error: invalid magic '") + std::to_string(magic) + "'"
|
||||
);
|
||||
throw irs::index_error(string_utils::to_string(
|
||||
"while checking header, error: invalid magic '%d'",
|
||||
magic
|
||||
));
|
||||
}
|
||||
|
||||
const auto format = read_string<std::string>(in);
|
||||
|
||||
if (compare(req_format, format) != 0) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "while checking header, error: format mismatch '" << format << "' != '" << req_format << "'";
|
||||
|
||||
throw irs::index_error(ss.str());
|
||||
throw irs::index_error(string_utils::to_string(
|
||||
"while checking header, error: format mismatch '%s' != '%s'",
|
||||
format.c_str(), req_format.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
const int32_t ver = in.read_int();
|
||||
|
||||
if (ver < min_ver || ver > max_ver) {
|
||||
throw irs::index_error(
|
||||
std::string("while checking header, error: invalid version '") + std::to_string(ver) + "'"
|
||||
);
|
||||
throw irs::index_error(string_utils::to_string(
|
||||
"while checking header, error: invalid version '%d'",
|
||||
ver
|
||||
));
|
||||
}
|
||||
|
||||
return ver;
|
||||
|
@ -107,4 +109,4 @@ int32_t check_header(
|
|||
|
||||
NS_END
|
||||
|
||||
NS_END
|
||||
NS_END
|
|
@ -25,6 +25,7 @@
|
|||
#define IRESEARCH_FORMATS_UTILS_H
|
||||
|
||||
#include "store/store_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "index/field_meta.hpp"
|
||||
|
||||
NS_ROOT
|
||||
|
@ -81,9 +82,10 @@ inline int64_t check_footer(index_input& in, int64_t checksum) {
|
|||
validate_footer(in);
|
||||
|
||||
if (checksum != in.read_long()) {
|
||||
throw index_error(
|
||||
std::string("while checking footer, error: invalid checksum '") + std::to_string(checksum) + "'"
|
||||
);
|
||||
throw index_error(string_utils::to_string(
|
||||
"while checking footer, error: invalid checksum '" IR_UINT64_T_SPECIFIER "'",
|
||||
checksum
|
||||
));
|
||||
}
|
||||
|
||||
return checksum;
|
||||
|
@ -106,4 +108,4 @@ inline int64_t checksum(const index_input& in) {
|
|||
NS_END
|
||||
NS_END
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -215,11 +215,10 @@ inline void prepare_output(
|
|||
out = state.dir->create(str);
|
||||
|
||||
if (!out) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "failed to create file, path: " << str;
|
||||
|
||||
throw detailed_io_error(ss.str());
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to create file, path: %s",
|
||||
str.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
format_utils::write_header(*out, format, version);
|
||||
|
@ -239,11 +238,10 @@ inline void prepare_input(
|
|||
in = state.dir->open(str, advice);
|
||||
|
||||
if (!in) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "failed to open file, path: " << str;
|
||||
|
||||
throw detailed_io_error(ss.str());
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to open file, path: %s",
|
||||
str.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
format_utils::check_header(*in, format, min_ver, max_ver);
|
||||
|
@ -652,9 +650,10 @@ void postings_writer::begin_doc(doc_id_t id, const frequency* freq) {
|
|||
}
|
||||
|
||||
if (id < doc.last) {
|
||||
throw index_error(
|
||||
std::string("while beginning doc in postings_writer, error: docs out of order '") + std::to_string(id) + "' < '" + std::to_string(doc.last) + "'"
|
||||
);
|
||||
throw index_error(string_utils::to_string(
|
||||
"while beginning doc in postings_writer, error: docs out of order '%d' < '%d'",
|
||||
id, doc.last
|
||||
));
|
||||
}
|
||||
|
||||
doc.doc(id - doc.last);
|
||||
|
@ -1534,7 +1533,7 @@ class offs_pay_iterator final: public pos_iterator {
|
|||
if (pay_lengths_[i]) {
|
||||
const auto size = pay_lengths_[i]; // length of current payload
|
||||
|
||||
oversize(pay_data_, pos + size);
|
||||
string_utils::oversize(pay_data_, pos + size);
|
||||
|
||||
#ifdef IRESEARCH_DEBUG
|
||||
const auto read = pos_in_->read_bytes(&(pay_data_[0]) + pos, size);
|
||||
|
@ -1561,7 +1560,7 @@ class offs_pay_iterator final: public pos_iterator {
|
|||
const uint32_t size = pay_in_->read_vint();
|
||||
if (size) {
|
||||
format_traits::read_block(*pay_in_, postings_writer::BLOCK_SIZE, enc_buf_, pay_lengths_);
|
||||
oversize(pay_data_, size);
|
||||
string_utils::oversize(pay_data_, size);
|
||||
|
||||
#ifdef IRESEARCH_DEBUG
|
||||
const auto read = pay_in_->read_bytes(&(pay_data_[0]), size);
|
||||
|
@ -1789,7 +1788,7 @@ class pay_iterator final : public pos_iterator {
|
|||
if (pay_lengths_[i]) {
|
||||
const auto size = pay_lengths_[i]; // current payload length
|
||||
|
||||
oversize(pay_data_, pos + size);
|
||||
string_utils::oversize(pay_data_, pos + size);
|
||||
|
||||
#ifdef IRESEARCH_DEBUG
|
||||
const auto read = pos_in_->read_bytes(&(pay_data_[0]) + pos, size);
|
||||
|
@ -1817,7 +1816,7 @@ class pay_iterator final : public pos_iterator {
|
|||
const uint32_t size = pay_in_->read_vint();
|
||||
if (size) {
|
||||
format_traits::read_block(*pay_in_, postings_writer::BLOCK_SIZE, enc_buf_, pay_lengths_);
|
||||
oversize(pay_data_, size);
|
||||
string_utils::oversize(pay_data_, size);
|
||||
|
||||
#ifdef IRESEARCH_DEBUG
|
||||
const auto read = pay_in_->read_bytes(&(pay_data_[0]), size);
|
||||
|
@ -2041,11 +2040,10 @@ void index_meta_writer::commit() {
|
|||
auto clear_pending = make_finally([this]{ meta_ = nullptr; });
|
||||
|
||||
if (!dir_->rename(src, dst)) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "failed to rename file, src path: " << src << " dst path: " << dst;
|
||||
|
||||
throw detailed_io_error(ss.str());
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to rename file, src path: '%s' dst path: '%s'",
|
||||
src.c_str(), dst.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
complete(*meta_);
|
||||
|
@ -2117,11 +2115,10 @@ void index_meta_reader::read(
|
|||
);
|
||||
|
||||
if (!in) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "failed to open file, path: " << meta_file;
|
||||
|
||||
throw detailed_io_error(ss.str());
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to open file, path: %s",
|
||||
meta_file.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
const auto checksum = format_utils::checksum(*in);
|
||||
|
@ -2195,7 +2192,10 @@ void segment_meta_writer::write(directory& dir, const segment_meta& meta) {
|
|||
byte_type flags = meta.column_store ? segment_meta_writer::flags_t::HAS_COLUMN_STORE : 0;
|
||||
|
||||
if (!out) {
|
||||
throw detailed_io_error("failed to create file, path: " + meta_file);
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to create file, path: %s",
|
||||
meta_file.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
format_utils::write_header(*out, FORMAT_NAME, FORMAT_MAX);
|
||||
|
@ -2235,11 +2235,10 @@ void segment_meta_reader::read(
|
|||
);
|
||||
|
||||
if (!in) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "failed to open file, path: " << meta_file;
|
||||
|
||||
throw detailed_io_error(ss.str());
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to open file, path: %s",
|
||||
meta_file.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
const auto checksum = format_utils::checksum(*in);
|
||||
|
@ -2338,7 +2337,10 @@ void document_mask_writer::write(
|
|||
auto out = dir.create(filename);
|
||||
|
||||
if (!out) {
|
||||
throw detailed_io_error("Failed to create file, path: " + filename);
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"Failed to create file, path: %s",
|
||||
filename.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
// segment can't have more than integer_traits<uint32_t>::const_max documents
|
||||
|
@ -2664,7 +2666,7 @@ void read_compact(
|
|||
return;
|
||||
}
|
||||
|
||||
irs::oversize(encode_buf, buf_size);
|
||||
irs::string_utils::oversize(encode_buf, buf_size);
|
||||
|
||||
#ifdef IRESEARCH_DEBUG
|
||||
const auto read = in.read_bytes(&(encode_buf[0]), buf_size);
|
||||
|
@ -2685,9 +2687,10 @@ void read_compact(
|
|||
);
|
||||
|
||||
if (!irs::type_limits<iresearch::type_t::address_t>::valid(buf_size)) {
|
||||
throw index_error(
|
||||
std::string("while reading compact, error: invalid buffer size '") + std::to_string(buf_size) + "'"
|
||||
);
|
||||
throw irs::index_error(string_utils::to_string(
|
||||
"while reading compact, error: invalid buffer size '" IR_SIZE_T_SPECIFIER "'",
|
||||
buf_size
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5004,10 +5007,10 @@ bool postings_reader::prepare(
|
|||
const uint64_t block_size = in.read_vint();
|
||||
|
||||
if (block_size != postings_writer::BLOCK_SIZE) {
|
||||
throw index_error(
|
||||
std::string("while preparing postings_reader in segment '") + state.meta->name
|
||||
+ "', error: invalid block size '" + std::to_string(block_size) + "'"
|
||||
);
|
||||
throw index_error(string_utils::to_string(
|
||||
"while preparing postings_reader, error: invalid block size '" IR_UINT64_T_SPECIFIER "'",
|
||||
block_size
|
||||
));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -5228,4 +5231,4 @@ NS_END // root
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
|
@ -177,11 +177,10 @@ inline void prepare_output(
|
|||
out = state.dir->create(str);
|
||||
|
||||
if (!out) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "failed to create file, path: " << str;
|
||||
|
||||
throw detailed_io_error(ss.str()) ;
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to create file, path: %s",
|
||||
str.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
format_utils::write_header(*out, format, version);
|
||||
|
@ -203,11 +202,10 @@ inline void prepare_input(
|
|||
in = state.dir->open(str, advice);
|
||||
|
||||
if (!in) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "failed to open file, path: " << str;
|
||||
|
||||
throw detailed_io_error(ss.str());
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to open file, path: %s",
|
||||
str.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
if (checksum) {
|
||||
|
@ -1820,4 +1818,4 @@ NS_END /* root */
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
|
@ -24,6 +24,7 @@
|
|||
#include "composite_reader_impl.hpp"
|
||||
#include "utils/directory_utils.hpp"
|
||||
#include "utils/singleton.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/type_limits.hpp"
|
||||
|
||||
#include "directory_reader.hpp"
|
||||
|
@ -321,9 +322,10 @@ directory_reader_impl::directory_reader_impl(
|
|||
}
|
||||
|
||||
if (!ctx.reader) {
|
||||
throw index_error(
|
||||
std::string("while opening reader for segment '") + segment.name + "', error: failed to open reader"
|
||||
);
|
||||
throw index_error(string_utils::to_string(
|
||||
"while opening reader for segment '%s', error: failed to open reader",
|
||||
segment.name.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
ctx.base = static_cast<doc_id_t>(docs_max);
|
||||
|
@ -356,4 +358,4 @@ NS_END
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
|
@ -30,6 +30,7 @@
|
|||
#include "utils/bitvector.hpp"
|
||||
#include "utils/directory_utils.hpp"
|
||||
#include "utils/index_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/timer_utils.hpp"
|
||||
#include "utils/type_limits.hpp"
|
||||
#include "utils/range.hpp"
|
||||
|
@ -109,10 +110,10 @@ bool add_document_mask_modified_records(
|
|||
auto reader = readers.emplace(meta);
|
||||
|
||||
if (!reader) {
|
||||
throw irs::index_error(
|
||||
std::string("while adding document mask modified records to document_mask of segment '") +meta.name
|
||||
+ "', error: failed to open segment"
|
||||
);
|
||||
throw irs::index_error(irs::string_utils::to_string(
|
||||
"while adding document mask modified records to document_mask of segment '%s', error: failed to open segment",
|
||||
meta.name.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
bool modified = false;
|
||||
|
@ -164,10 +165,10 @@ bool add_document_mask_modified_records(
|
|||
auto reader = readers.emplace(ctx.segment_.meta);
|
||||
|
||||
if (!reader) {
|
||||
throw irs::index_error(
|
||||
std::string("while adding document mask modified records to flush_segment_context of segment '") + ctx.segment_.meta.name
|
||||
+ "', error: failed to open segment"
|
||||
);
|
||||
throw irs::index_error(irs::string_utils::to_string(
|
||||
"while adding document mask modified records to flush_segment_context of segment '%s', error: failed to open segment",
|
||||
ctx.segment_.meta.name.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
assert(doc_limits::valid(ctx.doc_id_begin_));
|
||||
|
@ -687,10 +688,10 @@ index_writer::flush_context_ptr index_writer::documents_context::update_segment(
|
|||
);
|
||||
|
||||
if (!segment.flush()) {
|
||||
throw index_error(
|
||||
std::string("while flushing segment '") + segment.writer_meta_.meta.name
|
||||
+ "', error: failed to flush segment"
|
||||
);
|
||||
throw index_error(string_utils::to_string(
|
||||
"while flushing segment '%s', error: failed to flush segment",
|
||||
segment.writer_meta_.meta.name.c_str()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2060,7 +2061,10 @@ bool index_writer::start() {
|
|||
|
||||
auto sync = [&dir](const std::string& file) {
|
||||
if (!dir.sync(file)) {
|
||||
throw detailed_io_error("failed to sync file, path: " + file);
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to sync file, path: %s",
|
||||
file.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2152,4 +2156,4 @@ NS_END
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
|
@ -24,6 +24,7 @@
|
|||
#include "composite_reader_impl.hpp"
|
||||
#include "search/bitset_doc_iterator.hpp"
|
||||
#include "store/store_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
#include "transaction_store.hpp"
|
||||
|
||||
|
@ -1066,7 +1067,7 @@ store_reader store_reader::reopen() const {
|
|||
|
||||
void store_writer::bstring_output::ensure(size_t pos) {
|
||||
if (pos >= buf_.size()) {
|
||||
oversize(buf_, irs::math::roundup_power2(pos + 1)); // 2*size growth policy, +1 for offset->size
|
||||
irs::string_utils::oversize(buf_, irs::math::roundup_power2(pos + 1)); // 2*size growth policy, +1 for offset->size
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "error/error.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/object_pool.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/utf8_path.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/crc.hpp"
|
||||
|
@ -37,8 +38,6 @@
|
|||
|
||||
#include <boost/locale/encoding.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
NS_LOCAL
|
||||
|
||||
inline size_t buffer_size(FILE* file) NOEXCEPT {
|
||||
|
@ -225,11 +224,10 @@ class fs_index_output : public buffered_index_output {
|
|||
crc.process_bytes(b, len_written);
|
||||
|
||||
if (len && len_written != len) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "failed to write buffer, written '" << len_written << "' out of '" << len << "' bytes";
|
||||
|
||||
throw detailed_io_error(ss.str());
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to write buffer, written '" IR_SIZE_T_SPECIFIER "' out of '" IR_SIZE_T_SPECIFIER "' bytes",
|
||||
len_written, len
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,11 +330,10 @@ class fs_index_input : public buffered_index_input {
|
|||
protected:
|
||||
virtual void seek_internal(size_t pos) override {
|
||||
if (pos >= handle_->size) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "seek out of range for input file, length '" << handle_->size << "', position '" << pos << "'";
|
||||
|
||||
throw detailed_io_error(ss.str());
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"seek out of range for input file, length '" IR_SIZE_T_SPECIFIER "', position '" IR_SIZE_T_SPECIFIER "'",
|
||||
handle_->size, pos
|
||||
));
|
||||
}
|
||||
|
||||
pos_ = pos;
|
||||
|
@ -350,11 +347,10 @@ class fs_index_input : public buffered_index_input {
|
|||
|
||||
if (handle_->pos != pos_) {
|
||||
if (fseek(stream, static_cast<long>(pos_), SEEK_SET) != 0) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "failed to seek to '" << pos_ << "' for input file, error '" << ferror(stream) << "'";
|
||||
|
||||
throw detailed_io_error(ss.str());
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to seek to '" IR_SIZE_T_SPECIFIER "' for input file, error '%d'",
|
||||
pos_, ferror(stream)
|
||||
));
|
||||
}
|
||||
|
||||
handle_->pos = pos_;
|
||||
|
@ -371,11 +367,10 @@ class fs_index_input : public buffered_index_input {
|
|||
}
|
||||
|
||||
// read error
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "failed to read from input file, read '" << read << "' out of '" << len << "' bytes, error '" << ferror(stream) << "'";
|
||||
|
||||
throw detailed_io_error(ss.str());
|
||||
throw detailed_io_error(string_utils::to_string(
|
||||
"failed to read from input file, read '" IR_SIZE_T_SPECIFIER "' out of '" IR_SIZE_T_SPECIFIER "' bytes, error '%d'",
|
||||
read, len, ferror(stream)
|
||||
));
|
||||
}
|
||||
|
||||
assert(handle_->pos == pos_);
|
||||
|
@ -684,4 +679,4 @@ NS_END
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "utils/crc.hpp"
|
||||
#include "utils/std.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
|
||||
NS_ROOT
|
||||
|
@ -423,7 +424,7 @@ void bytes_input::read_from(data_input& in, size_t size) {
|
|||
return;
|
||||
}
|
||||
|
||||
oversize(buf_, size);
|
||||
string_utils::oversize(buf_, size);
|
||||
|
||||
#ifdef IRESEARCH_DEBUG
|
||||
const auto read = in.read_bytes(&(buf_[0]), size);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "shared.hpp"
|
||||
#include "error/error.hpp"
|
||||
#include "compression.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/type_limits.hpp"
|
||||
|
||||
#include <lz4.h>
|
||||
|
@ -33,7 +34,7 @@ NS_ROOT
|
|||
compressor::compressor(unsigned int chunk_size):
|
||||
dict_size_(0),
|
||||
stream_(LZ4_createStream(), [](void* ptr)->void { LZ4_freeStream(reinterpret_cast<LZ4_stream_t*>(ptr)); }) {
|
||||
oversize(buf_, LZ4_COMPRESSBOUND(chunk_size));
|
||||
string_utils::oversize(buf_, LZ4_COMPRESSBOUND(chunk_size));
|
||||
}
|
||||
|
||||
void compressor::compress(const char* src, size_t size) {
|
||||
|
@ -51,7 +52,7 @@ void compressor::compress(const char* src, size_t size) {
|
|||
assert(dict_size_ >= 0);
|
||||
}
|
||||
|
||||
oversize(buf_, LZ4_compressBound(src_size) + dict_size_);
|
||||
string_utils::oversize(buf_, LZ4_compressBound(src_size) + dict_size_);
|
||||
|
||||
// reload the LZ4 dictionary if buf_ has changed
|
||||
if (&(buf_[0]) != dict_store) {
|
||||
|
|
|
@ -255,8 +255,8 @@ NS_END
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
tracking_directory::tracking_directory(
|
||||
directory& impl, bool track_open /*= false*/):
|
||||
impl_(impl), track_open_(track_open) {
|
||||
directory& impl, bool track_open /*= false*/
|
||||
) : impl_(impl), track_open_(track_open) {
|
||||
}
|
||||
|
||||
tracking_directory::~tracking_directory() {}
|
||||
|
@ -403,15 +403,15 @@ bool tracking_directory::sync(const std::string& name) NOEXCEPT {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
ref_tracking_directory::ref_tracking_directory(
|
||||
directory& impl, bool track_open /*= false*/
|
||||
):
|
||||
attribute_(impl.attributes().emplace<index_file_refs>()),
|
||||
directory& impl,
|
||||
bool track_open /*= false*/
|
||||
) : attribute_(impl.attributes().emplace<index_file_refs>()),
|
||||
impl_(impl),
|
||||
track_open_(track_open) {
|
||||
}
|
||||
|
||||
ref_tracking_directory::ref_tracking_directory(
|
||||
ref_tracking_directory&& other
|
||||
ref_tracking_directory&& other
|
||||
) NOEXCEPT
|
||||
: attribute_(other.attribute_), // references do not require std::move(...)
|
||||
impl_(other.impl_), // references do not require std::move(...)
|
||||
|
@ -449,7 +449,7 @@ index_output::ptr ref_tracking_directory::create(
|
|||
auto ref = attribute_->add(name);
|
||||
|
||||
SCOPED_LOCK(mutex_);
|
||||
refs_.emplace(*ref, std::move(ref));
|
||||
refs_.emplace(ref);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -500,7 +500,7 @@ index_input::ptr ref_tracking_directory::open(
|
|||
auto ref = attribute_->add(name);
|
||||
SCOPED_LOCK(mutex_);
|
||||
|
||||
refs_.emplace(*ref, std::move(ref));
|
||||
refs_.emplace(ref);
|
||||
} catch (...) {
|
||||
IR_LOG_EXCEPTION();
|
||||
|
||||
|
@ -519,9 +519,15 @@ bool ref_tracking_directory::remove(const std::string& name) NOEXCEPT {
|
|||
try {
|
||||
attribute_->remove(name);
|
||||
|
||||
// aliasing ctor
|
||||
const index_file_refs::ref_t ref(
|
||||
index_file_refs::ref_t(),
|
||||
&name
|
||||
);
|
||||
|
||||
SCOPED_LOCK(mutex_);
|
||||
|
||||
refs_.erase(name);
|
||||
refs_.erase(ref);
|
||||
return true;
|
||||
} catch (...) {
|
||||
IR_LOG_EXCEPTION();
|
||||
|
@ -542,10 +548,16 @@ bool ref_tracking_directory::rename(
|
|||
auto ref = attribute_->add(dst);
|
||||
|
||||
{
|
||||
// aliasing ctor
|
||||
const index_file_refs::ref_t src_ref(
|
||||
index_file_refs::ref_t(),
|
||||
&src
|
||||
);
|
||||
|
||||
SCOPED_LOCK(mutex_);
|
||||
|
||||
refs_.emplace(dst, ref);
|
||||
refs_.erase(src);
|
||||
refs_.emplace(ref);
|
||||
refs_.erase(src_ref);
|
||||
}
|
||||
|
||||
attribute_->remove(src);
|
||||
|
@ -571,7 +583,7 @@ bool ref_tracking_directory::visit_refs(
|
|||
SCOPED_LOCK(mutex_);
|
||||
|
||||
for (const auto& ref: refs_) {
|
||||
if (!visitor(ref.second)) {
|
||||
if (!visitor(ref)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ struct IRESEARCH_API tracking_directory: public directory {
|
|||
typedef std::unordered_set<std::string> file_set;
|
||||
|
||||
// @param track_open - track file refs for calls to open(...)
|
||||
tracking_directory(directory& impl, bool track_open = false);
|
||||
explicit tracking_directory(directory& impl, bool track_open = false);
|
||||
virtual ~tracking_directory();
|
||||
directory& operator*() NOEXCEPT;
|
||||
using directory::attributes;
|
||||
|
@ -155,7 +155,7 @@ struct IRESEARCH_API ref_tracking_directory: public directory {
|
|||
public:
|
||||
DECLARE_UNIQUE_PTR(ref_tracking_directory);
|
||||
// @param track_open - track file refs for calls to open(...)
|
||||
ref_tracking_directory(directory& impl, bool track_open = false);
|
||||
explicit ref_tracking_directory(directory& impl, bool track_open = false);
|
||||
ref_tracking_directory(ref_tracking_directory&& other) NOEXCEPT;
|
||||
virtual ~ref_tracking_directory();
|
||||
directory& operator*() NOEXCEPT;
|
||||
|
@ -185,11 +185,17 @@ struct IRESEARCH_API ref_tracking_directory: public directory {
|
|||
bool visit_refs(const std::function<bool(const index_file_refs::ref_t& ref)>& visitor) const;
|
||||
|
||||
private:
|
||||
typedef std::unordered_set<
|
||||
index_file_refs::ref_t,
|
||||
index_file_refs::counter_t::hash,
|
||||
index_file_refs::counter_t::equal_to
|
||||
> refs_t;
|
||||
|
||||
IRESEARCH_API_PRIVATE_VARIABLES_BEGIN
|
||||
index_file_refs::attribute_t& attribute_;
|
||||
directory& impl_;
|
||||
mutable std::mutex mutex_; // for use with refs_
|
||||
mutable std::unordered_map<string_ref, index_file_refs::ref_t> refs_;
|
||||
mutable refs_t refs_;
|
||||
bool track_open_;
|
||||
IRESEARCH_API_PRIVATE_VARIABLES_END
|
||||
};
|
||||
|
|
|
@ -2676,7 +2676,9 @@ typename num_put_facet<CharType, CvtType>::iter_type num_put_facet<CharType, Cvt
|
|||
auto ctx = context();
|
||||
|
||||
if (!ctx) {
|
||||
throw irs::detailed_io_error("failed to retrieve ICU formatter in num_put_facet::do_put(...)");
|
||||
throw irs::detailed_io_error(
|
||||
"failed to retrieve ICU formatter in num_put_facet::do_put(...)"
|
||||
);
|
||||
}
|
||||
|
||||
static_assert(sizeof(int64_t) == sizeof(long long), "sizeof(int64_t) != sizeof(long long)");
|
||||
|
@ -3771,4 +3773,4 @@ NS_END
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <mutex>
|
||||
#include "shared.hpp"
|
||||
#include "utils/noncopyable.hpp"
|
||||
|
@ -40,37 +40,59 @@ class ref_counter : public util::noncopyable { // noncopyable because shared_ptr
|
|||
public:
|
||||
typedef std::shared_ptr<const Key> ref_t;
|
||||
|
||||
struct equal_to : Equal {
|
||||
bool operator()(const ref_t& lhs, const ref_t& rhs) const {
|
||||
assert(lhs && rhs);
|
||||
return Equal::operator()(*lhs, *rhs);
|
||||
}
|
||||
}; // equal_to
|
||||
|
||||
struct hash : Hash {
|
||||
bool operator()(const ref_t& value) const {
|
||||
assert(value);
|
||||
return Hash::operator()(*value);
|
||||
}
|
||||
}; // hash
|
||||
|
||||
ref_t add(Key&& key) {
|
||||
SCOPED_LOCK(lock_);
|
||||
|
||||
auto itr = refs_.emplace(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(key),
|
||||
std::forward_as_tuple(nullptr)
|
||||
);
|
||||
auto res = refs_.emplace(ref_t(), &key);
|
||||
|
||||
if (itr.second) {
|
||||
itr.first->second.reset(&(itr.first->first), memory::noop_deleter());
|
||||
if (res.second) {
|
||||
try {
|
||||
const_cast<ref_t&>(*res.first) = std::make_shared<const Key>(std::forward<Key>(key));
|
||||
} catch (...) {
|
||||
// rollback
|
||||
refs_.erase(res.first);
|
||||
return ref_t();
|
||||
}
|
||||
}
|
||||
|
||||
return itr.first->second;
|
||||
return *res.first;
|
||||
}
|
||||
|
||||
bool remove(const Key& key) {
|
||||
const ref_t ref(ref_t(), &key); // aliasing ctor
|
||||
|
||||
SCOPED_LOCK(lock_);
|
||||
return refs_.erase(key) > 0;
|
||||
return refs_.erase(ref) > 0;
|
||||
}
|
||||
|
||||
bool contains(const Key& key) const NOEXCEPT {
|
||||
const ref_t ref(ref_t(), &key); // aliasing ctor
|
||||
|
||||
SCOPED_LOCK(lock_);
|
||||
return refs_.find(key) != refs_.end();
|
||||
return refs_.find(ref) != refs_.end();
|
||||
}
|
||||
|
||||
size_t find(const Key& key) const NOEXCEPT {
|
||||
SCOPED_LOCK(lock_);
|
||||
auto itr = refs_.find(key);
|
||||
const ref_t ref(ref_t(), &key); // aliasing ctor
|
||||
|
||||
return itr == refs_.end() ? 0 : (itr->second.use_count() - 1); // -1 for usage by refs_ itself
|
||||
SCOPED_LOCK(lock_);
|
||||
auto itr = refs_.find(ref);
|
||||
|
||||
return itr == refs_.end() ? 0 : (itr->use_count() - 1); // -1 for usage by refs_ itself
|
||||
}
|
||||
|
||||
bool empty() const NOEXCEPT {
|
||||
|
@ -83,9 +105,12 @@ class ref_counter : public util::noncopyable { // noncopyable because shared_ptr
|
|||
SCOPED_LOCK(lock_);
|
||||
|
||||
for (auto itr = refs_.begin(), end = refs_.end(); itr != end;) {
|
||||
auto visit_next = visitor(itr->first, itr->second.use_count() - 1); // -1 for usage by refs_ itself
|
||||
auto& ref = *itr;
|
||||
assert(*itr);
|
||||
|
||||
if (remove_unused && itr->second.unique()) {
|
||||
auto visit_next = visitor(*ref, ref.use_count() - 1); // -1 for usage by refs_ itself
|
||||
|
||||
if (remove_unused && ref.unique()) {
|
||||
itr = refs_.erase(itr);
|
||||
} else {
|
||||
++itr;
|
||||
|
@ -101,7 +126,7 @@ class ref_counter : public util::noncopyable { // noncopyable because shared_ptr
|
|||
|
||||
private:
|
||||
mutable std::recursive_mutex lock_; // recursive to allow usage for 'this' from withing visit(...)
|
||||
std::unordered_map<Key, ref_t, Hash, Equal> refs_;
|
||||
std::unordered_set<ref_t, hash, equal_to> refs_;
|
||||
}; // ref_counter
|
||||
|
||||
NS_END
|
||||
|
|
|
@ -129,17 +129,6 @@ NS_ROOT
|
|||
|
||||
typedef std::basic_string<byte_type> bstring;
|
||||
|
||||
template<typename T>
|
||||
inline std::basic_string<T>& oversize(
|
||||
// 31 == 32 - 1: because std::basic_string reserves a \0 at the end
|
||||
// 32 is the original default value used in bytes_builder
|
||||
std::basic_string<T>& buf, size_t size = 31
|
||||
) {
|
||||
buf.resize(size);
|
||||
buf.resize(buf.capacity()); // use up the entire buffer
|
||||
return buf;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @class basic_string_ref
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2018 ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed 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.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Andrey Abramov
|
||||
/// @author Vasiliy Nabatchikov
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef IRESEARCH_STRING_UTILS_H
|
||||
#define IRESEARCH_STRING_UTILS_H
|
||||
|
||||
#include "shared.hpp"
|
||||
|
||||
NS_ROOT
|
||||
NS_BEGIN(string_utils)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief resize string to the full capacity of resize to the specified size
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename T>
|
||||
inline std::basic_string<T>& oversize(
|
||||
// 31 == 32 - 1: because std::basic_string reserves a \0 at the end
|
||||
// 32 is the original default value used in bytes_builder
|
||||
std::basic_string<T>& buf, size_t size = 31
|
||||
) {
|
||||
buf.resize(size);
|
||||
buf.resize(buf.capacity()); // use up the entire buffer
|
||||
return buf;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @param destination buffer
|
||||
/// @return as per sprintf(...)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename... Args>
|
||||
inline int to_string(std::string& buf, const char* format, Args&&... args) {
|
||||
char ch;
|
||||
auto result = snprintf(&ch, 0, format, std::forward<Args>(args)...);
|
||||
|
||||
if (result <= 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
auto start = buf.size();
|
||||
|
||||
++result; // +1 because snprintf(...) requires space for '\0'
|
||||
buf.resize(buf.size() + result);
|
||||
|
||||
try {
|
||||
result = snprintf(&buf[start], result, format, std::forward<Args>(args)...);
|
||||
buf.resize(start + std::max(0, result));
|
||||
} catch (...) {
|
||||
buf.resize(start);
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @return formatted string
|
||||
/// @note asserts on failure
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename... Args>
|
||||
inline std::string to_string(const char* format, Args&&... args) {
|
||||
std::string buf;
|
||||
const auto result = to_string(buf, format, std::forward<Args>(args)...);
|
||||
|
||||
assert(result >= 0);
|
||||
assert(size_t(result) == buf.size());
|
||||
|
||||
UNUSED(result);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
NS_END // string_utils
|
||||
NS_END
|
||||
|
||||
#endif
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "tests_shared.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/block_pool.hpp"
|
||||
#include "utils/misc.hpp"
|
||||
|
||||
|
@ -124,7 +125,7 @@ class block_pool_test : public test_base {
|
|||
|
||||
if (i % 3 == 0) { // read data within slice
|
||||
bstring payload;
|
||||
size_t size = r.read(&(oversize(payload, slice_data.size())[0]), slice_data.size());
|
||||
size_t size = r.read(&(string_utils::oversize(payload, slice_data.size())[0]), slice_data.size());
|
||||
EXPECT_TRUE(slice_data.size() == size);
|
||||
EXPECT_TRUE(memcmp(slice_data.c_str(), payload.data(), std::min(slice_data.size(), size)) == 0);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "utils/ref_counter.hpp"
|
||||
#include <unordered_map>
|
||||
|
||||
namespace tests {
|
||||
class ref_counter_tests: public ::testing::Test {
|
||||
|
|
Loading…
Reference in New Issue