Pull to refresh

Еще раз об электронной библиотеке для PocketBook

Reading time 4 min
Views 4.5K
Приветствую тебя, Хабр!

Данная статейка — всего лишь развернутый комментарий к тексту «Электронная библиотека для PocketBook: автоматическая обработка» от dsd_corp, поскольку я, будучи бесплотным (readonly) духом не могу (пока) оставлять обычные комментарии. Впрочем, не буду обсуждать политику Хабра, а перейду к делу.

Во-первых, хочется выразить автору благодарность за его статью. Я узнал много полезного о давно используемом мной PocketBook 360° и привел помойку на нем в относительный порядок. Скрипт, как и обещал автор, оказался переносимым (у меня линукс), если не считать небольшого неудобства с кодировками.

Ниже я просто приведу свои замечания.

  1. Директорию, где хранятся собственно книги, лучше поименовать так, чтобы она начиналась с точки. Само устройство следует древней юниксовой традиции «файлы с точки — для заточки» и не показывает их. То есть в скрипте следует изменить $storagename на, например, '.zipstorage'.
  2. Я обнаружил, что имена создаваемых файлов записаны в кодировке cp1251 (неужели в винде до сих пор не перешли на юникод?). Это мне показалось очень неудобным, поэтому я попробовал отредактировать скрипт, чтобы получился кошерный utf8. Вначале наивно сделал

    sed -i 's/windows-1251/utf8/g' *php *.inc

    и т.д., но получилось хреново, поскольку скрипт делает довольно нетривиальные вещи, в частности, понимает, какая исходная кодировка у входных fb2-файлов и грамотно перекодирует. Кроме того, я вижу текст на PHP чуть ли не в первый раз в жизни. Поэтому я вернул всё, как было, и просто делал

    convmv -f cp1251 -t utf8 -r --notest out_dir/dest/

    каждый раз после выполнения скрипта.
  3. То, что ссылки по авторам раскладываются слишком глубоко ('Буквы А-Я'/первая буква/три первые буквы/автор) мне показалось неудобным. По крайней мере, когда книг не очень много, это не оправдано. Я придумал как сделать лучше, а именно: сбалансировать дерево, ограничив количество элементов на верхних уровнях, так чтобы они помещались на одной странице (например, это 10 при моих настройках). Тогда путь будет выглядеть как 'Аве-Арц/Аксаков', то есть получится примерно как в именовании томов энциклопедии. В зависимости от количества книг могут понадобиться дополнительные уровни, коих должно быть примерно логарифм от количества авторов. Кажется, такая штука по-научному называется префиксным деревом. Я пока эту фичу не реализовал, а просто укоротил изначальную раскладку до 'первая буква/автор'.
  4. Иногда (вероятно, на битых fb2-файлах) скрипт может вести себя неадекватно — зажирает всю память и начинает свопиться. Я не стал заниматься отладкой; вероятно мне проще переписать функционал на более привычном языке, чем разбираться с PHP. Правда, я не уверен, что доберусь хотя бы до этого, тем более что я перегнал почти всю свою библиотеку, и пока всё удовл.
  5. Экспериментируя с тем, как работают файлы-ссылки, я не сразу понял, как именно именуются файловые системы с точки зрения устройства. А именно, в /mnt/ext2 монтируется внешняя SD-карта, а внутренняя память — в /mnt/ext1. (Когда я экспериментировал, писал сразу на внутреннюю память, и у меня не работали ссылки с '/mnt/ext2'.) Такое именование довольно контринтуитивно — ext2 вызывает однозначную ассоциацию с названием файловой системы (впрочем, на карте всё равно vfat). Поэтому, применяя скрипт, необходимо помнить, что он готовит файлы именно для первого раздела внешней карты. Иначе в конце нужно сделать как-то так:

    find out_dir/dest/Библиотека -name '*.flk' -exec sed -i 's/ext2/ext1/' '{}' \;

    Также я попробовал использовать относительные, а не абсолютные flk-ссылки, но они, похоже совсем не работают. Если кто знает что-либо по поводу относительных ссылок, пусть поделится.
  6. Насчет эффективности копирования. Я не испытал особых проблем (всего-то полтора гига), но есть кое-какие соображения по оптимизации. Во-первых, кажется сомнительной идея зиповать файлы — мы имеем устройство с очень медленным процессором и сравнительно быстрым носителем. Поэтому время открывания файлов может ухудшиться из-за сжатия. Впрочем, здесь необходимы тесты. Во-вторых, для ускорения заливки на карту можно подготовить образ раздела и потом потом скопировать его на карту целиком утилитой dd. Как делать образ раздела на файле я даже почти помню — для этого нужна утилитка losetup, превращающая файл в устройство, на которое можно напустить mkfs и mount.


UPD

Как копировать образ


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

  1. Во-первых, необходимо узнать точный размер нужного раздела флешки. Допустим, что устройство определилось как /dev/sdc:

    # fdisk -l /dev/sdc
    ...
    Disk /dev/sdc: 4 GB, 4127195136 bytes
    64 heads, 32 sectors/track, 3936 cylinders
    Units = cylinders of 2048 * 512 = 1048576 bytes

    Device Boot Start End Blocks Id System
    /dev/sdc1 1 3934 4028400 83 Linux


    Здесь имеем размер раздела 4028400 блоков по 512 байт.
  2. Далее, нужно создать файл на диске в точности такого же размера. Поскольку утилита dd имеет опцию bs (размер блока), то нам даже не нужно умножать 4028400 на 512. Впрочем, в данном случае для dd размер блока не играет роли, главное чтобы bs*count было равно в точности требуемому размеру в байтах.

    $ dd if=/dev/zero of=image bs=512 count=4028400
  3. Создаем файловую систему на полученном файле:
    $ /sbin/mkdosfs image
  4. Монтируем файл-образ как устройство (для этого необходим ядерный модуль loop, который есть в ядрах всех современных дистрибутивов по умолчанию), копируем файлы, отмонтируем:
    $ mkdir mnt
    # mount -o loop image mnt
    # cp -r ...файлы... mnt
    # umount mnt
    $ rmdir mnt

  5. Теперь копируем файл-образ на место раздела (важно не ошибиться с именем устройства):
    # dd if=image of=/dev/sdc1

Готово! Можно подмонтировать флешку и убедиться, что ее содержимое соответствует ожидаемому.

Бывает, что на устройстве есть битые блоки, тогда всё усложняется. В этом случае можно скопировать образ раздела в файл, вместо того чтобы создавать его заново (пункты 1-3):

# dd if=/dev/sdc1 of=image conv=noerror

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

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

Tags:
Hubs:
+8
Comments 30
Comments Comments 30

Articles