VATTR *vattr_next( VATTR *vp ) { if( vp == NULL ) { return ( vattr_first() ); } return ( ( VATTR * ) hash_nextentry( &mudstate.vattr_name_htab ) ); }
/** Return a list of all available locks * \param buff the buffer * \param bp a pointer to the current position in the buffer. * \param name if not NULL, only show locks with this prefix */ void list_locks(char *buff, char **bp, const char *name) { lock_list **locks, *lk; bool first = 1; int nlocks = 0, n; locks = mush_calloc(htab_locks.entries, sizeof(lock_list), "lock.list"); for (lk = hash_firstentry(&htab_locks); lk; lk = hash_nextentry(&htab_locks)) { /* Skip those that don't match */ if (name && !string_prefix(lk->type, name)) continue; locks[nlocks++] = lk; } qsort(locks, nlocks, sizeof lk, lock_compare); for (n = 0; n < nlocks; n += 1) { if (first) { first = 0; } else { safe_chr(' ', buff, bp); } safe_str(strupper(locks[n]->type), buff, bp); } mush_free(locks, "lock.list"); }
/** Rebuild a single help file index. Used in inotify reindexing. * \param filename the name of the help file to reindex. * \return true if a help file was reindexed, false otherwise. */ bool help_reindex_by_name(const char *filename) { help_file *curr; bool retval = 0; for (curr = hash_firstentry(&help_files); curr; curr = hash_nextentry(&help_files)) { if (strcmp(curr->file, filename) == 0) { if (curr->indx) mush_free(curr->indx, "help_index"); curr->indx = NULL; curr->entries = 0; help_build_index(curr, curr->admin); retval = 1; } } return retval; }
/** Rebuild a help file index. * \verbatim * This command implements @readcache. * \endverbatim * \param player the enactor. */ void help_reindex(dbref player) { help_file *curr; for (curr = hash_firstentry(&help_files); curr; curr = hash_nextentry(&help_files)) { if (curr->indx) { mush_free(curr->indx, "help_index"); curr->indx = NULL; curr->entries = 0; } help_build_index(curr, curr->admin); } if (player != NOTHING) { notify(player, T("Help files reindexed.")); do_rawlog(LT_WIZ, "Help files reindexed by %s(#%d)", Name(player), player); } else do_rawlog(LT_WIZ, "Help files reindexed."); }
static void ReportMatchedTopics(dbref executor, const UTF8 *topic, CHashTable *htab) { bool matched = false; UTF8 *topic_list = NULL; UTF8 *buffp = NULL; struct help_entry *htab_entry; for (htab_entry = (struct help_entry *)hash_firstentry(htab); htab_entry != NULL; htab_entry = (struct help_entry *)hash_nextentry(htab)) { mudstate.wild_invk_ctr = 0; if ( htab_entry->key && quick_wild(topic, htab_entry->key)) { if (!matched) { matched = true; topic_list = alloc_lbuf("help_write"); buffp = topic_list; } safe_str(htab_entry->key, topic_list, &buffp); safe_chr(' ', topic_list, &buffp); safe_chr(' ', topic_list, &buffp); } } if (!matched) { notify(executor, tprintf(T("No entry for \xE2\x80\x98%s\xE2\x80\x99."), topic)); } else { notify(executor, tprintf(T("Here are the entries which match \xE2\x80\x98%s\xE2\x80\x99:"), topic)); *buffp = '\0'; notify(executor, topic_list); free_lbuf(topic_list); } }
void helpindex_clean(int iHelpfile) { CHashTable *htab = mudstate.aHelpDesc[iHelpfile].ht; if (NULL == htab) { return; } struct help_entry *htab_entry; for (htab_entry = (struct help_entry *)hash_firstentry(htab); htab_entry; htab_entry = (struct help_entry *)hash_nextentry(htab)) { if (htab_entry->key) { MEMFREE(htab_entry->key); htab_entry->key = NULL; } delete htab_entry; htab_entry = NULL; } delete mudstate.aHelpDesc[iHelpfile].ht; mudstate.aHelpDesc[iHelpfile].ht = NULL; }
void do_dbclean( dbref player, dbref cause, int key ) { VATTR *vp, *vpx; dbref i, end; int ca, n_oldtotal, n_oldtop, n_deleted, n_renumbered, n_objt, n_atrt, got; char *as, *str; int *used_table; ATTR **new_table; UFUN *ufp; CMDENT *cmdp; ADDENT *addp; raw_broadcast( 0, "GAME: Cleaning database. Game may freeze for a few minutes." ); used_table = ( int * ) XCALLOC( mudstate.attr_next, sizeof( int ), "dbclean.used_table" ); n_oldtotal = mudstate.attr_next; n_oldtop = anum_alc_top; n_deleted = n_renumbered = n_objt = n_atrt = 0; /* * Non-user-defined attributes are always considered used. */ for( i = 0; i < A_USER_START; i++ ) { used_table[i] = i; } /* * Walk the database. Mark all the attribute numbers in use. */ atr_push(); DO_WHOLE_DB( i ) { for( ca = atr_head( i, &as ); ca; ca = atr_next( &as ) ) { used_table[ca] = ca; } } atr_pop(); /* * Walk the vattr table. If a number isn't in use, zorch it. */ vp = vattr_first(); while( vp ) { vpx = vp; vp = vattr_next( vp ); if( used_table[vpx->number] == 0 ) { anum_set( vpx->number, NULL ); hashdelete( vpx->name, &mudstate.vattr_name_htab ); XFREE( vpx, "dbclean.vpx" ); n_deleted++; } } /* * The user-defined function, added command, and hook structures embed * * attribute numbers. Clean out the ones we've deleted, resetting them * * to the *Invalid (A_TEMP) attr. */ for( ufp = ( UFUN * ) hash_firstentry( &mudstate.ufunc_htab ); ufp != NULL; ufp = ( UFUN * ) hash_nextentry( &mudstate.ufunc_htab ) ) { if( used_table[ufp->atr] == 0 ) { ufp->atr = A_TEMP; } } for( cmdp = ( CMDENT * ) hash_firstentry( &mudstate.command_htab ); cmdp != NULL; cmdp = ( CMDENT * ) hash_nextentry( &mudstate.command_htab ) ) { if( cmdp->pre_hook ) { if( used_table[cmdp->pre_hook->atr] == 0 ) { cmdp->pre_hook->atr = A_TEMP; } } if( cmdp->post_hook ) { if( used_table[cmdp->post_hook->atr] == 0 ) { cmdp->post_hook->atr = A_TEMP; } } if( cmdp->userperms ) { if( used_table[cmdp->userperms->atr] == 0 ) { cmdp->userperms->atr = A_TEMP; } } if( cmdp->callseq & CS_ADDED ) { for( addp = ( ADDENT * ) cmdp->info.added; addp != NULL; addp = addp->next ) { if( used_table[addp->atr] == 0 ) { addp->atr = A_TEMP; } } } } /* * Walk the table we've created of used statuses. When we find free * * slots, walk backwards to the first used slot at the end of the * * table. Write the number of the free slot into that used slot. */ for( i = A_USER_START, end = mudstate.attr_next - 1; ( i < mudstate.attr_next ) && ( i < end ); i++ ) { if( used_table[i] == 0 ) { while( ( end > i ) && ( used_table[end] == 0 ) ) { end--; } if( end > i ) { used_table[end] = used_table[i] = i; end--; } } } /* * Renumber the necessary attributes in the vattr tables. */ for( i = A_USER_START; i < mudstate.attr_next; i++ ) { if( used_table[i] != i ) { vp = ( VATTR * ) anum_get( i ); if( vp ) { vp->number = used_table[i]; vp->flags |= AF_DIRTY; anum_set( used_table[i], ( ATTR * ) vp ); anum_set( i, NULL ); n_renumbered++; } } } /* * Now we walk the database. For every object, if we have an attribute * * we're renumbering (the slot number is not equal to the array value * * at that slot), we delete the old attribute and add the new one. */ atr_push(); DO_WHOLE_DB( i ) { got = 0; for( ca = atr_head( i, &as ); ca; ca = atr_next( &as ) ) { if( used_table[ca] != ca ) { str = atr_get_raw( i, ca ); atr_add_raw( i, used_table[ca], str ); atr_clr( i, ca ); n_atrt++; got = 1; } } if( got ) { n_objt++; } } atr_pop(); /* * The new end of the attribute table is the first thing we've * * renumbered. */ for( end = A_USER_START; ( ( end == used_table[end] ) && ( end < mudstate.attr_next ) ); end++ ); mudstate.attr_next = end; /* * We might be able to shrink the size of the attribute table. * * If the current size of the table is less than the initial * * size, shrink it back down to the initial size. * * Otherwise, shrink it down so it's the current top plus the * * initial size, as if we'd just called anum_extend() for it. */ if( anum_alc_top > mudconf.init_size + A_USER_START ) { if( mudstate.attr_next < mudconf.init_size + A_USER_START ) { end = mudconf.init_size + A_USER_START; } else { end = mudstate.attr_next + mudconf.init_size; } if( end < anum_alc_top ) { new_table = ( ATTR ** ) XCALLOC( end + 1, sizeof( ATTR * ), "dbclean.new_table" ); for( i = 0; i < mudstate.attr_next; i++ ) { new_table[i] = anum_table[i]; } XFREE( anum_table, "dbclean.anum_table" ); anum_table = new_table; anum_alc_top = end; } } /* * Go through the function and added command tables again, and * * take care of the attributes that got renumbered. */ for( ufp = ( UFUN * ) hash_firstentry( &mudstate.ufunc_htab ); ufp != NULL; ufp = ( UFUN * ) hash_nextentry( &mudstate.ufunc_htab ) ) { if( used_table[ufp->atr] != ufp->atr ) { ufp->atr = used_table[ufp->atr]; } } for( cmdp = ( CMDENT * ) hash_firstentry( &mudstate.command_htab ); cmdp != NULL; cmdp = ( CMDENT * ) hash_nextentry( &mudstate.command_htab ) ) { if( cmdp->pre_hook ) { if( used_table[cmdp->pre_hook->atr] != cmdp->pre_hook->atr ) cmdp->pre_hook->atr = used_table[cmdp->pre_hook->atr]; } if( cmdp->post_hook ) { if( used_table[cmdp->post_hook->atr] != cmdp->post_hook->atr ) cmdp->post_hook->atr = used_table[cmdp->post_hook->atr]; } if( cmdp->userperms ) { if( used_table[cmdp->userperms->atr] != cmdp->userperms->atr ) cmdp->userperms->atr = used_table[cmdp->userperms->atr]; } if( cmdp->callseq & CS_ADDED ) { for( addp = ( ADDENT * ) cmdp->info.added; addp != NULL; addp = addp->next ) { if( used_table[addp->atr] != addp->atr ) { addp->atr = used_table[addp->atr]; } } } } /* * Clean up. */ XFREE( used_table, "dbclean.used_table" ); if( anum_alc_top != n_oldtop ) { notify_check( player, player, MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN, "Cleaned %d user attribute slots (reduced to %d): %d deleted, %d renumbered (%d objects and %d individual attrs touched). Table size reduced from %d to %d.", n_oldtotal - A_USER_START, mudstate.attr_next - A_USER_START, n_deleted, n_renumbered, n_objt, n_atrt, n_oldtop, anum_alc_top ); } else { notify_check( player, player, MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN, "Cleaned %d attributes (now %d): %d deleted, %d renumbered (%d objects and %d individual attrs touched).", n_oldtotal, mudstate.attr_next, n_deleted, n_renumbered, n_objt, n_atrt ); } raw_broadcast( 0, "GAME: Database cleaning complete." ); }