Storable
СОДЕРЖАНИЕ
- ИМЯ
- СИНТАКСИС
- ОПИСАНИЕ
- ХРАНЕНИЕ В ПАМЯТИ
- КОНСУЛЬТАТИВНАЯ БЛОКИРОВКА
- СКОРОСТЬ
- КАНОНИЧЕСКОЕ ПРЕДСТАВЛЕНИЕ
- ССЫЛКИ НА КОД
- ВЕРСИОННАЯ СОСТОЯТЕЛЬНОСТЬ
- ОТЧЕТ ОБ ОШИБКАХ
- ТОЛЬКО ДЛЯ МАСТЕРОВ
- Магия Storable
- ПРИМЕРЫ
- ПРЕДУПРЕЖДЕНИЕ О БЕЗОПАСНОСТИ
- ПРЕДУПРЕЖДЕНИЕ
- РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ
- ОШИБКИ
- АВТОРЫ
- АВТОР
- СМОТРИТЕ ТАКЖЕ
ИМЯ
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значением истинным становится невозможно определить, была ли исходные данные строкой Юникода или последовательностью байтов, которые случайно являются допустимым 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 ГБ элементов, но в cperl это приводит к ошибке. Сам 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_freezeobj, 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_thawobj, cloning, serialized, ... -
Вспомогательная функция десериализации, вызываемая для объекта во время десериализации. Но подождите: если мы десериализуем, разве объекта ещё нет?
Неправильно: механизм Storable создаёт пустой для вас. Если вы знаете Eiffel, вы можете рассматривать
STORABLE_thawкак альтернативную функцию создания.Это означает, что вспомогательная функция может наследоваться, как и любой другой метод, и что obj — это ваш освящённый указатель для этого конкретного экземпляра.
Другие аргументы должны быть знакомы, если вы знаете
STORABLE_freeze: cloning — true, когда мы участвуем в операции глубокого клонирования, serialized — сериализованная строка, которую вы вернули механизму вSTORABLE_freeze, и может быть необязательный список ссылок в том же порядке, что вы предоставили во время сериализации, указывающий на десериализованные объекты (которые были обработаны механизмом Storable).Если механизм Storable не находит вспомогательную функцию
STORABLE_thaw, он пытается загрузить класс, потребовав пакет динамически (используя имя освящённого пакета), а затем повторно пытается найти вспомогательную функцию. Если в этот момент вспомогательная функция не найдена, механизм генерирует ошибку. Обратите внимание, что этот механизм потерпит неудачу, если вы определите несколько классов в одном файле, но perlmod предупредил вас.Вам нужно использовать эту информацию, чтобы заполнить obj так, как вы хотите.
Возвращаемое значение: ничего.
-
STORABLE_attachclass, 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, мы проверяем предел рекурсии стека для ссылок, массивов и хешей до максимальной глубины ~1200-35000, иначе мы можем попасть в переполнение стека. В JSON::XS этот предел составляет 512. При ссылках, которые не ссылаются друг на друга непосредственно, такого ограничения пока нет, поэтому вы можете столкнуться с ошибкой переполнения стека (segfault).
У этой проверки и выполненных проверок есть некоторые ограничения:
-
Размер стека во время компиляции может отличаться от размера стека во время выполнения, например, размер стека может быть изменён с помощью ulimit(1). Если он больше во время выполнения, Storable может излишне вызвать ошибку при freeze() или thaw().
-
Размер стека может отличаться в потоке.
-
Пределы рекурсии для массивов и хешей проверяются отдельно по отношению к той же глубине рекурсии. Замороженная структура с большой последовательностью вложенных массивов внутри многих вложенных хешей может исчерпать стек процессора, не вызвав защиты от рекурсии Storable.
Вы можете контролировать максимальную глубину рекурсии для массивов и хешей, изменив
$Storable::recursion_limitи$Storable::recursion_limit_hashсоответственно. Любое из них можно установить в-1, чтобы предотвратить любые проверки глубины, хотя это не рекомендуется. -
-
Вы можете создать бесконечные циклы, если объекты, которые вы сериализуете с помощью 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(). Обратите внимание, что GNU-реализация утилиты file версии 3.38 или выше, помимо других типов файлов Perl, должна изначально содержать поддержку распознавания файлов Storable.
Вы также можете использовать следующие функции для извлечения информации о заголовке файла из изображений 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} перла, который создал это изображение. Это строка типа "1234" (32-битный малый порядок) или "87654321" (64-битный большой порядок). Это должно совпадать с текущим перлом, чтобы изображение было читаемым Storable. -
intsize,longsize,ptrsize,nvsize -
Эти элементы присутствуют только когда
netorderложно. Это размеры различных C-типов данных перла, который создал это изображение. Эти значения должны совпадать с текущим перлом, чтобы изображение было читаемым 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истинен, если изображение — это изображение файла.Если аргумент $must_be_file задан и равен ИСТИНА, то возвращается
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 могут привести к уязвимостям безопасности, если вы принимаете документы Storable из ненадежных источников с установленными по умолчанию флагами. Наиболее очевидно, что опциональная (по умолчанию выключенная) возможность сериализации ссылок 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 или Serial являются лучшими вариантами и обеспечивают максимальную совместимость, но обратите внимание, что Serial по умолчанию небезопасен.
ПРЕДУПРЕЖДЕНИЕ
Если вы используете ссылки в качестве ключей в своих хеш-таблицах, вас ждёт разочарование при получении данных. Действительно, 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::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 в истинное значение, чтобы этот 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, и ваше сообщение будет задержано, пока он не перенаправит его нам.
См. также
© 1993–2020 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.28.3/Storable