aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib/src/vespa/searchlib/diskindex/fileheader.cpp
blob: 02ae7b714bc89872af348a8fc6a12388fed21b04 (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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "fileheader.h"
#include <vespa/searchlib/bitcompression/compression.h>
#include <vespa/vespalib/stllike/asciistream.h>
#include <vespa/vespalib/data/fileheader.h>
#include <vespa/fastos/file.h>
#include <cinttypes>
#include <cassert>
#include <arpa/inet.h>

#include <vespa/log/log.h>
LOG_SETUP(".diskindex.fileheader");

namespace search::diskindex {

using bitcompression::FeatureDecodeContextBE;

FileHeader::FileHeader()
    : _bigEndian(false),
      _completed(false),
      _version(0),
      _headerLen(0),
      _fileBitSize(0),
      _formats()
{
}

FileHeader::~FileHeader() = default;

bool
FileHeader::taste(const vespalib::string &name,
                  const TuneFileSeqRead &tuneFileRead)
{
    vespalib::FileHeader header;
    uint32_t headerLen;
    uint64_t fileSize;
    {
        FastOS_File file;


        if (tuneFileRead.getWantDirectIO()) {
            file.EnableDirectIO();
        }
        bool res = file.OpenReadOnly(name.c_str());
        if (!res) {
            return false;
        }

        fileSize = file.getSize();
        try {
            headerLen = header.readFile(file);
            assert(headerLen >= header.getSize());
            (void) headerLen;
        } catch (vespalib::IllegalHeaderException &e) {
            if (e.getMessage() != "Failed to read header info." &&
                e.getMessage() != "Failed to verify magic bits.") {
                LOG(error, "FileHeader::tastGeneric(\"%s\") exception: %s",
                    name.c_str(), e.getMessage().c_str());
            }
            return false;
        }
    }

    _version = 1;
    _headerLen = headerLen;
    _bigEndian = htonl(1) == 1;
    if (header.hasTag("endian")) {
        vespalib::string endian(header.getTag("endian").asString());
        if (endian == "big") {
            _bigEndian = true;
        } else if (endian == "little") {
            _bigEndian = false;
        } else {
            LOG(error, "Bad endian: %s", endian.c_str());
            return false;
        }
    }

    if (header.hasTag("frozen")) {
        _completed = header.getTag("frozen").asInteger() != 0;
    } else {
        LOG(error, "FileHeader::taste(\"%s\"): Missing frozen tag", name.c_str());
        return false;
    }
    if (header.hasTag("fileBitSize")) {
        _fileBitSize = header.getTag("fileBitSize").asInteger();
        if (_completed && _fileBitSize < 8 * _headerLen) {
            LOG(error, "FileHeader::taste(\"%s\"): fleBitSize(%" PRIu64 ") < 8 * headerLen(%u)",
                name.c_str(), _fileBitSize, _headerLen);
            return false;
        }
        if (_completed && _fileBitSize > 8 * fileSize) {
            LOG(error, "FileHeader::taste(\"%s\"): fleBitSize(%" PRIu64 ") > 8 * fileSize(%" PRIu64 ")",
                name.c_str(), _fileBitSize, fileSize);
            LOG_ABORT("should not be reached");
        }
    } else {
        LOG(error, "FileHeader::taste(\"%s\"): Missing fileBitSize tag", name.c_str());
        return false;
    }
    for (uint32_t i = 0; ;++i) {
        vespalib::asciistream as;
        as << "format." << i;
        vespalib::stringref key(as.str());
        if (!header.hasTag(key)) {
            break;
        }
        _formats.push_back(header.getTag(key).asString());
    }
    return true;
}

bool
FileHeader::taste(const vespalib::string &name, const TuneFileSeqWrite &tuneFileWrite)
{
    TuneFileSeqRead tuneFileRead;
    if (tuneFileWrite.getWantDirectIO()) {
        tuneFileRead.setWantDirectIO();
    }
    return taste(name, tuneFileRead);
}

bool
FileHeader::taste(const vespalib::string &name, const TuneFileRandRead &tuneFileSearch)
{
    TuneFileSeqRead tuneFileRead;
    if (tuneFileSearch.getWantDirectIO()) {
        tuneFileRead.setWantDirectIO();
    }
    return taste(name, tuneFileRead);
}

}