Spec-Zone.ru › Perl 5.38

Storable

СОДЕРЖАНИЕ

  • НАЗВАНИЕ
  • СИНТАКСИС
  • ОПИСАНИЕ
  • ХРАНЕНИЕ В ПАМЯТИ
  • КОНСУЛЬТАТИВНАЯ БЛОКИРОВКА
  • СКОРОСТЬ
  • КАНОНИЧЕСКОЕ ПРЕДСТАВЛЕНИЕ
  • ССЫЛКИ НА КОД
  • ВЕРСИОННАЯ СОСТАВЛЯЕМОСТЬ
  • СООБЩЕНИЕ ОБ ОШИБКАХ
  • ТОЛЬКО ДЛЯ МАСТЕРОВ
    • Гачки
    • Предикаты
    • Рекурсия
    • Глубокое клонирование
  • Магия Storable
  • ПРИМЕРЫ
  • ПРЕДУПРЕЖДЕНИЕ О БЕЗОПАСНОСТИ
  • ПРЕДУПРЕЖДЕНИЕ
  • РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ
  • ОШИБКИ
    • Данные 64-разрядного формата в Perl 5.6.0 и 5.6.1
  • АВТОРЫ
  • АВТОР
  • СМОТРИТЕ ТАКЖЕ

НАЗВАНИЕ

Storable - сохранение структур данных Perl

СИНТАКСИС

use Storable;
store \%table, 'file';
$hashref = retrieve('file');

use Storable qw(nstore store_fd nstore_fd freeze thaw dclone);

# Network order
nstore \%table, 'file';
$hashref = retrieve('file');	# There is NO nretrieve()

# Storing to and retrieving from an already opened file
store_fd \@array, \*STDOUT;
nstore_fd \%table, \*STDOUT;
$aryref = fd_retrieve(\*SOCKET);
$hashref = fd_retrieve(\*SOCKET);

# Serializing to memory
$serialized = freeze \%table;
%table_clone = %{ thaw($serialized) };

# Deep (recursive) cloning
$cloneref = dclone($ref);

# Advisory locking
use Storable qw(lock_store lock_nstore lock_retrieve)
lock_store \%table, 'file';
lock_nstore \%table, 'file';
$hashref = lock_retrieve('file');

ОПИСАНИЕ

Пакет Storable обеспечивает сохранение ваших структур данных Perl, содержащих SCALAR, ARRAY, HASH или REF объекты, то есть всё, что удобно хранить на диске и извлекать впоследствии.

Он может использоваться стандартным способом, вызывая store со ссылкой на объект, который нужно сохранить, вместе с именем файла, куда нужно записать изображение.

Процедура возвращает undef при проблемах ввода-вывода или других внутренних ошибках, а в противном случае — истинное значение. Серьёзные ошибки распространяются как исключение die.

Для извлечения данных, сохранённых на диске, используйте retrieve с именем файла. Сохранённые объекты реконструируются в памяти, и возвращается ссылка на корневой объект. В случае ошибки ввода-вывода при чтении возвращается undef. Другие серьёзные ошибки распространяются через die.

Поскольку хранение выполняется рекурсивно, вы можете поместить ссылки на объекты, которые разделяют много общих данных, в один массив или хэш-таблицу, а затем сохранить этот объект. Таким образом, при извлечении всего объекта, объекты будут продолжать разделять то, что они первоначально разделяли.

За счёт небольшого накладных расходов на заголовки, вы можете сохранять данные в уже открытый дескриптор файла, используя процедуру store_fd, а извлекать данные из файла с помощью fd_retrieve. Эти имена не импортируются по умолчанию, поэтому вам нужно будет сделать это явно, если вам нужны эти процедуры. Дескриптор файла, который вы предоставляете, должен быть уже открыт, для чтения, если вы собираетесь извлечь данные, и для записи, если хотите сохранить.

store_fd(\%table, *STDOUT) || die "can't store to stdout\n";
$hashref = fd_retrieve(*STDIN);

Вы также можете сохранять данные в сетевом порядке для простоты обмена между платформами или при сохранении на сокете, известно, что он подключен удалённо. Процедуры для вызова имеют начальный префикс n для сетевого порядка, как в nstore и nstore_fd. При извлечении данные будут правильно восстановлены, так что вам не нужно знать, восстанавливаете ли вы данные из родного или сетевого порядка. Двойные значения сохраняются строковой формой для обеспечения переносимости, с небольшой потерей точности в последних десятичных знаках.

При использовании fd_retrieve, объекты извлекаются последовательно, один объект (то есть одно рекурсивное дерево) на связанный store_fd.

Если вы предпочитаете объектно-ориентированный подход, вы можете унаследовать от Storable и напрямую сохранить свои объекты, вызвав store в качестве метода. Тот факт, что корень дерева, подлежащего сохранению, является освящённой ссылкой (то есть объектом), учитывается при извлечении, чтобы извлечь не ссылку на этот объект, а сам объект-ссылку. (В противном случае вы получите ссылку на этот освящённый объект).

ХРАНЕНИЕ В ПАМЯТИ

Двигатель Storable также может сохранять данные в скаляр Perl, а затем извлекать их. Это используется в основном для заморозки сложной структуры в безопасном компактном месте памяти (где её можно, возможно, отправить другому процессу через некоторое IPC, так как заморозка структуры также сериализует её фактически). Позже, и, возможно, где-то ещё, вы можете разморозить скаляр Perl и воссоздать исходную сложную структуру в памяти.

Удивительно, что вызываемые процедуры называются freeze и thaw. Если вы хотите отправить замороженный скаляр на другую машину, используйте nfreeze для получения переносимого изображения.

Обратите внимание, что заморозка и немедленная разморозка структуры объекта фактически выполняет глубокое клонирование этой структуры:

dclone(.) = thaw(freeze(.))

Storable предоставляет интерфейс dclone, который не создаёт промежуточного скаляра, а вместо этого замораживает структуру в некотором внутреннем пространстве памяти и сразу же размораживает её.

КОНСУЛЬТАТИВНАЯ БЛОКИРОВКА

Процедуры lock_store и lock_nstore эквивалентны store и nstore, за исключением того, что они получают эксклюзивную блокировку файла перед записью. Аналогично, lock_retrieve выполняет то же самое, что и retrieve, но также получает общую блокировку файла перед чтением.

Как и в любой схеме консультативной блокировки, защита работает только в том случае, если вы систематически используете lock_store и lock_retrieve. Если одна сторона вашего приложения использует store, а другая — lock_retrieve, защиты не будет.

Внутренняя консультативная блокировка реализуется с помощью функции Perl flock(). Если ваша система не поддерживает flock(), или если вы используете файлы через NFS, вы можете использовать другие формы блокировки, используя модули, такие как LockFile::Simple, которые блокируют файл с помощью записи в файловой системе, а не блокируя дескриптор файла.

СКОРОСТЬ

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

КАНОНИЧЕСКОЕ ПРЕДСТАВЛЕНИЕ

Обычно Storable сохраняет элементы хэшей в порядке, в котором они хранятся внутри Perl, то есть псевдослучайно. Если вы установите $Storable::canonical в некоторое TRUE значение, Storable сохранит хэши с элементами, отсортированными по ключу. Это позволяет сравнивать структуры данных, сравнивая их замороженные представления (или даже сжатые замороженные представления), что может быть полезно для создания таблиц поиска для сложных запросов.

Канонический порядок не подразумевает сетевой порядок; это два ортогональных параметра.

ССЫЛКИ НА КОД

Начиная с версии Storable 2.05, ссылки на КОД могут быть сериализованы с помощью B::Deparse. Чтобы включить эту функцию, установите $Storable::Deparse в истинное значение. Чтобы включить десериализацию, $Storable::Eval должно быть установлено в истинное значение. Имейте в виду, что десериализация выполняется через eval, что опасно, если файл Storable содержит вредоносные данные. Вы можете установить $Storable::Eval в ссылку на подпрограмму, которая будет использоваться вместо eval. См. пример ниже с использованием отсека Safe для десериализации ссылок на КОД.

Если $Storable::Deparse и/или $Storable::Eval установлены в ложные значения, то значение $Storable::forgive_me (см. ниже) учитывается при сериализации и десериализации.

ВЕРСИОННАЯ СОСТАВЛЯЕМОСТЬ

Этот выпуск Storable может использоваться в более новой версии Perl для сериализации данных, которые не поддерживаются более старыми версиями Perl. По умолчанию Storable попытается сделать правильный выбор, croak() в случае обнаружения данных, которые он не может десериализовать. Тем не менее, значения по умолчанию можно изменить следующим образом:

utf8 данные

Perl 5.6 добавил поддержку символов Юникода с кодовыми точками > 255, а Perl 5.8 имеет полную поддержку символов Юникода в ключах хешей. Perl внутренне кодирует строки с этими символами с помощью utf8, а Storable сериализует их как utf8. По умолчанию, если более старая версия Perl встречает значение utf8, которое она не может представить, она croak(). Чтобы изменить это поведение, чтобы Storable десериализовывал закодированные utf8 значения как строку байтов (эффективно удаляя флаг is_utf8), установите $Storable::drop_utf8 в некоторое TRUE значение. Это форма потери данных, потому что при $drop_utf8 true становится невозможно определить, были ли исходные данные строкой Юникода или последовательностью байтов, которые оказываются допустимыми utf8.

ограниченные хеши

Perl 5.8 добавляет поддержку ограниченных хешей, у которых ключи ограничены заданным набором, и значения могут быть заблокированы для чтения. По умолчанию, когда Storable сталкивается с ограниченным хешем на perl, который их не поддерживает, он десериализует его как обычный хеш, молча отбрасывая любые ключевые заполнитель и оставляя ключи и все значения разблокированными. Чтобы заставить Storable croak() вместо этого, установите $Storable::downgrade_restricted в FALSE значение. Чтобы восстановить значение по умолчанию, верните его в некоторое TRUE значение.

Стратегия хеширования cperl PERL_PERTURB_KEYS_TOP имеет известную проблему с ограниченными хешами.

объекты огромных размеров

В 64-битных системах некоторые структуры данных могут превышать предел 2Г (т.е. I32_MAX). В 32-битных системах также строки между I32 и U32 (2Г-4Г). С Storable 3.00 (не в ядре perl5) мы можем хранить и извлекать эти объекты, даже если сам perl5 не может их обработать. Это строки длиннее 4Г, массивы с более чем 2Г элементами и хеши с более чем 2Г элементами. cperl запрещает хеши с более чем 2Г элементами, но при этом терпит неудачу. perl5 сам по себе, по крайней мере, до 5.26, позволяет это, но не может перебирать их. Обратите внимание, что создание таких объектов может вызвать исключения «недостаточно памяти» операционной системой, прежде чем perl успеет прервать процесс.

файлы из будущих версий Storable

Более ранние версии Storable сразу же выдавали ошибку, если они встречали файл с более высоким внутренним номером версии, чем тот, о котором знал читающий Storable. Внутренние номера версии увеличиваются каждый раз, когда к лексикону формата файла добавляются новые типы данных (например, ограниченные хеши). Это означало, что более новый модуль Storable не мог записать файл, читаемый более старой версией Storable, даже если создающий модуль не записывал новые типы данных.

Эта версия Storable отложит ошибку до тех пор, пока не встретит тип данных в файле, который она не распознаёт. Это означает, что она продолжит чтение файлов, сгенерированных более новыми модулями Storable, которые осторожны в том, что они записывают, что облегчает обновление модулей Storable в смешанной среде.

Старое поведение мгновенной ошибки может быть восстановлено путём установки $Storable::accept_future_minor в некоторое FALSE значение.

Все эти переменные не оказывают влияния на более новые версии Perl, которые поддерживают соответствующую функцию.

ОБРАБОТКА ОШИБОК

Storable использует парадигму «исключений», в которой не пытается обойти сбои: если происходит что-то плохое, генерируется исключение с точки зрения вызывающего кода (см. Carp и croak()). Используйте eval {}, чтобы перехватить эти исключения.

Когда Storable генерирует ошибку, он пытается сообщить об ошибке с помощью функции logcroak() из пакета Log::Agent, если она доступна.

Обычные ошибки сообщаются путём возврата store() или retrieve() undef. Такие ошибки, как правило, являются ошибками ввода-вывода (или ошибками усечённого потока при извлечении).

Когда Storable генерирует ошибку «Максимальная глубина рекурсии с вложенными структурами превышена», у нас уже закончилось место в стеке. К сожалению, в некоторых более ранних версиях Perl очистка рекурсивной структуры данных приводит к рекурсии в вызовах освобождения, что приведёт к переполнению стека при очистке. Тогда эта структура данных не будет должным образом очищена, она будет уничтожена только при глобальном уничтожении.

ТОЛЬКО ДЛЯ ЭКСПЕРТОВ

Обработчики

Любой класс может определять обработчики, которые будут вызываться во время процесса сериализации и десериализации объектов, являющихся экземплярами этого класса. Эти обработчики могут переопределять способ выполнения сериализации (а следовательно, и способ выполнения симметричной десериализации).

Так как мы ранее сказали:

dclone(.) = thaw(freeze(.))

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

Поэтому, когда вовлечены обработчики сериализации,

dclone(.) <> thaw(freeze(.))

Ну, вы можете их синхронизировать, но нет гарантии, что это всегда будет работать для классов, написанных кем-то другим. Кроме того, нет большой пользы в этом: обработчик сериализации может хранить только один атрибут объекта, что, вероятно, не то, что должно происходить при глубоком клонировании того же объекта.

Вот интерфейс обработки:

STORABLE_freeze obj, cloning

Обработчик сериализации, вызываемый над объектом во время сериализации. Он может наследоваться или определяться в самом классе, как и любой другой метод.

Аргументы: obj — объект для сериализации, cloning — флаг, указывающий, выполняется ли dclone() или обычная сериализация через store() или freeze().

Возвращаемое значение: СПИСОК ($serialized, $ref1, $ref2, ...) где $serialized — сериализованная форма, которая будет использоваться, а необязательные $ref1, $ref2 и т. д. — дополнительные ссылки, которые вы хотите позволить движку Storable сериализовать.

При десериализации вам будет возвращён тот же СПИСОК, но все дополнительные ссылки будут указывать в десериализованную структуру.

В первый раз при срабатывании обработчика в потоке сериализации, вы можете вернуть пустой список. Это будет сигналом для движка Storable отбросить этот обработчик для данного класса и вернуться к стандартной сериализации базовых данных Perl. Обработчик снова будет обработано стандартным образом при следующей сериализации.

Если вы не знаете лучше, обработчик сериализации должен всегда возвращать:

sub STORABLE_freeze {
    my ($self, $cloning) = @_;
    return if $cloning;         # Regular default serialization
    ....
}

чтобы сохранить разумную семантику dclone().

STORABLE_thaw obj, cloning, serialized, ...

Обработчик десериализации, вызываемый над объектом во время десериализации. Но подождите: если мы десериализуем, объекта ещё нет... правильно?

Неправильно: движок Storable создаёт пустой для вас. Если вы знаете Eiffel, вы можете рассматривать STORABLE_thaw как альтернативную процедуру создания.

Это означает, что обработчик может наследоваться как любой другой метод, и что obj — ваш благословлённый указатель для этого конкретного экземпляра.

Другие аргументы должны быть знакомы, если вы знаете STORABLE_freeze: cloning — true, когда мы участвуем в операции глубокого клонирования, serialized — сериализованная строка, которую вы вернули движку в STORABLE_freeze, и может быть необязательный список ссылок в том же порядке, в котором вы их предоставили при сериализации, указывающий на десериализованные объекты (которые были обработаны движком Storable).

Когда движок Storable не находит обработчик STORABLE_thaw, он пытается загрузить класс, динамически потребовав пакет (используя имя благословлённого пакета), а затем пытается найти обработчик снова. Если в этот момент обработчик не найден, движок генерирует ошибку. Обратите внимание, что этот механизм потерпит неудачу, если вы определите несколько классов в одном файле, но perlmod предупреждал вас об этом.

Вам предстоит использовать эту информацию для заполнения obj в соответствии с вашими потребностями.

Возвращаемое значение: ничего.

STORABLE_attach class, cloning, serialized

Хотя STORABLE_freeze и STORABLE_thaw полезны для классов, где каждый экземпляр независим, этот механизм испытывает трудности (или несовместим) с объектами, которые существуют как общие ресурсы процесса или системы, такие как одиночные объекты, пулы баз данных, кэши или мемоизированные объекты.

Альтернативный метод STORABLE_attach предоставляет решение для этих общих объектов. Вместо STORABLE_freeze --> STORABLE_thaw, вы реализуете STORABLE_freeze --> STORABLE_attach вместо этого.

Аргументы: class — класс, который мы присоединяем, cloning — флаг, указывающий, выполняется ли dclone() или обычная десериализация через thaw(), а serialized — хранимая строка для объекта ресурса.

Поскольку эти объекты ресурсов считаются принадлежащими всему процессу/системе, а не "свойством" того, что сериализуется, никакие ссылки внутри объекта не должны включаться в сериализованную строку. Таким образом, в любом классе, реализующем STORABLE_attach, метод STORABLE_freeze не может возвращать никакие ссылки, а Storable выдаст ошибку, если STORABLE_freeze попытается вернуть ссылки.

Вся информация, необходимая для "присоединения" обратно к общему объекту ресурса, должна быть только в возвращаемой строке STORABLE_freeze. В противном случае, STORABLE_freeze работает как обычно для классов STORABLE_attach.

Поскольку STORABLE_attach получает класс (а не объект), он также возвращает объект непосредственно, а не изменяет переданный объект.

Возвращаемое значение: объект типа class

Предикаты

Предикаты не экспортируются. Их необходимо вызывать, явно предваряя их именем пакета Storable.

Storable::last_op_in_netorder

Предикат Storable::last_op_in_netorder() покажет вам, использовался ли сетевой порядок при последней операции store или retrieve. Если вы не знаете, как использовать это, просто забудьте об этом.

Storable::is_storing

Возвращает true, если выполняется операция store (через обработчик STORABLE_freeze).

Storable::is_retrieving

Возвращает true, если выполняется операция retrieve (через обработчик STORABLE_thaw).

Рекурсия

С обработчиками появляется возможность рекурсии обратно к движку Storable. В действительности, обработчики — это обычный Perl-код, а Storable удобен для сериализации и десериализации, так почему бы не использовать его для обработки сериализованной строки?

Однако, есть несколько моментов, которые вам нужно знать:

  • От версии Storable 3.05 до 3.13 мы исследовали предел рекурсии стека для ссылок, массивов и хешей до максимальной глубины ~1200-35000, в противном случае мы могли столкнуться с переполнением стека. В JSON::XS этот предел составляет 512. При ссылках, не ссылающихся друг на друга немедленно, такого предела ещё нет, поэтому вы можете столкнуться с ошибкой segfault из-за переполнения стека.

    Эти исследования и проверки имеют некоторые ограничения:

    • Размер стека во время компиляции может отличаться от размера стека во время выполнения, например, размер стека может быть изменён с помощью ulimit(1). Если он больше во время выполнения, Storable может излишне отклонить freeze() или thaw(). Если он больше во время компиляции, Storable может получить ошибку segmentation fault при обработке глубокой структуры во время выполнения.

    • Размер стека может отличаться в потоке.

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

    Поэтому теперь они имеют простые значения по умолчанию вместо проверки во время компиляции.

    Вы можете управлять максимальной глубиной рекурсии массивов и хешей, изменив $Storable::recursion_limit и $Storable::recursion_limit_hash соответственно. Оба значения могут быть установлены в -1, чтобы предотвратить любые проверки глубины, хотя это не рекомендуется.

    Если вы хотите проверить пределы, инструмент stacksize включён в распределение Storable.

  • Вы можете создать бесконечные циклы, если вещи, которые вы сериализуете через freeze() (например), указывают обратно на объект, который мы пытаемся сериализовать в обработчике.

  • Общие ссылки между объектами не останутся общими: если мы сериализуем список объектов [A, C], где оба объекта A и C ссылаются на ОДИН и тот же объект B, и если есть обработчик сериализации в A, который говорит freeze(B), то при десериализации мы получим [A', C'], где A' ссылается на B', но C' ссылается на D, глубокую копию B'. Топология не сохранилась.

  • Максимальный предел рекурсии стека для вашей системы возвращается stack_depth() и stack_depth_hash(). Предел для хешей обычно вдвое меньше предела для массивов и ссылок, так как API Perl для хешей не является оптимальным.

Вот почему STORABLE_freeze позволяет вам предоставить список ссылок для сериализации. Движок гарантирует, что они будут сериализованы в том же контексте, что и другие объекты, и, следовательно, что общие объекты останутся общими.

В примере выше [A, C], обработчик STORABLE_freeze мог бы вернуть:

("something", $self->{B})

и часть B была бы сериализована движком. В STORABLE_thaw, вы получите ссылку на объект B', десериализованный для вас.

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

Глубокое клонирование

В модуле Clone на CPAN реализовано глубокое клонирование напрямую, т. е. без заморозки в памяти и разморозки результата. В какой-то момент он должен заменить dclone() из Storable. Однако в настоящее время он не поддерживает обработчики Storable для переопределения способов выполнения глубокого клонирования.

Магия Storable

Да, её много :-) Но точнее, в системах UNIX есть утилита file, которая распознаёт файлы данных по их содержимому (обычно по их первым байтам). Для работы этого необходимо, чтобы определённый файл под названием magic знал о подписи данных. Местоположение этого файла конфигурации зависит от типа UNIX; часто это что-то вроде /usr/share/misc/magic или /etc/magic. Вашему системному администратору необходимо обновить файл magic. Необходимая информация о подписи выводится в стандартный вывод, если вызвать Storable::show_file_magic(). Обратите внимание, что реализация file от GNU, версия 3.38 или более поздняя, должна по умолчанию поддерживать распознавание файлов Storable помимо других типов файлов Perl.

Вы также можете использовать следующие функции для извлечения информации о заголовке файла из изображений Storable:

$info = Storable::file_magic( $filename )

Если данный файл является изображением Storable, возвращает хеш, описывающий его. Если файл читаем, но не является изображением Storable, возвращает undef. Если файл не существует или нечитаем, выводится сообщение об ошибке.

Возвращаемый хеш имеет следующие элементы:

version

Возвращает версию формата файла. Это строка, например, "2.7".

Обратите внимание, что этот номер версии не совпадает с номером версии самого модуля Storable. Например, Storable v0.7 создаёт файлы в формате v2.0, а Storable v2.15 создаёт файлы в формате v2.7. Номер версии формата файла увеличивается только при добавлении новых функций, которые могли бы сбить с толку более старые версии модуля.

Файлы, более старые, чем v2.0, будут иметь один из номеров версии "-1", "0" или "1". В то время не использовались второстепенные номера.

version_nv

Возвращает номер версии формата файла в виде числа. Это строка, например, "2.007". Это значение подходит для числовых сравнений.

Функция-константа Storable::BIN_VERSION_NV возвращает сравнимое число, которое представляет собой наибольший номер версии файла, который эта версия Storable полностью поддерживает (но см. обсуждение $Storable::accept_future_minor выше). Функция-константа Storable::BIN_WRITE_VERSION_NV возвращает версию файла, которая может быть меньше Storable::BIN_VERSION_NV в некоторых конфигурациях.

major, minor

Также возвращает номер версии формата файла. Если версия "2.7", то major будет 2, а minor - 7. Элемент minor отсутствует, когда major меньше 2.

hdrsize

Это число байтов, занимаемых заголовком Storable.

netorder

Истина, если изображение хранит данные в сетевом порядке. Это означает, что оно было создано с помощью nstore() или аналогичной функции.

byteorder

Этот элемент присутствует только когда netorder ложно. Это строка $Config{byteorder} perl, который создал это изображение. Это строка, например, "1234" (32-битный little endian) или "87654321" (64-битный big endian). Она должна совпадать с текущим perl для того, чтобы изображение было читаемо Storable.

intsize, longsize, ptrsize, nvsize

Эти элементы присутствуют только когда netorder ложно. Это размеры различных C-типов данных perl, который создал это изображение. Они должны совпадать с текущим perl для того, чтобы изображение было читаемо Storable.

Элемент nvsize присутствует только для формата файла v2.2 и выше.

file

Имя файла.

$info = Storable::read_magic( $buffer )
$info = Storable::read_magic( $buffer, $must_be_file )

Переменная $buffer должна содержать изображение Storable или первые несколько байтов изображения. Если $buffer начинается с заголовка Storable, то возвращается хеш, описывающий изображение; в противном случае возвращается undef.

Хеш имеет ту же структуру, что и возвращаемый Storable::file_magic(). Элемент file равен true, если изображение является файловым.

Если аргумент $must_be_file указан и равен TRUE, то возвращается undef, если изображение не похоже на дамп файла.

Максимальный размер заголовка Storable в настоящее время составляет 21 байт. Если предоставленный $buffer содержит только часть изображения Storable, его размер должен быть как минимум таким, чтобы read_magic() распознал его как таковое.

ПРИМЕРЫ

Вот несколько примеров кода, демонстрирующих возможное использование Storable:

use Storable qw(store retrieve freeze thaw dclone);

%color = ('Blue' => 0.1, 'Red' => 0.8, 'Black' => 0, 'White' => 1);

store(\%color, 'mycolors') or die "Can't store %a in mycolors!\n";

$colref = retrieve('mycolors');
die "Unable to retrieve from mycolors!\n" unless defined $colref;
printf "Blue is still %lf\n", $colref->{'Blue'};

$colref2 = dclone(\%color);

$str = freeze(\%color);
printf "Serialization of %%color is %d bytes long.\n", length($str);
$colref3 = thaw($str);

который выведет (на моём компьютере):

Blue is still 0.100000
Serialization of %color is 102 bytes long.

Сериализация ссылок CODE и десериализация в безопасном отсеке:

use Storable qw(freeze thaw);
use Safe;
use strict;
my $safe = new Safe;
       # because of opcodes used in "use strict":
$safe->permit(qw(:default require));
local $Storable::Deparse = 1;
local $Storable::Eval = sub { $safe->reval($_[0]) };
my $serialized = freeze(sub { 42 });
my $code = thaw($serialized);
$code->() == 42;

ПРЕДУПРЕЖДЕНИЕ ОБ ОПАСНОСТИ

Не принимайте документы Storable из недоверенных источников! Нет способа настроить Storable, чтобы он мог безопасно обрабатывать недоверенные данные. Хотя существуют различные варианты, которые могут использоваться для смягчения конкретных проблем безопасности, эти варианты не обеспечивают полную гарантию безопасности для пользователя, и обработка недоверенных данных может привести к ошибкам segmentation fault, выполнению удалённого кода или эскалации привилегий. Ниже перечислены известные функции, которые представляют собой проблемы безопасности, которые должны учитываться пользователями этого модуля.

Наиболее очевидно, что необязательная (по умолчанию отключённая) функция сериализации ссылок CODE позволяет передавать код в процесс десериализации. Кроме того, любой сериализованный объект заставит Storable загрузить модуль, соответствующий классу объекта, в модуле десериализации. При манипулировании именами модулей это может загрузить практически любой код. Наконец, деструкторы десериализованного объекта будут вызываться, когда объекты уничтожаются в процессе десериализации. Злонамеренно составленные документы Storable могут поместить такие объекты в значение ключа хеша, который перезаписывается другой парой ключ/значение в том же хеше, что вызывает немедленное выполнение деструктора.

Чтобы отключить благословение объектов во время разморозки/извлечения, удалите флаг BLESS_OK = 2 из $Storable::flags или установите второй аргумент для thaw/retrieve в 0.

Чтобы отключить привязку данных во время разморозки/извлечения, удалите флаг TIE_OK = 4 из $Storable::flags или установите второй аргумент для thaw/retrieve в 0.

При значении $Storable::flags = 6 по умолчанию создание или уничтожение случайных объектов, даже переименованных объектов, может контролироваться злоумышленником. См. CVE-2015-1592 и его модуль metasploit.

Если ваше приложение требует обработки данных из недоверенных источников, лучше использовать менее мощный и более безопасный формат сериализации и реализацию. Если ваши данные достаточно просты, Cpanel::JSON::XS или Data::MessagePack являются хорошими альтернативами. Для более сложных структур данных, содержащих различные специфичные для Perl типы данных, такие как регулярные выражения или алиасированные данные, Sereal является лучшей альтернативой и обеспечивает максимальную совместимость. Обратите внимание, что Sereal по умолчанию небезопасен, но вы можете настроить кодировщик и декодер, чтобы смягчить любые проблемы безопасности.

ПРЕДУПРЕЖДЕНИЕ

Если вы используете ссылки в качестве ключей в своих хеш-таблицах, вы, скорее всего, будете разочарованы при получении ваших данных. Действительно, Perl строит строки ссылок, используемых в качестве ключей хеш-таблицы. Если вы позже захотите получить доступ к элементам по другой строке ссылки (т. е. используя ту же ссылку, которая использовалась для ключа изначально, чтобы записать значение в хеш-таблицу), это будет работать, потому что обе ссылки строятся в одну и ту же строку.

Однако это не будет работать в последовательности операций store и retrieve, так как адреса в полученных объектах, которые являются частью строковых представлений ссылок, вероятно, будут отличаться от исходных адресов. Топология вашей структуры сохраняется, но не скрытые семантические значения, подобные этим.

В платформах, где это важно, не забудьте вызвать binmode() для описателей, которые вы передаёте в функции Storable.

Хранение данных в каноническом формате, содержащих большие хеши, может быть значительно медленнее, чем хранение тех же данных в обычном формате, поскольку необходимо выделять, заполнять, сортировать и освобождать временные массивы для хранения ключей каждого хеша. Некоторые тесты показали, что скорость хранения уменьшилась вдвое — точная величина штрафа зависит от сложности ваших данных. Замедления при получении данных нет.

РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ

Библиотека Storable теперь имеет экспериментальную поддержку хранения регулярных выражений, но существуют значительные ограничения:

  • Требуется perl 5.8 или более поздняя версия.

  • Регулярные выражения с блоками кода, например /(?{ ... })/ или /(??{ ... })/, вызовут исключение при размораживании.

  • Синтаксис и флаги регулярных выражений менялись на протяжении истории perl, поэтому регулярное выражение, замороженное в одной версии perl, может не разморозиться или работать по-другому в другой версии perl.

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

Storable сгенерирует исключение, если замороженное регулярное выражение не удастся разморозить.

ОШИБКИ

Вы не можете хранить GLOB, FORMLINE и т. д. Если вы можете определить семантику этих операций, не стесняйтесь улучшать Storable, чтобы он мог с ними работать.

Функции хранения croak, если они столкнутся с такими ссылками, если вы не установите $Storable::forgive_me на какое-то значение TRUE. В этом случае сообщение об ошибке преобразуется в предупреждение, и вместо него хранится бессмысленная строка.

Установка $Storable::canonical может привести к тому, что замороженные строки не будут совпадать из-за возможной строковой интерпретации чисел. Когда существует строковая версия скаляра, хранится именно она; поэтому, если вы используете числа в качестве строк между двумя операциями заморозки тех же структур данных, вы получите разные результаты.

При хранении двойных чисел в сетевом порядке их значение хранится в виде текста. Однако вы также не должны ожидать, что нечисловые значения с плавающей точкой, такие как бесконечность и «не число», успешно пройдут через пару nstore()/retrieve().

Поскольку Storable не знает и не заботится о наборах символов (хотя он знает, что символы могут иметь ширину более восьми бит), любая разница в интерпретации кодов символов между хост- и целевой системами — ваша проблема. В частности, если хост и целевая система используют разные кодовые точки для представления символов, используемых в текстовом представлении чисел с плавающей точкой, вы не сможете обмениваться данными с плавающей точкой, даже с помощью nstore().

Storable::drop_utf8 — грубый инструмент. Нет возможности вернуть все строки как последовательности utf8 или попытаться преобразовать данные utf8 обратно в 8-битные и croak(), если преобразование не удается.

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

64-битные данные в perl 5.6.0 и 5.6.1

Этот раздел относится только к вам, если у вас есть данные, записанные Storable 2.02 или более ранней версией в perl 5.6.0 или 5.6.1 на Unix или Linux, которые были сконфигурированы с поддержкой 64-битных целых чисел (не по умолчанию). Если вы использовали предварительно скомпилированный perl, а не запускали Configure для создания собственного perl из исходного кода, то это, скорее всего, вас не затронет, и вы можете прекратить чтение (если вас это не интересует). Если вы используете perl на Windows, это вас не затронет.

Storable записывает заголовок файла, который содержит размеры различных типов языка C для компилятора C, который построил Storable (если запись не выполняется в сетевом порядке), и откажется загружать файлы, записанные Storable на той же (или совместимой) архитектуре. Эта проверка и проверка порядка байтов машины необходимы, потому что размеры различных полей в файле определяются размерами типов языка C, поэтому файлы, записанные на разных архитектурах, несовместимы. Это сделано для повышения скорости. (При записи в сетевом порядке все поля записываются как стандартные длины, что позволяет полную совместимость, но требует больше времени на чтение и запись)

Perl 5.6.x ввел возможность необязательной настройки интерпретатора perl для использования типа C long long для хранения 64-битных целых чисел в 32-битных системах. Однако из-за того, как система конфигурации Perl генерировала файлы конфигурации C на платформах, отличных от Windows, и способа, которым Storable генерирует свой заголовок, в заголовке файла Storable не отражалось, использовал ли perl, выполняющий запись, 32 или 64-битные целые числа, несмотря на то, что Storable хранил некоторые данные в файле по-другому. Следовательно, Storable, работающий в perl с 64-битными целыми числами, будет читать заголовок из файла, записанного 32-битным perl, не осознавая, что данные фактически имеют незначительно несовместимый формат, и затем серьезно ошибётся (возможно, аварийно завершит работу), если встретит сохраненное целое число. Это ошибка проектирования.

Теперь Storable изменен так, чтобы записывать и считывать заголовок файла с информацией о размере целых чисел. Невозможно определить, был ли старый файл, который читается, записан с 32 или 64-битными целыми числами (у них один и тот же заголовок), поэтому невозможно автоматически переключиться на правильный режим обратной совместимости. Таким образом, по умолчанию Storable использует новое, правильное поведение.

Это означает, что если у вас есть данные, записанные Storable 1.x, работающим в perl 5.6.0 или 5.6.1, настроенным с 64-битными целыми числами на Unix или Linux, по умолчанию этот Storable откажется от их чтения, выдав ошибку Порядок байтов несовместим. Если у вас есть такие данные, вам следует установить $Storable::interwork_56_64bit в значение true, чтобы этот Storable читал и записывал файлы со старым заголовком. Вы также должны перенести свои данные или любой более старый perl, с которым вы общаетесь, на эту текущую версию Storable.

Если у вас нет данных, записанных с указанной выше конфигурацией perl, то вам ничего не нужно и не следует делать. Не устанавливайте флаг — Storable на идентично настроенном perl откажется загружать их, а Storable на другой настроенной версии perl загрузит их, полагая, что они корректны для него, и тогда вполне возможно, что он потерпит неудачу или аварийно завершит работу во время чтения.

АВТОРЫ

Благодарим (в хронологическом порядке):

Jarkko Hietaniemi <jhi@iki.fi>
Ulrich Pfeifer <pfeifer@charly.informatik.uni-dortmund.de>
Benjamin A. Holzman <bholzman@earthlink.net>
Andrew Ford <A.Ford@ford-mason.co.uk>
Gisle Aas <gisle@aas.no>
Jeff Gresham <gresham_jeffrey@jpmorgan.com>
Murray Nesbitt <murray@activestate.com>
Marc Lehmann <pcg@opengroup.org>
Justin Banks <justinb@wamnet.com>
Jarkko Hietaniemi <jhi@iki.fi> (AGAIN, as perl 5.7.0 Pumpkin!)
Salvador Ortiz Garcia <sog@msg.com.mx>
Dominic Dunlop <domo@computer.org>
Erik Haugan <erik@solbors.no>
Benjamin A. Holzman <ben.holzman@grantstreet.com>
Reini Urban <rurban@cpan.org>
Todd Rinaldo <toddr@cpanel.net>
Aaron Crane <arc@cpan.org>

за их сообщения об ошибках, предложения и вклад.

Benjamin Holzman внес вклад в поддержку связанных переменных, Andrew Ford — в канонический порядок для хешей, а Gisle Aas исправил несколько моих заблуждений относительно внутренней работы perl и оптимизировал вывод «тегов» в потоках вывода, просто подсчитывая объекты вместо их маркировки (что приводит к двоичной несовместимости для изображения Storable, начиная с версии 0.6 — более старые изображения, конечно, все еще правильно интерпретируются). Murray Nesbitt сделал Storable потокобезопасным. Marc Lehmann добавил поддержку перегрузки и ссылок на связанные элементы. Benjamin Holzman добавил улучшение производительности для перегруженных классов; благодарим Grant Street Group за оплату счета. Reini Urban взял на себя поддержку с p5p, и добавил исправления безопасности и поддержку больших объектов.

АВТОР

Storable был написан Raphael Manfredi <Raphael_Manfredi@pobox.com>. Сейчас поддержка осуществляется cperl http://perl11.org/cperl

Пожалуйста, отправляйте нам сообщения о проблемах, исправлениях ошибок, комментариях и жалобах, хотя если у вас есть комплименты, отправляйте их Raphael. Пожалуйста, не отправляйте Raphael сообщения о проблемах, так как он больше не работает над Storable, и ваше сообщение задержится, пока он не перенаправит его нам.

СМОТРИТЕ ТАКЖЕ

Clone.

© 1993–2023 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.38.0/Storable

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API