3 #include <TypeConstants.h>
12 // NameIndexPrimaryKey
13 class NameIndexPrimaryKey
{
15 NameIndexPrimaryKey(const Entry
*entry
,
16 const char *name
= NULL
)
17 : entry(entry
), name(name
? name
: entry
->GetName()) {}
18 NameIndexPrimaryKey(const char *name
)
19 : entry(NULL
), name(name
) {}
25 // NameIndexGetPrimaryKey
26 class NameIndexGetPrimaryKey
{
28 inline NameIndexPrimaryKey
operator()(const Entry
*a
)
30 return NameIndexPrimaryKey(a
);
33 inline NameIndexPrimaryKey
operator()(const Entry
*a
) const
35 return NameIndexPrimaryKey(a
);
40 // NameIndexPrimaryKeyCompare
41 class NameIndexPrimaryKeyCompare
44 inline int operator()(const NameIndexPrimaryKey
&a
,
45 const NameIndexPrimaryKey
&b
) const
47 if (a
.entry
!= NULL
&& a
.entry
== b
.entry
)
49 return strcmp(a
.name
, b
.name
);
56 typedef TwoKeyAVLTree
<Entry
*, NameIndexPrimaryKey
, NameIndexPrimaryKeyCompare
,
57 NameIndexGetPrimaryKey
>
60 class NameIndex::EntryTree
: public _EntryTree
{};
63 // NameIndexEntryIterator
64 class NameIndexEntryIterator
: public AbstractIndexEntryIterator
,
65 public EntryListener
{
67 NameIndexEntryIterator();
68 virtual ~NameIndexEntryIterator();
70 virtual Entry
*GetCurrent();
71 virtual Entry
*GetCurrent(uint8
*buffer
, size_t *keyLength
);
72 virtual Entry
*GetPrevious();
73 virtual Entry
*GetNext();
75 virtual status_t
Suspend();
76 virtual status_t
Resume();
78 bool SetTo(NameIndex
*index
, const char *name
, bool ignoreValue
= false);
80 virtual void EntryRemoved(Entry
*entry
);
83 friend class NameIndex
;
85 typedef AbstractIndexEntryIterator BaseClass
;
89 NameIndex::EntryTree::Iterator fIterator
;
98 NameIndex::NameIndex(Volume
*volume
)
99 : Index(volume
, "name", B_STRING_TYPE
, false),
100 fEntries(new(nothrow
) EntryTree
)
102 if (fInitStatus
== B_OK
&& !fEntries
)
103 fInitStatus
= B_NO_MEMORY
;
104 if (fInitStatus
== B_OK
) {
105 fInitStatus
= fVolume
->AddEntryListener(this,
106 NULL
, ENTRY_LISTEN_ANY_ENTRY
| ENTRY_LISTEN_ALL
);
111 NameIndex::~NameIndex()
114 fVolume
->RemoveEntryListener(this, NULL
);
117 // Actually we would need to maintain a list of iterators and unset the
118 // still existing iterators here. But since the name index is deleted
119 // when the volume is unmounted, there shouldn't be any iterators left
125 NameIndex::CountEntries() const
127 return fEntries
->CountItems();
132 NameIndex::Changed(Entry
*entry
, const char *oldName
)
134 status_t error
= B_BAD_VALUE
;
135 if (entry
&& oldName
) {
136 EntryTree::Iterator it
;
138 = fEntries
->Find(NameIndexPrimaryKey(entry
, oldName
), entry
, &it
);
139 if (foundEntry
&& *foundEntry
== entry
) {
141 error
= fEntries
->Insert(entry
);
143 // udpate live queries
144 _UpdateLiveQueries(entry
, oldName
, entry
->GetName());
152 NameIndex::EntryAdded(Entry
*entry
)
155 fEntries
->Insert(entry
);
157 // udpate live queries
158 _UpdateLiveQueries(entry
, NULL
, entry
->GetName());
164 NameIndex::EntryRemoved(Entry
*entry
)
167 fEntries
->Remove(entry
, entry
);
169 // udpate live queries
170 _UpdateLiveQueries(entry
, entry
->GetName(), NULL
);
174 // InternalGetIterator
175 AbstractIndexEntryIterator
*
176 NameIndex::InternalGetIterator()
178 NameIndexEntryIterator
*iterator
= new(nothrow
) NameIndexEntryIterator
;
180 if (!iterator
->SetTo(this, NULL
, true)) {
189 AbstractIndexEntryIterator
*
190 NameIndex::InternalFind(const uint8
*key
, size_t length
)
192 if (!key
|| length
== 0)
195 // if the key is not null-terminated, copy it
196 uint8 clonedKey
[kMaxIndexKeyLength
];
197 if (key
[length
- 1] != '\0') {
198 if (length
>= kMaxIndexKeyLength
)
199 length
= kMaxIndexKeyLength
- 1;
201 memcpy(clonedKey
, key
, length
);
202 clonedKey
[length
] = '\0';
207 NameIndexEntryIterator
*iterator
= new(nothrow
) NameIndexEntryIterator
;
209 if (!iterator
->SetTo(this, (const char *)key
)) {
217 // _UpdateLiveQueries
219 NameIndex::_UpdateLiveQueries(Entry
* entry
, const char* oldName
,
222 fVolume
->UpdateLiveQueries(entry
, entry
->GetNode(), GetName(),
223 GetType(), (const uint8
*)oldName
, (oldName
? strlen(oldName
) : 0),
224 (const uint8
*)newName
, (newName
? strlen(newName
) : 0));
228 // NameIndexEntryIterator
231 NameIndexEntryIterator::NameIndexEntryIterator()
232 : AbstractIndexEntryIterator(),
241 NameIndexEntryIterator::~NameIndexEntryIterator()
248 NameIndexEntryIterator::GetCurrent()
250 return (fIndex
&& fIterator
.GetCurrent() ? *fIterator
.GetCurrent() : NULL
);
255 NameIndexEntryIterator::GetCurrent(uint8
*buffer
, size_t *keyLength
)
257 Entry
*entry
= GetCurrent();
259 strncpy((char*)buffer
, entry
->GetName(), kMaxIndexKeyLength
);
260 *keyLength
= strlen(entry
->GetName());
267 NameIndexEntryIterator::GetPrevious()
271 if (!(fIterator
.GetCurrent() && fIsNext
))
272 fIterator
.GetPrevious();
274 return (fIndex
&& fIterator
.GetCurrent() ? *fIterator
.GetCurrent() : NULL
);
279 NameIndexEntryIterator::GetNext()
283 if (!(fIterator
.GetCurrent() && fIsNext
))
286 return (fIndex
&& fIterator
.GetCurrent() ? *fIterator
.GetCurrent() : NULL
);
291 NameIndexEntryIterator::Suspend()
293 status_t error
= (!fSuspended
? B_OK
: B_BAD_VALUE
);
295 if (fIterator
.GetCurrent()) {
296 error
= fIndex
->GetVolume()->AddEntryListener(this,
297 *fIterator
.GetCurrent(), ENTRY_LISTEN_REMOVED
);
307 NameIndexEntryIterator::Resume()
309 status_t error
= (fSuspended
? B_OK
: B_BAD_VALUE
);
311 if (fIterator
.GetCurrent()) {
312 error
= fIndex
->GetVolume()->RemoveEntryListener(this,
313 *fIterator
.GetCurrent());
323 NameIndexEntryIterator::SetTo(NameIndex
*index
, const char *name
,
332 fIndex
->fEntries
->GetIterator(&fIterator
);
333 return fIterator
.GetCurrent();
335 return fIndex
->fEntries
->FindFirst(name
, &fIterator
);
342 NameIndexEntryIterator::EntryRemoved(Entry */
*entry*/
)