Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > bd5c3d824c3db63ffd9226c15941e6ad > files > 112

mozart-1.4.0-1mdv2010.0.i586.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD><TITLE>4 Pickles for Persistent Data Structures</TITLE><LINK href="ozdoc.css" rel="stylesheet" type="text/css"></HEAD><BODY><TABLE align="center" border="0" cellpadding="6" cellspacing="6" class="nav"><TR bgcolor="#DDDDDD"><TD><A href="node4.html#chapter.modman">&lt;&lt; Prev</A></TD><TD><A href="node1.html">- Up -</A></TD><TD><A href="node6.html#chapter.mof">Next &gt;&gt;</A></TD></TR></TABLE><DIV id="chapter.pickle"><H1><A name="chapter.pickle">4 Pickles for Persistent Data Structures</A></H1><P> Applications often require to store their state on file and load the saved data later. Oz supports this by <EM>pickling</EM> of data structures: Data structures are made persistent by writing them to files. </P><DIV id="section.pickle.values"><H2><A name="section.pickle.values">4.1 Stateless, Stateful, and Sited Nodes</A></H2><P> Values, or more precisely nodes,<A href="node5.html#label18"><SUP>1</SUP></A> in Oz are either stateless or stateful: </P><DL><DT>Stateful </DT><DD><P>Basic data structures that are <EM>stateful</EM> include cells, variables, and ports. Since objects, arrays and dictionaries are conceptually composed of cells, they are stateful as well. </P></DD><DT>Stateless </DT><DD><P><EM>Stateless</EM> data structures are literals, numbers, records, classes, chunks, and procedures. </P></DD></DL><P> </P><P> In addition, nodes in the store can be <EM>sited</EM>: the node is specific to a particular site; it is a site-bound resource. For example, classes for files (<CODE>Open<SPAN class="keyword">.</SPAN>file</CODE>) and widget classes for graphics (for example, <CODE>Tk<SPAN class="keyword">.</SPAN>toplevel</CODE>) are sited. </P><P> Only stateless and un-sited nodes can be made persistent by pickling. </P></DIV><DIV id="section.pickle.operations"><H2><A name="section.pickle.operations">4.2 Loading and Saving Values</A></H2><P> After executing the following statement </P><BLOCKQUOTE class="code"><CODE>X=a(<SPAN class="keyword">proc</SPAN><SPAN class="variablename">&nbsp;</SPAN>{<SPAN class="functionname">$</SPAN>&nbsp;Y}&nbsp;Y=X&nbsp;<SPAN class="keyword">end</SPAN>&nbsp;1&nbsp;2&nbsp;f:X)</CODE></BLOCKQUOTE><P> <CODE>X</CODE> refers to a record node. The node can be <EM>saved</EM> or <EM>pickled</EM> to the file <CODE>test.ozp</CODE> by executing </P><BLOCKQUOTE class="code"><CODE>{Pickle<SPAN class="keyword">.</SPAN>save&nbsp;X&nbsp;<SPAN class="string">'test.ozp'</SPAN>}</CODE></BLOCKQUOTE><P> </P><P> Pickling traverses the entire graph reachable from the root node (which is referred to by <CODE>X</CODE> in our example), creates a portable description of the graph and writes the description to a file. </P><P> The pickled data structure can be loaded by </P><BLOCKQUOTE class="code"><CODE>Z={Pickle<SPAN class="keyword">.</SPAN>load&nbsp;<SPAN class="string">'test.ozp'</SPAN>}</CODE></BLOCKQUOTE><P> Now <CODE>Z</CODE> refers to a graph which is an isomorphic clone of the graph that has been saved. For our example this means: what can be reached from <CODE>X</CODE> and <CODE>Z</CODE> is equal. For example </P><BLOCKQUOTE class="code"><CODE>X<SPAN class="keyword">.</SPAN>1<SPAN class="keyword">==</SPAN>Z<SPAN class="keyword">.</SPAN>1</CODE></BLOCKQUOTE><P> evaluates to <CODE><SPAN class="keyword">true</SPAN></CODE>. In fact, <CODE>X</CODE> and <CODE>Z</CODE> cannot be distinguished. </P><P> Loading of pickles works across the internet: it is possible to give a url rather than just a filename. For example, if you have a public html directory <CODE>~/public_html</CODE> and you move the pickle file <CODE>test.ozp</CODE> there, everybody can load the pickle across the internet. Suppose that the url of your public html directory is <CODE>http://www.ps.uni-sb.de/~schulte/</CODE>, then the pickle can be loaded by </P><BLOCKQUOTE class="code"><CODE>Z={Pickle<SPAN class="keyword">.</SPAN>load&nbsp;<SPAN class="string">'http://www.ps.uni-sb.de/~schulte/test.ozp'</SPAN>}</CODE></BLOCKQUOTE><P> </P></DIV><DIV id="section.pickle.db"><H2><A name="section.pickle.db">4.3 Example: The Data Base Revisited</A></H2><P> To extend the data base we developed in <A href="node3.html#section.development.db">Section&nbsp;2.3</A> with persistence, we just add two procedures to load and save a data base and extend the export specification accordingly. The toplevel structure of the functor definition is as follows: </P><P></P><DL><DT><SPAN class="chunktitle"><SPAN class="chunkborder">&lt;</SPAN><A name="label15">PDB.oz</A><SPAN class="chunkborder">&gt;=</SPAN></SPAN></DT><DD class="code"><CODE><SPAN class="keyword">functor</SPAN>&nbsp;<BR>&nbsp;&nbsp;<SPAN class="keyword">import</SPAN>&nbsp;Pickle<BR>&nbsp;&nbsp;</CODE><SPAN class="chunktitle"><SPAN class="chunkborder">&lt;</SPAN><A href="node5.html#label16">Export specification for PDB.oz</A><SPAN class="chunkborder">&gt;</SPAN></SPAN><CODE>&nbsp;<BR>&nbsp;&nbsp;</CODE><SPAN class="chunktitle"><SPAN class="chunkborder">&lt;</SPAN><A href="node5.html#label17">Body for PDB.oz</A><SPAN class="chunkborder">&gt;</SPAN></SPAN><CODE>&nbsp;<BR><SPAN class="keyword">end</SPAN></CODE></DD></DL><P> </P><P> The functor imports the system module <CODE>Pickle</CODE>. The export specification is just extended by the fields <CODE>load</CODE> and <CODE>save</CODE>. </P><P></P><DL><DT><SPAN class="chunktitle"><SPAN class="chunkborder">&lt;</SPAN><A name="label16">Export specification for PDB.oz</A><SPAN class="chunkborder">&gt;=</SPAN></SPAN></DT><DD class="code"><SPAN class="chunktitle"><SPAN class="chunkborder">&lt;</SPAN><A href="node3.html#label11">Export specification for DB.oz</A><SPAN class="chunkborder">&gt;</SPAN></SPAN><CODE>&nbsp;<BR>&nbsp;&nbsp;&nbsp;load:&nbsp;Load<BR>&nbsp;&nbsp;&nbsp;save:&nbsp;Save</CODE></DD></DL><P> </P><P> The body for <CODE>PDB.oz</CODE> is as follows: </P><DL><DT><SPAN class="chunktitle"><SPAN class="chunkborder">&lt;</SPAN><A name="label17">Body for PDB.oz</A><SPAN class="chunkborder">&gt;=</SPAN></SPAN></DT><DD class="code"><SPAN class="chunktitle"><SPAN class="chunkborder">&lt;</SPAN><A href="node24.html#label72">Body for DB.oz</A><SPAN class="chunkborder">&gt;</SPAN></SPAN><CODE>&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;<SPAN class="keyword">proc</SPAN><SPAN class="variablename">&nbsp;</SPAN>{<SPAN class="functionname">Save</SPAN>&nbsp;File}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{Pickle<SPAN class="keyword">.</SPAN>save&nbsp;{Ctr&nbsp;get($)}<SPAN class="keyword">#</SPAN>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{Dictionary<SPAN class="keyword">.</SPAN>toRecord&nbsp;db&nbsp;Data}&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File}<BR>&nbsp;&nbsp;&nbsp;<SPAN class="keyword">end</SPAN>&nbsp;<BR>&nbsp;&nbsp;&nbsp;<SPAN class="keyword">proc</SPAN><SPAN class="variablename">&nbsp;</SPAN>{<SPAN class="functionname">Load</SPAN>&nbsp;File}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I<SPAN class="keyword">#</SPAN>D={Pickle<SPAN class="keyword">.</SPAN>load&nbsp;File}<BR>&nbsp;&nbsp;&nbsp;<SPAN class="keyword">in</SPAN>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{Dictionary<SPAN class="keyword">.</SPAN>removeAll&nbsp;Data}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{Ctr&nbsp;init(I)}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{Record<SPAN class="keyword">.</SPAN>forAllInd&nbsp;D<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class="keyword">proc</SPAN><SPAN class="variablename">&nbsp;</SPAN>{<SPAN class="functionname">$</SPAN>&nbsp;K&nbsp;E}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{Dictionary<SPAN class="keyword">.</SPAN>put&nbsp;Data&nbsp;K&nbsp;E}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class="keyword">end</SPAN>}<BR>&nbsp;&nbsp;&nbsp;<SPAN class="keyword">end</SPAN></CODE></DD></DL><P> </P><P> <CODE>Save</CODE> takes as input the filename of the pickle, whereas <CODE>Load</CODE> takes the url from which the pickle can be loaded. </P><P> When using the persistent data base, it has to be kept in mind that it does not offer concurrency control: Simultaneous add and remove, as well as load and save operations performed by several threads might leave the data base in an inconsistent state. In ??? we will develop the data base in a data base server that also allows for concurrency control. </P><P> Note that since we only extended the functionality the functor provides, all programs that used the non-persistent data base could, in principle, still use the persistent data base with out being recompiled. We say <EM>could</EM> because the implementaion of the persistent database is named <CODE>PDB.ozf</CODE> rather than <CODE>DB.ozf</CODE>. However, you can give it a try and simply rename <CODE>PDB.ozf</CODE> to <CODE>DB.ozf</CODE>: all applications based on the the non-persistent implementation will continue to work as before but now using the persistent implementation (though without actually taking advantage of the persistency). </P></DIV><DIV id="section.pickle.compression"><H2><A name="section.pickle.compression">4.4 Pickle Compression</A></H2><P> Pickles can also be compressed so that they occupy less space on disk. For example, a compressed pickle for <CODE>X</CODE> can be written to file <CODE>testz.ozp</CODE> by </P><BLOCKQUOTE class="code"><CODE>{Pickle<SPAN class="keyword">.</SPAN>saveCompressed&nbsp;X&nbsp;<SPAN class="string">'testz.ozp'</SPAN>&nbsp;</CODE><CODE><I>LevelI</I></CODE><CODE>}</CODE></BLOCKQUOTE><P> <CODE><I>LevelI</I></CODE> is an integer between <CODE>0</CODE> and <CODE>9</CODE> specifying the compression level: the higher the value the better the compression, but the longer pickling takes. A value of <CODE>0</CODE> gives no compression. </P><P> Compression time and ratio depend on the data being pickled. The compression ratio might vary between 20 and 80 percent, while compression at level 9 is usually less than 2 times slower than using no compression. </P></DIV></DIV><TABLE align="center" border="0" cellpadding="6" cellspacing="6" class="nav"><TR bgcolor="#DDDDDD"><TD><A href="node4.html#chapter.modman">&lt;&lt; Prev</A></TD><TD><A href="node1.html">- Up -</A></TD><TD><A href="node6.html#chapter.mof">Next &gt;&gt;</A></TD></TR></TABLE><HR align="left" width="30%"><DIV class="footnote"><A name="label18">1. </A>A node may also be an unbound variable, i.&nbsp;e. a value that is not yet determined</DIV><HR><ADDRESS><A href="http://www.ps.uni-sb.de/~duchier/">Denys&nbsp;Duchier</A>, <A href="http://www.ps.uni-sb.de/~kornstae/">Leif&nbsp;Kornstaedt</A> and&nbsp;<A href="http://www.ps.uni-sb.de/~schulte/">Christian&nbsp;Schulte</A><BR><SPAN class="version">Version 1.4.0 (20090610)</SPAN></ADDRESS></BODY></HTML>