3
A brief file description
5
@section license License
7
Licensed to the Apache Software Foundation (ASF) under one
8
or more contributor license agreements. See the NOTICE file
9
distributed with this work for additional information
10
regarding copyright ownership. The ASF licenses this file
11
to you under the Apache License, Version 2.0 (the
12
"License"); you may not use this file except in compliance
13
with the License. You may obtain a copy of the License at
15
http://www.apache.org/licenses/LICENSE-2.0
17
Unless required by applicable law or agreed to in writing, software
18
distributed under the License is distributed on an "AS IS" BASIS,
19
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
See the License for the specific language governing permissions and
21
limitations under the License.
28
CacheDisk::open(char *s, off_t blocks, off_t askip, int ahw_sector_size, int fildes, bool clear)
31
hw_sector_size = ahw_sector_size;
35
/* we can't use fractions of store blocks. */
37
io.aiocb.aio_fildes = fd;
38
io.aiocb.aio_reqprio = 0;
40
// determine header size and hence start point by successive approximation
42
for (int i = 0; i < 3; i++) {
43
l = (len * STORE_BLOCK_SIZE) - (start - skip);
44
if (l >= MIN_PART_SIZE) {
45
header_len = sizeof(DiskHeader) + (l / MIN_PART_SIZE - 1) * sizeof(DiskPartBlock);
47
header_len = sizeof(DiskHeader);
49
start = skip + header_len;
52
disk_parts = (DiskPart **) xmalloc((l / MIN_PART_SIZE + 1) * sizeof(DiskPart **));
53
memset(disk_parts, 0, (l / MIN_PART_SIZE + 1) * sizeof(DiskPart **));
54
header_len = ROUND_TO_STORE_BLOCK(header_len);
55
start = skip + header_len;
56
num_usable_blocks = (off_t(len * STORE_BLOCK_SIZE) - (start - askip)) >> STORE_BLOCK_SHIFT;
59
header = (DiskHeader *) malloc(header_len);
61
header = (DiskHeader *) valloc(header_len);
64
memset(header, 0, header_len);
66
SET_HANDLER(&CacheDisk::clearDone);
70
SET_HANDLER(&CacheDisk::openStart);
71
io.aiocb.aio_offset = skip;
72
io.aiocb.aio_buf = (char *) header;
73
io.aiocb.aio_nbytes = header_len;
74
io.thread = AIO_CALLBACK_THREAD_ANY;
79
CacheDisk::~CacheDisk()
83
for (int i = 0; i < (int) header->num_partitions; i++) {
84
DiskPartBlockQueue *q = NULL;
85
while (disk_parts[i] && (q = (disk_parts[i]->dpb_queue.pop()))) {
93
DiskPartBlockQueue *q = NULL;
94
while ((q = (free_blocks->dpb_queue.pop()))) {
102
CacheDisk::clearDisk()
104
delete_all_partitions();
106
io.aiocb.aio_offset = skip;
107
io.aiocb.aio_buf = header;
108
io.aiocb.aio_nbytes = header_len;
109
io.thread = AIO_CALLBACK_THREAD_ANY;
115
CacheDisk::clearDone(int event, void *data)
118
ink_assert(event == AIO_EVENT_DONE);
120
if ((int) io.aiocb.aio_nbytes != (int) io.aio_result) {
121
Warning("Could not clear disk header for disk %s: declaring disk bad", path);
126
SET_HANDLER(&CacheDisk::openDone);
127
return openDone(EVENT_IMMEDIATE, 0);
131
CacheDisk::openStart(int event, void *data)
134
ink_assert(event == AIO_EVENT_DONE);
136
if ((int) io.aiocb.aio_nbytes != (int) io.aio_result) {
137
Warning("could not read disk header for disk %s: declaring disk bad", path);
139
SET_HANDLER(&CacheDisk::openDone);
140
return openDone(EVENT_IMMEDIATE, 0);
143
if (header->magic != DISK_HEADER_MAGIC || header->num_blocks != len) {
144
Warning("disk header different for disk %s: clearing the disk", path);
145
SET_HANDLER(&CacheDisk::clearDone);
151
/* populate disk_parts */
154
SET_HANDLER(&CacheDisk::openDone);
155
return openDone(EVENT_IMMEDIATE, 0);
159
CacheDisk::openDone(int event, void *data)
162
NOWARN_UNUSED(event);
163
if (cacheProcessor.start_done) {
164
SET_HANDLER(&CacheDisk::syncDone);
165
cacheProcessor.diskInitialized();
168
eventProcessor.schedule_in(this, HRTIME_MSECONDS(5), ET_CALL);
176
io.aiocb.aio_offset = skip;
177
io.aiocb.aio_buf = header;
178
io.aiocb.aio_nbytes = header_len;
179
io.thread = AIO_CALLBACK_THREAD_ANY;
185
CacheDisk::syncDone(int event, void *data)
189
ink_assert(event == AIO_EVENT_DONE);
191
if ((int) io.aiocb.aio_nbytes != (int) io.aio_result) {
192
Warning("Error writing disk header for disk %s:disk bad", path);
200
/* size is in store blocks */
202
CacheDisk::create_partition(int number, off_t size_in_blocks, int scheme)
204
if (size_in_blocks == 0)
207
DiskPartBlockQueue *q = free_blocks->dpb_queue.head;
208
DiskPartBlockQueue *closest_match = q;
212
off_t max_blocks = MAX_PART_SIZE >> STORE_BLOCK_SHIFT;
213
size_in_blocks = (size_in_blocks <= max_blocks) ? size_in_blocks : max_blocks;
215
int blocks_per_part = PART_BLOCK_SIZE / STORE_BLOCK_SIZE;
216
// ink_assert(!(size_in_blocks % blocks_per_part));
217
DiskPartBlock *p = 0;
218
for (; q; q = q->link.next) {
219
if (q->b->len >= (unsigned int) size_in_blocks) {
224
if (closest_match->b->len < q->b->len)
229
if (!p && !closest_match)
232
if (!p && closest_match) {
233
/* allocate from the closest match */
237
ink_assert(size_in_blocks > (int) p->len);
238
/* allocate in 128 megabyte chunks. The Remaining space should
240
size_in_blocks = (p->len - (p->len % blocks_per_part));
241
wasted_space += p->len % blocks_per_part;
244
free_blocks->dpb_queue.remove(q);
245
free_space -= p->len;
246
free_blocks->size -= p->len;
248
int new_size = p->len - size_in_blocks;
249
if (new_size >= blocks_per_part) {
250
/* create a new partition */
251
DiskPartBlock *dpb = &header->part_info[header->num_diskpart_blks];
253
dpb->len -= size_in_blocks;
254
dpb->offset += ((off_t) size_in_blocks * STORE_BLOCK_SIZE);
256
DiskPartBlockQueue *new_q = NEW(new DiskPartBlockQueue());
258
free_blocks->dpb_queue.enqueue(new_q);
259
free_blocks->size += dpb->len;
260
free_space += dpb->len;
261
header->num_diskpart_blks++;
265
p->len = size_in_blocks;
272
/* add it to its disk_part */
273
for (i = 0; i < header->num_partitions; i++) {
274
if (disk_parts[i]->part_number == number) {
275
disk_parts[i]->dpb_queue.enqueue(q);
276
disk_parts[i]->num_partblocks++;
277
disk_parts[i]->size += q->b->len;
281
if (i == header->num_partitions) {
282
disk_parts[i] = NEW(new DiskPart());
283
disk_parts[i]->num_partblocks = 1;
284
disk_parts[i]->part_number = number;
285
disk_parts[i]->disk = this;
286
disk_parts[i]->dpb_queue.enqueue(q);
287
disk_parts[i]->size = q->b->len;
288
header->num_partitions++;
295
CacheDisk::delete_partition(int number)
298
for (i = 0; i < header->num_partitions; i++) {
299
if (disk_parts[i]->part_number == number) {
301
DiskPartBlockQueue *q;
302
for (q = disk_parts[i]->dpb_queue.head; q;) {
303
DiskPartBlock *p = q->b;
304
p->type = CACHE_NONE_TYPE;
306
free_space += p->len;
309
DiskPartBlockQueue *temp_q = q->link.next;
310
disk_parts[i]->dpb_queue.remove(q);
311
free_blocks->dpb_queue.enqueue(q);
314
free_blocks->num_partblocks += disk_parts[i]->num_partblocks;
315
free_blocks->size += disk_parts[i]->size;
317
delete disk_parts[i];
318
/* move all the other disk parts */
319
for (unsigned int j = i; j < (header->num_partitions - 1); j++) {
320
disk_parts[j] = disk_parts[j + 1];
322
header->num_partitions--;
330
CacheDisk::update_header()
335
DiskPartBlockQueue *q = NULL;
336
while ((q = (free_blocks->dpb_queue.pop()))) {
341
free_blocks = NEW(new DiskPart());
342
free_blocks->part_number = -1;
343
free_blocks->disk = this;
344
free_blocks->num_partblocks = 0;
345
free_blocks->size = 0;
348
for (i = 0; i < header->num_diskpart_blks; i++) {
349
DiskPartBlockQueue *dpbq = NEW(new DiskPartBlockQueue());
350
bool dpbq_referenced = false;
351
dpbq->b = &header->part_info[i];
352
if (header->part_info[i].free) {
353
free_blocks->num_partblocks++;
354
free_blocks->size += dpbq->b->len;
355
free_blocks->dpb_queue.enqueue(dpbq);
356
dpbq_referenced = true;
357
free_space += dpbq->b->len;
360
int part_number = header->part_info[i].number;
361
for (j = 0; j < n; j++) {
362
if (disk_parts[j]->part_number == part_number) {
363
disk_parts[j]->dpb_queue.enqueue(dpbq);
364
dpbq_referenced = true;
365
disk_parts[j]->num_partblocks++;
366
disk_parts[j]->size += dpbq->b->len;
371
// did not find a matching partition number. create a new
373
disk_parts[j] = NEW(new DiskPart());
374
disk_parts[j]->part_number = part_number;
375
disk_parts[j]->disk = this;
376
disk_parts[j]->num_partblocks = 1;
377
disk_parts[j]->size = dpbq->b->len;
378
disk_parts[j]->dpb_queue.enqueue(dpbq);
379
dpbq_referenced = true;
382
// check to see if we even used the dpbq allocated
383
if (dpbq_referenced == false) {
388
ink_assert(n == header->num_partitions);
392
CacheDisk::get_diskpart(int part_number)
395
for (i = 0; i < header->num_partitions; i++) {
396
if (disk_parts[i]->part_number == part_number) {
397
return disk_parts[i];
404
CacheDisk::delete_all_partitions()
406
header->part_info[0].offset = start;
407
header->part_info[0].len = num_usable_blocks;
408
header->part_info[0].type = CACHE_NONE_TYPE;
409
header->part_info[0].free = 1;
411
header->magic = DISK_HEADER_MAGIC;
412
header->num_used = 0;
413
header->num_partitions = 0;
414
header->num_free = 1;
415
header->num_diskpart_blks = 1;
416
header->num_blocks = len;