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 при проблемах с вводом-выводом или других внутренних ошибках, и true в противном случае. Серьёзные ошибки распространяются как исключение 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, никакой защиты не будет.
Внутренняя консультативная блокировка реализована с помощью процедуры flock() Perl. Если ваша система не поддерживает flock(), или вы используете файлы через NFS, вы можете использовать другие виды блокировки, используя модули, такие как LockFile::Simple, которые блокируют файл с помощью записи в файловой системе, а не блокировки дескриптора файла.
СКОРОСТЬ
Ядро Storable написано на C для обеспечения хорошей скорости. Были реализованы дополнительные оптимизации на низком уровне при манипулировании внутренними структурами Perl, чтобы пожертвовать инкапсуляцией в пользу большей скорости.
КАНОНИЧЕСКОЕ ПРЕДСТАВЛЕНИЕ
Обычно Storable сохраняет элементы хешей в порядке их внутреннего хранения в Perl, т.е. псевдослучайном. Если вы установите $Storable::canonical в некоторое TRUE значение, Storable будет сохранять хеши с элементами, отсортированными по ключу. Это позволяет сравнивать структуры данных путём сравнения их замороженных представлений (или даже сжатых замороженных представлений), что может быть полезно для создания таблиц поиска для сложных запросов.
Канонический порядок не подразумевает сетевой порядок; они являются двумя ортогональными настройками.
ССЫЛКИ НА КОД
Начиная с версии Storable 2.05, ссылки на код могут сериализовываться с помощью B::Deparse. Чтобы включить эту функцию, установите $Storable::Deparse в значение true. Для включения десериализации, $Storable::Eval должно быть установлено в значение true. Помните, что десериализация выполняется через 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_utf8true становится невозможно определить, были ли исходные данные строкой Юникода или последовательностью байтов, которые случайно являются допустимым 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, если она доступна.
Обычные ошибки сообщаются через возвращаемое undef значение store() или retrieve(). Такие ошибки обычно являются ошибками ввода-вывода (или ошибками усеченной потоковой передачи при извлечении).
Когда 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 желаемым образом.
Возвращаемое значение: none.
-
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 до 3.13 мы проверяли предел рекурсии стека для ссылок, массивов и хэшей до максимальной глубины ~1200-35000, в противном случае мы могли попасть в переполнение стека. В JSON::XS этот предел составляет 512. Если ссылки не ссылаются друг на друга непосредственно, такого предела пока нет, поэтому вы можете попасть в сегфолт из-за переполнения стека.
У этих проверок и выполненных нами проверок есть некоторые ограничения:
-
Размер стека во время компиляции может отличаться от размера стека во время выполнения, например, размер стека может быть изменён с помощью ulimit(1). Если он больше во время выполнения, Storable может необоснованно завершить freeze() или thaw(). Если он больше во время компиляции, Storable может получить сегментно-ошибочное сообщение при обработке глубокой структуры во время выполнения.
-
Размер стека может отличаться в потоке.
-
Пределы рекурсии для массивов и хэшей проверяются отдельно по отношению к той же глубине рекурсии; замороженная структура с большой последовательностью вложенных массивов внутри многих вложенных хэшей может исчерпать стек процессора, не вызвав защиты от рекурсии 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(). Обратите внимание, что GNU-реализация утилиты file, версия 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 могут привести к уязвимостям безопасности, если вы принимаете документы 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 или 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 для использования типа long long C, чтобы разрешить хранение 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
Пожалуйста, пишите нам с проблемами, исправлениями ошибок, комментариями и жалобами, хотя если у вас есть комплименты, вы должны отправить их Рафаэлю. Пожалуйста, не отправляйте Рафаэлю проблемы, так как он больше не работает над Storable, и ваше сообщение будет задержано, пока он не перенаправит его нам.
СМОТРИТЕ ТАКЖЕ
© 1993–2021 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.36.0/Storable