aboutsummaryrefslogtreecommitdiffstats
path: root/searchcore/src/vespa/searchcore/proton/attribute/attributedisklayout.cpp
blob: 40b24f2ec2684776ef7c462924eb4938e405ab6d (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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "attributedisklayout.h"
#include "attribute_directory.h"
#include <vespa/vespalib/io/fileutil.h>
#include <cassert>
#include <filesystem>

namespace proton {

AttributeDiskLayout::AttributeDiskLayout(const vespalib::string &baseDir, PrivateConstructorTag)
    : _baseDir(baseDir),
      _mutex(),
      _dirs()
{
    std::filesystem::create_directory(std::filesystem::path(_baseDir));
    vespalib::File::sync(vespalib::dirname(_baseDir));
}

AttributeDiskLayout::~AttributeDiskLayout() = default;

std::vector<vespalib::string>
AttributeDiskLayout::listAttributes()
{
    std::vector<vespalib::string> attributes;
    std::shared_lock<std::shared_mutex> guard(_mutex);
    for (const auto &dir : _dirs)  {
        attributes.emplace_back(dir.first);
    }
    return attributes;
}

void
AttributeDiskLayout::scanDir()
{
    std::filesystem::directory_iterator dir_scan{std::filesystem::path(_baseDir)};
    for (auto& entry : dir_scan) {
        if (entry.is_directory()) {
            createAttributeDir(entry.path().filename().string());
        }
    }
}

std::shared_ptr<AttributeDirectory>
AttributeDiskLayout::getAttributeDir(const vespalib::string &name)
{
    std::shared_lock<std::shared_mutex> guard(_mutex);
    auto itr = _dirs.find(name);
    if (itr == _dirs.end()) {
        return std::shared_ptr<AttributeDirectory>();
    } else {
        return itr->second;
    }
}

std::shared_ptr<AttributeDirectory>
AttributeDiskLayout::createAttributeDir(const vespalib::string &name)
{
    std::lock_guard<std::shared_mutex> guard(_mutex);
    auto itr = _dirs.find(name);
    if (itr == _dirs.end()) {
        auto dir = std::make_shared<AttributeDirectory>(shared_from_this(), name);
        auto insres = _dirs.insert(std::make_pair(name, dir));
        assert(insres.second);
        return dir;
    } else {
        return itr->second;
    }
}

void
AttributeDiskLayout::removeAttributeDir(const vespalib::string &name, search::SerialNum serialNum)
{
    auto dir = getAttributeDir(name);
    if (dir) {
        auto writer = dir->getWriter();
        if (writer) {
            writer->invalidateOldSnapshots(serialNum);
            writer->removeInvalidSnapshots();
            if (writer->removeDiskDir()) {
                std::lock_guard<std::shared_mutex> guard(_mutex);
                auto itr = _dirs.find(name);
                assert(itr != _dirs.end());
                assert(dir.get() == itr->second.get());
                _dirs.erase(itr);
                writer->detach();
            }
        } else {
            std::lock_guard<std::shared_mutex> guard(_mutex);
            auto itr = _dirs.find(name);
            if (itr != _dirs.end()) {
                assert(dir.get() != itr->second.get());
            }
        }
    }
}

std::shared_ptr<AttributeDiskLayout>
AttributeDiskLayout::create(const vespalib::string &baseDir)
{
    auto diskLayout = std::make_shared<AttributeDiskLayout>(baseDir, PrivateConstructorTag());
    diskLayout->scanDir();
    return diskLayout;
}

std::shared_ptr<AttributeDiskLayout>
AttributeDiskLayout::createSimple(const vespalib::string &baseDir)
{
    auto diskLayout = std::make_shared<AttributeDiskLayout>(baseDir, PrivateConstructorTag());
    return diskLayout;
}

} // namespace proton