Allex (all_x) wrote,
Allex
all_x

Глубокая отладка или Минус на минус – это плюс, но только первый раз.

Последнюю неделю провел в глубокой отладке Semantic MediaWiki. Очень непросто искать нетривиальную ошибку в незнакомой системе. Обычно бросаю довольно быстро, если не удаётся разобраться сходу. Но тут, что называется “закусил удила”. Попробовал несколько новых инструментов, немного разобрался с устройством Semantic MediaWiki и нашел причину странного поведения.

Всё началось с того, что понадобился удобный способ выполнять вычисления на страницах MediaWiki. Установил расширение Scribuntu, немного почитал про Lua и реализовал необходимые функции. Дальше началось странное – функция возвращает число, которое становится значением свойства. Все значения выводятся нормально за исключением '1' — вместо него появляется ссылка на совершенно непричастную страницу. Чудеса начались.

Задаю вопрос в списке рассылки, параллельно пытаюсь повторить неправильное поведение. В процессе выясняется, что в нашей wiki была страница '1', которую затем переименовали в “совершенно непричастную страницу” без перенаправления с '1' на новую страницу. Из списка рассылки отвечают, что действительно, была такая ошибка и перенаправление в базе данных устанавливалось, даже если эта галочка при переименовании страницы была снята, надо проверить на последней версии.

Устанавливаю MediaWiki последней версии. Пытаюсь повторить странное поведение — сначала всё в порядке, но после нескольких переименований значение свойства таки меняется.

Лезу в исходники и базу данных старой wiki – действительно, в исходниках проблема есть, перенаправления в базе данных установлены. Если бы я не успел попробовать на последней версии – успокоился бы. Но в последней версии-то ошибка исправлена, а с переименованиями всё равно что-то неладно!

После долгих поисков нашлась последовательность действий, приводящая к странному результату:

  • cоздать страницу ’1′
  • создать страницу ‘S’ с определением подобъекта, имеющего свойство P=1
  • создать страницу ‘Q’ с запросом, выводящим подобъект и его свойство.
  • переименовать ’1′ в ‘One без установки перенаправления
  • перейти на страницу ‘Q’
  • убедиться, что значение P по-прежнему 1
  • заново создать страницу 1 и переименовать её в ‘Two’
  • перейти на страницу ‘Q’
  • убедиться, что значение P изменилось на Two

Чудеса продолжаются. Точно не знаю, какое поведение правильное, но оба варианта правильными быть не могут, значит ошибка точно есть!

Включаю MediaWiki debug toolbar:

$wgDebugToolbar = true;

И с помощью отладочной печати пытаюсь разобраться, что происходит. Когда надоело повторять одни и те же действия, установил Selenium IDE и записал скрипт – “вкалывают роботы, счастлив человек”.

Когда отладочной печати стало не хватать и появились мечты о нормальном отладчике PHP кода на удалённом веб-сервере, разобрался в вопросе, установил xdebug и Eclipse с PHP Development Tools. Наставил себе точек останова и нашел, что после первого переименования страницы значение семантического свойства в таблице smw_di_wikipage тоже меняется, но по окончании транзакции этих изменений в базе данных нет! Оттрассировал все операции с этой таблицей и понял, что изменения откатываются с помощью задания на обновление информации о странице 'S', которое выполняется уже после обработки переименования страницы '1', поэтому-то я его в отладчике и не поймал.

А почему же после второго переименования не произошло обновления страницы 'S' и отката изменений в семантической информации? Оказывается, есть ещё поле smw_proptable_hash в таблице smw_object_ids, в котором хранится хэш сериализованного массива свойств. Перед обновлением свойств считается новый хэш и, если он совпадает со старым, изменения не записываются, потому что они уже в базе. В этом случае данные точно не соответствовали тому, что лежало в базе, а хэши были одинаковые.

Вот и первая ошибка: при переименовании страницы таблица со значениями свойств изменяется, а её хэш не обновляется, поэтому и отката изменений не происходит – хэш не изменился, значит и изменений не было.

Но почему эта ошибка проявляется только при втором переименовании? А потому что

Вторая ошибка: при сериализации массива свойств первый раз ключами в нём являются числа, а во втором и последующих – строковое представление этих чисел. Привет поклонникам динамической типизации!

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


Из блога софт, хард & интERнет
Tags: mediawiki, php, scribuntu, selenium, semantic mediawiki, xdebug, Интернет, Разработка, отладка
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments