Palm Record Operation Semantic

  • Введение
  • Классический Data Manager
  • Записи
  • Ресурсы
  • Локинг записей и ресурсов
  • Защита базы
  • NVFS. Первая попытка
  • Записи
  • Ресурсы
  • Локинг
  • Защита
  • NVFS в PalmOS 5.4.9
  • Заключение
  • Введение

    Статья занудно описывает семантику (ну да, смысл, суть) операций над базами в Palm OS Data Manager. Сие творение было написано как возмущенная реакция на изменения в Palm OS 5.4.9 (начало в этом треде: http://forum.sources.ru/index.php?showtopic=119558 ) . Читать с интонациями писателя Коклюшкина.

    Классический Data Manager

    В классической Palm OS Data Manager располагает свои базы в кучах памяти и реализован как надстройка над Memory Manager. Это приводит к тому, что хэндлы записей можно рассматривать как обычные хэндлы блоков в динамической куче, которые можно лочить, данные которых можно читать итд. Различия между хэндлами из динамической памяти и из хранилища следующие:

    Чем плохи эти действия? Тем, что они идут в обход Data Manager и не дают ему возможности изменить, например, размер базы при resize записи с помощью MemHandleResize. В принципе изменить размер можно, но где и когда это аукнется - неизвестно.

    Какие операции над записями и ресурсами предлагаются программисту?

    Записи

    У записей в базе существуют два признака: busy и dirty. Операции доступа к записям изменяют состояние этих битов.
    операциясмыслдействия с флагом busyдействия с флагом dirtyдействия, если флаг busy выставлен
    DmGetRecordВозвращает хэндл записи для модификациивыставляетне трогаетвозвращает ошибку
    DmQueryRecordВозвращает хэндл записи для чтенияне изменяетне изменяетне влияет на функцию
    DmReleaseRecordОсвобождает записьсбрасываетвыставляет по параметрутребует выставленного флага

    Некоторые неверные действия с этими функциями ловится, а некоторые нет.

    Ресурсы

    Базы ресурсов не содержат признаков записей, поэтому существует только две функции доступа к записям
    операциясмысл
    DmGet(1)ResourceВозвращает хэндл записи
    Dm Release ResourceОсовобождает хэндл записи

    Никакой проверки правильного использования пары функций нет.

    Локинг записей и ресурсов

    Функции DmGet* возвращают хэндлы. Эти хэндлы можно и нужно лочить для работы с данными. Важно понять, что залоченность этих хэндлов абсолютно безразлична Data Manager. Единственное исключение: после любого сброса функция DmInit разлочивает все записи во всех кучах storage. Все остальное время записи могут быть залочены или разлочены. Освобождение записи или закрытие базы на это не влияет.

    Лок ресурса часто применяется программами-резидентами для регистрации процедурного аларма или нотификации. Такой код лочит ресурс code#1 и передает указатель в функцию регистрации. Даже после выхода из программы указатель на обработчик останется валидным.

    Защита базы

    К сожалению лок записи не спасает от удаления базы. В этом случае у залочившей ресурс программы нет никакой возможности обнаружить, что указатель на ресурс больше не валиден. Для предотвращения такой ситуации в API есть функция DmProtectDatabase, которая защищает базу и не позволяет удалять ее. Эта функция не запрещает модифицировать записи базы, но это уже не так принципиально, вряд ли кто-то полезет изменять записи в чужой базе. А вот удалить незащищенную базу можно из любого файл менеджера.

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

    NVFS. Первая попытка

    Реализация Data Manager на базе NVFS отличается от классики тем, что базы больше не хранятся в адресуемой памяти. С первого взгляда кажется, что существующее DM API позволяет сделать прозрачную подзагрузку записей в кэш. Не получилось. Почему?

    Записи

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

    статусописаниеможет ли быть выгружена при очистке кэша
    загружена для модификациизапись загружена функцией Dm Get Recordне может
    загружена для чтениязапись загружена функцией Dm Query Record или DmRecordInfoможет. остается хэндл, указывающий на блок размера 0
    загружена для повторного использованиязапись после вызова Dm Release Record с dirty==falseможет
    грязнаязапись после вызова Dm Release Record с dirty==falseне может
    сиротазапись после вызова Dm Query Record и ужатая до блока размером 0не может

    Отметим следующие нюансы.

    Как мы видим, в целом все хорошо и предсказуемо. По крайней мере пока.

    Ресурсы

    Переходя к ресурсам, хочется грязно выругаться. API Resource Manager не позволяет программисту выразить свои намерения также явно, как и в Record API. Наличие опциональной Dm Release Record не дает никакой информации о том, была ли запись модифицирована или нет.

    Как это делает NVFS? Скорее всего этот уровень отслеживает вызовы DmWrite и неявно выставляет внутренний бит dirty для таких ресурсов.

    статусописаниеможет ли быть выгружена при очистке кэша
    загруженаресурс загружен функцией DmGet(1)Resourceне может
    загружена для повторного использованиязапись после вызова Dm Release Resourceможет
    грязнаяизмененная запись после вызова Dm Release Resourceне может

    Отметим следующие нюансы.

    Локинг

    Похоже, что залоченные ресурсы и записи кэш не очищает. Что он с ними делает - неизвестно. На следующие вопросы ответ неизвестен:

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

    Защита

    Факт защищенности базы никак не влияет на логику кэша. Точка.

    NVFS в PalmOS 5.4.9

    К чему привела вышеописанная логика?

    Горе-разработчики NVFS посмотрели на это безобразие и решили переделать. Все и сразу.

    И сделали следующее:

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

    Заключение

    Как же надежно защитить свой резидент от превратностей NVFS? Рекомендуется следующий вариант. Он был проверен на программах YAHM и Rus Hack и показал высокую стабильность:

    Инсталляция резидента:

    Запрещение резидента: