Так, ну, спустя 2,5 года готов доложить, что проблема вроде бы решена
Дело оказалось в моих кривых руках, неумении читать логи и весьма своеобразной реакции пвпгн на ошибки.
Значит:
хочу выставить игроку побольше побед. Пишу:
/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 работает идеально.
Сначала, как я понял, сбрасывая весь буфер в базу, а потом перечитывая весь буфер обратно из базы.
Тем самым, гарантируя синхронность базы и буфера.