Skip to forum content

You are not logged in. Please login or register.


forums.pvpgn.pro → [RU] Tech Support → [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Pages 1

You must login or register to post a reply

RSS topic feed

Posts: 36

1 (edited by iltmpz 24.11.2014 19:48)

Topic: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Приветствую всех!

У меня есть pvpgn-сервер с базой на mysql. Примерно 50-70 игроков постоянно онлайн, в базе больше 100000 аккаунтов (надо будет почистить 70-80%, но объемы примерно такие).

Есть задача управления этими аккаунтами: как ручного, так и автоматизированного.
Наиболее простым способом автоматизированного управления я вижу прямое редактирование базы sql-запросами.
А управление аккаунтами вручную удобнее всего через /set аккаунт параметр.

Однако и с той, и с другой стороны имеет место следующая проблема: я меняю данные в базе, а pvpgn об этом не знает. Мало того, что данные у игрока не обновляются, они еще и перезаписывают значение, выставленное мной в базе. Конечно не каждый раз - как повезет - смотря по тому, что сервер будет делать раньше, чтение или запись в базу.
В другую сторону: поменял данные у игрока через /set, изменения в базе не отразились по прошествии даже нескольких часов, несмотря на то, что он входил-выходил несколько раз.

Думаю, такое поведение характерно больше для аккаунтов, которые недавно проявляли активность и закэшировались на сервере, но ведь именно ими хотелось бы в первую очередь управлять.

В идеале хотелось бы поменять в базе несколько аккаунтов, после чего как-то заставить сервер перечитать данные из базы именно по ним. Ну или точно так же записать в базу данные по нескольким указанным мной аккаунтам.

Остановка и перезапуск для этих целей в моем случае неприемлем: сервер работает месяцами без остановок.
Если нет готовых решений для моей задачи, готов был взяться за дописывание небольшого куска кода, с этим проблем нет.
Но было бы здорово сначала узнать, какие есть варианты или куда лезть, потому что о внутреннем устройстве pvpgn я имею весьма смутное представление...

2

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

У PvPGN односторонняя синхронизация с сервера к бд, поэтому иногда и происходит затирание данных. При запущенном сервере лучше не менять данные в бд напрямую.

Алгоритм следующий:
1. Настройки юзера грузятся из бд в кеш (память) при попытке их чтения/записи.
2. Каждые "usersync" секунд кеш проверяется и, в случае изменений, они перезаписываются в бд.
3. Если кеш юзера не использовался на чтение/запись в течение "userflush" секунд, то он удаляется.
Далее по кругу.

usersync и userflush настраиваются в конфиге bnetd.conf


Если автоматизировать, то лучше через бота, который будет логиниться на сервер и выполнять /set команды (есть бот на php).
Чтобы бот мог соединиться с сервером, у аккаунта должен быть auth_botlogin=true

Do not ask for support in PM.

3

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Большое спасибо за обстоятельный ответ!

HarpyWar wrote:

1. Настройки юзера грузятся из бд в кеш при попытке чтения/записи.
2. Каждые "usersync" секунд кеш проверяется и, в случае изменений, они сбрасываются в бд.
3. Если кеш юзера не использовался на чтение/запись в течение "userflush" секунд, то он удаляется.
Далее по кругу.

Примерно понял, а при выходе пользователя кэш (если изменился) принудительно записывается в базу сразу если выставлен параметр sync_on_logoff? А если не выставлен, то так же по прошествии usersync секунд?

Еще вопрос вдогонку:
А в каких случаях используется кэш юзера? Последняя активность юзера, которую можно увидеть через /finger это последнее использование кэша или если другой юзер запросит данные об этом, к его кэшу тоже произойдет обращение?
Вообще, есть какая-то возможность узнать, когда последний раз происходило чтение-запись из кэша и из базы?

У меня была ситуация: я выставил юзеру параметр (command_groups) через /set, после чего ждал около 5 часов - изменения в базе так и не появились. Хотя usersync и userflush я уменьшил в 10 раз (30 и 120 секунд соответственно). Я же правильно понял, что сохранение данных в базу не зависит от активности пользователя и должно было произойти не позже 30 секунд?
К сожалению, смоделировать ситуацию четко я не могу, раз на раз не приходится.

HarpyWar wrote:

Если автоматизировать, то лучше через бота, который будет логиниться на сервер и выполнять /set команды (бот на php).
Чтобы бот мог соединиться с сервером, у аккаунта должна быть опция auth_botlogin=true

Понятно, значит подключиться к pvpgn "изнутри" невозможно, только через внешнего бота? Жалко, не хотелось с этим связываться, но может быть ничего плохого в этом и нет, если все будет работать стабильно и убрать его с основного канала...

4

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

iltmpz wrote:

Примерно понял, а при выходе пользователя кэш (если изменился) принудительно записывается в базу сразу если выставлен параметр sync_on_logoff? А если не выставлен, то так же по прошествии usersync секунд?

Всё так.

iltmpz wrote:

А в каких случаях используется кэш юзера? Последняя активность юзера, которую можно увидеть через /finger это последнее использование кэша или если другой юзер запросит данные об этом, к его кэшу тоже произойдет обращение?

Idle в /finger это время с момента последнего использования юзером команд чата.
Если юзер запросит через /finger инфу о другом юзере, то, само собой, произойдет обращение к кешу этого другого юзера.

iltmpz wrote:

У меня была ситуация: я выставил юзеру параметр (command_groups) через /set, после чего ждал около 5 часов - изменения в базе так и не появились. Хотя usersync и userflush я уменьшил в 10 раз (30 и 120 секунд соответственно).

Вполне возможно, что это баг. Хотя в исходниках синхронизация и сброс кеша происходит по вполне четким условиям (см. функции ниже).

iltmpz wrote:

Я же правильно понял, что сохранение данных в базу не зависит от активности пользователя и должно было произойти не позже 30 секунд?

Не должно, но в соответствие с предыдущим может пройти и больше  smile.

iltmpz wrote:

Вообще, есть какая-то возможность узнать, когда последний раз происходило чтение-запись из кэша и из базы?

См. account->attrgroup->dirtytime (последнее изменение кеша) и account->attrgroup->lastaccess (последнее обращение к кешу):

/account.c
extern int account_save(t_account * account, unsigned flags)
extern int account_flush(t_account * account, unsigned flags)
/attrgroup.c
extern int attrgroup_save(t_attrgroup *attrgroup, int flags)
extern int attrgroup_flush(t_attrgroup *attrgroup, int flags)
iltmpz wrote:

Понятно, значит подключиться к pvpgn "изнутри" невозможно, только через внешнего бота? Жалко, не хотелось с этим связываться, но может быть ничего плохого в этом и нет, если все будет работать стабильно и убрать его с основного канала...

Через бд это тоже извне. Изнутри - это через плагины какие-нибудь, но такого ещё нет smile
Этот бот -  скрипт, логинится на сервер и выполняет команды, затем сразу же выходит. Если дополнительно не выполнять /join channel, то его присутствие не будет замечено остальными юзерами вара3.
Имхо, с ним все должно работать стабильно.

Do not ask for support in PM.

5

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

iltmpz wrote:

У меня была ситуация: я выставил юзеру параметр (command_groups) через /set, после чего ждал около 5 часов - изменения в базе так и не появились.

На сервере изменения от /set появляются мгновенно. Это ведь то, что тебе нужно?

Еще можно подключаться к pvpgn через irc и разрешить коннект на irc только с loopback или адреса бота.

6

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Понял, спасибо за объяснения, подумаю, хотя в общем уже практически решил запускать бота. Пусть он будет и медленнее, чем прямые запросы к базе, но спешить вроде особо некуда - аккаунты можно и час обойти, а не за секунду...

Вот по поводу бага - это конечно неприятно: не хотелось бы иметь баги в своем сервере. Буду смотреть, если еще что проявится - постараюсь внимательнее все проверить.

xpeh wrote:

На сервере изменения от /set появляются мгновенно. Это ведь то, что тебе нужно?

В общем да, просто странно, что изменения в базу не прописались. А если бы он вышел? После входа в следующий раз сохранились бы изменения? К сожалению не смог проверить, применились изменения или нет, и сохранились ли, просто выполнил /set еще раз, и все записалось в базу.
Вообще, кажется, было так, что изменения иногда не применялись, хотя это с чужих слов. Причем чаще не применялись изменения в таблице BNET, чем Records.

xpeh wrote:

Еще можно подключаться к pvpgn через irc и разрешить коннект на irc только с loopback или адреса бота.

Тоже интересно, хотя я сейчас склоняюсь к боту, в принципе, думаю, меня это устроит...

7

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

iltmpz wrote:

А если бы он вышел? После входа в следующий раз сохранились бы изменения?

Если он вышел и данные не записались в бд, то они остаются в кеше и при следующем входе грузятся из него. При /shutdown всегда происходит синхронизация, поэтому данные потеряются только если сервер упадет.

Хотя на самом деле странно, что изменения не сохраняются даже при выходе юзера. Если есть возможность, установи все уровни loglevels и поищи в нем аккаунты, которые не синхронизируются  по времени сильно больше, чем установлен usersync. Или сюда выложи лог, посмотрим.

Добавлено: 03.04.2012 19:31

iltmpz wrote:

аккаунты можно и час обойти, а не за секунду...

Для чего требуется обходить все аккаунты?

Do not ask for support in PM.

8

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

iltmpz wrote:

Вот по поводу бага - это конечно неприятно: не хотелось бы иметь баги в своем сервере.

Это pvpgn. Привыкай smile
Как там на самом деле работает кеширование, известно только разрабам и тому, кто просмотрел весь отвечающий за это код. Думаю, то, что пишет харпи - на самом деле по большей части предположения.

iltmpz wrote:

Тоже интересно, хотя я сейчас склоняюсь к боту, в принципе, думаю, меня это устроит...

Ну это тот же бот, только подключен он будет через irc, а не через протокол бота. На выбор.

iltmpz wrote:

аккаунты можно и час обойти

Так а что конкретно тебе надо? Сделать поиск во всех аккаунтах и изменить небольшую часть из них? Тогда будет лучше поиск сделать через SQL, а менять уже через set. Можно сделать команду для принудительного дампа кеша, это будет лучше, чем обходить 100к акков. И насколько актуальные должны быть данные? Пару часов пойдет? Тогда можно и не париться с дампом, а перед изменением проверять ботом их актуальность.

9 (edited by iltmpz 03.04.2012 23:23)

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

HarpyWar wrote:

Если он вышел и данные не записались в бд, то они остаются в кеше и при следующем входе грузятся из него.

Это при условии, что синхронизация не нарушена, т.е. что сервер вообще помнит, что он еще данные в базу не записал, а я в этом не уверен, потому что за 5 часов мог бы и записать, при таймауте 30 сек.

HarpyWar wrote:

При /shutdown всегда происходит синхронизация, поэтому данные потеряются только если сервер упадет.

Кстати, я правильно понимаю, что форсировать синхронизацию также поможет /rehash, и что он же kill -HUP?

Логи посмотрю, я пока не включал trace и debug, включу если надо будет...

HarpyWar wrote:

Для чего требуется обходить все аккаунты?

Пока еще не знаю, ну например статы поправить самому всем, по формуле, а вообще пока не определился, какой функционал мне может понадобиться...

Посмотрел код бота - в общем сделано очень просто, хотя и несколько опасно:

        fwrite($this->fp,"/".$cmd."\r\n/help help\r\n");
        do {
...
        } while (!strstr($buffer,'/he') && !strstr($buffer,'1018 INFO "/help [<command>] - does this"'));

Неизвестно, что попадет в вывод, я бы на такого бота функцию сбора данных не рискнул возложить...
Но в целом, задумка ясна, тем более, команды он должен исправно серверу отправлять, попробую что-нибудь на базе этого дела изобразить...

Добавлено: 03.04.2012 23:15

xpeh wrote:

Это pvpgn. Привыкай

Там все так плохо? Вообще я смотрел код версии 1.78, на которой сервер работал раньше - стиль программирования конечно оценил: прямо на стеке заводится массив побольше [1024], а потом туда sprintf пишет строку, и авось суммарная длина этой строки не превысит длину массива...
В версии 1.85 (которая из портов поставилась) уже массивы создаются на куче и запись идет через snprintf.
Если у авторов ко всему остальному такое же отношение, как к переполнению буфера, то неудивительно, что там встречаются баги...

xpeh wrote:

Сделать поиск во всех аккаунтах и изменить небольшую часть из них? Тогда будет лучше поиск сделать через SQL, а менять уже через set. Можно сделать команду для принудительного дампа кеша, это будет лучше, чем обходить 100к акков.

Да, поиск однозначно в sql, тем более как я понимаю, команды противоположной /set нет, и например вытащить хеш пароля или другую какую экзотику через чат просто невозможно? А вот принудительный дамп кеша это дело, ну т.е. сброс кеша в базу по команде, а дальше sql для чтения базы.
Пока еще не знаю, до чего меня доведут мои желания работать с базой, хотя задержка в пару часов это по-моему многовато...
В общем спасибо, пока попробую прикрутить скрипт, а там посмотрю, что дальше делать...

10

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Я все это проверял на сервере, без большого количества аккаунтов. На основе этого и исходников, предполагаю, что так и должно работать с любым количеством.

/rehash только переподгружает конфиги сервера, но не синхронизирует аккаунты. Про kill -HUP не в курсе.

Иногда могут появляться ошибки, при которых синхронизация не выполняется, поэтому лучше посмотреть в логах, почему так. Но измененный кеш не должен затираться до сброса изменений в бд.

Do not ask for support in PM.

11 (edited by iltmpz 04.04.2012 14:14)

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Про rehash понятно, читал тут в мануале про конфиги, думал, может к кешу тоже применяется. Ну нет, значит нет.

HarpyWar wrote:

Иногда могут появляться ошибки, при которых синхронизация не выполняется, поэтому лучше посмотреть в логах, почему так. Но измененный кеш не должен затираться до сброса изменений в бд.

Т.е. синхронизация перестает выполняться для вообще всех аккаунтов, а при shutdown синхронизация происходит?

А вообще, я так думаю, пригодилось бы:

xpeh wrote:

сделать команду для принудительного дампа кеша

или точнее, для принудительного сброса данных в базу. Я так понимаю, если знать какая функция это делает, то достаточно строчек 5 кода дописать: добавить "/команду". А потом уже можно запросами из базы все необходимые данные вытаскивать, в актуальном состоянии.
И тогда получается единственный стабильный работающий вариант: для чтения базы - сброс данных в базу и чтение через mysql, для записи - подключение через бота и выполнение команд.

12 (edited by kucc 04.04.2012 18:50)

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

xpeh wrote:

Вот по поводу бага - это конечно неприятно: не хотелось бы иметь баги в своем сервереЭто pvpgn. Привыкай smile
Как там на самом деле работает кеширование, известно только разрабам и тому, кто просмотрел весь отвечающий за это код. Думаю, то, что пишет харпи - на самом деле по большей части предположения.

Я можно сказать разобрался с кешем, но всю схему объяснять не буду, так как нет времени и желания.
Скажу коротко что параметр сохраняется вот так в память - hlist_add(&attrgroup, &attr)
проверяется   attr = hlist_entry(%attrgrup,&attr), ну соответственно если найден такой же запрос на получения цифры или параметра в бд, выдает уже существующий в кеше который был полученный ранее, а если не найден то берет из базы.
При /shutdown он просто сохраняет всё в базу, но параметры кеша и сам кеш не очищает.

13

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Хотел написать пост, кликнул не на то и драный firefox не сохранил текст. Опера сохраняла все на ура.

iltmpz wrote:

тем более как я понимаю, команды противоположной /set нет

/set без параметров. Справка по командам

iltmpz wrote:

Я так понимаю, если знать какая функция это делает

Посмотри на /shutdown, он-то должен дампать кеш.

iltmpz wrote:

Там все так плохо? Вообще я смотрел код версии 1.78, на которой сервер работал раньше - стиль программирования конечно оценил: прямо на стеке заводится массив побольше [1024], а потом туда sprintf пишет строку, и авось суммарная длина этой строки не превысит длину массива...
В версии 1.85 (которая из портов поставилась) уже массивы создаются на куче и запись идет через snprintf.
Если у авторов ко всему остальному такое же отношение, как к переполнению буфера, то неудивительно, что там встречаются баги...

Посмотри clan.c от 1.8.x, потом посмотри changelog и diff, начиная хотя бы с 1.8.1. Там до 1.8.5 патчили сегфолты при разборе пакетов, а в 1.8.4 - вообще скулю. И все это имхо в clan.c. Сегфолты при разборе пакетов - это вообще их специализация. Сколько уже людей приходило на оффорум и создавало топики "караул, нас ипут, спасайте, сервак падает!", а в ответ - тишина. Вообще софтина архаичная. Будь она на языке с GC вроде явы/сисярпа, большей части проблем бы не было, а так, бОльшая часть проблем от нежелания выделять память. Сишник - не человек, и ему предстоит очень трудная ночь.
А эти переполнения можно заюзать для чего-то, кроме DoS?

Про отношение авторов - когда-то видимо брали код откуда попало, вот и появлялись шедевры вроде того же clan.c. Реальных изменений в 1.8.x не было года с 2005, только багфиксы. Они попытались переписать серв на С++ (1.99), но не осилили и он до stable так и не дошел. Теперь все девелоперы свалили, остались одни суппортеры. То есть, где-то с 2005 года сервер фактически не развивался. Лучше бы вместо дрочева на 1.99 пофиксили очевидные баги в 1.8.х, вроде нарушений протокола Battle.Net.

kucc wrote:

Я можно сказать разобрался с кешем, но всю схему объяснять не буду, так как нет времени и желания.
Скажу коротко что параметр сохраняется вот так в память - hlist_add(&attrgroup, &attr)
проверяется   attr = hlist_entry(%attrgrup,&attr), ну соответственно если найден такой же запрос на получения цифры или параметра в бд, выдает уже существующий в кеше который был полученный ранее, а если не найден то берет из базы.
При /shutdown он просто сохраняет всё в базу, но параметры кеша и сам кеш не очищает.

Вопрос был вообще-то про то, как дампнуть кеш.
Как он не очищает кеш, если программа закрывается и освобождает всю память? smile

14

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

xpeh wrote:

Вопрос был вообще-то про то, как дампнуть кеш.
Как он не очищает кеш, если программа закрывается и освобождает всю память? smile

Я не говорю что происходит после закрытия самого сервака точнее убийства процесса, а что происходит во время команды /shutdown /saveaccounts
Ну так и ответ был как он хранит кеш, думаю зная как сохраняет можно уже понять как его вытащить, только зачем?
Я при удалении объекта сперва удаляю с кеша потом сразу же с базы.

15

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

kucc wrote:

Ну так и ответ был как он хранит кеш, думаю зная как сохраняет можно уже понять как его вытащить, только зачем?
Я при удалении объекта сперва удаляю с кеша потом сразу же с базы.

Это не совсем то, что нужно ТС.

16

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

xpeh wrote:
kucc wrote:

Ну так и ответ был как он хранит кеш, думаю зная как сохраняет можно уже понять как его вытащить, только зачем?
Я при удалении объекта сперва удаляю с кеша потом сразу же с базы.

Это не совсем то, что нужно ТС.

По мне кокраз это ему и надо, пример, хочет удалить пользователя, удаляем всё из кеша и скл запросом - всё через пвпгн.
Хочет обновить измененный параметр напрямую из скл, хотя уже кеш загружен с данным параметром, обновляем просто кеш новым параметром.
Что не так? Пример пожалуйста того что нужно.

17

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Пусть ТС сам скажет, что он хочет.

18

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

xpeh wrote:

/set без параметров.

Опс, невнимательно я справку читал, действительно есть, спасибо smile

xpeh wrote:

Посмотри на /shutdown, он-то должен дампать кеш.

Ну в общем да, это понятно, просто, вдруг кто-то уже это дело проходил и знает сразу...

xpeh wrote:

Там до 1.8.5 патчили сегфолты при разборе пакетов, а в 1.8.4 - вообще скулю

Мдя, в общем, понятно все с ними, хотя в те времена многие таким способом софт писали. Что сайты с register_globals, в виде одной сплошной дырки для хакеров, что вот и пвпгн туда же.
Наткнулся тут на неучтенный sprintf в массив [256], создаваемый на стеке - это в версии уже 1.8.5, прошелся по исходникам поиском - нашел еще несколько десятков таких же мест. Неужели разработчикам было трудно их все так же понаходить поиском и поправить на snprintf'ы? Вопрос получаса. А еще лучше - написать обертку для snprintf, и заменить ей все sprintf и snprintf, чтобы она проверяла длину и в случае попытки переполнения ошибку в лог писала. Может быть, займусь на досуге...

xpeh wrote:

А эти переполнения можно заюзать для чего-то, кроме DoS?

Ага, ни много ни мало, для выполнения произвольного кода с правами процесса.
Достаточно лишь правильно вычислить адрес возврата из функции, чтобы он указывал на код, загруженный в тот же стек.
Если случился segfault, значит, всего лишь была неправильно сформирована входная строка. Правильно же заданная строка даст шелл или что там нужно, а сервер продолжит работать как ни в чем ни бывало.

xpeh wrote:

Лучше бы вместо дрочева на 1.99 пофиксили очевидные баги в 1.8.х, вроде нарушений протокола Battle.Net.

А что там за нарушения протокола Battle.Net?

kucc wrote:

думаю зная как сохраняет можно уже понять как его вытащить, только зачем?
Я при удалении объекта сперва удаляю с кеша потом сразу же с базы.

Хочется его не столько вытащить, сколько сбросить в базу. Чтобы быть уверенным, что мой select вытащит актуальные данные. А ты в смысле удаляешь его 2 раза - сначала из кеша, потом из базы?

Добавлено: 05.04.2012 10:15

kucc wrote:

Что не так? Пример пожалуйста того что нужно.

Пример: юзер зарегистрировался, зашел на канал, там ссылка на веб-морду управления аккаунтом. Он заходит, надо, чтобы веб-морда видела актуальные данные сразу, а не через usersync секунд, тем более если кеширование подвиснет на неопределенное время. А то юзер не поймет, если ему дают ссылку на сервис, а сервис не работает...

19 (edited by kucc 05.04.2012 10:28)

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

iltmpz wrote:

Пример: юзер зарегистрировался, зашел на канал, там ссылка на веб-морду управления аккаунтом. Он заходит, надо, чтобы веб-морда видела актуальные данные сразу, а не через usersync секунд, тем более если кеширование подвиснет на неопределенное время. А то юзер не поймет, если ему дают ссылку на сервис, а сервис не работает...

Первый вариант: сделать сохранение в базу данных всего кеша раз в минуту. (Будет мощная загрузка)
Второй вариант: отключить кеш для выводимых параметрах чтоб он их сохранял напрямую без участи hlist (ведь не только нужны свежие данные данного нового пользователя но и всех других)
Третий вариант: привязать веб морду не к базе а через пвпгн путем отправки и получения пакетов (сложная штука но зато какая)
Четвертый вариант: если только проблема в новеньких, то при создании аккаунта, сделать чтоб он не в кеш сохранял а напрямую в базу (это легко и просто)

20

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

iltmpz wrote:

А что там за нарушения протокола Battle.Net?

forums.pvpgn.org/index.php?topic=3437.0

iltmpz wrote:

Наткнулся тут на неучтенный sprintf в массив [256], создаваемый на стеке - это в версии уже 1.8.5, прошелся по исходникам поиском - нашел еще несколько десятков таких же мест.

Где это?

21

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Про нарушение протокола, вроде нарушение протокола не сильно мешает, потому и не исправляют наверно,

xpeh wrote:

Где это?

Точно не помню где первый раз наткнулся, кажется имя канала записывалось sprintf'ом в такой массив. Ну в любом случае поиском по sprintf по дереву исходников все такие места находятся...

22

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

iltmpz wrote:

Про нарушение протокола, вроде нарушение протокола не сильно мешает, потому и не исправляют наверно,

Тем не менее, это ошибка. Не исправляют, потому что в 1.8.x фиксят только критические баги. В 1.99 это имхо пофикшено, как и сообщение "аккаунт залочен" вместо "неправильный пароль". Вот только 1.99 не нужен.

iltmpz wrote:

Точно не помню где первый раз наткнулся, кажется имя канала записывалось sprintf'ом в такой массив. Ну в любом случае поиском по sprintf по дереву исходников все такие места находятся...

Там небось не только такие места находятся, а все подряд.
Кстати, а современные компиляторы их разве автоматом на безопасные версии не заменяют?

23 (edited by iltmpz 05.04.2012 11:22)

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

xpeh wrote:

В 1.99 это имхо пофикшено, как и сообщение "аккаунт залочен" вместо "неправильный пароль". Вот только 1.99 не нужен.

Кстати да, а при любой ошибке создания аккаунта пишет - такой аккаунт уже существует, интересно, пофиксено это в 1.99 или нет...
А почему не нужен? Сырой и глючный?
Я поставил 1.85 в основном потому, что для 1.99 нужен был cmake, к которым мне разбираться не хотелось, а в портах был 1.85

xpeh wrote:

Там небось не только такие места находятся, а все подряд.
Кстати, а современные компиляторы их разве автоматом на безопасные версии не заменяют?

Да, я бы сказал, там все такие места подряд и надо править. Вообще не представляю себе ситуацию, когда бы стоило использовать sprintf, это же запись в массив строки, длина которой совершенно не известна.
А их невозможно заменить - тут дело не в компиляторе, а в функции. Помню, gcc при использовании gets писал, что функция небезопасна и советовал ее заменить на fgets, но это все, что может сделать компилятор.
В принципе, современные технологии имеют технологии запрета выполнения кода на стеке, так что вместо получения хакером шелла, программа будет просто "мирно" падать в segfault. Впрочем, технологии весьма спорные, и я не думаю, что стоит их применять для pvpgn...

24

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

iltmpz wrote:

Кстати да, а при любой ошибке создания аккаунта пишет - такой аккаунт уже существует, интересно, пофиксено это в 1.99 или нет...

Кода "аккаунты создавать нельза, регистрация через web" в протоколе нет. В остальном - могли и пофиксить.

iltmpz wrote:

А почему не нужен? Сырой и глючный?

Я им серьезно не пользовался, но вроде бы сыроват. Серверов на нем маловато. Писькаповцы пытались с ним что-то сделать, он у них упал при запуске, и они к нему больше не возвращались. Но это было давно.

iltmpz wrote:

А их невозможно заменить - тут дело не в компиляторе, а в функции. Помню, gcc при использовании gets писал, что функция небезопасна и советовал ее заменить на fgets, но это все, что может сделать компилятор.

msdn.microsoft.com/en-us/library … 80%29.aspx

In C++, using these functions is simplified by template overloads; the overloads can infer buffer length automatically (eliminating the need to specify a size argument) and they can automatically replace older, non-secure functions with their newer, secure counterparts. For more information, see Secure Template Overloads.

Может, ты в теме разбираешься? Можно, чтобы прога при падении в сегфолт выводила хотя бы строку, на которой он произошел?

25

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

xpeh wrote:

and they can automatically replace older, non-secure functions with their newer, secure counterparts

Да, интересно, не слышал про такие перегрузки. Сейчас почитал - люботытно сделали, впрочем, если не ошибаюсь, можно и C-препроцессор для этих целей использовать (что-то наподобие #define sprintf(a,b,...) snprintf(a,sizeof(a),b,...) ). Просто чтобы по всему коду не лазить и не править во всех местах. Попробую пожалуй подсунуть такой макрос вместо snprintf, для мониторинга и логирования ошибок переполнения.
Впрочем, такой подход тоже не панацея от утечек - в данном случае работает только для статически заданных массивов: "Note that these template overloads only work for static arrays. Dynamically allocated buffers require additional source code changes". Отсюда: msdn.microsoft.com/en-us/library … 80%29.aspx

xpeh wrote:

Можно, чтобы прога при падении в сегфолт выводила хотя бы строку, на которой он произошел?

Чтобы строку выводила - насколько я понимаю нельзя, да и происходит оно обычно внутри функций наподобие spintf, а не в пользовательской. Но можно проанализировать соответствующий файл .core, вроде оттуда довольно понятна цепочка вызова функций, внутри которых произошло падение, правда я не разбирался...

26

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Ну может можно как-то сделать, чтобы прога выводила stack trace аки языки со сборкой мусора. Или хотя бы выдавала файл, который можно было бы переправить девелоперам, чтобы они разобрались. Потому что сейчас на проблемы индейцев шерифу глубоко пофиг.

iltmpz wrote:

да и происходит оно обычно внутри функций наподобие spintf, а не в пользовательской.

Совсем типичный баг - падение при разборе пакетов. Как я понимаю, происходит при касте структуры на область памяти и выход за границу выделенной памяти.

27

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Файл, который можно переправить девелоперам, это как я понимаю .core и есть, там вся инфа об ошибке. Только что-то мне подсказывает, что девелоперам на все эти файлы девелоперам все равно пофиг...

Добавлено: 14.04.2012 04:02

Так, кажется проблему более-менее локализовал:
Происходит это примерно так:
- я делаю /set user BNET\auth_command_groups 255
- права появляются
- проходит время, и оказывается, что прав уже нет, вернулись обратно на 1.
При этом в логах (loglevels = fatal,error,warn,info,debug,trace) ничего интересного, ну или я проглядел, честно говоря понятия не имею, на предмет чего именно смотреть логи.

Такая проблема имеет место именно после команды /set (с любыми параметрами).
Остальные команды в таком поведении замечены не были.

Никто ничего подобного не замечал?
Займусь чтением исходников на премет сравнения команды /set с остальными.

28

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Да нет, set прекрасно все время сохранялся. Или у тебя сервер падает и берется несохранное состояние из базы, или что-то другое дает юзеру cg 1.
Вместо

/set user BNET\auth_command_groups 255

можешь юзать

/cg add user 12345678

29 (edited by iltmpz 15.04.2012 07:46)

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

xpeh wrote:

Да нет, set прекрасно все время сохранялся. Или у тебя сервер падает и берется несохранное состояние из базы, или что-то другое дает юзеру cg 1.

Ну да, знаю про /cg, надо будет остальных админов научить этим пользоваться, но вопрос не в этом, а в /set, почему он у меня не работает.
Кстати, одна из приоритетных задач - редактирование /stats - интересно, это делается другими способами кроме /set?
/stats тоже слетает иногда к исходному значению, т.е. данные явно читаются заново из базы.

А вот падений сервера я вообще не знаю. Ну, может, раз в пару недель сервер уходил в перезагрузку из-за проблем с питанием, потом восстанавливался, но проблема с /set явно не из-за этого.

30

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Хз, УМВР.
С /set есть опасности - я как-то набрал "/set acct BNET\auth\command_groups 255 " (с лишним пробелом), в результате на аккаунте оказались cg 0 вместо 12345678.

31 (edited by kucc 22.04.2012 21:45)

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

iltmpz wrote:

Так, кажется проблему более-менее локализовал:
Происходит это примерно так:
- я делаю /set user BNET\auth_command_groups 255
- права появляются
- проходит время, и оказывается, что прав уже нет, вернулись обратно на 1.
При этом в логах (loglevels = fatal,error,warn,info,debug,trace) ничего интересного, ну или я проглядел, честно говоря понятия не имею, на предмет чего именно смотреть логи.

Что то в первый раз слышу, а зачем ты даешь через /set  а не через ЦГ, я сколько раз иконку туже ставил через /set всегда срабатывает и не сбрасывается.
Посмотри проходит ли в кеш при /set
Кстати напиши в асю иль в агент объясни что нужно по подробнее там, помогу чем смогу.
Хотя надо разобрать и команду /set по подробнее.

32

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Так, ну, спустя 2,5 года готов доложить, что проблема вроде бы решена smile

Дело оказалось в моих кривых руках, неумении читать логи и весьма своеобразной реакции пвпгн на ошибки.

Значит:
хочу выставить игроку побольше побед. Пишу:
/set iltest22 record/w2bn_0_wins
value currently not set

- ага, значение пока не установлено, устанавливаю:

/set iltest22 record/w2bn_0_wins 999
Key set succesfully for "iltest22" (record/w2bn_0_wins = "999")

Все здорово, говорит пвпгн, значение установилось.

Могу даже проверить всякими разными способами:
/set iltest22 record/w2bn_0_wins
Current value of record/w2bn_0_wins is "999"
Или вот так:
/stats iltest22
Normal games: 999-0-0

Ура, ура, ура, я поставил значение! Я же поставил, все хорошо? И проверил?
Только вот проходит время - может быть несколько минут или что-то вроде того, и этот самый iltest22 пишет мне ругательное письмо, что нифига у него побед нет - они куда-то пропали! Куда именно?

Во-первых, должен сказать, что я, лошара, не умею читать логи (я верю, что они тогда писались, я просто не догадался их почитать, не могли ведь они не писаться?).

Во-вторых, огромное спасибо HarpyWar за проделанную огромную работу с новым PVPGN и в частности за функцию /save.
Как я понимаю, она была сделана именно по моей просьбе из этой темы, потому что именно то, о чем я тогда просил и чего мне как раз и не хватало для полного выявления проблемы. И чего вроде бы больше никто нигде не просил...

Итак, что мне удалось выявить:
После "успешного" выполнения /set iltest22 record/w2bn_0_wins 999
Key set succesfully for "iltest22" (record/w2bn_0_wins = "999")
- делаю /save, сразу ищу новое значение в базе. Не нахожу. Значит что-то не так.
Лезу в логи и натыкаюсь на следующее:
Nov 24 17:03:40 [error] sql_write_attrs: could not INSERT attribute 'record_w2bn_0_wins'->'999'

И тут до меня доходит: Таблица-то называется Record! А вовсе не record.
Т.е. сначала, пока значение лежало в буфере, оно отображалось правильно.
Потом пвпгн пытался сбросить его в базу, выдавал вот эту ошибку и сбрасывал значение к исходному!
и потом, в результате - в базе значение не изменилось, а /stats выдает старые данные! Хотя раньше вроде бы все сработало.

Регистр букв определяет все, правда не в момент установки значения - в этот момент все было отлично, о чем он и написал - а в момент попытки записать значение в базу.

1. В общем, огромное спасибо, всем участвовавшим - правильный ответ:
/set iltest22 Record/w2bn_0_wins 999
После этого /save отлично помогает выявить опечатки, если они вдруг были допущены.

2. Большая просьба не исправлять эту ошибку простой проверкой типа:

if (!strncasecmp(key, "Record", 6)) {
tmp = xstrdup(key);
std::strncpy(tmp, "Record", 6);
}

потому как проблема учета и неучета регистров и весьма специфического поведения достаточно фундаментальна и требует серьезного переосмысления механизма, иначе придется долго латать баги. Я бы сказал, главная проблема не в регистрозависимости базы и регистронезависимости буфера, а в том, что значение было якобы установлено, пользователю было сообщено об успехе, после чего попытка фактически установить значение в базе - провалилась.
Об этой особенности поведения сервера в любом случае полезно знать.

3. Формально говоря, к пвпгн у меня в данном случае претензий нет - ошибка в логах была, неверно обработанное значение корректно откатилось.
То, что я не умею читать логи - это исключительно мои проблемы. Хотя бы иногда надо заглядывать в лог на предмет поиска [error] - до полного прояснения для себя, что там за error вылез.

Добавлено: 25.11.2014 10:34

Небольшое уточнение справедливости ради:
Попытался вчера сделать /set iltest22 record/w2bn_0_wins 995
- т.е. в заведомо неверном регистре, не делая после этого /save.
В результате через несколько часов так и не увидев в логах ошибки, полез в базу, и обнаружил, что значение установилось. Хотя регистр был неправильным.

Так что предположу, что значение устанавливается разными способами в соответствии с какой-то внутренней логикой - иногда регистрозависимо, иногда - нет.
Ну и в случаях регистрозависимости у меня происходил откат. Аналогично команде /save.

Вникать в детали этой внутренней логики и способов у меня желания нет, потому что интересовавшая меня ошибка найдена: /set в правильном регистре и дополняющий его /save работает идеально.
Сначала, как я понял, сбрасывая весь буфер в базу, а потом перечитывая весь буфер обратно из базы.
Тем самым, гарантируя синхронность базы и буфера.

33 (edited by kucc 26.11.2014 08:48)

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

До сих пор не пойму, зачем нужна эта команда? Когда есть /cg
А если иконки, то можно сделать или кажись уже есть команда /icon

По поводу команды /save - кажись она только сохраняет в базу и не очищает кэш.

34

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Команда нужна в данном случае, чтобы выставить юзеру нужное число побед/поражений.
Бывает, например, кто-нибудь победу украл, надо вернуть, или создал новый аккаунт и просит туда победы перенести.

По поводу кэша - я тут должен уточнить, что я изначально неправильно использовал терминологию: то, что я 2,5 года назад называл кэшем - на самом деле буфер. В последнем посте я это исправил.
Т.е. данные считываются из базы в буфер pvpgn, система работает с ними, после чего записывает их обратно в базу.

Кажется, некоторое кэширование у sql-данных тоже есть, с целью уменьшения числа обращений к базе, про него ничего сказать не могу.
По поводу команды /save - она сначала сбрасывает буфер в базу: accountlist_save(FS_FORCE | FS_ALL);
А потом: accountlist_flush(FS_FORCE | FS_ALL);
То ли очищает буфер, то ли перечитывает данные в буфер из базы...

35 (edited by kucc 26.11.2014 12:39)

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

/wins

static int _handle_wins_command(t_connection * c, char const *text)
{
  t_account * account;
  char *accname;
  char *race;
  char key[MAX_MESSAGE_LEN + 1];
  char *value;
  int number;
  char t[MAX_MESSAGE_LEN];
  unsigned int i,j;
  char         arg1[256];
  char         arg2[256];
  char         arg3[256];

  char const * user;
  char const * ip;
  ip = addr_num_to_ip_str(conn_get_addr(c));
  user = conn_get_username(c);


  strncpy(t, text, MAX_MESSAGE_LEN - 1);
  for (i=0; t[i]!=' ' && t[i]!='\0'; i++); /* skip command /set */

  for (; t[i]==' '; i++); /* skip spaces */
  for (j=0; t[i]!=' ' && t[i]!='\0'; i++) /* get username */
    if (j<sizeof(arg1)-1) arg1[j++] = t[i];
  arg1[j] = '\0';

  for (; t[i]==' '; i++); /* skip spaces */
  for (j=0; t[i]!=' ' && t[i]!='\0'; i++) /* get key */
    if (j<sizeof(arg2)-1) arg2[j++] = t[i];
  arg2[j] = '\0';

  for (; t[i]==' '; i++); /* skip spaces */
  for (j=0; t[i]!='\0'; i++) /* get value */
    if (j<sizeof(arg3)-1) arg3[j++] = t[i];
  arg3[j] = '\0';

  accname  = arg1;
  race     = arg2;
  value    = arg3;
  number    = atoi(value);

  if ((arg1[0] =='\0') || (arg2[0]=='\0'))
  {
    message_send_text(c,message_type_info,c,"используйте: /wins <ник> <раса> [побед]");
  }

  if (!(account = accountlist_find_account(accname)))
    {
      message_send_text(c,message_type_error,c,"Неправильный пользователь.");
      return 0;
    }

      if (std::strcmp(race, "humans") != 0 && std::strcmp(race, "orcs") != 0 && std::strcmp(race, "random") != 0 && std::strcmp(race, "nightelves") != 0 && std::strcmp(race, "undead") != 0 && std::strcmp(race, "demons") != 0 )
    {
        snprintf(msgtemp, sizeof(msgtemp), "Раса введена неправильно. Используйте /wins <ник> <раса> <побед>");
        message_send_text(c,message_type_info,c,msgtemp);
        snprintf(msgtemp, sizeof(msgtemp), "Доступные расы: humans/orcs/random/nightelves/undead/demons");
        message_send_text(c,message_type_info,c,msgtemp);
        return 0;
    }

    snprintf(key, sizeof(key), "Record\\W3XP\\%s\\wins",race);

  if (*value == '\0')
    {
      if (account_get_strattr(account,key))
    {
        snprintf(msgtemp, sizeof(msgtemp), "Тюкующее количество побед: \"%.128s\" ",account_get_strattr(account,key));
      message_send_text(c,message_type_error,c,msgtemp);
    }
      else
    message_send_text(c,message_type_error,c,"Параметр неправильный");
      return 0;
  } 
  
  if (number < 0 || number > 1500)  {
      message_send_text(c,message_type_error,c,"Колличество побед не должно быть меньше 0 и больше 1500");
    return 0;
  }
  
  snprintf(msgtemp, sizeof(msgtemp), "Прошлое колличество побед: \"%.128s\" за расу \"%s\"",account_get_strattr(account,key),race);
  message_send_text(c,message_type_error,c,msgtemp);

  if (account_set_strattr(account,key,itoa(number,value,10))<0)
    message_send_text(c,message_type_error,c,"Невозможно установить победы");
  else {
      //лог wins
      snprintf(msgtemp, sizeof(msgtemp), "Успешно установленно \"%d\" побед за расу \"%s\" для аккаунта \"%s\"",number,race,accname);
        message_send_text(c,message_type_error,c,msgtemp);
     eventlog(eventlog_level_admin, __FUNCTION__, "\"%s\" установил побед \"%d\" за расу \"%s\" для аккаунта \"%s\" с АйПи (%s)",  user,number,race,accname, ip);
  }
  return 0;
}

/losses

static int _handle_loss_command(t_connection * c, char const *text)
{
  t_account * account;
  char *accname;
  char *race;
  char key[MAX_MESSAGE_LEN + 1];
  char *value;
  int number;
  char t[MAX_MESSAGE_LEN];
  unsigned int i,j;
  char         arg1[256];
  char         arg2[256];
  char         arg3[256];

  char const * user;
  char const * ip;
  ip = addr_num_to_ip_str(conn_get_addr(c));
  user = conn_get_username(c);


  strncpy(t, text, MAX_MESSAGE_LEN - 1);
  for (i=0; t[i]!=' ' && t[i]!='\0'; i++); /* skip command /set */

  for (; t[i]==' '; i++); /* skip spaces */
  for (j=0; t[i]!=' ' && t[i]!='\0'; i++) /* get username */
    if (j<sizeof(arg1)-1) arg1[j++] = t[i];
  arg1[j] = '\0';

  for (; t[i]==' '; i++); /* skip spaces */
  for (j=0; t[i]!=' ' && t[i]!='\0'; i++) /* get key */
    if (j<sizeof(arg2)-1) arg2[j++] = t[i];
  arg2[j] = '\0';

  for (; t[i]==' '; i++); /* skip spaces */
  for (j=0; t[i]!='\0'; i++) /* get value */
    if (j<sizeof(arg3)-1) arg3[j++] = t[i];
  arg3[j] = '\0';

  accname  = arg1;
  race     = arg2;
  value    = arg3;
  number    = atoi(value);

  if ((arg1[0] =='\0') || (arg2[0]=='\0'))
  {
    message_send_text(c,message_type_info,c,"используйте: /loss <ник> <раса> [поражений]");
  }

  if (!(account = accountlist_find_account(accname)))
    {
      message_send_text(c,message_type_error,c,"Неправильный пользователь.");
      return 0;
    }

      if (std::strcmp(race, "humans") != 0 && std::strcmp(race, "orcs") != 0 && std::strcmp(race, "random") != 0 && std::strcmp(race, "nightelves") != 0 && std::strcmp(race, "undead") != 0 && std::strcmp(race, "demons") != 0 )
    {
        snprintf(msgtemp, sizeof(msgtemp), "Раса введена неправильно. Используйте /loss <ник> <раса> <поражений>");
        message_send_text(c,message_type_info,c,msgtemp);
        snprintf(msgtemp, sizeof(msgtemp), "Доступные расы: humans/orcs/random/nightelves/undead/demons");
        message_send_text(c,message_type_info,c,msgtemp);
        return 0;
    }

    snprintf(key, sizeof(key), "Record\\W3XP\\%s\\losses",race);

  if (*value == '\0')
    {
      if (account_get_strattr(account,key))
    {
        snprintf(msgtemp, sizeof(msgtemp), "Тюкующее количество поражений: \"%.128s\" ",account_get_strattr(account,key));
      message_send_text(c,message_type_error,c,msgtemp);
    }
      else
    message_send_text(c,message_type_error,c,"Параметр неправильный");
      return 0;
  } 
  
  if (number < 0 || number > 1500)  {
      message_send_text(c,message_type_error,c,"Колличество поражений не должно быть меньше 0 и больше 1500");
    return 0;
  }
  
  snprintf(msgtemp, sizeof(msgtemp), "Прошлое колличество поражений: \"%.128s\" за расу \"%s\"",account_get_strattr(account,key),race);
  message_send_text(c,message_type_error,c,msgtemp);

  if (account_set_strattr(account,key,itoa(number,value,10))<0)
    message_send_text(c,message_type_error,c,"Невозможно установить поражения");
  else {
      //лог wins
      snprintf(msgtemp, sizeof(msgtemp), "Успешно установленно \"%d\" поражений за расу \"%s\" для аккаунта \"%s\"",number,race,accname);
        message_send_text(c,message_type_error,c,msgtemp);
     eventlog(eventlog_level_admin, __FUNCTION__, "\"%s\" установил поражения \"%d\" за расу \"%s\" для аккаунта \"%s\" с АйПи (%s)",  user,number,race,accname, ip);
  }
  return 0;
}

/level

static int _handle_level_command(t_connection * c, char const *text)
{
  t_account * account;
  char *accname;
  char key[MAX_MESSAGE_LEN + 1];
  char *value;
  int number;
  char t[MAX_MESSAGE_LEN];
  unsigned int i,j;
  char         arg1[256];
  char         arg2[256];
  char         arg3[256];

  char const * user;
  char const * ip;
  ip = addr_num_to_ip_str(conn_get_addr(c));
  user = conn_get_username(c);


  strncpy(t, text, MAX_MESSAGE_LEN - 1);
  for (i=0; t[i]!=' ' && t[i]!='\0'; i++); /* skip command /set */

  for (; t[i]==' '; i++); /* skip spaces */
  for (j=0; t[i]!=' ' && t[i]!='\0'; i++) /* get username */
    if (j<sizeof(arg1)-1) arg1[j++] = t[i];
  arg1[j] = '\0';

  for (; t[i]==' '; i++); /* skip spaces */
  for (j=0; t[i]!='\0'; i++) /* get value */
    if (j<sizeof(arg2)-1) arg2[j++] = t[i];
  arg2[j] = '\0';

  accname  = arg1;
  value    = arg2;
  number    = atoi(value);

  if (arg1[0] =='\0')
  {
    message_send_text(c,message_type_info,c,"используйте: /level <ник> [уровень]");
  }

  if (!(account = accountlist_find_account(accname)))
    {
      message_send_text(c,message_type_error,c,"Неправильный пользователь.");
      return 0;
    }

    snprintf(key, sizeof(key), "Record\\W3XP\\solo\\level");

  if (*value == '\0')
    {
      if (account_get_strattr(account,key))
    {
        snprintf(msgtemp, sizeof(msgtemp), "Тюкущий уровень: \"%.128s\" ",account_get_strattr(account,key));
      message_send_text(c,message_type_error,c,msgtemp);
    }
      else
    message_send_text(c,message_type_error,c,"Параметр неправильный");
      return 0;
  } 
  
  if (number < 0 || number > 999)  {
      message_send_text(c,message_type_error,c,"Уровень не можеть быть меньше 0 и больше 999");
    return 0;
  }
  
  snprintf(msgtemp, sizeof(msgtemp), "Прошлый уровень: \"%.128s\" ",account_get_strattr(account,key));
  message_send_text(c,message_type_error,c,msgtemp);

  if (account_set_strattr(account,key,itoa(number,value,10))<0)
    message_send_text(c,message_type_error,c,"Невозможно установить новый уровень");
  else {
      //лог wins
     snprintf(msgtemp, sizeof(msgtemp), "Успешно установлен новый уровень: %d для аккаунта \"%s\"",number,accname);
     message_send_text(c,message_type_error,c,msgtemp);
     eventlog(eventlog_level_admin, __FUNCTION__, "\"%s\" установил уровень \"%d\" для аккаунта \"%s\" с АйПи (%s)",  user,number,accname, ip);
  }
  return 0;
}

36

Re: [решено] Как форсировать синхронизацию между PVPGN и базой mysql?

Действительно, /set больше команда для дебага, и в ней легко ошибиться в названии полей и таблиц. Если часто требуется выставлять победы, лучше сделать отдельные команды.


На самом деле, здесь ошибка не в PvPGN, а в MySQL. При создании БД можно выбрать тип сравнения, и если установить его в "*_general_ci", то выборка по таблицам и полям будет регистронезависимая (например, для кодировки UTF8 будет utf8_general_ci).
Тип сравнения можно задать по-умолчанию в конфиге MySQL dev.mysql.com/doc/refman/5.0/en/ … tions.html

Do not ask for support in PM.

Posts: 36

Pages 1

You must login or register to post a reply

Who now at forum

Currently view post: 1 guest, 0 registered users

forums.pvpgn.pro → [RU] Tech Support → [решено] Как форсировать синхронизацию между PVPGN и базой mysql?