1/*
2 * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "Block.h"
8
9#include <fs_cache.h>
10
11#include "Transaction.h"
12#include "Volume.h"
13
14
15void
16Block::TransferFrom(Block& other)
17{
18	Put();
19
20	fVolume = other.fVolume;
21	fData = other.fData;
22	fIndex = other.fIndex;
23	fTransaction = other.fTransaction;
24
25	other.fVolume = NULL;
26	other.fData = NULL;
27}
28
29
30bool
31Block::GetReadable(Volume* volume, uint64 blockIndex)
32{
33	Put();
34
35	return _Init(volume, blockIndex,
36		block_cache_get(volume->BlockCache(), blockIndex), NULL);
37}
38
39
40bool
41Block::GetWritable(Volume* volume, uint64 blockIndex, Transaction& transaction)
42{
43	Put();
44
45	status_t error = transaction.RegisterBlock(blockIndex);
46	if (error != B_OK)
47		return false;
48
49	return _Init(volume, blockIndex,
50		block_cache_get_writable(volume->BlockCache(), blockIndex,
51			transaction.ID()),
52		&transaction);
53}
54
55
56bool
57Block::GetZero(Volume* volume, uint64 blockIndex, Transaction& transaction)
58{
59	Put();
60
61	status_t error = transaction.RegisterBlock(blockIndex);
62	if (error != B_OK)
63		return false;
64
65	return _Init(volume, blockIndex,
66		block_cache_get_empty(volume->BlockCache(), blockIndex,
67			transaction.ID()),
68		&transaction);
69}
70
71
72status_t
73Block::MakeWritable(Transaction& transaction)
74{
75	if (fVolume == NULL)
76		return B_BAD_VALUE;
77	if (fTransaction != NULL)
78		return B_OK;
79
80	status_t error = transaction.RegisterBlock(fIndex);
81	if (error != B_OK)
82		return error;
83
84	error = block_cache_make_writable(fVolume->BlockCache(), fIndex,
85		transaction.ID());
86	if (error != B_OK) {
87		transaction.PutBlock(fIndex, NULL);
88		return error;
89	}
90
91	fTransaction = &transaction;
92	return B_OK;
93}
94
95
96void
97Block::Put()
98{
99	if (fVolume != NULL) {
100		if (fTransaction != NULL)
101			fTransaction->PutBlock(fIndex, fData);
102
103		block_cache_put(fVolume->BlockCache(), fIndex);
104		fVolume = NULL;
105		fData = NULL;
106	}
107}
108
109
110bool
111Block::_Init(Volume* volume, uint64 blockIndex, const void* data,
112	Transaction* transaction)
113{
114	if (data == NULL)
115		return false;
116
117	fVolume = volume;
118	fData = const_cast<void*>(data);
119	fIndex = blockIndex;
120	fTransaction = transaction;
121
122	return true;
123}
124