diff --git a/src/add-ons/kernel/file_cache/launch_speedup.cpp b/src/add-ons/kernel/file_cache/launch_speedup.cpp index 27a37cbe88..562c2b3d82 100644 --- a/src/add-ons/kernel/file_cache/launch_speedup.cpp +++ b/src/add-ons/kernel/file_cache/launch_speedup.cpp @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -64,6 +63,33 @@ struct node { 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 NodeTable; + class Session { public: Session(team_id team, const char *name, dev_t device, @@ -94,7 +120,6 @@ class Session { void Prefetch(); Session *&Next() { return fNext; } - static uint32 NextOffset() { return offsetof(Session, fNext); } private: struct node *_FindNode(dev_t device, ino_t node); @@ -102,7 +127,7 @@ class Session { Session *fNext; char fName[B_OS_NAME_LENGTH]; mutex fLock; - hash_table *fNodeHash; + NodeTable *fNodeHash; struct node *fNodes; int32 fNodeCount; team_id fTeam; @@ -127,8 +152,8 @@ class SessionGetter { }; static Session *sMainSession; -static hash_table *sTeamHash; -static hash_table *sPrefetchHash; +static SessionTable *sTeamHash; +static PrefetchTable *sPrefetchHash; static Session *sMainPrefetchSessions; // singly-linked list static recursive_lock sLock; @@ -140,83 +165,61 @@ node_ref::node_ref() } -static int -node_compare(void *_node, const void *_key) -{ - struct node *node = (struct node *)_node; - const struct node_ref *key = (node_ref *)_key; +struct PrefetchHash { + typedef node_ref KeyType; + typedef Session ValueType; - if (node->ref.device == key->device && node->ref.node == key->node) - return 0; + size_t HashKey(KeyType key) const + { + 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 PrefetchTable; -static uint32 -node_hash(void *_node, const void *_key, uint32 range) -{ - struct node *node = (struct node *)_node; - const struct node_ref *key = (node_ref *)_key; +struct SessionHash { + typedef team_id KeyType; + typedef Session ValueType; - if (node != NULL) - return VNODE_HASH(node->ref.device, node->ref.node) % range; + size_t HashKey(KeyType key) const + { + 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 -prefetch_compare(void *_session, const void *_key) -{ - Session *session = (Session *)_session; - const struct node_ref *key = (node_ref *)_key; + ValueType*& GetLink(ValueType* value) const + { + return value->Next(); + } +}; - if (session->NodeRef().device == key->device - && 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; -} +typedef BOpenHashTable SessionTable; static void @@ -234,7 +237,7 @@ stop_session(Session *session) RecursiveLocker locker(&sLock); if (session->Team() >= B_OK) - hash_remove(sTeamHash, session); + sTeamHash->Remove(session); if (session == sMainSession) sMainSession = NULL; @@ -282,7 +285,7 @@ start_session(team_id team, dev_t device, ino_t node, const char *name, } if (team >= B_OK) - hash_insert(sTeamHash, session); + sTeamHash->Insert(session); session->Lock(); return session; @@ -354,7 +357,7 @@ load_prefetch_data() session->Next() = sMainPrefetchSessions; sMainPrefetchSessions = session; } 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'; 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; fTimestamp = system_time(); @@ -419,27 +426,22 @@ Session::~Session() mutex_destroy(&fLock); // free all nodes + struct node *node, *next = NULL; if (fNodeHash) { // ... from the hash - uint32 cookie = 0; - 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); + node = fNodeHash->Clear(true); } else { // ... from the list - struct node *node = fNodes, *next = NULL; - - for (; node != NULL; node = next) { - next = node->next; - free(node); - } + node = fNodes; } + for (; node != NULL; node = next) { + next = node->next; + free(node); + } + + delete fNodeHash; StopWatchingTeam(); } @@ -461,7 +463,7 @@ Session::_FindNode(dev_t device, ino_t node) key.device = device; 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) return; - hash_insert(fNodeHash, node); + fNodeHash->Insert(node); fNodeCount++; } @@ -488,7 +490,7 @@ Session::RemoveNode(dev_t device, ino_t id) { struct node *node = _FindNode(device, id); if (node != NULL && --node->ref_count <= 0) { - hash_remove(fNodeHash, node); + fNodeHash->Remove(node); fNodeCount--; } } @@ -605,11 +607,9 @@ Session::Save() // enlarge file, so that it can be written faster ftruncate(fd, 512 * 1024); - struct hash_iterator iterator; - struct node *node; - - hash_open(fNodeHash, &iterator); - while ((node = (struct node *)hash_next(fNodeHash, &iterator)) != NULL) { + NodeTable::Iterator iterator(fNodeHash); + while (iterator.HasNext()) { + struct node *node = iterator.Next(); snprintf(name, sizeof(name), "%ld:%Ld\n", node->ref.device, node->ref.node); ssize_t bytesWritten = write(fd, name, strlen(name)); @@ -621,8 +621,6 @@ Session::Save() fileSize += bytesWritten; } - hash_close(fNodeHash, &iterator, false); - ftruncate(fd, fileSize); close(fd); @@ -661,7 +659,7 @@ SessionGetter::SessionGetter(team_id team, Session **_session) if (sMainSession != NULL) fSession = sMainSession; else - fSession = (Session *)hash_lookup(sTeamHash, &team); + fSession = sTeamHash->Lookup(team); if (fSession != NULL) { if (!fSession->IsClosing()) @@ -814,14 +812,17 @@ uninit() // free all sessions from the hashes - uint32 cookie = 0; - Session *session; - while ((session = (Session *)hash_remove_first(sTeamHash, &cookie)) != NULL) { + Session *session = sTeamHash->Clear(true); + while (session != NULL) { + Session *next = session->next; delete session; + session = next; } - cookie = 0; - while ((session = (Session *)hash_remove_first(sPrefetchHash, &cookie)) != NULL) { + session = sPrefetchHash->Clear(true); + while (session != NULL) { + Session *next = session->next; delete session; + session = next; } // free all sessions from the main prefetch list @@ -832,8 +833,8 @@ uninit() session = sMainPrefetchSessions; } - hash_uninit(sTeamHash); - hash_uninit(sPrefetchHash); + delete sTeamHash; + delete sPrefetchHash; recursive_lock_destroy(&sLock); } @@ -841,14 +842,14 @@ uninit() static status_t init() { - sTeamHash = hash_init(64, Session::NextOffset(), &team_compare, &team_hash); - if (sTeamHash == NULL) + sTeamHash = new(std::nothrow) SessionTable(); + if (sTeamHash == NULL || sTeamHash->Init(64) != B_OK) return B_NO_MEMORY; status_t status; - sPrefetchHash = hash_init(64, Session::NextOffset(), &prefetch_compare, &prefetch_hash); - if (sPrefetchHash == NULL) { + sPrefetchHash = new(std::nothrow) PrefetchTable(); + if (sPrefetchHash == NULL || sPrefetchHash->Init(64) != B_OK) { status = B_NO_MEMORY; goto err1; } @@ -876,9 +877,9 @@ init() err3: recursive_lock_destroy(&sLock); - hash_uninit(sPrefetchHash); + delete sPrefetchHash; err1: - hash_uninit(sTeamHash); + delete sTeamHash; return status; }