diff -r ea5c1f855ce0 -r 02cc96355b09 core/AdminCache.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/AdminCache.cpp Wed Jan 24 21:51:49 2007 +0000 @@ -0,0 +1,568 @@ +#include +#include +#include "AdminCache.h" +#include "ShareSys.h" + +AdminCache g_Admins; + +AdminCache::AdminCache() +{ + m_pCmdOverrides = NULL; + m_pCmdGrpOverrides = NULL; + m_pStrings = new BaseStringTable(1024); + m_pMemory = m_pStrings->GetMemTable(); + m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID; + m_pGroups = sm_trie_create(); +} + +AdminCache::~AdminCache() +{ + if (m_pCmdGrpOverrides) + { + sm_trie_destroy(m_pCmdGrpOverrides); + } + + if (m_pCmdOverrides) + { + sm_trie_destroy(m_pCmdOverrides); + } + + InvalidateGroupCache(); + + if (m_pGroups) + { + sm_trie_destroy(m_pGroups); + } + + delete m_pStrings; +} + +void AdminCache::OnSourceModAllInitialized() +{ + g_ShareSys.AddInterface(NULL, this); +} + +void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, AdminFlag flag) +{ + if (type == Override_Command) + { + _AddCommandOverride(cmd, flag); + } else if (type == Override_CommandGroup) { + _AddCommandGroupOverride(cmd, flag); + } +} + +bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, AdminFlag *pFlag) +{ + if (type == Override_Command) + { + return _GetCommandOverride(cmd, pFlag); + } else if (type == Override_CommandGroup) { + return _GetCommandGroupOverride(cmd, pFlag); + } + + return false; +} + +void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type) +{ + if (type == Override_Command) + { + return _UnsetCommandOverride(cmd); + } else if (type == Override_CommandGroup) { + return _UnsetCommandGroupOverride(cmd); + } +} + +void AdminCache::_AddCommandGroupOverride(const char *group, AdminFlag flag) +{ + if (!m_pCmdGrpOverrides) + { + m_pCmdGrpOverrides = sm_trie_create(); + } + + /* :TODO: Notify command system */ + + sm_trie_insert(m_pCmdGrpOverrides, group, (void *)flag); +} + +void AdminCache::_AddCommandOverride(const char *cmd, AdminFlag flag) +{ + if (!m_pCmdOverrides) + { + m_pCmdOverrides = sm_trie_create(); + } + + /* :TODO: Notify command system */ + + sm_trie_insert(m_pCmdOverrides, cmd, (void *)flag); +} + +bool AdminCache::_GetCommandGroupOverride(const char *cmd, AdminFlag *pFlag) +{ + if (!m_pCmdGrpOverrides) + { + return false; + } + + if (!pFlag) + { + return sm_trie_retrieve(m_pCmdGrpOverrides, cmd, NULL); + } else { + void *object; + bool ret; + if (ret=sm_trie_retrieve(m_pCmdGrpOverrides, cmd, &object)) + { + *pFlag = (AdminFlag)(int)object; + } + return ret; + } +} + +bool AdminCache::_GetCommandOverride(const char *cmd, AdminFlag *pFlag) +{ + if (!m_pCmdOverrides) + { + return false; + } + + if (!pFlag) + { + return sm_trie_retrieve(m_pCmdOverrides, cmd, NULL); + } else { + void *object; + bool ret; + if (ret=sm_trie_retrieve(m_pCmdOverrides, cmd, &object)) + { + *pFlag = (AdminFlag)(int)object; + } + return ret; + } +} + +void AdminCache::_UnsetCommandGroupOverride(const char *group) +{ + if (!m_pCmdGrpOverrides) + { + return; + } + + /* :TODO: Notify command system */ + + sm_trie_delete(m_pCmdGrpOverrides, group); +} + +void AdminCache::_UnsetCommandOverride(const char *cmd) +{ + if (!m_pCmdOverrides) + { + return; + } + + /* :TODO: Notify command system */ + + sm_trie_delete(m_pCmdOverrides, cmd); +} + +void AdminCache::DumpCommandOverrideCache(OverrideType type) +{ + if (type == Override_Command && m_pCmdOverrides) + { + sm_trie_clear(m_pCmdOverrides); + } else if (type == Override_CommandGroup && m_pCmdGrpOverrides) { + sm_trie_clear(m_pCmdGrpOverrides); + } +} + +GroupId AdminCache::AddGroup(const char *group_name) +{ + if (sm_trie_retrieve(m_pGroups, group_name, NULL)) + { + return INVALID_GROUP_ID; + } + + GroupId id; + AdminGroup *pGroup; + if (m_FreeGroupList != INVALID_GROUP_ID) + { + pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList); + assert(pGroup->magic == GRP_MAGIC_UNSET); + id = m_FreeGroupList; + m_FreeGroupList = pGroup->next_grp; + } else { + id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup); + } + + pGroup->immune_default = false; + pGroup->immune_global = false; + pGroup->immune_table = -1; + pGroup->magic = GRP_MAGIC_SET; + pGroup->next_grp = INVALID_GROUP_ID; + pGroup->pCmdGrpTable = NULL; + pGroup->pCmdTable = NULL; + pGroup->nameidx = m_pStrings->AddString(group_name); + memset(pGroup->addflags, 0, sizeof(AdminFlag) * AdminFlags_TOTAL); + + if (m_FirstGroup == INVALID_GROUP_ID) + { + m_FirstGroup = id; + m_LastGroup = id; + pGroup->prev_grp = INVALID_GROUP_ID; + } else { + AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup); + assert(pPrev->magic == GRP_MAGIC_SET); + pPrev->next_grp = id; + pGroup->prev_grp = m_LastGroup; + m_LastGroup = id; + } + + sm_trie_insert(m_pGroups, group_name, (void *)id); + + return id; +} + +GroupId AdminCache::FindGroupByName(const char *group_name) +{ + void *object; + + if (!sm_trie_retrieve(m_pGroups, group_name, &object)) + { + return INVALID_GROUP_ID; + } + + GroupId id = (GroupId)object; + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return INVALID_GROUP_ID; + } + + return id; +} + +void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + if (flag < Admin_None || flag >= AdminFlags_TOTAL) + { + return; + } + + pGroup->addflags[flag] = enabled; +} + +bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return false; + } + + if (flag < Admin_None || flag >= AdminFlags_TOTAL) + { + return false; + } + + return pGroup->addflags[flag]; +} + +unsigned int AdminCache::GetGroupAddFlags(GroupId id, AdminFlag flags[], unsigned int total) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return 0; + } + + unsigned int r = 0; + + for (unsigned int i = Admin_None + 1; + i < AdminFlags_TOTAL && r < total; + i++) + { + if (pGroup->addflags[i]) + { + flags[r++] = (AdminFlag)i; + } + } + + return r; +} + +void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + if (type == Immunity_Default) + { + pGroup->immune_default = enabled; + } else if (type == Immunity_Global) { + pGroup->immune_global = enabled; + } +} + +bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return false; + } + + if (type == Immunity_Default) + { + return pGroup->immune_default; + } else if (type == Immunity_Global) { + return pGroup->immune_global; + } + + return false; +} + +void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + AdminGroup *pOther = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pOther || pOther->magic != GRP_MAGIC_SET) + { + return; + } + + /* We always need to resize the immunity table */ + int *table, tblidx; + if (pOther->immune_table == -1) + { + tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table); + table[0] = 0; + } else { + int *old_table = (int *)m_pMemory->GetAddress(pOther->immune_table); + tblidx = m_pMemory->CreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table); + /* Get the old address again in caes of resize */ + old_table = (int *)m_pMemory->GetAddress(pOther->immune_table); + table[0] = old_table[0]; + for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++) + { + table[i] = old_table[i]; + } + } + + /* Assign */ + pOther->immune_table = tblidx; + + /* Add to the array */ + table[0]++; + table[table[0]] = other_id; +} + +unsigned int AdminCache::GetGroupImmunityCount(GroupId id) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return 0; + } + + if (pGroup->immune_table == -1) + { + return 0; + } + + int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table); + + return table[0]; +} + +GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return INVALID_GROUP_ID; + } + + if (pGroup->immune_table == -1) + { + return INVALID_GROUP_ID; + } + + int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table); + if (number >= (unsigned int)table[0]) + { + return INVALID_GROUP_ID; + } + + return table[1 + number]; +} + +void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + Trie *pTrie = NULL; + if (type == Override_Command) + { + if (pGroup->pCmdTable == NULL) + { + pGroup->pCmdTable = sm_trie_create(); + } + pTrie = pGroup->pCmdTable; + } else if (type == Override_CommandGroup) { + if (pGroup->pCmdGrpTable == NULL) + { + pGroup->pCmdGrpTable = sm_trie_create(); + } + pTrie = pGroup->pCmdGrpTable; + } else { + return; + } + + sm_trie_insert(pTrie, name, (void *)(int)rule); +} + +bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return false; + } + + Trie *pTrie = NULL; + if (type == Override_Command) + { + if (pGroup->pCmdTable == NULL) + { + return false; + } + pTrie = pGroup->pCmdTable; + } else if (type == Override_CommandGroup) { + if (pGroup->pCmdGrpTable == NULL) + { + return false; + } + pTrie = pGroup->pCmdGrpTable; + } else { + return false; + } + + void *object; + if (!sm_trie_retrieve(pTrie, name, &object)) + { + return false; + } + + if (pRule) + { + *pRule = (OverrideRule)(int)object; + } + + return true; +} + +void AdminCache::InvalidateGroup(GroupId id) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + AdminGroup *pOther; + + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + const char *str = m_pStrings->GetString(pGroup->nameidx); + sm_trie_delete(m_pGroups, str); + + /* Unlink from the live dbllink list */ + if (id == m_FirstGroup && id == m_LastGroup) + { + m_LastGroup = INVALID_GROUP_ID; + m_FirstGroup = INVALID_GROUP_ID; + } else if (id == m_FirstGroup) { + m_FirstGroup = pGroup->next_grp; + pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup); + pOther->prev_grp = INVALID_GROUP_ID; + } else if (id == m_LastGroup) { + m_LastGroup = pGroup->prev_grp; + pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup); + pOther->next_grp = INVALID_GROUP_ID; + } else { + pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp); + pOther->next_grp = pGroup->next_grp; + pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp); + pOther->prev_grp = pGroup->prev_grp; + } + + /* Free any used memory to be safe */ + if (pGroup->pCmdGrpTable) + { + sm_trie_destroy(pGroup->pCmdGrpTable); + pGroup->pCmdGrpTable = NULL; + } + if (pGroup->pCmdTable) + { + sm_trie_destroy(pGroup->pCmdTable); + pGroup->pCmdTable = NULL; + } + + /* Link into the free list */ + pGroup->magic = GRP_MAGIC_UNSET; + pGroup->next_grp = m_FreeGroupList; + m_FreeGroupList = id; + + /* :TODO: remove this group from any users */ +} + +void AdminCache::InvalidateGroupCache() +{ + /* Nuke the free list */ + m_FreeGroupList = -1; + + /* Nuke reverse lookups */ + sm_trie_clear(m_pGroups); + + /* Free memory on groups */ + GroupId cur = m_FirstGroup; + AdminGroup *pGroup; + while (cur != INVALID_GROUP_ID) + { + pGroup = (AdminGroup *)m_pMemory->GetAddress(cur); + assert(pGroup->magic == GRP_MAGIC_SET); + if (pGroup->pCmdGrpTable) + { + sm_trie_destroy(pGroup->pCmdGrpTable); + } + if (pGroup->pCmdTable) + { + sm_trie_destroy(pGroup->pCmdTable); + } + cur = pGroup->next_grp; + } + + m_FirstGroup = INVALID_GROUP_ID; + m_LastGroup = INVALID_GROUP_ID; + + /* :TODO: dump the admin cache */ + + /* Reset the memory table */ + m_pMemory->Reset(); +}