aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/datastore/array_store_dynamic_type_mapper.hpp
blob: 525659f2a8e3d35403a2d276a5a20f56597fa53e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "array_store_dynamic_type_mapper.h"
#include "dynamic_array_buffer_type.h"
#include "aligner.h"
#include <algorithm>
#include <cmath>
#include <limits>
#include <optional>

namespace vespalib::datastore {

template <typename ElemT>
ArrayStoreDynamicTypeMapper<ElemT>::ArrayStoreDynamicTypeMapper()
    : ArrayStoreTypeMapper(),
      _max_static_array_buffer_type_id(0)
{
}

template <typename ElemT>
ArrayStoreDynamicTypeMapper<ElemT>::ArrayStoreDynamicTypeMapper(uint32_t max_buffer_type_id, double grow_factor, size_t max_buffer_size)
    : ArrayStoreTypeMapper(),
      _max_static_array_buffer_type_id(0)
{
    setup_array_sizes(max_buffer_type_id, grow_factor, max_buffer_size);
}

template <typename ElemT>
void
ArrayStoreDynamicTypeMapper<ElemT>::setup_array_sizes(uint32_t max_buffer_type_id, double grow_factor, size_t max_buffer_size)
{
    _array_sizes.clear();
    _array_sizes.reserve(max_buffer_type_id + 1);
    _array_sizes.emplace_back(0); // type id 0 is fallback for large arrays
    size_t array_size = 1u;
    size_t entry_size = sizeof(ElemT);
    bool dynamic_arrays = false;
    for (uint32_t type_id = 1; type_id <= max_buffer_type_id; ++type_id) {
        if (type_id > 1) {
            array_size = std::max(array_size +  1, static_cast<size_t>(std::floor(array_size * grow_factor)));
            if (array_size > _array_sizes.back() + 1 || dynamic_arrays) {
                if (!dynamic_arrays) {
                    _max_static_array_buffer_type_id = type_id - 1;
                    dynamic_arrays = true;
                }
                entry_size = DynamicBufferType::calc_entry_size(array_size);
                array_size = DynamicBufferType::calc_array_size(entry_size);
            } else {
                entry_size = array_size * sizeof(ElemT);
            }
        }
        if (entry_size > std::numeric_limits<uint32_t>::max() ||
            entry_size >= 2 * max_buffer_size) {
            break;
        }
        _array_sizes.emplace_back(array_size);
    }
    if (!dynamic_arrays) {
        _max_static_array_buffer_type_id = _array_sizes.size() - 1;
    }
}

template <typename ElemT>
ArrayStoreDynamicTypeMapper<ElemT>::~ArrayStoreDynamicTypeMapper() = default;

template <typename ElemT>
size_t
ArrayStoreDynamicTypeMapper<ElemT>::get_entry_size(uint32_t type_id) const
{
    auto array_size = get_array_size(type_id);
    if (type_id <= _max_static_array_buffer_type_id) {
        return array_size * sizeof(ElemT);
    } else {
        return DynamicBufferType::calc_entry_size(array_size);
    }
}

}