-
Notifications
You must be signed in to change notification settings - Fork 2
/
FileINode.cc
152 lines (134 loc) · 4.4 KB
/
FileINode.cc
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
* File: FileINode.cpp
* Author: Tobias Fleig <tobifleig@gmail.com>
*
* Created on September 16, 2015, 11:11 PM
*/
#include "FileINode.h"
#include "INode.h"
#include <cmath>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <vector>
#include "Constants.inc"
#include "DataBlockList.h"
#include "StreamUtils.inc"
#include "DataBlock.h"
namespace SDI4FS {
FileINode::FileINode(STREAM &input) : INode(input), entries() {
// verify INode type
if (getType() != SDI4FS_INODE_TYPE_REGULARFILE) {
std::cout << "fs: fatal error - inconsistency - reading FileINode from INode of different type: " << getType() << std::endl;
return;
}
if (isInlined()) {
// read stored content
readN(input, &data[0], getInternalSize_b());
} else {
// read stored ids of DataBlockLists
for (int i = 0; i < SDI4FS_MAX_DATABLOCKLISTS_PER_FILE; ++i) {
uint32_t linkTarget;
read32(input, &linkTarget);
if (linkTarget != 0) {
entries.push_back(linkTarget);
} else {
// no gaps allowed
break;
}
}
}
}
FileINode::FileINode(uint32_t id) : INode(id, SDI4FS_INODE_TYPE_REGULARFILE), entries() {
}
void FileINode::convertToNonInline(DataBlockList *blockList, DataBlock &dataBlock) {
pushDataBlockList(blockList->getId());
dataBlock.write((char*) &data[0], 0, getInternalSize_b());
setInlined(false);
}
bool FileINode::pushDataBlockList(uint32_t id) {
if (entries.size() == SDI4FS_MAX_DATABLOCKLISTS_PER_FILE) {
// full
return false;
}
entries.push_back(id);
return true;
}
uint32_t FileINode::popDataBlockList() {
// cannot empty below 1
if (entries.size() == 1) {
return 0;
}
uint32_t result = entries[entries.size() - 1];
entries.pop_back();
return result;
}
uint32_t FileINode::getDataBlockList(size_t index) {
if (entries.size() <= index) {
return 0;
}
return entries[index];
}
bool FileINode::readInline(char *target, uint32_t pos, std::size_t n) {
if (!isInlined()) {
std::cout << "fs: error - attempting to read inline data from non-inline FileINode: " << getId() << std::endl;
return false;
}
if (pos > SDI4FS_MAX_BYTES_PER_INODE || (pos + n) > SDI4FS_MAX_BYTES_PER_INODE) {
std::cout << "fs: error - attempting to read inline data with out-of-bound positions:" << getId() << " " << pos << " " << n << std::endl;
return false;
}
memcpy(target, &data[pos], n);
return true;
}
bool FileINode::writeInline(const char *source, uint32_t pos, std::size_t n) {
if (!isInlined()) {
std::cout << "fs: error - attempting to write inline data to non-inline FileINode: " << getId() << std::endl;
return false;
}
if (pos > SDI4FS_MAX_BYTES_PER_INODE || (pos + n) > SDI4FS_MAX_BYTES_PER_INODE) {
std::cout << "fs: error - attempting to write inline data with out-of-bound positions:" << getId() << " " << pos << " " << n << std::endl;
return false;
}
memcpy(&data[pos], source, n);
return true;
}
uint32_t FileINode::getUserVisibleSize_b() {
if (isInlined()) {
return SDI4FS_BLOCK_SIZE;
} else {
size_t numberOfDataBlockLists = entries.size();
size_t numberOfDataBlocks = ceil(getInternalSize_b() / ((float) SDI4FS_MAX_BYTES_PER_DATABLOCK));
// 1 FileINode + #DataBlockLists + #DataBlocks
return ((1 + numberOfDataBlockLists + numberOfDataBlocks) * SDI4FS_BLOCK_SIZE);
}
}
void FileINode::setInternalSize_b(uint32_t size_b) {
// verify range
if (size_b <= SDI4FS_MAX_FILE_SIZE) {
INode::setInternalSize_b(size_b);
} else {
std::cout << "fs: cannot set internal size of file " << getId() << ", file size limit exceeded (" << size_b << ")" << std::endl;
}
}
void FileINode::save(STREAM &output) {
INode::save(output);
if (isInlined()) {
// write content
writeN(output, &data[0], getInternalSize_b());
} else {
// write entries
for (auto iter = entries.begin(); iter != entries.end(); ++iter) {
// write id
write32(output, *iter);
}
// null rest
for (int i = entries.size(); i < SDI4FS_MAX_DATABLOCKLISTS_PER_FILE; ++i) {
// write 0 (zero)
write32(output, 0);
}
}
}
FileINode::~FileINode() {
}
} // SDI4FS