launch_speedup: convert to BOpenHashTable.

This commit is contained in:
Adrien Destugues
2015-01-12 10:13:57 +01:00
parent c4718ea973
commit 756ce47ea9
+116 -115
View File
@@ -19,7 +19,6 @@
#include <Node.h> #include <Node.h>
#include <util/kernel_cpp.h> #include <util/kernel_cpp.h>
#include <util/khash.h>
#include <util/AutoLock.h> #include <util/AutoLock.h>
#include <thread.h> #include <thread.h>
#include <team.h> #include <team.h>
@@ -64,6 +63,33 @@ struct node {
size_t part_count; size_t part_count;
}; };
struct NodeHash {
typedef node_ref KeyType;
typedef node ValueType;
size_t HashKey(KeyType key) const
{
return VNODE_HASH(key.device, key.node);
}
size_t Hash(ValueType* value) const
{
return HashKey(value->ref);
}
bool Compare(KeyType key, ValueType* node) const
{
return (node->ref.device == key.device && node->ref.node == key.node);
}
ValueType*& GetLink(ValueType* value) const
{
return value->next;
}
};
typedef BOpenHashTable<NodeHash> NodeTable;
class Session { class Session {
public: public:
Session(team_id team, const char *name, dev_t device, Session(team_id team, const char *name, dev_t device,
@@ -94,7 +120,6 @@ class Session {
void Prefetch(); void Prefetch();
Session *&Next() { return fNext; } Session *&Next() { return fNext; }
static uint32 NextOffset() { return offsetof(Session, fNext); }
private: private:
struct node *_FindNode(dev_t device, ino_t node); struct node *_FindNode(dev_t device, ino_t node);
@@ -102,7 +127,7 @@ class Session {
Session *fNext; Session *fNext;
char fName[B_OS_NAME_LENGTH]; char fName[B_OS_NAME_LENGTH];
mutex fLock; mutex fLock;
hash_table *fNodeHash; NodeTable *fNodeHash;
struct node *fNodes; struct node *fNodes;
int32 fNodeCount; int32 fNodeCount;
team_id fTeam; team_id fTeam;
@@ -127,8 +152,8 @@ class SessionGetter {
}; };
static Session *sMainSession; static Session *sMainSession;
static hash_table *sTeamHash; static SessionTable *sTeamHash;
static hash_table *sPrefetchHash; static PrefetchTable *sPrefetchHash;
static Session *sMainPrefetchSessions; static Session *sMainPrefetchSessions;
// singly-linked list // singly-linked list
static recursive_lock sLock; static recursive_lock sLock;
@@ -140,83 +165,61 @@ node_ref::node_ref()
} }
static int struct PrefetchHash {
node_compare(void *_node, const void *_key) typedef node_ref KeyType;
{ typedef Session ValueType;
struct node *node = (struct node *)_node;
const struct node_ref *key = (node_ref *)_key;
if (node->ref.device == key->device && node->ref.node == key->node) size_t HashKey(KeyType key) const
return 0; {
return VNODE_HASH(key.device, key.node);
}
return -1; size_t Hash(ValueType* value) const
} {
return HashKey(value->NodeRef());
}
bool Compare(KeyType key, ValueType* session) const
{
return (session->NodeRef().device == key.device
&& session->NodeRef().node == key.node);
}
ValueType*& GetLink(ValueType* value) const
{
return value->Next();
}
};
typedef BOpenHashTable<PrefetchHash> PrefetchTable;
static uint32 struct SessionHash {
node_hash(void *_node, const void *_key, uint32 range) typedef team_id KeyType;
{ typedef Session ValueType;
struct node *node = (struct node *)_node;
const struct node_ref *key = (node_ref *)_key;
if (node != NULL) size_t HashKey(KeyType key) const
return VNODE_HASH(node->ref.device, node->ref.node) % range; {
return key;
}
return VNODE_HASH(key->device, key->node) % range; size_t Hash(ValueType* value) const
} {
return HashKey(value->Team());
}
bool Compare(KeyType key, ValueType* session) const
{
return session->Team == key;
}
static int ValueType*& GetLink(ValueType* value) const
prefetch_compare(void *_session, const void *_key) {
{ return value->Next();
Session *session = (Session *)_session; }
const struct node_ref *key = (node_ref *)_key; };
if (session->NodeRef().device == key->device typedef BOpenHashTable<SessionHash> SessionTable;
&& session->NodeRef().node == key->node)
return 0;
return -1;
}
static uint32
prefetch_hash(void *_session, const void *_key, uint32 range)
{
Session *session = (Session *)_session;
const struct node_ref *key = (node_ref *)_key;
if (session != NULL)
return VNODE_HASH(session->NodeRef().device, session->NodeRef().node) % range;
return VNODE_HASH(key->device, key->node) % range;
}
static int
team_compare(void *_session, const void *_key)
{
Session *session = (Session *)_session;
const team_id *team = (const team_id *)_key;
if (session->Team() == *team)
return 0;
return -1;
}
static uint32
team_hash(void *_session, const void *_key, uint32 range)
{
Session *session = (Session *)_session;
const team_id *team = (const team_id *)_key;
if (session != NULL)
return session->Team() % range;
return *team % range;
}
static void static void
@@ -234,7 +237,7 @@ stop_session(Session *session)
RecursiveLocker locker(&sLock); RecursiveLocker locker(&sLock);
if (session->Team() >= B_OK) if (session->Team() >= B_OK)
hash_remove(sTeamHash, session); sTeamHash->Remove(session);
if (session == sMainSession) if (session == sMainSession)
sMainSession = NULL; sMainSession = NULL;
@@ -282,7 +285,7 @@ start_session(team_id team, dev_t device, ino_t node, const char *name,
} }
if (team >= B_OK) if (team >= B_OK)
hash_insert(sTeamHash, session); sTeamHash->Insert(session);
session->Lock(); session->Lock();
return session; return session;
@@ -354,7 +357,7 @@ load_prefetch_data()
session->Next() = sMainPrefetchSessions; session->Next() = sMainPrefetchSessions;
sMainPrefetchSessions = session; sMainPrefetchSessions = session;
} else { } else {
hash_insert(sPrefetchHash, session); sPrefetchHash->Insert(session);
} }
} }
@@ -384,7 +387,11 @@ Session::Session(team_id team, const char *name, dev_t device,
fName[0] = '\0'; fName[0] = '\0';
mutex_init(&fLock, "launch speedup session"); mutex_init(&fLock, "launch speedup session");
fNodeHash = hash_init(64, 0, &node_compare, &node_hash); fNodeHash = new(std::nothrow) NodeTable();
if (fNodeHash && fNodeHash->Init(64) != B_OK) {
delete fNodeHash;
fNodeHash = NULL;
}
fActiveUntil = system_time() + seconds * 1000000LL; fActiveUntil = system_time() + seconds * 1000000LL;
fTimestamp = system_time(); fTimestamp = system_time();
@@ -419,27 +426,22 @@ Session::~Session()
mutex_destroy(&fLock); mutex_destroy(&fLock);
// free all nodes // free all nodes
struct node *node, *next = NULL;
if (fNodeHash) { if (fNodeHash) {
// ... from the hash // ... from the hash
uint32 cookie = 0; node = fNodeHash->Clear(true);
struct node *node;
while ((node = (struct node *)hash_remove_first(fNodeHash, &cookie)) != NULL) {
//TRACE((" node %ld:%Ld\n", node->ref.device, node->ref.node));
free(node);
}
hash_uninit(fNodeHash);
} else { } else {
// ... from the list // ... from the list
struct node *node = fNodes, *next = NULL; node = fNodes;
for (; node != NULL; node = next) {
next = node->next;
free(node);
}
} }
for (; node != NULL; node = next) {
next = node->next;
free(node);
}
delete fNodeHash;
StopWatchingTeam(); StopWatchingTeam();
} }
@@ -461,7 +463,7 @@ Session::_FindNode(dev_t device, ino_t node)
key.device = device; key.device = device;
key.node = node; key.node = node;
return (struct node *)hash_lookup(fNodeHash, &key); return fNodeHash->Lookup(key);
} }
@@ -478,7 +480,7 @@ Session::AddNode(dev_t device, ino_t id)
if (node == NULL) if (node == NULL)
return; return;
hash_insert(fNodeHash, node); fNodeHash->Insert(node);
fNodeCount++; fNodeCount++;
} }
@@ -488,7 +490,7 @@ Session::RemoveNode(dev_t device, ino_t id)
{ {
struct node *node = _FindNode(device, id); struct node *node = _FindNode(device, id);
if (node != NULL && --node->ref_count <= 0) { if (node != NULL && --node->ref_count <= 0) {
hash_remove(fNodeHash, node); fNodeHash->Remove(node);
fNodeCount--; fNodeCount--;
} }
} }
@@ -605,11 +607,9 @@ Session::Save()
// enlarge file, so that it can be written faster // enlarge file, so that it can be written faster
ftruncate(fd, 512 * 1024); ftruncate(fd, 512 * 1024);
struct hash_iterator iterator; NodeTable::Iterator iterator(fNodeHash);
struct node *node; while (iterator.HasNext()) {
struct node *node = iterator.Next();
hash_open(fNodeHash, &iterator);
while ((node = (struct node *)hash_next(fNodeHash, &iterator)) != NULL) {
snprintf(name, sizeof(name), "%ld:%Ld\n", node->ref.device, node->ref.node); snprintf(name, sizeof(name), "%ld:%Ld\n", node->ref.device, node->ref.node);
ssize_t bytesWritten = write(fd, name, strlen(name)); ssize_t bytesWritten = write(fd, name, strlen(name));
@@ -621,8 +621,6 @@ Session::Save()
fileSize += bytesWritten; fileSize += bytesWritten;
} }
hash_close(fNodeHash, &iterator, false);
ftruncate(fd, fileSize); ftruncate(fd, fileSize);
close(fd); close(fd);
@@ -661,7 +659,7 @@ SessionGetter::SessionGetter(team_id team, Session **_session)
if (sMainSession != NULL) if (sMainSession != NULL)
fSession = sMainSession; fSession = sMainSession;
else else
fSession = (Session *)hash_lookup(sTeamHash, &team); fSession = sTeamHash->Lookup(team);
if (fSession != NULL) { if (fSession != NULL) {
if (!fSession->IsClosing()) if (!fSession->IsClosing())
@@ -814,14 +812,17 @@ uninit()
// free all sessions from the hashes // free all sessions from the hashes
uint32 cookie = 0; Session *session = sTeamHash->Clear(true);
Session *session; while (session != NULL) {
while ((session = (Session *)hash_remove_first(sTeamHash, &cookie)) != NULL) { Session *next = session->next;
delete session; delete session;
session = next;
} }
cookie = 0; session = sPrefetchHash->Clear(true);
while ((session = (Session *)hash_remove_first(sPrefetchHash, &cookie)) != NULL) { while (session != NULL) {
Session *next = session->next;
delete session; delete session;
session = next;
} }
// free all sessions from the main prefetch list // free all sessions from the main prefetch list
@@ -832,8 +833,8 @@ uninit()
session = sMainPrefetchSessions; session = sMainPrefetchSessions;
} }
hash_uninit(sTeamHash); delete sTeamHash;
hash_uninit(sPrefetchHash); delete sPrefetchHash;
recursive_lock_destroy(&sLock); recursive_lock_destroy(&sLock);
} }
@@ -841,14 +842,14 @@ uninit()
static status_t static status_t
init() init()
{ {
sTeamHash = hash_init(64, Session::NextOffset(), &team_compare, &team_hash); sTeamHash = new(std::nothrow) SessionTable();
if (sTeamHash == NULL) if (sTeamHash == NULL || sTeamHash->Init(64) != B_OK)
return B_NO_MEMORY; return B_NO_MEMORY;
status_t status; status_t status;
sPrefetchHash = hash_init(64, Session::NextOffset(), &prefetch_compare, &prefetch_hash); sPrefetchHash = new(std::nothrow) PrefetchTable();
if (sPrefetchHash == NULL) { if (sPrefetchHash == NULL || sPrefetchHash->Init(64) != B_OK) {
status = B_NO_MEMORY; status = B_NO_MEMORY;
goto err1; goto err1;
} }
@@ -876,9 +877,9 @@ init()
err3: err3:
recursive_lock_destroy(&sLock); recursive_lock_destroy(&sLock);
hash_uninit(sPrefetchHash); delete sPrefetchHash;
err1: err1:
hash_uninit(sTeamHash); delete sTeamHash;
return status; return status;
} }