#ifndef DIRECTORY_ENTRY_TABLE_H
#define DIRECTORY_ENTRY_TABLE_H
#include <util/OpenHashTable.h>
#include "AllocationInfo.h"
#include "DebugSupport.h"
#include "Misc.h"
#include "Node.h"
struct DirectoryEntryHash {
struct Key {
ino_t id;
const char* name;
Key(ino_t i, const char* n) : id(i), name(n) {}
};
typedef Key KeyType;
typedef Entry ValueType;
size_t HashKey(KeyType key) const
{
return node_child_hash(key.id, key.name);
}
size_t Hash(ValueType* value) const
{
return HashKey(Key(value->GetParent()->GetID(), value->GetName()));
}
bool Compare(KeyType key, ValueType* value) const
{
return (value->GetParent()->GetID() == key.id
&& !strcmp(value->GetName(), key.name));
}
ValueType*& GetLink(ValueType* value) const
{
return value->HashLink();
}
};
class DirectoryEntryTable {
public:
DirectoryEntryTable();
~DirectoryEntryTable();
status_t InitCheck() const;
status_t AddEntry(Directory *node, Entry *child);
status_t AddEntry(ino_t, Entry *child);
status_t RemoveEntry(Directory *node, Entry *child);
status_t RemoveEntry(ino_t id, Entry *child);
status_t RemoveEntry(ino_t id, const char *name);
Entry *GetEntry(ino_t id, const char *name);
void GetAllocationInfo(AllocationInfo &info)
{
info.AddDirectoryEntryTableAllocation(0, fTable.TableSize(),
sizeof(void*), fTable.CountElements());
}
protected:
BOpenHashTable<DirectoryEntryHash> fTable;
status_t fInitStatus;
};
DirectoryEntryTable::DirectoryEntryTable()
{
fInitStatus = fTable.Init(1000);
}
DirectoryEntryTable::~DirectoryEntryTable()
{
}
status_t
DirectoryEntryTable::InitCheck() const
{
RETURN_ERROR(fInitStatus);
}
status_t
DirectoryEntryTable::AddEntry(Directory *node, Entry *child)
{
status_t error = (node && child ? B_OK : B_BAD_VALUE);
if (error == B_OK)
error = AddEntry(node->GetID(), child);
return error;
}
status_t
DirectoryEntryTable::AddEntry(ino_t id, Entry *child)
{
status_t error = (child ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
RemoveEntry(id, child);
SET_ERROR(error, fTable.Insert(child));
}
return error;
}
status_t
DirectoryEntryTable::RemoveEntry(Directory *node, Entry *child)
{
status_t error = (node && child ? B_OK : B_BAD_VALUE);
if (error == B_OK)
error = RemoveEntry(node->GetID(), child->GetName());
return error;
}
status_t
DirectoryEntryTable::RemoveEntry(ino_t id, Entry *child)
{
status_t error = (child ? B_OK : B_BAD_VALUE);
if (error == B_OK)
error = RemoveEntry(id, child->GetName());
return error;
}
status_t
DirectoryEntryTable::RemoveEntry(ino_t id, const char *name)
{
Entry* child = fTable.Lookup(DirectoryEntryHash::Key(id, name));
if (!child)
return B_NAME_NOT_FOUND;
return fTable.Remove(child) ? B_OK : B_ERROR;
}
Entry *
DirectoryEntryTable::GetEntry(ino_t id, const char *name)
{
Entry *child = fTable.Lookup(DirectoryEntryHash::Key(id, name));
return child;
}
#endif