summaryrefslogtreecommitdiffstats
path: root/library/cpp/on_disk/chunks/chunked_helpers.cpp
blob: b3aa5c8234c62284f189e9b72e528485e40caf2c (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
#include <util/ysaveload.h>

#include "chunked_helpers.h"

TBlob GetBlock(const TBlob& blob, size_t index) {
    TChunkedDataReader reader(blob);
    if (index >= reader.GetBlocksCount())
        ythrow yexception() << "index " << index << " is >= than block count " << reader.GetBlocksCount();
    size_t begin = (const char*)reader.GetBlock(index) - (const char*)blob.Data();
    return blob.SubBlob(begin, begin + reader.GetBlockLen(index));
}
 
/*************************** TNamedChunkedDataReader ***************************/ 
 
static const char* NamedChunkedDataMagic = "NamedChunkedData";
 
TNamedChunkedDataReader::TNamedChunkedDataReader(const TBlob& blob)
    : TChunkedDataReader(blob)
{ 
    if (TChunkedDataReader::GetBlocksCount() < 1) 
        throw yexception() << "Too few blocks"; 
 
    size_t block = TChunkedDataReader::GetBlocksCount() - 1; 
    size_t magicLen = strlen(NamedChunkedDataMagic); 
    if (GetBlockLen(block) < magicLen || memcmp(GetBlock(block), NamedChunkedDataMagic, magicLen) != 0) 
        throw yexception() << "Not a valid named chunked data file"; 
 
    TMemoryInput input(static_cast<const char*>(GetBlock(block)) + magicLen, GetBlockLen(block) - magicLen);
    Load(&input, Names); 
 
    size_t index = 0; 
    for (TVector<TString>::const_iterator it = Names.begin(); it != Names.end(); ++it, ++index) {
        if (!it->empty()) 
            NameToIndex[*it] = index; 
    } 
} 
 
/*************************** TNamedChunkedDataWriter ***************************/ 
 
TNamedChunkedDataWriter::TNamedChunkedDataWriter(IOutputStream& slave)
    : TChunkedDataWriter(slave) 
{ 
} 
 
TNamedChunkedDataWriter::~TNamedChunkedDataWriter() {
} 
 
void TNamedChunkedDataWriter::NewBlock() { 
    NewBlock(""); 
} 
 
void TNamedChunkedDataWriter::NewBlock(const TString& name) {
    if (!name.empty()) { 
        if (NameToIndex.count(name) != 0) 
            throw yexception() << "Block name is not unique"; 
        NameToIndex[name] = Names.size(); 
    } 
    Names.push_back(name); 
    TChunkedDataWriter::NewBlock(); 
} 
 
void TNamedChunkedDataWriter::WriteFooter() { 
    NewBlock(""); 
    Write(NamedChunkedDataMagic); 
    Save(this, Names); 
    TChunkedDataWriter::WriteFooter(); 
}