Super performance improvement to groups system, caching permissions levels and atcommand permissions saving thousands of thousands of dbmap lookups.
git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16443 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
5f33bf4bd9
commit
ae40bf0ec7
@ -60,6 +60,8 @@ typedef struct AliasInfo AliasInfo;
|
|||||||
struct AtCommandInfo {
|
struct AtCommandInfo {
|
||||||
char command[ATCOMMAND_LENGTH];
|
char command[ATCOMMAND_LENGTH];
|
||||||
AtCommandFunc func;
|
AtCommandFunc func;
|
||||||
|
char* at_groups;/* quick @commands "can-use" lookup */
|
||||||
|
char* char_groups;/* quick @charcommands "can-use" lookup */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AliasInfo {
|
struct AliasInfo {
|
||||||
@ -8393,8 +8395,19 @@ static void atcommand_commands_sub(struct map_session_data* sd, const int fd, At
|
|||||||
for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) {
|
for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) {
|
||||||
unsigned int slen = 0;
|
unsigned int slen = 0;
|
||||||
|
|
||||||
if (!pc_can_use_command(sd, cmd->command, type))
|
switch( type ) {
|
||||||
continue;
|
case COMMAND_CHARCOMMAND:
|
||||||
|
if( cmd->char_groups[sd->group_pos] == 0 )
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case COMMAND_ATCOMMAND:
|
||||||
|
if( cmd->at_groups[sd->group_pos] == 0 )
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
slen = strlen(cmd->command);
|
slen = strlen(cmd->command);
|
||||||
|
|
||||||
@ -8583,8 +8596,8 @@ ACMD_FUNC(set) {
|
|||||||
/**
|
/**
|
||||||
* Fills the reference of available commands in atcommand DBMap
|
* Fills the reference of available commands in atcommand DBMap
|
||||||
**/
|
**/
|
||||||
#define ACMD_DEF(x) { #x, atcommand_ ## x }
|
#define ACMD_DEF(x) { #x, atcommand_ ## x, NULL, NULL }
|
||||||
#define ACMD_DEF2(x2, x) { x2, atcommand_ ## x }
|
#define ACMD_DEF2(x2, x) { x2, atcommand_ ## x, NULL, NULL }
|
||||||
void atcommand_basecommands(void) {
|
void atcommand_basecommands(void) {
|
||||||
/**
|
/**
|
||||||
* Command reference list, place the base of your commands here
|
* Command reference list, place the base of your commands here
|
||||||
@ -9039,8 +9052,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
|
|||||||
|
|
||||||
//Grab the command information and check for the proper GM level required to use it or if the command exists
|
//Grab the command information and check for the proper GM level required to use it or if the command exists
|
||||||
info = get_atcommandinfo_byname(atcommand_checkalias(command + 1));
|
info = get_atcommandinfo_byname(atcommand_checkalias(command + 1));
|
||||||
if (info == NULL)
|
if (info == NULL) {
|
||||||
{
|
|
||||||
if( pc_get_group_level(sd) ) { // TODO: remove or replace with proper permission
|
if( pc_get_group_level(sd) ) { // TODO: remove or replace with proper permission
|
||||||
sprintf(output, msg_txt(153), command); // "%s is Unknown Command."
|
sprintf(output, msg_txt(153), command); // "%s is Unknown Command."
|
||||||
clif_displaymessage(fd, output);
|
clif_displaymessage(fd, output);
|
||||||
@ -9052,8 +9064,8 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
|
|||||||
|
|
||||||
// type == 1 : player invoked
|
// type == 1 : player invoked
|
||||||
if (type == 1) {
|
if (type == 1) {
|
||||||
if ((*command == atcommand_symbol && !pc_can_use_command(sd, atcommand_checkalias(command + 1), COMMAND_ATCOMMAND)) ||
|
if ((*command == atcommand_symbol && info->at_groups[sd->group_pos] == 0) ||
|
||||||
(*command == charcommand_symbol && !pc_can_use_command(sd, atcommand_checkalias(command + 1), COMMAND_CHARCOMMAND))) {
|
(*command == charcommand_symbol && info->char_groups[sd->group_pos] == 0) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9175,17 +9187,50 @@ static void atcommand_config_read(const char* config_filename)
|
|||||||
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' command aliases in '"CL_WHITE"%s"CL_RESET"'.\n", num_aliases, config_filename);
|
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' command aliases in '"CL_WHITE"%s"CL_RESET"'.\n", num_aliases, config_filename);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
void atcommand_db_load_groups(int* group_ids) {
|
||||||
|
DBIterator *iter = db_iterator(atcommand_db);
|
||||||
|
AtCommandInfo* cmd;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) {
|
||||||
|
cmd->at_groups = aMalloc( pc_group_max * sizeof(char) );
|
||||||
|
cmd->char_groups = aMalloc( pc_group_max * sizeof(char) );
|
||||||
|
for(i = 0; i < pc_group_max; i++) {
|
||||||
|
if( pc_group_can_use_command(group_ids[i], cmd->command, COMMAND_ATCOMMAND ) )
|
||||||
|
cmd->at_groups[i] = 1;
|
||||||
|
else
|
||||||
|
cmd->at_groups[i] = 0;
|
||||||
|
if( pc_group_can_use_command(group_ids[i], cmd->command, COMMAND_CHARCOMMAND ) )
|
||||||
|
cmd->char_groups[i] = 1;
|
||||||
|
else
|
||||||
|
cmd->char_groups[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbi_destroy(iter);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void atcommand_db_clear(void) {
|
||||||
|
|
||||||
|
if (atcommand_db != NULL) {
|
||||||
|
DBIterator *iter = db_iterator(atcommand_db);
|
||||||
|
AtCommandInfo* cmd;
|
||||||
|
|
||||||
|
for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) {
|
||||||
|
aFree(cmd->at_groups);
|
||||||
|
aFree(cmd->char_groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbi_destroy(iter);
|
||||||
|
|
||||||
void atcommand_db_clear(void)
|
|
||||||
{
|
|
||||||
if (atcommand_db != NULL)
|
|
||||||
db_destroy(atcommand_db);
|
db_destroy(atcommand_db);
|
||||||
|
}
|
||||||
if (atcommand_alias_db != NULL)
|
if (atcommand_alias_db != NULL)
|
||||||
db_destroy(atcommand_alias_db);
|
db_destroy(atcommand_alias_db);
|
||||||
}
|
}
|
||||||
|
|
||||||
void atcommand_doload(void)
|
void atcommand_doload(void) {
|
||||||
{
|
|
||||||
atcommand_db_clear();
|
atcommand_db_clear();
|
||||||
atcommand_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH);
|
atcommand_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH);
|
||||||
atcommand_alias_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH);
|
atcommand_alias_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH);
|
||||||
@ -9193,12 +9238,10 @@ void atcommand_doload(void)
|
|||||||
atcommand_config_read(ATCOMMAND_CONF_FILENAME);
|
atcommand_config_read(ATCOMMAND_CONF_FILENAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_init_atcommand(void)
|
void do_init_atcommand(void) {
|
||||||
{
|
|
||||||
atcommand_doload();
|
atcommand_doload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_final_atcommand(void)
|
void do_final_atcommand(void) {
|
||||||
{
|
|
||||||
atcommand_db_clear();
|
atcommand_db_clear();
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
|
|||||||
|
|
||||||
void do_init_atcommand(void);
|
void do_init_atcommand(void);
|
||||||
void do_final_atcommand(void);
|
void do_final_atcommand(void);
|
||||||
|
void atcommand_db_load_groups(int* group_ids);
|
||||||
|
|
||||||
bool atcommand_exists(const char* name);
|
bool atcommand_exists(const char* name);
|
||||||
|
|
||||||
|
16
src/map/pc.c
16
src/map/pc.c
@ -101,7 +101,7 @@ inline int pc_get_group_id(struct map_session_data *sd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline int pc_get_group_level(struct map_session_data *sd) {
|
inline int pc_get_group_level(struct map_session_data *sd) {
|
||||||
return pc_group_id2level(pc_get_group_id(sd));
|
return sd->group_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data)
|
static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||||
@ -922,6 +922,10 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
|
|||||||
|
|
||||||
sd->login_id2 = login_id2;
|
sd->login_id2 = login_id2;
|
||||||
sd->group_id = group_id;
|
sd->group_id = group_id;
|
||||||
|
|
||||||
|
/* load user permissions */
|
||||||
|
pc_group_pc_load(sd);
|
||||||
|
|
||||||
memcpy(&sd->status, st, sizeof(*st));
|
memcpy(&sd->status, st, sizeof(*st));
|
||||||
|
|
||||||
if (st->sex != sd->status.sex) {
|
if (st->sex != sd->status.sex) {
|
||||||
@ -8625,16 +8629,6 @@ bool pc_can_use_command(struct map_session_data *sd, const char *command, AtComm
|
|||||||
return pc_group_can_use_command(pc_get_group_id(sd), command, type);
|
return pc_group_can_use_command(pc_get_group_id(sd), command, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if player has a permission
|
|
||||||
* @param sd Player map session data
|
|
||||||
* @param permission permission to check
|
|
||||||
*/
|
|
||||||
bool pc_has_permission(struct map_session_data *sd, int permission)
|
|
||||||
{
|
|
||||||
return pc_group_has_permission(pc_get_group_id(sd), permission);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if commands used by a player should be logged
|
* Checks if commands used by a player should be logged
|
||||||
* according to their group setting.
|
* according to their group setting.
|
||||||
|
@ -158,7 +158,8 @@ struct map_session_data {
|
|||||||
} special_state;
|
} special_state;
|
||||||
int login_id1, login_id2;
|
int login_id1, login_id2;
|
||||||
unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex]
|
unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex]
|
||||||
int group_id;
|
int group_id, group_pos, group_level;
|
||||||
|
unsigned int permissions;/* group permissions */
|
||||||
|
|
||||||
int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18
|
int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18
|
||||||
struct mmo_charstatus status;
|
struct mmo_charstatus status;
|
||||||
@ -669,7 +670,7 @@ int pc_getrefinebonus(int lv,int type);
|
|||||||
bool pc_can_give_items(struct map_session_data *sd);
|
bool pc_can_give_items(struct map_session_data *sd);
|
||||||
|
|
||||||
bool pc_can_use_command(struct map_session_data *sd, const char *command, AtCommandType type);
|
bool pc_can_use_command(struct map_session_data *sd, const char *command, AtCommandType type);
|
||||||
bool pc_has_permission(struct map_session_data *sd, int permission);
|
#define pc_has_permission(sd, permission) ( ((sd)->permissions&permission) != 0 )
|
||||||
bool pc_should_log_commands(struct map_session_data *sd);
|
bool pc_should_log_commands(struct map_session_data *sd);
|
||||||
|
|
||||||
int pc_setrestartvalue(struct map_session_data *sd,int type);
|
int pc_setrestartvalue(struct map_session_data *sd,int type);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "../common/nullpo.h"
|
#include "../common/nullpo.h"
|
||||||
#include "../common/showmsg.h"
|
#include "../common/showmsg.h"
|
||||||
#include "../common/strlib.h" // strcmp
|
#include "../common/strlib.h" // strcmp
|
||||||
|
#include "../common/socket.h"
|
||||||
|
|
||||||
#include "atcommand.h" // AtCommandType
|
#include "atcommand.h" // AtCommandType
|
||||||
#include "pc_groups.h"
|
#include "pc_groups.h"
|
||||||
@ -28,8 +29,10 @@ struct GroupSettings {
|
|||||||
config_setting_t *inherit; // groups.[].inherit
|
config_setting_t *inherit; // groups.[].inherit
|
||||||
bool inheritance_done; // have all inheritance rules been evaluated?
|
bool inheritance_done; // have all inheritance rules been evaluated?
|
||||||
config_setting_t *root; // groups.[]
|
config_setting_t *root; // groups.[]
|
||||||
|
int group_pos;/* pos on load */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int pc_group_max; /* known number of groups */
|
||||||
|
|
||||||
static config_t pc_group_config;
|
static config_t pc_group_config;
|
||||||
static DBMap* pc_group_db; // id -> GroupSettings
|
static DBMap* pc_group_db; // id -> GroupSettings
|
||||||
@ -153,6 +156,7 @@ static void read_config(void)
|
|||||||
group_settings->permissions = config_setting_get_member(group, "permissions");
|
group_settings->permissions = config_setting_get_member(group, "permissions");
|
||||||
group_settings->inheritance_done = false;
|
group_settings->inheritance_done = false;
|
||||||
group_settings->root = group;
|
group_settings->root = group;
|
||||||
|
group_settings->group_pos = i;
|
||||||
|
|
||||||
strdb_put(pc_groupname_db, groupname, group_settings);
|
strdb_put(pc_groupname_db, groupname, group_settings);
|
||||||
idb_put(pc_group_db, id, group_settings);
|
idb_put(pc_group_db, id, group_settings);
|
||||||
@ -292,6 +296,23 @@ static void read_config(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' groups in '"CL_WHITE"%s"CL_RESET"'.\n", group_count, config_filename);
|
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' groups in '"CL_WHITE"%s"CL_RESET"'.\n", group_count, config_filename);
|
||||||
|
|
||||||
|
|
||||||
|
if( ( pc_group_max = group_count ) ) {
|
||||||
|
DBIterator *iter = db_iterator(pc_group_db);
|
||||||
|
GroupSettings *group_settings = NULL;
|
||||||
|
int* group_ids = aMalloc( pc_group_max * sizeof(int) );
|
||||||
|
int i = 0;
|
||||||
|
for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
|
||||||
|
group_ids[i++] = group_settings->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
atcommand_db_load_groups(group_ids);
|
||||||
|
|
||||||
|
aFree(group_ids);
|
||||||
|
|
||||||
|
dbi_destroy(iter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -346,7 +367,20 @@ bool pc_group_can_use_command(int group_id, const char *command, AtCommandType t
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
void pc_group_pc_load(struct map_session_data * sd) {
|
||||||
|
GroupSettings *group = NULL;
|
||||||
|
if ((group = id2group(sd->group_id)) == NULL) {
|
||||||
|
ShowWarning("pc_group_pc_load: %s (AID:%d) logged in with unknown group id (%d)! kicking...\n",
|
||||||
|
sd->status.name,
|
||||||
|
sd->status.account_id,
|
||||||
|
sd->group_id);
|
||||||
|
set_eof(sd->fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sd->permissions = group->e_permissions;
|
||||||
|
sd->group_pos = group->group_pos;
|
||||||
|
sd->group_level = group->level;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Checks if player group has a permission
|
* Checks if player group has a permission
|
||||||
* @param group_id ID of the group
|
* @param group_id ID of the group
|
||||||
@ -439,8 +473,19 @@ void do_final_pc_groups(void)
|
|||||||
* Used in @reloadatcommand
|
* Used in @reloadatcommand
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
void pc_groups_reload(void)
|
void pc_groups_reload(void) {
|
||||||
{
|
struct map_session_data* sd = NULL;
|
||||||
|
struct s_mapiterator* iter = NULL;
|
||||||
|
|
||||||
do_final_pc_groups();
|
do_final_pc_groups();
|
||||||
do_init_pc_groups();
|
do_init_pc_groups();
|
||||||
|
|
||||||
|
/* refresh online users permissions */
|
||||||
|
iter = mapit_getallusers();
|
||||||
|
for (sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) {
|
||||||
|
pc_group_pc_load(sd);
|
||||||
|
}
|
||||||
|
mapit_free(iter);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,15 @@
|
|||||||
|
|
||||||
#include "atcommand.h" // AtCommandType
|
#include "atcommand.h" // AtCommandType
|
||||||
|
|
||||||
|
extern int pc_group_max;
|
||||||
|
|
||||||
bool pc_group_exists(int group_id);
|
bool pc_group_exists(int group_id);
|
||||||
bool pc_group_can_use_command(int group_id, const char *command, AtCommandType type);
|
bool pc_group_can_use_command(int group_id, const char *command, AtCommandType type);
|
||||||
bool pc_group_has_permission(int group_id, int permission);
|
bool pc_group_has_permission(int group_id, int permission);
|
||||||
bool pc_group_should_log_commands(int group_id);
|
bool pc_group_should_log_commands(int group_id);
|
||||||
const char* pc_group_id2name(int group_id);
|
const char* pc_group_id2name(int group_id);
|
||||||
int pc_group_id2level(int group_id);
|
int pc_group_id2level(int group_id);
|
||||||
|
void pc_group_pc_load(struct map_session_data *);
|
||||||
|
|
||||||
void do_init_pc_groups(void);
|
void do_init_pc_groups(void);
|
||||||
void do_final_pc_groups(void);
|
void do_final_pc_groups(void);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user