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