пятница, 31 декабря 2010 г.

Чиним f-spot

Я использую f-spot в качестве менеджера коллекций фотографий на своем домашнем компьютере. К сожалению, начиная с версии 0.8.0 f-spot испортился: тамбнейлы превратились в серые квадратики, а при клике на них фотографии открывались на долю секунды и f-spot тут же падал. Поиск в интернете вывел на баг #627745. В двух словах баг заключается в том, что если в пути к файлам с фотографиями встречаются директории с нелатинскими символами, то f-spot благополучно падает. В пути к моим фото присутствует директория Снимки/, так что мне не повезло.
Некоторое время я терпеливо ждал выхода следующей версии f-spot. Но, f-spot 0.8.2 вышел, а проблема осталась. Пришла пора действовать. Итак, для восстановления работоспособности f-spot была применена стратегия, состоящая из двух основных пунктов:
  1. Сделать так, чтобы путь к файлам с фотографиями не содержал нелатинских символов
  2. Сделать так, чтобы f-spot узнал об изменениях в пункте 1
Первый пункт достигается очень просто: нужно использовать старые добрые символические ссылки:
ln -s Снимки Pictures
Теперь к фотографиям можно обращаться через путь Pictures/ вместо Снимки/.
Чтобы реализовать второй пункт, нужно знать как f-spot хранит информацию о фотографиях. А делает он это с помощью базы данных photos.db, которая обычно находится в директории ~/.config/f-spot/. Редактировать эту БД можно с помощью утилиты sqlite3. Естественно, перед тем как изменять БД, неплохо создать ее резервную копию, просто скопировав файл photos.db. Итак, открываем БД для внесения нужных изменений:
sqlite3 photos.db
Эта команда загружает интерактивную среду sqlite. Для просмотра перечня таблиц вводим
sqlite> .tables
exports         meta            photo_versions  rolls         
jobs            photo_tags      photos          tags
Поля отдельной таблицы можно увидеть с помощью команды .schema:
sqlite> .schema photos
CREATE TABLE photos (
    id          INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
    time            INTEGER NOT NULL, 
    base_uri        STRING NOT NULL, 
    filename        STRING NOT NULL, 
    description     TEXT NOT NULL, 
    roll_id         INTEGER NOT NULL, 
    default_version_id  INTEGER NOT NULL, 
    rating          INTEGER NULL 
);
Увидеть, где находятся данные, содержащие пути с директорией Снимки/ было просто: достаточно выполнить select * from для всех (или только подозрительных) таблиц. Оказалось, что данные о путях содержатся в полях base_uri таблиц photos и photo_versions.
Теперь нужно выполнить замену Снимки на Pictures во всех данных для этих полей:
sqlite> update photos set base_uri=replace(base_uri,"Снимки","Pictures")
   ...> where base_uri like "%Снимки%";
sqlite> update photo_versions set base_uri=replace(base_uri,"Снимки","Pictures")
   ...> where base_uri like "%Снимки%";
Всё. Выходим из среды sqlite:
sqlite> .quit
Теперь запускаем f-spot: тамбнейлы должны появиться, при клике на них фотографии должны показываться без проблем. Осталось изменить имя директории, в которую будут импортироваться фото в дальнейшем c Снимки на Pictures: это можно сделать прямо в f-spot из меню Правка -> Параметры.

P.S. Похоже, что этот баг не связан напрямую с f-spot, возможно он присутствует на уровне mono или Gnome.

P.P.S. Я пробовал использовать shotwell, но f-spot мне по-прежнему кажется симпатичней, несмотря на свою глючность. Возможно, в дальнейшем я перейду на shotwell, когда его допилят.

воскресенье, 19 декабря 2010 г.

Вышел Geant4 9.4 и ChargeExchangeMC (aka Cexmc)

17 декабря вышла новая версия библиотеки для моделирования прохождения элементарных частиц в веществе Geant4 9.4. Geant4 широко применяется при моделировании физических экспериментов, а также в медицине и космофизике.
Для меня данный релиз замечателен тем, что в него в качестве одного из advanced examples вошла программа ChargeExchangeMC, автором которой я являюсь. Программа применялась для моделирования реального эксперимента в Петербургском Институте Ядерной Физики. Первая версия, написанная на фортране, была в дальнейшем переписана с нуля на C++ с использованием Geant4.
Основные особенности программы:
  1. Это достаточно большой проект, он включает 71 заголовочный файл и 63 файла исходников, общий размер программного кода превышает 20 тысяч строк
  2. Геометрия установки полностью описана в формате GDML. Это позволит гибко изменять описание установки без изменения исходного кода
  3. Для упрощения анализа данных используются гистограммы на основе библиотеки CERN ROOT
  4. Реализована модель реконструкции данных с гибкой настройкой различных параметров
  5. В программе реализован гибкий алгоритм на основе шаблонов C++ для возможности легкого изменения изучаемых взаимодействий
  6. Персистентное хранение данных реализовано с помощью библиотеки boost::serialization
  7. Пользовательский фильтр данных позволяет изменять полученные данные с помощью специальных скриптов. Грамматика скриптов описана с помощью библиотеки boost::spirit
  8. Run manager имеет уникальный режим проигрывания событий (replay mode), который позволяет пересчитывать уже имеющиеся данные с параметрами, отличными от исходных
Документацию по установке и использованию программы можно найти здесь.

четверг, 9 декабря 2010 г.

Реорганизация структуры репозитория Subversion

Ситуация: Имеется репозиторий Subversion, который управляет среднего размера проектом, скажем my_project, уже в течение года. Соответственно, присутствует богатая история изменений. Но... Изначально структура репозитория была спланирована недальновидно, в частности были допущены следующие две оплошности:
  1. Импорт исходного кода осуществлялся в корневую директорию, выделенную для Subversion
  2. Не была создана промежуточная директория trunk/. Напомним, что в Subversion реализация хранения тегов и веток (в том числе главной) не различаются: фактически это просто разные поддиректории внутри проекта. Поэтому в Subversion обычно предлагается структурировать проект с использованием следующих канонических поддиректорий: trunk/ (для главной ветки), branches/ (для побочных веток) и tags/ (для тегов)
Первый пункт означает, что невозможно нормальным способом добавить еще один проект в корневую директорию Subversion (у меня она расположена в ~/svn/). Второй пункт означает, что невозможно нормальным способом создать теги и ветки для существующего проекта. Именно со второй проблемой я и столкнулся, когда всплыла необходимость выделить отдельную ветку для поддержания проекта при использовании старой версии одной из сторонних библиотек.

Постановка задачи: изменить существующий (или создать новый) репозиторий Subversion, в котором будет возможно создавать новые проекты, и в котором структура существующего проекта будет приведена к канонической (с использованием трех поддиректорий trunk/, branches/ и tags/), и при этом будет сохранена в работоспособном состоянии история всех изменений данного проекта без добавления служебных ревизий в ее начало.

Решение: будем создавать новый репозиторий. Для этого сначала выполним дамп существующего репозитория в файл:
svnadmin dump ~/svn/ > my_project_svn_dump
Теперь, предварительно забекапив директорию ~/svn/, удаляем все, что в ней находится, и создаем новый репозиторий для проекта my_project:
svnadmin create ~/svn/my_project
Теперь нам нужно загрузить дамп истории в новый репозиторий. Но предварительно его следует отредактировать (дамп репозитория представляет собой обычный ASCII файл), сохранив на всякий случай исходную копию. Поскольку в старый репозиторий проект был импортирован из директории my_project/, а имя нового репозитория уже содержит название my_project, то нам нужно удалить все упоминания об этой директории внутри файла. Однако, мы поступим проще: нам ведь все равно нужна поддиректория trunk/, так что зачем удалять упоминания о my_project/ внутри дампа, когда это можно просто заменить на trunk/? Итак, ищем строку
Node-path: my_project
и заменяем ее на
Node-path: trunk
Кроме того, my_project входит в состав путей к файлам, поэтому ищем все вхождения
Node-path: my_project/
и заменяем их на
Node-path: trunk/
Замену вхождений легко автоматизировать с помощью текстового редактора, например vim.
А теперь загружаем отредактированный дамп старого репозитория в новый:

svnadmin load ~/svn/my_project < my_project_svn_dump
Если все прошло успешно, то нас можно поздравить: новый репозиторий будет содержать всю историю изменений из старого репозитория без каких-либо дополнений.
Осталось добавить директории branches/ и tags/ (я перенесу части строки для удобства, на самом деле это однострочная команда):
svn mkdir -m "branches and tags directories added"
    file:///home/user/svn/my_project/tags
    file:///home/user/svn/my_project/branches
Теперь можно делать чекаут из нового репозитория и продолжать работу с проектом:
svn co file:///home/user/svn/my_poject/trunk my_project
Disclaimer: Обязательно делайте бекап репозитория перед какими-либо изменениями внутри него. Также неплохо сохранять копию дампа репозитория до тех пор, пока вы не осознали до конца, что все изменения прошли успешно.

суббота, 4 декабря 2010 г.

Отключение автоматического монтирования отдельных разделов диска устройства, подключаемого через USB

Имеется в наличии медиаплеер Iconbit HDR12L, в который установлен внутренний диск размером 500Гб. Диск был размечен устройством следующим образом:
Устр-во Загр     Начало       Конец       Блоки     Id  Система
/dev/sdc1           16065   967386104   483685020    7  HPFS/NTFS
/dev/sdc2       967386105   967707404      160650   82  Linux своп / Solaris
/dev/sdc3       967707405   976125464     4209030   83  Linux
/dev/sdc4       976125465   976446764      160650   83  Linux 
При обмене файлов с компьютером интерес представляет только первый раздел с NTFS системой. Но по умолчанию в моем дистрибутиве (Fedora 14) монтируются все три раздела (исключение составляет 2-ой раздел с подкачкой). Соответственно, задача формулируется следующим образом: отключить автоматическое монтирование разделов /dev/sdc3 и /dev/sdc4 при подключении медиаплеера через USB.
За работу со съемными носителями в Linux традиционно отвечают две подсистемы: udev и hal. Первая подсистема привязывает устройства к корневой файловой системе в директории /dev, а вторая работает на более высоком уровне и определяет что делать с новым устройством: для съемных носителей это что обычно заключается в монтировании носителя в корневую файловую систему. Соответственно, нас интересует уровень hal и мы создаем новое правило hal для медиаплеера iconbit и помещаем его в новый файл /etc/hal/fdi/policy/90-iconbit.fdi. Вот его содержимое:
<?xml version="1.0" encoding="UTF-8"?>

<deviceinfo version="0.2">
  <device>
    <match key="volume.label" string_outof="iconbit_p3;iconbit_p4">
      <merge key="volume.ignore" type="bool">true</merge>
    </match>
  </device>
</deviceinfo>
На этом примере видно, что правила hal записываются в формате xml. В нашем правиле будут проверяться метки разделов: если метка раздела совпадает с iconbit_p3 или iconbit_p4, то он не будет монтироваться (значение volume.ignore для таких разделов устанавливается в true). Важно отметить, что удобные метки разделов я установил сам. Вместо проверки на совпадение метки раздела можно установить проверку на совпадение с uuid раздела: в этом случае ключом будет не volume.label, а volume.uuid. Атрибут string_outof соответствует выбору между несколькими вариантами, разделенными точкой с запятой; если нужно осуществлять проверку только для одного варианта, то вместо string_outof нужно использовать string.
Всё. Прекрасно. Перезапускаем hal и оно ... не работает. Проблема в том, что в новых дистрибутивах (в Fedora начиная с версии 11) для работы со съемными носителями вместо hal используется подсистема udisks из DeviceKit. В udisks несколько иной подход, и здесь нам таки придется добавлять правила на уровне udev. Итак, создаем файл /etc/udev/rules.d/90-iconbit.rules co следующим содержимым:
# iconbit auxiliary partitions
ENV{ID_FS_TYPE}=="ext3", \
  ENV{ID_FS_LABEL}=="iconbit_p3|iconbit_p4", \
  ENV{UDISKS_PRESENTATION_HIDE}="1"
Теперь, после перезагрузки компьютера, цель достигнута: при подключении медиаплеера к компьютеру через USB монтируется только один раздел с NTFS.
Примеры использования правил udisks можно найти в файле  /lib/udev/rules.d/80-udisks.rules.

Update. В Fedora 17, а может быть даже раньше, система udisks была заменена на udisks2, в которой синтаксис правил опять изменился. Теперь правило для iconbit выглядит так:
# iconbit auxiliary partitions
ENV{ID_FS_TYPE}=="ext3", \
  ENV{ID_FS_LABEL}=="iconbit_p3|iconbit_p4", \
  ENV{UDISKS_IGNORE}="1"
Кроме того, файлы правил теперь находятся в директории /usr/lib/udev/rules.d/. И еще, лично я переименовал 90-iconbit.rules в 98-iconbit.rule (хотя конкретное значение численного префикса в названии файла не играет существенной роли до тех пор, пока указанные в нем правила не пересекаются с правилами из других файлов в этой директории).