storable.html
来自「perl教程」· HTML 代码 · 共 740 行 · 第 1/3 页
HTML
740 行
whether the original data was the Unicode string, or a series of bytes
that happen to be valid utf8.</p>
</dd>
</li>
<dt><strong><a name="item_restricted_hashes">restricted hashes</a></strong>
<dd>
<p>Perl 5.8 adds support for restricted hashes, which have keys
restricted to a given set, and can have values locked to be read only.
By default, when Storable encounters a restricted hash on a perl
that doesn't support them, it will deserialize it as a normal hash,
silently discarding any placeholder keys and leaving the keys and
all values unlocked. To make Storable <code>croak()</code> instead, set
<code>$Storable::downgrade_restricted</code> to a <code>FALSE</code> value. To restore
the default set it back to some <code>TRUE</code> value.</p>
</dd>
</li>
<dt><strong><a name="item_files_from_future_versions_of_storable">files from future versions of Storable</a></strong>
<dd>
<p>Earlier versions of Storable would immediately croak if they encountered
a file with a higher internal version number than the reading Storable
knew about. Internal version numbers are increased each time new data
types (such as restricted hashes) are added to the vocabulary of the file
format. This meant that a newer Storable module had no way of writing a
file readable by an older Storable, even if the writer didn't store newer
data types.</p>
</dd>
<dd>
<p>This version of Storable will defer croaking until it encounters a data
type in the file that it does not recognize. This means that it will
continue to read files generated by newer Storable modules which are careful
in what they write out, making it easier to upgrade Storable modules in a
mixed environment.</p>
</dd>
<dd>
<p>The old behaviour of immediate croaking can be re-instated by setting
<code>$Storable::accept_future_minor</code> to some <code>FALSE</code> value.</p>
</dd>
</li>
</dl>
<p>All these variables have no effect on a newer Perl which supports the
relevant feature.</p>
<p>
</p>
<hr />
<h1><a name="error_reporting">ERROR REPORTING</a></h1>
<p>Storable uses the "exception" paradigm, in that it does not try to workaround
failures: if something bad happens, an exception is generated from the
caller's perspective (see <a href="../lib/Carp.html">the Carp manpage</a> and <code>croak()</code>). Use eval {} to trap
those exceptions.</p>
<p>When Storable croaks, it tries to report the error via the <code>logcroak()</code>
routine from the <code>Log::Agent</code> package, if it is available.</p>
<p>Normal errors are reported by having <code>store()</code> or <code>retrieve()</code> return <a href="../lib/Pod/perlfunc.html#item_undef"><code>undef</code></a>.
Such errors are usually I/O errors (or truncated stream errors at retrieval).</p>
<p>
</p>
<hr />
<h1><a name="wizards_only">WIZARDS ONLY</a></h1>
<p>
</p>
<h2><a name="hooks">Hooks</a></h2>
<p>Any class may define hooks that will be called during the serialization
and deserialization process on objects that are instances of that class.
Those hooks can redefine the way serialization is performed (and therefore,
how the symmetrical deserialization should be conducted).</p>
<p>Since we said earlier:</p>
<pre>
dclone(.) = thaw(freeze(.))</pre>
<p>everything we say about hooks should also hold for deep cloning. However,
hooks get to know whether the operation is a mere serialization, or a cloning.</p>
<p>Therefore, when serializing hooks are involved,</p>
<pre>
dclone(.) <> thaw(freeze(.))</pre>
<p>Well, you could keep them in sync, but there's no guarantee it will always
hold on classes somebody else wrote. Besides, there is little to gain in
doing so: a serializing hook could keep only one attribute of an object,
which is probably not what should happen during a deep cloning of that
same object.</p>
<p>Here is the hooking interface:</p>
<dl>
<dt><strong><a name="item_storable_freeze_obj_2c_cloning"><code>STORABLE_freeze</code> <em>obj</em>, <em>cloning</em></a></strong>
<dd>
<p>The serializing hook, called on the object during serialization. It can be
inherited, or defined in the class itself, like any other method.</p>
</dd>
<dd>
<p>Arguments: <em>obj</em> is the object to serialize, <em>cloning</em> is a flag indicating
whether we're in a <code>dclone()</code> or a regular serialization via <code>store()</code> or freeze().</p>
</dd>
<dd>
<p>Returned value: A LIST <code>($serialized, $ref1, $ref2, ...)</code> where $serialized
is the serialized form to be used, and the optional $ref1, $ref2, etc... are
extra references that you wish to let the Storable engine serialize.</p>
</dd>
<dd>
<p>At deserialization time, you will be given back the same LIST, but all the
extra references will be pointing into the deserialized structure.</p>
</dd>
<dd>
<p>The <strong>first time</strong> the hook is hit in a serialization flow, you may have it
return an empty list. That will signal the Storable engine to further
discard that hook for this class and to therefore revert to the default
serialization of the underlying Perl data. The hook will again be normally
processed in the next serialization.</p>
</dd>
<dd>
<p>Unless you know better, serializing hook should always say:</p>
</dd>
<dd>
<pre>
<span class="keyword">sub</span><span class="variable"> STORABLE_freeze </span><span class="operator">{</span>
<span class="keyword">my</span> <span class="operator">(</span><span class="variable">$self</span><span class="operator">,</span> <span class="variable">$cloning</span><span class="operator">)</span> <span class="operator">=</span> <span class="variable">@_</span><span class="operator">;</span>
<span class="keyword">return</span> <span class="keyword">if</span> <span class="variable">$cloning</span><span class="operator">;</span> <span class="comment"># Regular default serialization</span>
<span class="operator">....</span>
<span class="operator">}</span>
</pre>
</dd>
<dd>
<p>in order to keep reasonable <code>dclone()</code> semantics.</p>
</dd>
</li>
<dt><strong><a name="item_storable_thaw_obj_2c_cloning_2c_serialized_2c__2e_"><code>STORABLE_thaw</code> <em>obj</em>, <em>cloning</em>, <em>serialized</em>, ...</a></strong>
<dd>
<p>The deserializing hook called on the object during deserialization.
But wait: if we're deserializing, there's no object yet... right?</p>
</dd>
<dd>
<p>Wrong: the Storable engine creates an empty one for you. If you know Eiffel,
you can view <code>STORABLE_thaw</code> as an alternate creation routine.</p>
</dd>
<dd>
<p>This means the hook can be inherited like any other method, and that
<em>obj</em> is your blessed reference for this particular instance.</p>
</dd>
<dd>
<p>The other arguments should look familiar if you know <code>STORABLE_freeze</code>:
<em>cloning</em> is true when we're part of a deep clone operation, <em>serialized</em>
is the serialized string you returned to the engine in <code>STORABLE_freeze</code>,
and there may be an optional list of references, in the same order you gave
them at serialization time, pointing to the deserialized objects (which
have been processed courtesy of the Storable engine).</p>
</dd>
<dd>
<p>When the Storable engine does not find any <code>STORABLE_thaw</code> hook routine,
it tries to load the class by requiring the package dynamically (using
the blessed package name), and then re-attempts the lookup. If at that
time the hook cannot be located, the engine croaks. Note that this mechanism
will fail if you define several classes in the same file, but <a href="../lib/Pod/perlmod.html">the perlmod manpage</a>
warned you.</p>
</dd>
<dd>
<p>It is up to you to use this information to populate <em>obj</em> the way you want.</p>
</dd>
<dd>
<p>Returned value: none.</p>
</dd>
</li>
<dt><strong><a name="item_storable_attach_class_2c_cloning_2c_serialized"><code>STORABLE_attach</code> <em>class</em>, <em>cloning</em>, <em>serialized</em></a></strong>
<dd>
<p>While <code>STORABLE_freeze</code> and <code>STORABLE_thaw</code> are useful for classes where
each instance is independant, this mechanism has difficulty (or is
incompatible) with objects that exist as common process-level or
system-level resources, such as singleton objects, database pools, caches
or memoized objects.</p>
</dd>
<dd>
<p>The alternative <code>STORABLE_attach</code> method provides a solution for these
shared objects. Instead of <code>STORABLE_freeze</code> --> <code>STORABLE_thaw</code>,
you implement <code>STORABLE_freeze</code> --> <code>STORABLE_attach</code> instead.</p>
</dd>
<dd>
<p>Arguments: <em>class</em> is the class we are attaching to, <em>cloning</em> is a flag
indicating whether we're in a <code>dclone()</code> or a regular de-serialization via
thaw(), and <em>serialized</em> is the stored string for the resource object.</p>
</dd>
<dd>
<p>Because these resource objects are considered to be owned by the entire
process/system, and not the "property" of whatever is being serialized,
no references underneath the object should be included in the serialized
string. Thus, in any class that implements <code>STORABLE_attach</code>, the
<code>STORABLE_freeze</code> method cannot return any references, and <code>Storable</code>
will throw an error if <code>STORABLE_freeze</code> tries to return references.</p>
</dd>
<dd>
<p>All information required to "attach" back to the shared resource object
<strong>must</strong> be contained <strong>only</strong> in the <code>STORABLE_freeze</code> return string.
Otherwise, <code>STORABLE_freeze</code> behaves as normal for <code>STORABLE_attach</code>
classes.</p>
</dd>
<dd>
<p>Because <code>STORABLE_attach</code> is passed the class (rather than an object),
it also returns the object directly, rather than modifying the passed
object.</p>
</dd>
<dd>
<p>Returned value: object of type <code>class</code></p>
</dd>
</li>
</dl>
<p>
</p>
<h2><a name="predicates">Predicates</a></h2>
<p>Predicates are not exportable. They must be called by explicitly prefixing
them with the Storable package name.</p>
<dl>
<dt><strong><a name="item_storable_3a_3alast_op_in_netorder"><code>Storable::last_op_in_netorder</code></a></strong>
<dd>
<p>The <code>Storable::last_op_in_netorder()</code> predicate will tell you whether
network order was used in the last store or retrieve operation. If you
don't know how to use this, just forget about it.</p>
</dd>
</li>
<dt><strong><a name="item_storable_3a_3ais_storing"><code>Storable::is_storing</code></a></strong>
<dd>
<p>Returns true if within a store operation (via STORABLE_freeze hook).</p>
</dd>
</li>
<dt><strong><a name="item_storable_3a_3ais_retrieving"><code>Storable::is_retrieving</code></a></strong>
<dd>
<p>Returns true if within a retrieve operation (via STORABLE_thaw hook).</p>
</dd>
</li>
</dl>
<p>
</p>
<h2><a name="recursion">Recursion</a></h2>
<p>With hooks comes the ability to recurse back to the Storable engine.
Indeed, hooks are regular Perl code, and Storable is convenient when
it comes to serializing and deserializing things, so why not use it
to handle the serialization string?</p>
<p>There are a few things you need to know, however:</p>
<ul>
<li>
<p>You can create endless loops if the things you serialize via <code>freeze()</code>
(for instance) point back to the object we're trying to serialize in
the hook.</p>
</li>
<li>
<p>Shared references among objects will not stay shared: if we're serializing
the list of object [A, C] where both object A and C refer to the SAME object
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?