1// Attribute.cpp
2
3#include "AllocationInfo.h"
4#include "Attribute.h"
5#include "Misc.h"
6#include "Node.h"
7#include "ramfs.h"
8#include "Volume.h"
9
10// constructor
11Attribute::Attribute(Volume *volume, Node *node, const char *name,
12					 uint32 type)
13	: DataContainer(volume),
14	  fNode(node),
15	  fName(name),
16	  fType(type),
17	  fIndex(NULL),
18	  fInIndex(false),
19	  fIterators()
20{
21}
22
23// destructor
24Attribute::~Attribute()
25{
26}
27
28// InitCheck
29status_t
30Attribute::InitCheck() const
31{
32	return (fName.GetString() ? B_OK : B_NO_INIT);
33}
34
35// SetType
36void
37Attribute::SetType(uint32 type)
38{
39	if (type != fType) {
40		if (fIndex)
41			fIndex->Removed(this);
42		fType = type;
43		if (AttributeIndex *index = GetVolume()->FindAttributeIndex(GetName(),
44																	fType)) {
45			index->Added(this);
46		}
47	}
48}
49
50// SetSize
51status_t
52Attribute::SetSize(off_t newSize)
53{
54	status_t error = B_OK;
55	off_t oldSize = DataContainer::GetSize();
56	if (newSize != oldSize) {
57		if (fNode)
58			fNode->MarkModified(B_STAT_MODIFICATION_TIME);
59
60		error = DataContainer::Resize(newSize);
61	}
62	return error;
63}
64
65// WriteAt
66status_t
67Attribute::WriteAt(off_t offset, const void *buffer, size_t size,
68				   size_t *bytesWritten)
69{
70	// get the current key for the attribute
71	uint8 oldKey[kMaxIndexKeyLength];
72	size_t oldLength;
73	GetKey(oldKey, &oldLength);
74
75	// write the new value
76	status_t error = DataContainer::WriteAt(offset, buffer, size, bytesWritten);
77
78	// If there is an index and a change has been made within the key, notify
79	// the index.
80	if (offset < kMaxIndexKeyLength && size > 0 && fIndex)
81		fIndex->Changed(this, oldKey, oldLength);
82
83	// update live queries
84	const uint8* newKey;
85	size_t newLength;
86	GetKey(&newKey, &newLength);
87	GetVolume()->UpdateLiveQueries(NULL, fNode, GetName(), fType, oldKey,
88		oldLength, newKey, newLength);
89
90	// node has been changed
91	if (fNode && size > 0)
92		fNode->MarkModified(B_STAT_MODIFICATION_TIME);
93
94	return error;
95}
96
97// SetIndex
98void
99Attribute::SetIndex(AttributeIndex *index, bool inIndex)
100{
101	fIndex = index;
102	fInIndex = inIndex;
103}
104
105// GetKey
106void
107Attribute::GetKey(const uint8 **key, size_t *length)
108{
109	if (key && length) {
110		GetFirstDataBlock(key, length);
111		*length = min(*length, kMaxIndexKeyLength);
112	}
113}
114
115// GetKey
116void
117Attribute::GetKey(uint8 *key, size_t *length)
118{
119	if (key && length) {
120		const uint8 *originalKey = NULL;
121		GetKey(&originalKey, length);
122		if (length > 0)
123			memcpy(key, originalKey, *length);
124	}
125}
126
127// AttachAttributeIterator
128void
129Attribute::AttachAttributeIterator(AttributeIterator *iterator)
130{
131	if (iterator && iterator->GetCurrent() == this && !iterator->IsSuspended())
132		fIterators.Insert(iterator);
133}
134
135// DetachAttributeIterator
136void
137Attribute::DetachAttributeIterator(AttributeIterator *iterator)
138{
139	if (iterator && iterator->GetCurrent() == this && iterator->IsSuspended())
140		fIterators.Remove(iterator);
141}
142
143// GetAllocationInfo
144void
145Attribute::GetAllocationInfo(AllocationInfo &info)
146{
147	DataContainer::GetAllocationInfo(info);
148	info.AddAttributeAllocation(GetSize());
149	info.AddStringAllocation(fName.GetLength());
150}
151
152