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// WriteAt
51status_t
52Attribute::WriteAt(off_t offset, const void *buffer, size_t size,
53				   size_t *bytesWritten)
54{
55	// get the current key for the attribute
56	uint8 oldKey[kMaxIndexKeyLength];
57	size_t oldLength;
58	GetKey(oldKey, &oldLength);
59
60	// write the new value
61	status_t error = DataContainer::WriteAt(offset, buffer, size, bytesWritten);
62
63	// If there is an index and a change has been made within the key, notify
64	// the index.
65	if (offset < kMaxIndexKeyLength && size > 0 && fIndex)
66		fIndex->Changed(this, oldKey, oldLength);
67
68	// update live queries
69	const uint8* newKey;
70	size_t newLength;
71	GetKey(&newKey, &newLength);
72	GetVolume()->UpdateLiveQueries(NULL, fNode, GetName(), fType, oldKey,
73		oldLength, newKey, newLength);
74
75	// node has been changed
76	if (fNode && size > 0)
77		fNode->MarkModified();
78
79	return error;
80}
81
82// SetIndex
83void
84Attribute::SetIndex(AttributeIndex *index, bool inIndex)
85{
86	fIndex = index;
87	fInIndex = inIndex;
88}
89
90// GetKey
91void
92Attribute::GetKey(const uint8 **key, size_t *length)
93{
94	if (key && length) {
95		GetFirstDataBlock(key, length);
96		*length = min(*length, kMaxIndexKeyLength);
97	}
98}
99
100// GetKey
101void
102Attribute::GetKey(uint8 *key, size_t *length)
103{
104	if (key && length) {
105		const uint8 *originalKey = NULL;
106		GetKey(&originalKey, length);
107		if (length > 0)
108			memcpy(key, originalKey, *length);
109	}
110}
111
112// AttachAttributeIterator
113void
114Attribute::AttachAttributeIterator(AttributeIterator *iterator)
115{
116	if (iterator && iterator->GetCurrent() == this && !iterator->IsSuspended())
117		fIterators.Insert(iterator);
118}
119
120// DetachAttributeIterator
121void
122Attribute::DetachAttributeIterator(AttributeIterator *iterator)
123{
124	if (iterator && iterator->GetCurrent() == this && iterator->IsSuspended())
125		fIterators.Remove(iterator);
126}
127
128// GetAllocationInfo
129void
130Attribute::GetAllocationInfo(AllocationInfo &info)
131{
132	DataContainer::GetAllocationInfo(info);
133	info.AddAttributeAllocation(GetSize());
134	info.AddStringAllocation(fName.GetLength());
135}
136
137