3 #include "AdminCache.h"
5 #include "ForwardSys.h"
9 AdminCache::AdminCache()
11 m_pCmdOverrides = NULL;
12 m_pCmdGrpOverrides = NULL;
13 m_pStrings = new BaseStringTable(1024);
14 m_pMemory = m_pStrings->GetMemTable();
15 m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID;
16 m_pGroups = sm_trie_create();
20 AdminCache::~AdminCache()
22 if (m_pCmdGrpOverrides)
24 sm_trie_destroy(m_pCmdGrpOverrides);
29 sm_trie_destroy(m_pCmdOverrides);
32 InvalidateGroupCache();
36 sm_trie_destroy(m_pGroups);
42 void AdminCache::OnSourceModAllInitialized()
44 m_pCacheFwd = g_Forwards.CreateForward("OnRebuildAdminCache", ET_Ignore, 1, NULL, Param_Cell);
45 g_ShareSys.AddInterface(NULL, this);
48 void AdminCache::OnSourceModShutdown()
50 g_Forwards.ReleaseForward(m_pCacheFwd);
54 void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, AdminFlag flag)
56 if (type == Override_Command)
58 _AddCommandOverride(cmd, flag);
59 } else if (type == Override_CommandGroup) {
60 _AddCommandGroupOverride(cmd, flag);
64 bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, AdminFlag *pFlag)
66 if (type == Override_Command)
68 return _GetCommandOverride(cmd, pFlag);
69 } else if (type == Override_CommandGroup) {
70 return _GetCommandGroupOverride(cmd, pFlag);
76 void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type)
78 if (type == Override_Command)
80 return _UnsetCommandOverride(cmd);
81 } else if (type == Override_CommandGroup) {
82 return _UnsetCommandGroupOverride(cmd);
86 void AdminCache::_AddCommandGroupOverride(const char *group, AdminFlag flag)
88 if (!m_pCmdGrpOverrides)
90 m_pCmdGrpOverrides = sm_trie_create();
93 /* :TODO: Notify command system */
95 sm_trie_insert(m_pCmdGrpOverrides, group, (void *)flag);
98 void AdminCache::_AddCommandOverride(const char *cmd, AdminFlag flag)
100 if (!m_pCmdOverrides)
102 m_pCmdOverrides = sm_trie_create();
105 /* :TODO: Notify command system */
107 sm_trie_insert(m_pCmdOverrides, cmd, (void *)flag);
110 bool AdminCache::_GetCommandGroupOverride(const char *cmd, AdminFlag *pFlag)
112 if (!m_pCmdGrpOverrides)
119 return sm_trie_retrieve(m_pCmdGrpOverrides, cmd, NULL);
123 if (ret=sm_trie_retrieve(m_pCmdGrpOverrides, cmd, &object))
125 *pFlag = (AdminFlag)(int)object;
131 bool AdminCache::_GetCommandOverride(const char *cmd, AdminFlag *pFlag)
133 if (!m_pCmdOverrides)
140 return sm_trie_retrieve(m_pCmdOverrides, cmd, NULL);
144 if (ret=sm_trie_retrieve(m_pCmdOverrides, cmd, &object))
146 *pFlag = (AdminFlag)(int)object;
152 void AdminCache::_UnsetCommandGroupOverride(const char *group)
154 if (!m_pCmdGrpOverrides)
159 /* :TODO: Notify command system */
161 sm_trie_delete(m_pCmdGrpOverrides, group);
164 void AdminCache::_UnsetCommandOverride(const char *cmd)
166 if (!m_pCmdOverrides)
171 /* :TODO: Notify command system */
173 sm_trie_delete(m_pCmdOverrides, cmd);
176 void AdminCache::DumpCommandOverrideCache(OverrideType type)
178 if (type == Override_Command && m_pCmdOverrides)
180 sm_trie_clear(m_pCmdOverrides);
181 } else if (type == Override_CommandGroup && m_pCmdGrpOverrides) {
182 sm_trie_clear(m_pCmdGrpOverrides);
186 GroupId AdminCache::AddGroup(const char *group_name)
188 if (sm_trie_retrieve(m_pGroups, group_name, NULL))
190 return INVALID_GROUP_ID;
195 if (m_FreeGroupList != INVALID_GROUP_ID)
197 pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList);
198 assert(pGroup->magic == GRP_MAGIC_UNSET);
199 id = m_FreeGroupList;
200 m_FreeGroupList = pGroup->next_grp;
202 id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup);
205 pGroup->immune_default = false;
206 pGroup->immune_global = false;
207 pGroup->immune_table = -1;
208 pGroup->magic = GRP_MAGIC_SET;
209 pGroup->next_grp = INVALID_GROUP_ID;
210 pGroup->pCmdGrpTable = NULL;
211 pGroup->pCmdTable = NULL;
212 pGroup->nameidx = m_pStrings->AddString(group_name);
213 memset(pGroup->addflags, 0, sizeof(AdminFlag) * AdminFlags_TOTAL);
215 if (m_FirstGroup == INVALID_GROUP_ID)
219 pGroup->prev_grp = INVALID_GROUP_ID;
221 AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
222 assert(pPrev->magic == GRP_MAGIC_SET);
223 pPrev->next_grp = id;
224 pGroup->prev_grp = m_LastGroup;
228 sm_trie_insert(m_pGroups, group_name, (void *)id);
233 GroupId AdminCache::FindGroupByName(const char *group_name)
237 if (!sm_trie_retrieve(m_pGroups, group_name, &object))
239 return INVALID_GROUP_ID;
242 GroupId id = (GroupId)object;
243 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
245 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
247 return INVALID_GROUP_ID;
253 void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled)
255 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
256 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
261 if (flag < Admin_None || flag >= AdminFlags_TOTAL)
266 pGroup->addflags[flag] = enabled;
269 bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag)
271 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
272 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
277 if (flag < Admin_None || flag >= AdminFlags_TOTAL)
282 return pGroup->addflags[flag];
285 unsigned int AdminCache::GetGroupAddFlagBits(GroupId id, bool flags[], unsigned int total)
287 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
288 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
296 i < AdminFlags_TOTAL && i < total;
299 flags[i] = pGroup->addflags[i];
305 void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled)
307 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
308 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
313 if (type == Immunity_Default)
315 pGroup->immune_default = enabled;
316 } else if (type == Immunity_Global) {
317 pGroup->immune_global = enabled;
321 bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type)
323 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
324 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
329 if (type == Immunity_Default)
331 return pGroup->immune_default;
332 } else if (type == Immunity_Global) {
333 return pGroup->immune_global;
339 void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id)
341 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
342 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
347 AdminGroup *pOther = (AdminGroup *)m_pMemory->GetAddress(id);
348 if (!pOther || pOther->magic != GRP_MAGIC_SET)
353 /* We always need to resize the immunity table */
355 if (pOther->immune_table == -1)
357 tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table);
360 int *old_table = (int *)m_pMemory->GetAddress(pOther->immune_table);
361 tblidx = m_pMemory->CreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table);
362 /* Get the old address again in caes of resize */
363 old_table = (int *)m_pMemory->GetAddress(pOther->immune_table);
364 table[0] = old_table[0];
365 for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++)
367 table[i] = old_table[i];
372 pOther->immune_table = tblidx;
374 /* Add to the array */
376 table[table[0]] = other_id;
379 unsigned int AdminCache::GetGroupImmunityCount(GroupId id)
381 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
382 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
387 if (pGroup->immune_table == -1)
392 int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
397 GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number)
399 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
400 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
402 return INVALID_GROUP_ID;
405 if (pGroup->immune_table == -1)
407 return INVALID_GROUP_ID;
410 int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
411 if (number >= (unsigned int)table[0])
413 return INVALID_GROUP_ID;
416 return table[1 + number];
419 void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule)
421 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
422 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
428 if (type == Override_Command)
430 if (pGroup->pCmdTable == NULL)
432 pGroup->pCmdTable = sm_trie_create();
434 pTrie = pGroup->pCmdTable;
435 } else if (type == Override_CommandGroup) {
436 if (pGroup->pCmdGrpTable == NULL)
438 pGroup->pCmdGrpTable = sm_trie_create();
440 pTrie = pGroup->pCmdGrpTable;
445 sm_trie_insert(pTrie, name, (void *)(int)rule);
448 bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule)
450 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
451 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
457 if (type == Override_Command)
459 if (pGroup->pCmdTable == NULL)
463 pTrie = pGroup->pCmdTable;
464 } else if (type == Override_CommandGroup) {
465 if (pGroup->pCmdGrpTable == NULL)
469 pTrie = pGroup->pCmdGrpTable;
475 if (!sm_trie_retrieve(pTrie, name, &object))
482 *pRule = (OverrideRule)(int)object;
488 void AdminCache::InvalidateGroup(GroupId id)
490 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
493 if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
498 const char *str = m_pStrings->GetString(pGroup->nameidx);
499 sm_trie_delete(m_pGroups, str);
501 /* Unlink from the live dbllink list */
502 if (id == m_FirstGroup && id == m_LastGroup)
504 m_LastGroup = INVALID_GROUP_ID;
505 m_FirstGroup = INVALID_GROUP_ID;
506 } else if (id == m_FirstGroup) {
507 m_FirstGroup = pGroup->next_grp;
508 pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup);
509 pOther->prev_grp = INVALID_GROUP_ID;
510 } else if (id == m_LastGroup) {
511 m_LastGroup = pGroup->prev_grp;
512 pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
513 pOther->next_grp = INVALID_GROUP_ID;
515 pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp);
516 pOther->next_grp = pGroup->next_grp;
517 pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp);
518 pOther->prev_grp = pGroup->prev_grp;
521 /* Free any used memory to be safe */
522 if (pGroup->pCmdGrpTable)
524 sm_trie_destroy(pGroup->pCmdGrpTable);
525 pGroup->pCmdGrpTable = NULL;
527 if (pGroup->pCmdTable)
529 sm_trie_destroy(pGroup->pCmdTable);
530 pGroup->pCmdTable = NULL;
533 /* Link into the free list */
534 pGroup->magic = GRP_MAGIC_UNSET;
535 pGroup->next_grp = m_FreeGroupList;
536 m_FreeGroupList = id;
538 /* :TODO: remove this group from any users */
541 void AdminCache::InvalidateGroupCache()
543 /* Nuke the free list */
544 m_FreeGroupList = -1;
546 /* Nuke reverse lookups */
547 sm_trie_clear(m_pGroups);
549 /* Free memory on groups */
550 GroupId cur = m_FirstGroup;
552 while (cur != INVALID_GROUP_ID)
554 pGroup = (AdminGroup *)m_pMemory->GetAddress(cur);
555 assert(pGroup->magic == GRP_MAGIC_SET);
556 if (pGroup->pCmdGrpTable)
558 sm_trie_destroy(pGroup->pCmdGrpTable);
560 if (pGroup->pCmdTable)
562 sm_trie_destroy(pGroup->pCmdTable);
564 cur = pGroup->next_grp;
567 m_FirstGroup = INVALID_GROUP_ID;
568 m_LastGroup = INVALID_GROUP_ID;
570 /* :TODO: dump the admin cache */
572 /* Reset the memory table */
576 void AdminCache::AddAdminListener(IAdminListener *pListener)
578 m_hooks.push_back(pListener);
581 void AdminCache::RemoveAdminListener(IAdminListener *pListener)
583 m_hooks.remove(pListener);
586 void AdminCache::DumpAdminCache(int cache_flags, bool rebuild)
588 if (cache_flags & ADMIN_CACHE_OVERRIDES)
590 DumpCommandOverrideCache(Override_Command);
591 DumpCommandOverrideCache(Override_CommandGroup);
594 if ((cache_flags & ADMIN_CACHE_ADMINS) ||
595 (cache_flags & ADMIN_CACHE_GROUPS))
597 /* Make sure the flag is set */
598 cache_flags |= ADMIN_CACHE_ADMINS;
599 /* :TODO: Dump admin cache */
602 if (cache_flags & ADMIN_CACHE_GROUPS)
604 InvalidateGroupCache();
609 List<IAdminListener *>::iterator iter;
610 IAdminListener *pListener;
611 for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
614 pListener->OnRebuildAdminCache(cache_flags);