1 |
|
|
/** |
2 |
|
|
* This file is part of the CernVM File System. |
3 |
|
|
*/ |
4 |
|
|
|
5 |
|
|
#include "item.h" |
6 |
|
|
|
7 |
|
|
#include <algorithm> |
8 |
|
|
#include <cassert> |
9 |
|
|
#include <cstdlib> |
10 |
|
|
#include <cstring> |
11 |
|
|
|
12 |
|
|
#include "ingestion/ingestion_source.h" |
13 |
|
|
#include "item_mem.h" |
14 |
|
|
#include "smalloc.h" |
15 |
|
|
#include "util_concurrency.h" |
16 |
|
|
|
17 |
|
958 |
FileItem::FileItem( |
18 |
|
|
IngestionSource* source, |
19 |
|
|
uint64_t min_chunk_size, |
20 |
|
|
uint64_t avg_chunk_size, |
21 |
|
|
uint64_t max_chunk_size, |
22 |
|
|
zlib::Algorithms compression_algorithm, |
23 |
|
|
shash::Algorithms hash_algorithm, |
24 |
|
|
shash::Suffix hash_suffix, |
25 |
|
|
bool may_have_chunks, |
26 |
|
|
bool has_legacy_bulk_chunk) |
27 |
|
|
: source_(source) |
28 |
|
|
, compression_algorithm_(compression_algorithm) |
29 |
|
|
, hash_algorithm_(hash_algorithm) |
30 |
|
|
, hash_suffix_(hash_suffix) |
31 |
|
|
, has_legacy_bulk_chunk_(has_legacy_bulk_chunk) |
32 |
|
|
, size_(kSizeUnknown) |
33 |
|
|
, may_have_chunks_(may_have_chunks) |
34 |
|
|
, chunk_detector_(min_chunk_size, avg_chunk_size, max_chunk_size) |
35 |
|
|
, bulk_hash_(hash_algorithm) |
36 |
|
958 |
, chunks_(1) |
37 |
|
|
{ |
38 |
|
958 |
int retval = pthread_mutex_init(&lock_, NULL); |
39 |
✗✓ |
958 |
assert(retval == 0); |
40 |
|
958 |
atomic_init64(&nchunks_in_fly_); |
41 |
|
958 |
atomic_init32(&is_fully_chunked_); |
42 |
|
958 |
} |
43 |
|
|
|
44 |
|
958 |
FileItem::~FileItem() { |
45 |
|
958 |
pthread_mutex_destroy(&lock_); |
46 |
|
958 |
} |
47 |
|
|
|
48 |
|
1814 |
void FileItem::RegisterChunk(const FileChunk &file_chunk) { |
49 |
|
1814 |
MutexLockGuard lock_guard(lock_); |
50 |
|
|
|
51 |
✓✓ |
1814 |
switch (file_chunk.content_hash().suffix) { |
52 |
|
|
case shash::kSuffixPartial: |
53 |
|
1668 |
chunks_.PushBack(file_chunk); |
54 |
|
1668 |
break; |
55 |
|
|
|
56 |
|
|
default: |
57 |
✗✓ |
146 |
assert(file_chunk.offset() == 0); |
58 |
✗✓ |
146 |
assert(file_chunk.size() == size_); |
59 |
✗✓ |
146 |
bulk_hash_ = file_chunk.content_hash(); |
60 |
|
|
break; |
61 |
|
|
} |
62 |
|
1814 |
atomic_dec64(&nchunks_in_fly_); |
63 |
|
1814 |
} |
64 |
|
|
|
65 |
|
|
|
66 |
|
|
//------------------------------------------------------------------------------ |
67 |
|
|
|
68 |
|
|
|
69 |
|
6825 |
ChunkItem::ChunkItem(FileItem *file_item, uint64_t offset) |
70 |
|
|
: file_item_(file_item) |
71 |
|
|
, offset_(offset) |
72 |
|
|
, size_(0) |
73 |
|
|
, is_bulk_chunk_(false) |
74 |
|
|
, upload_handle_(NULL) |
75 |
|
6825 |
, compressor_(zlib::Compressor::Construct(file_item->compression_algorithm())) |
76 |
|
|
{ |
77 |
|
6825 |
hash_ctx_.algorithm = file_item->hash_algorithm(); |
78 |
|
6825 |
hash_ctx_.size = shash::GetContextSize(hash_ctx_.algorithm); |
79 |
|
6825 |
hash_ctx_buffer_ = smalloc(hash_ctx_.size); |
80 |
|
6825 |
hash_ctx_.buffer = hash_ctx_buffer_; |
81 |
|
6825 |
shash::Init(hash_ctx_); |
82 |
|
6825 |
hash_value_.algorithm = hash_ctx_.algorithm; |
83 |
|
6825 |
hash_value_.suffix = shash::kSuffixPartial; |
84 |
|
6825 |
file_item_->IncNchunksInFly(); |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
|
88 |
|
149 |
void ChunkItem::MakeBulkChunk() { |
89 |
|
149 |
is_bulk_chunk_ = true; |
90 |
|
149 |
hash_value_.suffix = file_item_->hash_suffix(); |
91 |
|
149 |
} |
92 |
|
|
|
93 |
|
|
|
94 |
|
|
//------------------------------------------------------------------------------ |
95 |
|
|
|
96 |
|
|
atomic_int64 BlockItem::managed_bytes_ = 0; |
97 |
|
|
|
98 |
|
|
|
99 |
|
2356 |
BlockItem::BlockItem(ItemAllocator *allocator) |
100 |
|
|
: allocator_(allocator) |
101 |
|
|
, type_(kBlockHollow) |
102 |
|
|
, tag_(-1) |
103 |
|
|
, file_item_(NULL) |
104 |
|
|
, chunk_item_(NULL) |
105 |
|
|
, data_(NULL) |
106 |
|
|
, capacity_(0) |
107 |
|
2356 |
, size_(0) |
108 |
|
2356 |
{ } |
109 |
|
|
|
110 |
|
|
|
111 |
|
1153503 |
BlockItem::BlockItem(int64_t tag, ItemAllocator *allocator) |
112 |
|
|
: allocator_(allocator) |
113 |
|
|
, type_(kBlockHollow) |
114 |
|
|
, tag_(tag) |
115 |
|
|
, file_item_(NULL) |
116 |
|
|
, chunk_item_(NULL) |
117 |
|
|
, data_(NULL) |
118 |
|
|
, capacity_(0) |
119 |
|
1153503 |
, size_(0) |
120 |
|
|
{ |
121 |
✗✓ |
1153569 |
assert(tag_ >= 0); |
122 |
|
1153569 |
} |
123 |
|
|
|
124 |
|
|
|
125 |
|
1156008 |
BlockItem::~BlockItem() { |
126 |
✓✓ |
1156008 |
if (data_) |
127 |
|
920350 |
allocator_->Free(data_); |
128 |
|
1156036 |
atomic_xadd64(&managed_bytes_, -static_cast<int64_t>(capacity_)); |
129 |
|
1156093 |
} |
130 |
|
|
|
131 |
|
|
|
132 |
|
106655 |
void BlockItem::Discharge() { |
133 |
|
106655 |
data_ = NULL; |
134 |
|
106655 |
size_ = capacity_ = 0; |
135 |
|
106655 |
} |
136 |
|
|
|
137 |
|
|
|
138 |
|
8768 |
void BlockItem::MakeStop() { |
139 |
✗✓ |
8768 |
assert(type_ == kBlockHollow); |
140 |
|
8768 |
type_ = kBlockStop; |
141 |
|
8768 |
} |
142 |
|
|
|
143 |
|
|
|
144 |
|
545922 |
void BlockItem::MakeData(uint32_t capacity) { |
145 |
✗✓ |
545922 |
assert(type_ == kBlockHollow); |
146 |
✗✓ |
545922 |
assert(allocator_ != NULL); |
147 |
✗✓ |
545922 |
assert(capacity > 0); |
148 |
|
|
|
149 |
|
545922 |
type_ = kBlockData; |
150 |
|
545922 |
capacity_ = capacity; |
151 |
|
545922 |
data_ = reinterpret_cast<unsigned char *>(allocator_->Malloc(capacity_)); |
152 |
|
545922 |
atomic_xadd64(&managed_bytes_, static_cast<int64_t>(capacity_)); |
153 |
|
545922 |
} |
154 |
|
|
|
155 |
|
|
|
156 |
|
|
/** |
157 |
|
|
* Move data from one block to another. |
158 |
|
|
*/ |
159 |
|
106655 |
void BlockItem::MakeDataMove(BlockItem *other) { |
160 |
✗✓ |
106655 |
assert(type_ == kBlockHollow); |
161 |
✗✓ |
106655 |
assert(other->type_ == kBlockData); |
162 |
✗✓ |
106655 |
assert(other->size_ > 0); |
163 |
|
|
|
164 |
|
106655 |
type_ = kBlockData; |
165 |
|
106655 |
capacity_ = size_ = other->size_; |
166 |
|
106655 |
data_ = other->data_; |
167 |
|
106655 |
allocator_ = other->allocator_; |
168 |
|
|
|
169 |
|
106655 |
other->Discharge(); |
170 |
|
106655 |
} |
171 |
|
|
|
172 |
|
|
|
173 |
|
|
/** |
174 |
|
|
* Copy a piece of one block's data into a new block. |
175 |
|
|
*/ |
176 |
|
494026 |
void BlockItem::MakeDataCopy( |
177 |
|
|
const unsigned char *data, |
178 |
|
|
uint32_t size) |
179 |
|
|
{ |
180 |
✗✓ |
494026 |
assert(type_ == kBlockHollow); |
181 |
✗✓ |
494026 |
assert(allocator_ != NULL); |
182 |
✗✓ |
494026 |
assert(size > 0); |
183 |
|
|
|
184 |
|
494026 |
type_ = kBlockData; |
185 |
|
494026 |
capacity_ = size_ = size; |
186 |
|
494026 |
data_ = reinterpret_cast<unsigned char *>(allocator_->Malloc(capacity_)); |
187 |
|
494038 |
memcpy(data_, data, size); |
188 |
|
494038 |
atomic_xadd64(&managed_bytes_, static_cast<int64_t>(capacity_)); |
189 |
|
494040 |
} |
190 |
|
|
|
191 |
|
|
|
192 |
|
119584 |
void BlockItem::Reset() { |
193 |
✗✓ |
119584 |
assert(type_ == kBlockData); |
194 |
|
|
|
195 |
|
119584 |
atomic_xadd64(&managed_bytes_, -static_cast<int64_t>(capacity_)); |
196 |
|
119584 |
allocator_->Free(data_); |
197 |
|
119584 |
data_ = NULL; |
198 |
|
119584 |
size_ = capacity_ = 0; |
199 |
|
119584 |
type_ = kBlockHollow; |
200 |
|
119584 |
} |
201 |
|
|
|
202 |
|
|
|
203 |
|
927293 |
void BlockItem::SetChunkItem(ChunkItem *value) { |
204 |
✗✓ |
927293 |
assert(value != NULL); |
205 |
✗✓ |
927293 |
assert(chunk_item_ == NULL); |
206 |
|
927293 |
chunk_item_ = value; |
207 |
|
927293 |
} |
208 |
|
|
|
209 |
|
|
|
210 |
|
1153556 |
void BlockItem::SetFileItem(FileItem *value) { |
211 |
✗✓ |
1153556 |
assert(value != NULL); |
212 |
✗✓ |
1153556 |
assert(file_item_ == NULL); |
213 |
|
1153556 |
file_item_ = value; |
214 |
|
1153556 |
} |
215 |
|
|
|
216 |
|
|
|
217 |
|
512 |
uint32_t BlockItem::Write(void *buf, uint32_t count) { |
218 |
✗✓ |
512 |
assert(type_ == kBlockData); |
219 |
|
|
|
220 |
|
512 |
uint32_t remaining = capacity_ - size_; |
221 |
|
512 |
uint32_t nbytes = std::min(remaining, count); |
222 |
|
512 |
memcpy(data_ + size_, buf, nbytes); |
223 |
|
512 |
size_ += nbytes; |
224 |
|
512 |
return nbytes; |
225 |
✓✗✓✗
|
45 |
} |