Merge lp:~pbeaman/akiban-persistit/sphinxdoc-release-notes into lp:akiban-persistit

Proposed by Peter Beaman
Status: Merged
Approved by: Nathan Williams
Approved revision: 314
Merged at revision: 312
Proposed branch: lp:~pbeaman/akiban-persistit/sphinxdoc-release-notes
Merge into: lp:akiban-persistit
Diff against target: 4768 lines (+2646/-1989)
26 files modified
doc/BasicAPI.rst (+332/-0)
doc/BasicAPI.txt (+0/-320)
doc/Configuration.rst (+273/-0)
doc/Configuration.txt (+0/-246)
doc/GettingStarted.rst (+270/-0)
doc/GettingStarted.txt (+0/-255)
doc/Management.rst (+446/-0)
doc/Management.txt (+0/-360)
doc/Miscellaneous.rst (+36/-0)
doc/Miscellaneous.txt (+0/-32)
doc/PhysicalStorage.rst (+142/-0)
doc/PhysicalStorage.txt (+0/-126)
doc/ReleaseNotes.rst (+84/-0)
doc/Security.rst (+93/-0)
doc/Security.txt (+0/-91)
doc/Serialization.rst (+250/-0)
doc/Serialization.txt (+0/-246)
doc/TOC.txt (+0/-19)
doc/Transactions.rst (+200/-0)
doc/Transactions.txt (+0/-179)
doc/build/build-doc.sh (+25/-8)
doc/build/build-doc.sh.orig (+48/-0)
doc/build/src/SphinxDocPrep.java (+147/-0)
doc/conf.py (+285/-0)
doc/index.rst (+15/-0)
doc/overview-summary.txt (+0/-107)
To merge this branch: bzr merge lp:~pbeaman/akiban-persistit/sphinxdoc-release-notes
Reviewer Review Type Date Requested Status
Nathan Williams Approve
Review via email: mp+108031@code.launchpad.net

Description of the change

This branch includes some work previously done but never proposed in lp:~pbeaman/akiban-persistit/sphinxdoc-1, and new work on the release notes.

This branch only changes the doc directory.

Changes:

Convert all the asciidoc source files to sphinx. Files xxx.txt are removed and different files xxx.rst are added with formatting encoded for sphinx.

Content edits in some files resulting from the change.

New doc/build/build.sh script which now places all output in the target directory.

With these changes you must have sphinx (v 1.1.3) to run the build process. A new Java program, SphinxDocPrep does the appropriate text replacements in the sphinx-formatted files. The result of running build.sh is:

    target/sphinx/source - .rst source files with links to the apidocs

    target/sphinx/html - html files resulting from running sphinx-build. Included: ReleaseNotes.html in HTML format.

    target/sphinx/text/ReleaseNotes - releases notes in flat text, suitable for pasting into Launchpad.

To post a comment you must log in.
Revision history for this message
Nathan Williams (nwilliams) wrote :

Looks plausible.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'doc/BasicAPI.rst'
2--- doc/BasicAPI.rst 1970-01-01 00:00:00 +0000
3+++ doc/BasicAPI.rst 2012-05-30 18:23:19 +0000
4@@ -0,0 +1,332 @@
5+.. _Basic-API:
6+
7+Basic API
8+=========
9+
10+Akiban Persistit stores data as key-value pairs in highly optimized B-Tree. (Actually, implements `B-Link Tree <http://www.cs.cornell.edu/courses/cs4411/2009sp/blink.pdf>`_ trees for greater concurrency). Like a Java Map implementation, Persistit associates at most one value with each unique instance of a Key value.
11+
12+Persistit provides classes and methods to access and modify keys and their associated values. Application code calls Persistit API methods to store, fetch, traverse and remove keys and records to and from the database.
13+
14+Persistit permits efficient multi-threaded concurrent access to database volumes. It is designed to minimize contention for critical resources and to maximize throughput on multi-processor machines. Concurrent ACID transactions are supported with multi-value concurrency control (MVCC).
15+
16+The Persistit Instance
17+----------------------
18+
19+To access Persistit, the application first constructs an instance of the ``com.persistit.Persistit`` class and initializes it. This instance is the keystone of all subsequent operations. It holds references to the buffers, maps, transaction contexts and other structures needed to access B-trees. The life cycle of a Persistit instance should be managed as follows:
20+
21+.. code-block:: java
22+
23+ final Persistit db = new Persistit();
24+ //
25+ // register any Coder and Renderer instances before initialization
26+ //
27+ db.initialize(configProperties);
28+ try {
29+ // do application work
30+ } finally {
31+ db.close();
32+ }
33+
34+The ``configProperties`` describe the memory allocation, initial set of volumes, the journal, and other settings needed to get Persistit started. See :ref:`Configuration` for details.
35+
36+The ``com.persistit.Persistit#close`` method gracefully flushes all modified data to disk, stops background threads and unregisters JMX MBeans.
37+
38+.. note::
39+
40+ The Persistit background threads are not daemon threads, so if your application returns
41+ from its static main method without calling ``close``, the JVM will not automatically exit.
42+
43+Although normal shutdown should always invoke ``close``, Persistit is designed to recover a consistent database state in the event of an abrupt shutdown or crash. See :ref:`Recovery`.
44+
45+.. _Key:
46+
47+Key
48+---
49+
50+The content of a ``com.persistit.Key`` is the unique identifier for a key/value pair within a tree. Internally a ``Key`` contains an array of bytes that constitute the physical identity of the key/value pair within a tree. Logically, a key consists of a sequence of zero or more Java values, each of which is called a *key segment*.
51+
52+The following value types are implicitly supported in keys::
53+
54+ null
55+ boolean (and Boolean)
56+ byte (and Byte)
57+ short (and Short)
58+ char (and Character)
59+ int (and Integer)
60+ long (and Long)
61+ float (and Float)
62+ double (and Double)
63+ java.lang.String
64+ java.math.BigInteger
65+ java.math.BigDecimal
66+ java.util.Date
67+ byte[]
68+
69+In addition, you may register custom implementations of the ``com.persistit.encoding.KeyCoder`` interface to support encoding of other object classes. By default, String values are encoded in UTF-8 format.
70+
71+Appending and Decoding Key Segments
72+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
73+
74+The ``Key`` class provides methods to encode and decode each of these types to and from a key segment. For each type listed above, there is an ``append`` method, a ``to`` method and a ``decode`` method. For example, for the long type, there are methods
75+
76+.. code-block:: java
77+
78+ public void append(long v)
79+ public void to(long v)
80+ public long decodeLong()
81+
82+The ``to`` methods replaces the final key segment with a different value (unless the key is empty, in which case it works the same as ``append``).
83+
84+For example:
85+
86+.. code-block:: java
87+
88+ key.clear(); // clear any previous key segments
89+ key.append("Atlantic"); // append segment "Atlantic"
90+ key.to("Pacific"); // replace "Atlantic" with "Pacific"
91+ key.reset(); // reset index to beginning
92+ String s = key.decode(); // s contains "Pacific"
93+
94+The Key class also provides methods to encode and decode Object values to and from a key. Strings, Dates, objects of the corresponding wrapper classes for the primitive types listed above, and objects supported by registered instances of ``com.persistit.encoding.KeyCoder`` are permitted. Primitive values are automatically boxed and unboxed as needed. The following code fragment demonstrates key manipulation with automatic conversion of primitive types and their wrappers.
95+
96+.. code-block:: java
97+
98+ key.clear(); // clear any previous key segments
99+ key.append(new Integer(1234));
100+ key.append("Atlantic");
101+ key.append(1.23d);
102+ key.reset(); // reset index to beginning for decoding
103+ int v = key.decodeInt(); // v will be 1234
104+ String s = (String)key.decode(); // s will be "Atlantic"
105+ Double d = (Double)decode(); // d will be 1.23d as a Double
106+
107+In this code segment, an object of type Integer is appended to the key’s value sequence, and then the same value is later decoded as a primitive int value. A String is appended and then decoded into a String. Finally, a primitive double value is appended and then decoded as an object of class Double.
108+
109+The maximum size of a serialized ``Key`` is 2,047 bytes.
110+
111+For further information, see ``com.persistit.Key``.
112+
113+
114+.. _Value:
115+
116+Value
117+-----
118+
119+A ``com.persistit.Value`` object holds a value. Unlike keys, Value objects have no restriction on the types of data they can represent, and they can hold much larger objects. In particular, a Value may contain null, any of the primitive types, or an object of any class.
120+
121+The backing store of a ``Value`` is a byte array that is written to a B-Tree data page, or in the case of a long record, multiple pages. The ``com.persistit.Value#put`` method variants encode (serialize) a Java primitive or Object value into the backing store, and the ``com.persistit.Value#get`` method variants decode (deserialize) the value.
122+
123+For example, in ``HelloWorld.java``, the line
124+
125+.. code-block:: java
126+
127+ dbex.getValue().put("World");
128+
129+serializes the String “World”, and the expression
130+
131+.. code-block:: java
132+
133+ dbex.getValue().get()
134+
135+decodes it. Persistit does not intrinsically cache decoded object values, nor does it track an object's state changes. Each call to the ``get()`` method returns a new instance of the object. However, you can use a ``com.persistit.encoding.ObjectCache`` to cache object values. ``ObjectCache`` is designed specifically to cache objects fetched from Persistit.
136+
137+Value Types
138+^^^^^^^^^^^
139+
140+``Value`` provides optimized predefined representations for the following types::
141+
142+ null
143+ all primitive types
144+ all arrays
145+ java.math.BigInteger
146+ java.math.BigDecimal
147+ java.lang.String
148+ java.util.Date
149+
150+In general, Persistit uses one of four mechanisms to encode a Java value into a Value object:
151+
152+- If the value is one of the predefined types listed above, Persistit uses its own internal serialization logic.
153+- If there is a registered ``com.persistit.encoding.ValueCoder`` for the object's class, Persistit delegates to it.
154+- If enabled, Persistit uses an accelerated serialization/deserialization mechanism to encode and decode objects.
155+- Otherwise, for classes that implement java.io.Serializable, Persistit attempts to perform default Java serialization and deserialization.
156+
157+A Value may also be in the undefined state, which results from performing a fetch operation on a key for which no value is present in the database. The undefined state is distinct from the value ``null`` and can be tested with the ``isDefined()`` method.
158+
159+See :ref:`Serialization` for additional information.
160+
161+Large Values
162+^^^^^^^^^^^^
163+
164+Persistit stores large values, in the current version up to 64MB in size. For example, it is possible to store an image’s backing bytes as a single value in the database. The size of the value to be stored is constrained by available heap memory; the entire value must be able to be serialized into an in-memory byte array in order for Persistit to store or retrieve it. Use ``com.persistit.Value#setMaximumSize`` to specify a the size constraint. Large values are broken up across multiple data pages and are not necessarily stored in contiguous file areas.
165+
166+The definition of “large” depends on the configuration properties. for example, for a volume with a page size of 16K bytes the threshold occurs at 6,108 bytes. A value having a serialized size smaller than this is stored in a single data page while a larger value is broken up and stored in multiple pages. For a smaller pages size the threshold is lower.
167+
168+On occasion it may be desirable to fetch only part of a large value. For example, it may be useful to extract summary information from the beginning of a the backing byte array for an Image. Variants versions of the ``fetch`` and ``traverse`` accept a minimum byte count parameter. When these methods are used only the specified minimum number bytes of the backing store are retrieved from the database. This technique can prevent Persistit from reading large numbers of pages from the disk in order to examine only a small portion of the record.
169+
170+.. _Exchange:
171+
172+Exchange
173+--------
174+
175+The primary low-level interface for interacting with Persistit is ``com.persistit.Exchange``. The Exchange class provides all methods for storing, deleting, fetching and traversing key/value pairs. These methods are summarized here and described in detail in the Javadoc API documentation.
176+
177+An Exchange instance contains references to a ``Key`` and a ``Value``. The methods ``com.persistit.Exchange.getKey()`` and ``com.persistit.Exchange.getValue()`` access these instances.
178+
179+To construct an Exchange you specify a Volume (or alias) and a tree name in its constructor. The constructor will optionally create a new tree in that Volume if a tree having the specified name has not already been created. An application may construct an arbitrary number of Exchange objects. Creating a new Exchange has no effect on the database if the specified tree already exists. Tree creation is thread-safe: multiple threads concurrently constructing Exchanges using the same Tree name will safely result in the creation of only one new tree.
180+
181+An Exchange is a moderately complex object that can consume tens of kilobytes to megabytes (depending on the sizes of the Key and Value) of heap space. Memory-constrained applications should construct Exchanges in moderatation.
182+
183+Persistit offers Exchange pooling to avoid rapidly creating and destroying Exchange objects in multi-threaded applications. An application may use the ``com.persistit.Persistit#getExchange`` and ``com.persistit.Persistit#releaseExchange`` methods to take and return an Exchange from and to a thread-local pool.
184+
185+An Exchange internally maintains some optimization information such that references to nearby Keys within a tree are accelerated. Performance may benefit from using a different Exchange for each area of the Tree being accessed.
186+
187+Concurrent Operations on Exchanges
188+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
189+
190+Although the underlying Persistit database is designed for highly concurrent multi-threaded operation, the ``Exchange`` class and its associated ``Key`` and ``Value`` instances are *not* thread-safe. Each thread should acquire and use its own Exchange objects when accessing the database. Nonetheless, multiple threads can execute database operations on overlapping data concurrently using their thread-private ``Exchange`` instances.
191+
192+Because Persistit permits concurrent operations by multiple threads, there is no guarantee that the underlying database will remain unchanged after an Exchange fetches or modifies its data. However, each operation on an Exchange is atomic, meaning that the inputs and outputs of each method are consistent with some valid state of the underlying Persistit backing store at some instant in time. The Exchange’s Value and Key objects represent that consistent state even if another thread subsequently modifies the database. Transactions, described below, allow multiple database operations to be performed atomically and consistently.
193+
194+Exchange API
195+^^^^^^^^^^^^
196+
197+An Exchange has permanent references to a ``com.persistit.Key`` and a ``com.persistit.Value``. Typically you work with an Exchange in one of the following patterns:
198+
199+- Modify the Key, perform a ``fetch`` operation, and extract the Value.
200+- Modify the Key, modify the Value, and then perform a ``store`` operation.
201+- Modify the Key, and then perform a ``remove`` operation.
202+- Optionally modify the Key, perform a ``traverse`` operation, then read the resulting Key and/or Value.
203+
204+These four methods, plus a few other methods listed here, are the primary low-level interface to the database. Semantics are as follows:
205+
206+``fetch``
207+ Reads the stored value associated with this Exchange's Key and modifies the Exchange’s Value to reflect that value.
208+``store``
209+ Inserts or replaces the key/value pair for the specified key in the Tree either by replacing the former value, if there was one, or inserting a new value.
210+``fetchAndStore``
211+ Reads and then replaces the stored value. Upon completion, Value reflects the formerly stored value for the current Key. This operation is atomic.
212+``remove``, ``removeAll``, ``removeKeyRange``
213+ Removes key/value pairs from the Tree. Versions of this method specify either a single key or a range of keys to be removed.
214+``fetchAndRemove``
215+ Fetches and then removes the stored value. Upon completion, Value reflects the formerly stored value for the current Key. This operation is atomic.
216+``traverse``, ``next``, ``previous``
217+ Modifies the Exchange’s Key and Value to reflect a successor or predecessor key within the tree. See ``com.persistit.Key`` for detailed information on the order of traversal.
218+``hasNext``, ``hasPrevious``
219+ Indicates, without modifying the Exchange’s Value or Key objects, whether there is a successor or predecessor key in the Tree.
220+``hasChildren``
221+ Indicates whether there are records having keys that are logical children. A *logical child* of some key *P* is any key that can be constructed by appending one or more key segments to *P*.
222+
223+For convenience, Exchange delegates ``append`` and ``to`` methods to ``com.persistit.Key``. For example, Exchange provides the following methods that delegate to the identically named methods of Key :
224+
225+.. code-block:: java
226+
227+ public Exchange append(long v)
228+ public Exchange append(String v)
229+ ...
230+
231+To allow code call-chaining these methods of Exchange return the same Exchange. For example, it is valid to write code such as
232+
233+.. code-block:: java
234+
235+ exchange.clear().append(" Pacific").append("Ocean").append(123).fetch();
236+
237+This example fetches the value associated with the concatenated key
238+``{“Pacific”, ”Ocean”, 123}``.
239+
240+Exchange also delegates other key manipulation methods. (See ``com.persistit.Exchange`` for detailed API documentation.)
241+
242+Traversing and Querying Collections of Data
243+-------------------------------------------
244+
245+An Exchange provides a number of methods for traversing a collection of records in the Persistit database. These include variations of the ``com.persistit.Exchange#traverse``, ``com.persistit.Exchange#next`` and ``com.persistit.Exchange#previous``. For all of these methods, Persistit does two things: it modifies the Exchange's ``Key`` to reflect a new key that is before or after the current key, and it modifies the ``Value`` associated with the Exchange to reflect the database value associated with that key.
246+
247+For example, this code from ``HelloWorld.java`` prints out the key and value of each record in a tree:
248+
249+.. code-block:: java
250+
251+ dbex.getKey().to(Key.BEFORE);
252+ while (dbex.next())
253+ {
254+ System.out.println(
255+ dbex.getKey().indexTo(0).decode() + " " +
256+ dbex.getValue().get());
257+ }
258+
259+In general, the traversal methods let you find a key in a tree related to the key you supply. In Persistit programs you frequently prime a key value by appending either ``com.persistit.Key#BEFORE`` or ``com.persistit.Key#AFTER``. A key containing either of these special values can never be stored in a tree; these are reserved to represent positions in key traversal order before the first valid key and after the last valid key, respectively. You then invoke next or previous, or any of the other traverse family variants, to enumerate keys within the tree.
260+
261+You can specify whether traversal is *deep* or *shallow*. Deep traversal traverses the logical children (see com.persistit.Key) of a key. Shallow traversal traverses only the logical siblings.
262+
263+.. _KeyFilter:
264+
265+Selecting key values with a KeyFilter
266+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
267+
268+A ``com.persistit.KeyFilter`` defines a subset of all possible key values. For example, a KeyFilter can select keys with certain fixed segment values, sets of values or ranges of values. Calling ``traverse``, ``next`` or ``previous`` with a KeyFilter efficiently traverses the subset of all keys in a Tree that match the filter.
269+
270+You construct a KeyFilter either by adding selection terms to it, or by calling the ``com.persistit.KeyParser#parseKeyFilter`` method of the ``com.persistit.KeyParser`` class to construct one from a string representation.
271+
272+Use of a KeyFilter is illustrated by the following code fragment:
273+
274+.. code-block:: java
275+
276+ Exchange ex = new Exchange("myVolume", "myTree", true);
277+ KeyFilter kf = new KeyFilter("{\"Bellini\":\"Britten\"}");
278+ ex.append(Key.BEFORE);
279+ while (ex.next(kf)){
280+ System.out.println(ex.getKey().reset().decodeString());
281+ }
282+
283+This simple example emits the string-valued keys within Tree “myTree” whose values fall alphabetically between “Bellini” and “Britten”, inclusive.
284+
285+
286+You will find an example with a KeyFilter in the examples/FindFileDemo directory.
287+
288+.. _PersistitMap:
289+
290+PersistitMap
291+------------
292+
293+In addition to low-level access methods on keys and values, Persistit provides ``com.persistit.PersistitMap``, which implements the ``java.util.SortedMap`` interface. PersistitMap uses the Persistit database as a backing store so that key/value pairs are persistent, potentially shared with all threads, and limited in number only by disk storage.
294+
295+Keys and Values for PersistitMap must conform to the constraints described above under :ref:`Key` and :ref:`Value`.
296+
297+The constructor for PersistitMap takes an Exchange as its sole parameter. All key/value pairs of the Map are stored within the tree identified by this Exchange. The Key supplied by the Exchange becomes the root of a logical tree. For example:
298+
299+.. code-block:: java
300+
301+ Exchange ex = new Exchange("myVolume", "myTree", true);
302+ ex.append("USA").append("MA");
303+ PersistitMap<String, String> map = new PersistitMap<String, String>(ex);
304+ map.put("Boston", "Hub");
305+
306+places a key/value pair into Tree “myTree” with the concatenated key ``{"USA ","MA","Boston"}`` and a value ``"Hub"``.
307+
308+Generally the expected behavior for an Iterator on a Map collection view is to throw a ``ConcurrentModificationException`` if the underlying collection changes. This is known as “fail-fast” behavior. PersistitMap implements this behavior by throwing a ``ConcurrentModificationException`` in the event the Tree containing the map changes after the Iterator is constructed.
309+
310+However, sometimes it may be desirable to use PersistitMap and its collections view interfaces to iterate across changing data, especially for large databases. PersistitMap provides the method ``com.persistit.PersistitMap#setAllowConcurrentModification`` to control whether changes made by other threads are permitted. By default, concurrent modifications are not allowed.
311+
312+.. note:: When ``PersistitMap`` is used within a transaction updates generated by other concurrent transactions are not visible and
313+ therefore cannot cause a ConcurrentModificationException. However, to avoid unpredictable results an Iterator created within the scope
314+ of a transaction must be used only within that transaction.
315+
316+
317+Exceptions in PersistitMap
318+^^^^^^^^^^^^^^^^^^^^^^^^^^
319+
320+Persistit operations throw a variety of exceptions that are subclasses of ``com.persistit.exception.PersistitException``. However, the methods of the SortedMap interface do not permit arbitrary checked exceptions to be thrown. Therefore, PersistitMap wraps any PersistitException generated by the underlying database methods within a ``com.persistit.PersistitMap.PersistitMapException``. This exception is unchecked and can therefore be thrown by methods of the Map interface. Applications using PersistitMap should catch and handle PersistitMap.PersistitMapException.
321+
322+Applying a KeyFilter to a PersistitMap Iterator
323+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
324+
325+You can specify a ``com.persistit.KeyFilter`` for the Iterator returned by the ``keySet()``, ``entrySet()`` and ``values()`` methods of ``com.persistit.PersistitMap``. The KeyFilter restricts the range of keys traversed by the Iterator. To set the KeyFilter, you must cast the Iterator to the inner class PersistitMap.ExchangeIterator, as shown here:
326+
327+.. code-block:: java
328+
329+ PersistitMap map = new PersistitMap(exchange);
330+ PersistitMap.ExchangeIterator iterator =
331+ (PersistitMap.ExchangeIterator)map.entrySet().iterator();
332+ iterator.setFilterTerm(KeyFilter.rangeTerm("A", "M"));
333+
334+In this example, the iterator will only access String-valued keys between “A” and “M”.
335+
336+
337
338=== removed file 'doc/BasicAPI.txt'
339--- doc/BasicAPI.txt 2012-04-30 22:09:31 +0000
340+++ doc/BasicAPI.txt 1970-01-01 00:00:00 +0000
341@@ -1,320 +0,0 @@
342-[[BasicAPI]]
343-= Basic API
344-
345-Akiban Persistit stores data as key-value pairs in highly optimized B-Tree footnote:[Technically, Persistit implements http://www.cs.cornell.edu/courses/cs4411/2009sp/blink.pdf[B-Link] trees for greater concurrency]. Like a Java Map implementation, Persistit associates at most one value with each unique instance of a Key value.
346-
347-Persistit provides classes and methods to access and modify keys and their associated values. Application code calls Persistit API methods to store, fetch, traverse and remove keys and records to and from the database.
348-
349-Persistit permits efficient multi-threaded concurrent access to database volumes. It is designed to minimize contention for critical resources and to maximize throughput on multi-processor machines. Concurrent ACID transactions are supported with multi-value concurrency control (MVCC).
350-
351-== The Persistit Instance
352-
353-To access Persistit, the application first constructs an instance of the +com.persistit.Persistit+ class and initializes it. This instance is the keystone of all subsequent operations. It holds references to the buffers, maps, transaction contexts and other structures needed to access B-trees. The life cycle of a Persistit instance should be managed as follows:
354-
355-[source,java]
356-----
357-final Persistit db = new Persistit();
358-//
359-// register any Coder and Renderer instances before initialization
360-//
361-db.initialize(configProperties);
362-try {
363- // do application work
364-} finally {
365- db.close();
366-}
367-----
368-
369-The +configProperties+ describe the memory allocation, initial set of volumes, the journal, and other settings needed to get Persistit started. See <<Configuration>> for details.
370-
371-The +com.persistit.Persistit#close+ method gracefully flushes all modified data to disk, stops background threads and unregisters JMX MBeans.
372-****
373-The Persistit background threads are not daemon threads, so if your application returns from its static main method without calling +close+, the JVM will not automically exit.
374-****
375-
376-Although normal shutdown should always invoke +close+, Persistit is designed to recover a consistent database state in the event of an abrupt shutdown or crash. See <<Recovery>>.
377-
378-[[Key]]
379-== Key
380-
381-The content of a +com.persistit.Key+ is the unique identifier for a key/value pair within a tree. Internally a +Key+ contains an array of bytes that constitute the physical identity of the key/value pair within a tree. Logically, a key consists of a sequence of zero or more Java values, each of which is called a _key segment_.
382-
383-The following value types are implicitly supported in keys:
384-
385-.Types Supported in +com.persistit.Key+
386-----
387-null
388-boolean (and Boolean)
389-byte (and Byte)
390-short (and Short)
391-char (and Character)
392-int (and Integer)
393-long (and Long)
394-float (and Float)
395-double (and Double)
396-java.lang.String
397-java.math.BigInteger
398-java.math.BigDecimal
399-java.util.Date
400-byte[]
401-----
402-
403-In addition, you may register custom implementations of the +com.persistit.encoding.KeyCoder+ interface to support encoding of other object classes. By default, String values are encoded in UTF-8 format.
404-****
405-TODO: Collation
406-****
407-
408-=== Appending and Decoding Key Segments
409-
410-The +Key+ class provides methods to encode and decode each of these types to and from a key segment. For each type listed above, there is an +append+ method, a +to+ method and a +decode+ method. For example, for the long type, there are methods
411-
412-[source,java]
413-----
414-public void append(long v)
415-public void to(long v)
416-public long decodeLong()
417-----
418-
419-The +to+ methods replaces the final key segment with a different value (unless the key is empty, in which case it works the same as +append+).
420-
421-For example:
422-
423-[source,java]
424-----
425-key.clear(); // clear any previous key segments
426-key.append("Atlantic"); // append segment "Atlantic"
427-key.to("Pacific"); // replace "Atlantic" with "Pacific"
428-key.reset(); // reset index to beginning
429-String s = key.decode(); // s contains "Pacific"
430-----
431-
432-The Key class also provides methods to encode and decode Object values to and from a key. Strings, Dates, objects of the corresponding wrapper classes for the primitive types listed above, and objects supported by registered instances of +com.persistit.encoding.KeyCoder+ are permitted. Primitive values are automatically boxed and unboxed as needed. The following code fragment demonstrates key manipulation with automatic conversion of primitive types and their wrappers.
433-
434-[source,java]
435-----
436-key.clear(); // clear any previous key segments
437-key.append(new Integer(1234));
438-key.append("Atlantic");
439-key.append(1.23d);
440-key.reset(); // reset index to beginning for decoding
441-int v = key.decodeInt(); // v will be 1234
442-String s = (String)key.decode(); // s will be "Atlantic"
443-Double d = (Double)decode(); // d will be 1.23d as a Double
444-----
445-
446-In this code segment, an object of type Integer is appended to the key’s value sequence, and then the same value is later decoded as a primitive int value. A String is appended and then decoded into a String. Finally, a primitive double value is appended and then decoded as an object of class Double.
447-
448-The maximum size of a serialized +Key+ is 2,047 bytes.
449-
450-For further information, see +com.persistit.Key+.
451-
452-
453-[[Value]]
454-== Value
455-
456-A +com.persistit.Value+ object holds a value. Unlike keys, Value objects have no restriction on the types of data they can represent, and they can hold much larger objects. In particular, a Value may contain null, any of the primitive types, or an object of any class.
457-
458-The backing store of a +Value+ is a byte array that is written to a B-Tree data page, or in the case of a long record, multiple pages. The +com.persistit.Value#put+ method variants encode (serialize) a Java primitive or Object value into the backing store, and the +com.persistit.Value#get+ method variants decode (deserialize) the value.
459-
460-For example, in +HelloWorld.java+, the line
461-
462-[source,java]
463-----
464-dbex.getValue().put("World");
465-----
466-
467-serializes the String “World”, and the expression
468-
469-[source,java]
470-----
471-dbex.getValue().get()
472-----
473-
474-decodes it. Persistit does not intrinsically cache decoded object values, nor does it track an object's state changes. Each call to the +get()+ method returns a new instance of the object. However, you can use a +com.persistit.encoding.ObjectCache+ to cache object values. +ObjectCache+ is designed specifically to cache objects fetched from Persistit.
475-
476-=== Value Types
477-
478-+Value+ provides optimized predefined representations for the following types:
479-
480-.Types Implicitly Supported by +com.persistit.Value+
481-----
482-null
483-all primitive types
484-all arrays
485-java.math.BigInteger
486-java.math.BigDecimal
487-java.lang.String
488-java.util.Date
489-----
490-In general, Persistit uses one of four mechanisms to encode a Java value into a Value object:
491-
492-- If the value is one of the predefined types listed above, Persistit uses its own internal serialization logic.
493-- If there is a registered +com.persistit.encoding.ValueCoder+ for the object's class, Persistit delegates to it.
494-- If enabled, Persistit uses an accelerated serialization/deserialization mechanism to encode and decode objects.
495-- Otherwise, for classes that implement java.io.Serializable, Persistit attempts to perform default Java serialization and deserialization.
496-
497-A Value may also be in the undefined state, which results from performing a fetch operation on a key for which no value is present in the database. The undefined state is distinct from the value +null+ and can be tested with the +isDefined()+ method.
498-
499-See <<Serialization>> for additional information.
500-
501-=== Large Values
502-
503-Persistit stores large values, in the current version up to 64MB in size. For example, it is possible to store an image’s backing bytes as a single value in the database. The size of the value to be stored is constrained by available heap memory; the entire value must be able to be serialized into an in-memory byte array in order for Persistit to store or retrieve it. Use +com.persistit.Value#setMaximumSize+ to specify a the size constraint. Large values are broken up across multiple data pages and are not necessarily stored in contiguous file areas.
504-
505-The definition of “large” depends on the configuration properties. for example, for a volume with a page size of 16K bytes the threshold occurs at 6,108 bytes. A value having a serialized size smaller than this is stored in a single data page while a larger value is broken up and stored in multiple pages. For a smaller pages size the threshold is lower.
506-
507-On occasion it may be desirable to fetch only part of a large value. For example, it may be useful to extract summary information from the beginning of a the backing byte array for an Image. Variants versions of the +fetch+ and +traverse+ accept a minimum byte count parameter. When these methods are used only the specified minimum number bytes of the backing store are retrieved from the database. This technique can prevent Persistit from reading large numbers of pages from the disk in order to examine only a small portion of the record.
508-
509-[[Exchange]]
510-== Exchange
511-
512-The primary low-level interface for interacting with Persistit is +com.persistit.Exchange+. The Exchange class provides all methods for storing, deleting, fetching and traversing key/value pairs. These methods are summarized here and described in detail in the Javadoc API documentation.
513-
514-An Exchange instance contains references to a +Key+ and a +Value+. The methods +com.persistit.Exchange.getKey()+ and +com.persistit.Exchange.getValue()+ access these instances.
515-
516-To construct an Exchange you specify a Volume (or alias) and a tree name in its constructor. The constructor will optionally create a new tree in that Volume if a tree having the specified name has not already been created. An application may construct an arbitrary number of Exchange objects. Creating a new Exchange has no effect on the database if the specified tree already exists. Tree creation is thread-safe: multiple threads concurrently constructing Exchanges using the same Tree name will safely result in the creation of only one new tree.
517-
518-An Exchange is a moderately complex object that can consume tens of kilobytes to megabytes (depending on the sizes of the Key and Value) of heap space. Memory-constrained applications should construct Exchanges in moderatation.
519-
520-Persistit offers Exchange pooling to avoid rapidly creating and destroying Exchange objects in multi-threaded applications. An application may use the +com.persistit.Persistit#getExchange+ and +com.persistit.Persistit#releaseExchange+ methods to take and return an Exchange from and to a thread-local pool.
521-
522-An Exchange internally maintains some optimization information such that references to nearby Keys within a tree are accelerated. Performance may benefit from using a different Exchange for each area of the Tree being accessed.
523-
524-=== Concurrent Operations on Exchanges
525-
526-Although the underlying Persistit database is designed for highly concurrent multi-threaded operation, the +Exchange+ class and its associated +Key+ and +Value+ instances are _not_ thread-safe. Each thread should acquire and use its own Exchange objects when accessing the database. Nonetheless, multiple threads can execute database operations on overlapping data concurrently using their thread-private +Exchange+ instances.
527-
528-Because Persistit permits concurrent operations by multiple threads, there is no guarantee that the underlying database will remain unchanged after an Exchange fetches or modifies its data. However, each operation on an Exchange is atomic, meaning that the inputs and outputs of each method are consistent with some valid state of the underlying Persistit backing store at some instant in time. The Exchange’s Value and Key objects represent that consistent state even if another thread subsequently modifies the database. Transactions, described below, allow multiple database operations to be performed atomically and consistently.
529-
530-=== Exchange API
531-
532-An Exchange has permanent references to a +com.persistit.Key+ and a +com.persistit.Value+. Typically you work with an Exchange in one of the following patterns:
533-
534-- Modify the Key, perform a +fetch+ operation, and extract the Value.
535-- Modify the Key, modify the Value, and then perform a +store+ operation.
536-- Modify the Key, and then perform a +remove+ operation.
537-- Optionally modify the Key, perform a +traverse+ operation, then read the resulting Key and/or Value.
538-
539-These four methods, plus a few other methods listed here, are the primary low-level interface to the database. Semantics are as follows:
540-
541-[horizontal]
542-+fetch+:: Reads the stored value associated with this Exchange's Key and modifies the Exchange’s Value to reflect that value.
543-+store+:: Inserts or replaces the key/value pair for the specified key in the Tree either by replacing the former value, if there was one, or inserting a new value.
544-+fetchAndStore+:: Reads and then replaces the stored value. Upon completion, Value reflects the formerly stored value for the current Key. This operation is atomic.
545-+remove+, +removeAll+, +removeKeyRange+:: Removes key/value pairs from the Tree. Versions of this method specify either a single key or a range of keys to be removed.
546-+fetchAndRemove+:: Fetches and then removes the stored value. Upon completion, Value reflects the formerly stored value for the current Key. This operation is atomic.
547-+traverse+, +next+, +previous+:: Modifies the Exchange’s Key and Value to reflect a successor or predecessor key within the tree. See +com.persistit.Key+ for detailed information on the order of traversal.
548-+hasNext+, +hasPrevious+:: Indicates, without modifying the Exchange’s Value or Key objects, whether there is a successor or predecessor key in the Tree.
549-+hasChildren+:: Indicates whether there are records having keys that are logical children. A _logical child_of some key _P_ is any key that can be constructed by appending one or more key segments to _P_.
550-
551-
552-For convenience, Exchange delegates +append+ and +to+ methods to +com.persistit.Key+. For example, Exchange provides the following methods that delegate to the identically named methods of Key :
553-
554-[source,java]
555-----
556-public Exchange append(long v)
557-public Exchange append(String v)
558-...
559-----
560-To allow code call-chaining these methods of Exchange return the same Exchange. For example, it is valid to write code such as
561-
562-[source,java]
563-----
564-exchange.clear().append(" Pacific").append("Ocean").append(123).fetch();
565-----
566-
567-This example fetches the value associated with the concatenated key
568-+{“Pacific”, ”Ocean”, 123}+.
569-
570-Exchange also delegates other key manipulation methods. (See +com.persistit.Exchange+ for detailed API documentation.)
571-
572-=== Traversing and Querying Collections of Data
573-
574-An Exchange provides a number of methods for traversing a collection of records in the Persistit database. These include variations of the +com.persistit.Exchange#traverse+, +com.persistit.Exchange#next+ and +com.persistit.Exchange#previous+. For all of these methods, Persistit does two things: it modifies the Exchange's +Key+ to reflect a new key that is before or after the current key, and it modifies the +Value+ associated with the Exchange to reflect the database value associated with that key.
575-
576-For example, this code from +HelloWorld.java+ prints out the key and value of each record in a tree:
577-
578-[source,java]
579-----
580- dbex.getKey().to(Key.BEFORE);
581- while (dbex.next())
582- {
583- System.out.println(
584- dbex.getKey().indexTo(0).decode() + " " +
585- dbex.getValue().get());
586- }
587-----
588-
589-In general, the traversal methods let you find a key in a tree related to the key you supply. In Persistit programs you frequently prime a key value by appending either +com.persistit.Key#BEFORE+ or +com.persistit.Key#AFTER+. A key containing either of these special values can never be stored in a tree; these are reserved to represent positions in key traversal order before the first valid key and after the last valid key, respectively. You then invoke next or previous, or any of the other traverse family variants, to enumerate keys within the tree.
590-
591-You can specify whether traversal is _deep_ or _shallow_. Deep traversal traverses the logical children (see com.persistit.Key) of a key. Shallow traversal traverses only the logical siblings.
592-
593-[[KeyFilter]]
594-=== Selecting key values with a KeyFilter
595-
596-A +com.persistit.KeyFilter+ defines a subset of all possible key values. For example, a KeyFilter can select keys with certain fixed segment values, sets of values or ranges of values. Calling +traverse+, +next+ or +previous+ with a KeyFilter efficiently traverses the subset of all keys in a Tree that match the filter.
597-
598-You construct a KeyFilter either by adding selection terms to it, or by calling the +com.persistit.KeyParser#parseKeyFilter+ method of the +com.persistit.KeyParser+ class to construct one from a string representation.
599-
600-Use of a KeyFilter is illustrated by the following code fragment:
601-
602-[source,java]
603-----
604-Exchange ex = new Exchange("myVolume", "myTree", true);
605-KeyFilter kf = new KeyFilter("{\"Bellini\":\"Britten\"}");
606-ex.append(Key.BEFORE);
607-while (ex.next(kf)){
608- System.out.println(ex.getKey().reset().decodeString());
609-}
610-----
611-
612-This simple example emits the string-valued keys within Tree “myTree” whose values fall alphabetically between “Bellini” and “Britten”, inclusive.
613-
614-
615-You will find an example with a KeyFilter in the examples/FindFileDemo directory.
616-
617-[[PersistitMap]]
618-=== PersistitMap
619-
620-In addition to low-level access methods on keys and values, Persistit provides +com.persistit.PersistitMap+, which implements the +java.util.SortedMap+ interface. PersistitMap uses the Persistit database as a backing store so that key/value pairs are persistent, potentially shared with all threads, and limited in number only by disk storage.
621-
622-Keys and Values for PersistitMap must conform to the constraints described above under <<Key>> and <<Value>>.
623-
624-The constructor for PersistitMap takes an Exchange as its sole parameter. All key/value pairs of the Map are stored within the tree identified by this Exchange. The Key supplied by the Exchange becomes the root of a logical tree. For example:
625-
626-[source,java]
627-----
628-Exchange ex = new Exchange("myVolume", "myTree", true);
629-ex.append("USA").append("MA");
630-PersistitMap<String, String> map = new PersistitMap<String, String>(ex);
631-map.put("Boston", "Hub");
632-----
633-
634-places a key/value pair into Tree “myTree” with the concatenated key +{"USA ","MA","Boston"}+ and a value +"Hub"+.
635-
636-Generally the expected behavior for an Iterator on a Map collection view is to throw a +ConcurrentModificationException+ if the underlying collection changes. This is known as “fail-fast” behavior. PersistitMap implements this behavior by throwing a +ConcurrentModificationException+ in the event the Tree containing the map changes after the Iterator is constructed.
637-
638-However, sometimes it may be desirable to use PersistitMap and its collections view interfaces to iterate across changing data, especially for large databases. PersistitMap provides the method +com.persistit.PersistitMap#setAllowConcurrentModification+ to control whether changes made by other threads are permitted. By default, concurrent modifications are not allowed.
639-
640-NOTE: when +PersistitMap+ is used within a transaction updates generated by other concurrent transactions are not visible and therefore cannot cause a ConcurrentModificationException. However, to avoid unpredictable results an Iterator created within the scope of a transaction must be used only within that transaction.
641-
642-
643-=== Exceptions in PersistitMap
644-
645-Persistit operations throw a variety of exceptions that are subclasses of +com.persistit.exception.PersistitException+. However, the methods of the SortedMap interface do not permit arbitrary checked exceptions to be thrown. Therefore, PersistitMap wraps any PersistitException generated by the underlying database methods within a +com.persistit.PersistitMap.PersistitMapException+. This exception is unchecked and can therefore be thrown by methods of the Map interface. Applications using PersistitMap should catch and handle PersistitMap.PersistitMapException.
646-
647-=== Applying a KeyFilter to a PersistitMap Iterator
648-
649-You can specify a +com.persistit.KeyFilter+ for the Iterator returned by the +keySet()+, +entrySet()+ and +values()+ methods of +com.persistit.PersistitMap+. The KeyFilter restricts the range of keys traversed by the Iterator. To set the KeyFilter, you must cast the Iterator to the inner class PersistitMap.ExchangeIterator, as shown here:
650-
651-[source,java]
652-----
653- PersistitMap map = new PersistitMap(exchange);
654- PersistitMap.ExchangeIterator iterator =
655- (PersistitMap.ExchangeIterator)map.entrySet().iterator();
656- iterator.setFilterTerm(KeyFilter.rangeTerm("A", "M"));
657-----
658-
659-In this example, the iterator will only access String-valued keys between “A” and “M”.
660-
661-
662
663=== added file 'doc/Configuration.rst'
664--- doc/Configuration.rst 1970-01-01 00:00:00 +0000
665+++ doc/Configuration.rst 2012-05-30 18:23:19 +0000
666@@ -0,0 +1,273 @@
667+.. _Configuration:
668+
669+Configuration
670+=============
671+
672+To initialize Akiban Persistit the embedding application defines a configuration and then invokes one of the ``com.persistit.Persistit#initialize`` methods. The configuration defines parameters used to determine locations of files, sizes of buffer pool and journal files, policies and other elements required when Persistit starts up. These parameters are managed by the ``com.persistit.Configuration`` class.
673+
674+An application can define the configuration in one of two equivalent ways:
675+
676+- Create a ``com.persistit.Configuration`` instance and set its properties through methods such as ``com.persistit.Configuration#setJournalPath``.
677+- Specify properties by name in a ``java.util.Properties`` instance and then pass the ``Properties`` to a ``Configuration`` constructor.
678+
679+The following code samples show different ways of using the ``com.persistit.Persistit#initialize`` method to configure and start Persistit:
680+
681+.. code-block:: java
682+
683+ final Persistit db = new Persistit();
684+ final Properties p = new Properties();
685+ p.setProperty("buffer.count.16384", "1000");
686+ p.setProperty("journalpath", "/home/akiban/data/journal");
687+ ...
688+ db.initialize(p);
689+
690+.. code-block:: java
691+
692+ final Persistit db = new Persistit();
693+ db.initialize("/home/akiban/my_config.properties");
694+
695+.. code-block:: java
696+
697+ final Persistit db = new Persistit();
698+ final Configuration c = new Configuration();
699+ c.getBufferPoolMap().get(16384).setCount(1000);
700+ c.setJournalPath("/home/akiban/data/journal");
701+ ...
702+ db.initialize(c);
703+
704+There are three essential elements in a Persistit configuration:
705+
706+- Memory for the buffer pool(s)
707+- Specifications for ``com.persistit.Volume`` instances
708+- Journal file path
709+
710+Configuring the Buffer Pool
711+---------------------------
712+
713+During initialization Persistit allocates a fixed amount of heap memory for use as buffers. Depending on the application, it is usually desirable to allocate most of a server’s physical memory to the JVM heap (using the ``-Xmx`` and ``-Xms`` JVM options) and then to allocate a large fraction of the heap to Persistit buffers. The buffer pool allocation is determined during initialization and remains constant until the embedding application calls ``com.persistit.Persistit#close`` to release all resources.
714+
715+The number of buffers, and therefore the heap memory consumed, is determined during initialization by the available heap memory and configuration parameters. The heap memory size is obtained from the platform MemoryMXBean which in turn supplies the value given by the ``-Xmx`` JVM property. Configuration parameters are specified by a collection of five ``com.persistit.Configuration.BufferPoolConfiguration`` objects, one for each of the possible buffer sizes 1,024, 2,048, 4,096, 8,192 and 16,384 bytes. The method ``com.persistit.Configuration#getBufferPoolMap(int)`` gets the ``BufferPoolConfiguration`` for a specified buffer size.
716+
717+A ``BufferPoolConfiguration`` contains the following attributes:
718+
719+ ``minimumCount``
720+ lower bound on the number of buffers. (Default is zero.)
721+ ``maximumCount``
722+ upper bound on the number of buffers. (Default is zero.)
723+ ``minimumMemory``
724+ lower bound on memory to allocate. (Default is zero bytes.)
725+ ``maximumMemory``
726+ upper bound on memory to allocate. (Default is Long.MAX_VALUE bytes.)
727+ ``reservedMemory``
728+ minimum number of bytes to reserve for use other than buffers. (Default is zero.)
729+ ``fraction``
730+ floating point value between 0.0f and 1.0f indicating how much of available memory too allocate. (Default is 1.0f.)
731+
732+Persistit uses the following algorithm to determine the number of buffers to allocate for each buffer size:
733+
734+.. code-block:: java
735+
736+ memoryToUse = fraction * (maxHeap - reservedMemory)
737+ memoryToUse = min(memoryToUse, maximumMemory)
738+ bufferCount = memoryToUse / bufferSizeWithOverhead
739+ bufferCount = max(minimumCount, min(maximumCount, count))
740+ if (bufferCount * bufferSize > maximumMemory) then FAIL
741+ if ((bufferCount + 1) * bufferSize < minimumMemory) then FAIL
742+ allocate bufferCount buffers
743+
744+In other words, Persistit computes a buffer count based on the memory parameters, bounds it by ``minimumCount`` and ``maximumCount`` and then checks whether the resulting allocation fits within the memory constraints. Note that ``bufferSizeWithOverhead`` is about 14% larger than the buffer size; the additional memory is reserved for indexing data and other overhead associated with the buffer.
745+
746+Typically an application uses a single buffer size, specifying either an absolute count or memory-based constraints for that size. This can be done by setting the attributes of the appropriate ``BufferPoolConfiguration`` object directly, or using Property values.
747+
748+The property named ``buffer.count.SSSS`` where ``SSSS`` is “1024”, “2048”, “4096”, “8192” or “16384” specifies an absolute count. For example,
749+
750+.. code-block:: java
751+
752+ buffer.count.8192 = 10000
753+
754+causes Persistit to allocate 10,000 buffers of size 8192.
755+
756+The property ``buffer.memory.SSSS`` specifies memory constraints as shown in this example
757+
758+.. code-block:: java
759+
760+ buffer.memory.8192 = 512K,20M,4M,0.6
761+
762+where 512K, 20M, 4M and 0.6 are the ``minimumMemory``, ``maximumMemory``, ``reservedMemory`` and ``fraction``, respectively.
763+
764+The MemoryMXBean supplies as its maximum heap size value the size given by the ``-Xmx`` JVM parameter.
765+
766+Heap Tuning
767+-----------
768+
769+This section pertains to the Oracle HotSpot(tm) Java virtual machine.
770+
771+.. note::
772+
773+ Buffer instances are long-lived objects. To avoid severe garbage collector overhead it is important for all of them
774+ to fit in the heap’s tenured generation. This issue becomes especially significant with multi-gigabyte heaps.
775+
776+By default the HotSpot server JVM allocates 1/3 of the heap to the new generation and 2/3 to the tenured generation, meaning that allocating more than 2/3 of the heap to buffers will result in bad performance.
777+
778+You can increase the fraction by specifying ``-XX:NewRatio=N`` where ``N`` indicates the ratio of tenured generation space to new generation space, or by using the ``-Xmn`` parameter to specify an absolute amount of memory for the new generation. Also, setting ``-Xms`` equal to ``-Xmx`` will avoid numerous garbage collection cycles during the start-up process.
779+
780+See [http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html] for further information on tuning the heap and garbage collector for the HotSpot JVM.
781+
782+Multiple Buffer Pools
783+---------------------
784+
785+In some cases it may be desirable to allocate two or more buffer pools having buffers of different sizes. For example, it may be beneficial to use a large number of small buffers to hold secondary index pages.
786+
787+When specifying multiple memory constraints for multiple buffer pools, the ``fraction`` property applies to the available memory before any buffers are allocated. So, for example,
788+
789+.. code-block:: java
790+
791+ buffer.memory.2048=64M,512G,2G,.2
792+ buffer.memory.16384=64M,512G,2G,.5
793+
794+results in two buffer pools having buffers of size 2,048 bytes and 16,384 bytes, respectively. Assuming that the ``-Xmx`` value is 12G, then 2,048 byte buffers will be allocated to fill 20% of 10GByte, 16,384 byte buffers will be allocated to fill 50% of 10GByte, and approximately 5GByte (30% of 10GByte plus 2GByte reserved) will be available to application code.
795+
796+Configuring Volumes
797+-------------------
798+
799+Persistit creates and/or opens a set of database volume files during start-up. An application can create, open and close additional volumes, but it is often convenient for volumes to be defined in the confiuration, outside of application code.
800+
801+The ``com.persistit.Configuration#getVolumeList`` method returns a List of ``com.persistit.VolumeSpecification`` objects. An application can construct and add new ``VolumeSpecification`` instances to this list before calling ``com.persistit.Persistit#initialize(Configuration)``. Alternatively, the application can define volume specifications as property values using the syntax:
802+
803+``volume.N = path[,attrname[:attrvalue]]...``
804+
805+where ``N`` is an arbitrary integer, ``path`` is the path specification of the volume file, and ``attrnames`` include:
806+
807+- ``pageSize``: Fixed length unit representing one page. Value must be one of 1024, 2048, 4096, 8192 or 16384. To open and use the Volume, the buffer pool must have available buffers of the same size.
808+
809+- ``create``: Persistit attempts to open an existing volume file with the specified *path*, or create a new one if the file does not exist.
810+
811+- ``createOnly``: Persistit throw a VolumeAlreadyExistsException if the file specified by path already exists. Otherwise it creates a new file with the specified path.
812+
813+- ``readOnly``: Opens a volume in read-only mode. An attempt to modify the volume results in a ReadOnlyVolumeException.
814+
815+- ``initialPages`` or ``initialSize``: Specifies the initial size of the newly created volume file, either as the count of pages or as the size in bytes.
816+
817+- ``extensionPages`` or ``extensionSize``: Specifies the extension size of the newly created volume, either as the count of pages or as the size in bytes. This is the size by which the volume file will expand when the volume needs to be enlarged.
818+
819+- ``maximumPages`` or ``maximumSize``: An upper limit on the number of pages this Volume may hold, either as the count of pages or as the size in bytes. An attempt to further enlarge the Volume will generate a VolumeFullException.
820+
821+- ``alias``: The name of this Volume used in constructing ``Exchange`` instances. If unspecified, the name is the simple file name given in the *path*, not including its dotted suffix.
822+
823+For example::
824+
825+ volume.1=/home/akiban/ffdemo,create,pageSize:16K,\
826+ initialSize:10M,extensionSize:10M,maximumSize:1G
827+
828+specifies a volume having the name “ffdemo” in the /home/akiban directory. A new volume will be created if there is no existing volume file, and when created it will have the initial, extension and maximum sizes of 10MByte, 10MByte and 1GByte, respectively. Its page size will be 16KByte, meaning that the configuration must also have a buffer pool of 16KByte buffers.
829+
830+System Volume
831+-------------
832+
833+One volume in a Persistit configuration must be designated as the system volume. It contains class meta data for objects stored serialized in Persistit Values. When a configuration specifies only one volume, that volume implicitly becomes the system volume by default. However, when a configuration specifies multiple volumes, you must indicate which volume will serve as the system volume. There are two ways to do this. By default, Persistit looks for a unique volume named “_system”. You can simply create a volume whose file name is “_system”.
834+
835+Alternatively, you can specify a system volume name explicitly with the ``sysvolume`` property (or ``com.persistit.Configuration#setSysVolume``). The value is the name or alias of the selected volume.
836+
837+Configuring the Journal Path
838+----------------------------
839+
840+The :ref:`Journal` consists of a series of sequentially numbered files located in directory specified by the configuration parameter ``journalpath``. The application can set this property by calling ``com.persistit.Configuration#setJournalPath`` prior to initializing Persistit or through the property::
841+
842+ journalpath=/ssd/data/my_app_journal
843+
844+The value specified can be either a
845+
846+- directory, in which case files named ``persistit_journal.NNNNNNNNNNNN`` will be created,
847+- or a file name, in which case journal files will be created by appending the suffix ``.NNNNNNNNNNNN``.
848+
849+Recommendations for Physical Media
850+----------------------------------
851+
852+The journal is written by appending records to the end of the highest-numbered file. Read operations occur while copying page images from the journal to their home volume files. While copying, Persistit attempts to perform large sequential read operations from the journal. Read operations also occur at random when Persistit needs to reload the image of a previously evicted page.
853+
854+Because of these characteristics a modern SSD (solid disk drive) is ideally suited for maintaining the journal. If no SSD is available in the server, placing the journal on a different physical disk drive than the volume file(s) can significantly improve performance.
855+
856+Other Configuration Parameters
857+------------------------------
858+
859+The following additional properties are defined for Persistit. Other properties may also reside in the Properties object or its backing file; Persistit simply ignores any property not listed here.
860+
861+ ``journalsize``: (``com.persistit.Configuration#setJournalSize``)
862+ Journal file block size. Default is 1,000,000,000 bytes. A new Persistit rolls over to a new journal file when this
863+ size is reached. Generally there is no reason to adjust this setting.
864+
865+ ``appendonly``: (``com.persistit.Configuration#setAppendOnly``), True or false (default).
866+ When true, Persistit’s journal starts up in *append-only* mode in which modified pages are only written to the
867+ journal and not copied to their home volumes. As a consequence, all existing journal files are preserved, and new
868+ modifications are written only to newly created journal files. The append-only flag can also be enabled or disabled
869+ by application code and through the JMX and RMI interfaces.
870+
871+ ``rmiport``: (``com.persistit.Configuration#setRmiPort``)
872+ Specifies a port number on which Persistit will create a temporary Remote Method Invocation registry. If this
873+ property is specified, Persistit creates a registry and registers a ``com.persistit.Management`` server on it. This
874+ allows remote access to management facilities within Persistit and permits the Swing-based administrative utility to
875+ attach to and manage a Persistit instance running on a headless server. The ``rmihost`` and ``rmiport`` properties
876+ are mutually exclusive.
877+
878+ ``rmihost``: (``com.persistit.Configuration#setRmiHost``)
879+ Specifies the URL of an Remote Method Invocation registry. If present, Persistit registers its a server for its
880+ ``com.persistit.Management`` interface at the specified external registry. The ``rmihost`` and ``rmiport``
881+ properties are mutually exclusive.
882+
883+ ``jmx``: (``com.persistit.Configuration#setJmxEnabled``), True or false (default).
884+ Specifies whether Persistit registers MXBeans with the platform MBean server. Set this value to ``true`` to enable
885+ access from ``jconsole`` and other management tools.
886+
887+ ``serialOverride``, ``constructorOverride``: (``com.persistit.Configuration#setSerialOverride`` ``com.persistit.Configuration#setConstructorOverride``)
888+ Control aspects of object serialization. See :ref:`Serialization`.
889+
890+ ``showgui``: (``com.persistit.Configuration#setShowGUI``), True of False.
891+ If true, Persistit attempts to create and display an instance of the AdminUI utility panel within the current JVM.
892+ Alternatively, AdminUI uses RMI and can be launched and run remotely if ``rmiport`` or ``rmihost`` has been
893+ specified.
894+
895+ ``logfile``: (``com.persistit.Configuration#setLogFile``)
896+ Name of a log file to which Persistit’s default logger will write diagnostic log entries. Applications generally
897+ install a logging adapter to reroute messages through Log4J, SLF4J or other logger. The ``logfile`` property is used
898+ only when no adapter has been installed.
899+
900+For all integer-valued properties, the suffix “K” may be used to represent kilo, “M” for mega, “G” for giga and “T” for tera. For example, “2M” represents the value 2,097,152.
901+
902+A Configuration Example
903+-----------------------
904+
905+Following is an example of a Persistit configuration properties file::
906+
907+ datapath = /var/opt/persistit/data
908+ logpath = /var/log/persistit
909+ logfile = ${logpath}/${timestamp}.log
910+
911+ buffer.count.16384 = 5000
912+
913+ volume.1 = ${datapath}/demo_data, create, pageSize:16K, \
914+ initialSize:1M, extensionSize:1M, maximumSize:10G, alias:data
915+
916+ volume.2 = ${datapath}/demo_system, create, pageSize:16K, \
917+ initialSize:100K, extensionSize:100K, maximumSize:1G
918+
919+ sysvolume = demo_system
920+
921+ journalpath = /ssd/persistit_journal
922+
923+With this configuration there will be 5,000 16K buffers in the buffer pool consuming heap space of approximately 93MB including overhead. Persistit will open or create volume files named ``/var/opt/persistit/data/demo_data`` and ``/var/opt/persistit/data/demo_system`` and a journal file named ``/ssd/persistit_journal.0000000000000000``. Persistit will write diagnostic logging output to a file such as ``/var/log/persistit/20110523172213.log``.
924+
925+The ``demo_data`` volume has the alias ``data``. Application code uses the name "data" to refer to it. The ``sysvolume`` property specifies that the ``demo_system`` volume is designated to hold class meta data for serialized objects.
926+
927+Property Value Substitution
928+---------------------------
929+
930+This example also illustrates how property value substitution can be used within a Persistit configuration. The value of the ``datapath`` replaces ``$\{datapath\}`` in the volume specification. The property name ``datapath`` is arbitrary; you may use any valid property name as a substitution variable. Similarly, the value of ``logpath`` replaces ``$\{logpath\}`` and the pseudo-property ``$\{timestamp\}`` expands to a timestamp in the form ``*yyyyMMddHHmm*`` to provides a unique time-based log file name.
931+
932+Incorporating Java System Properties
933+------------------------------------
934+
935+You may also specify any configuration property as a Java system property with the prefix ``com.persisit.`` System properties override values specified as properties. For example, you can override the value of ``buffer.count.8192`` specifying::
936+
937+ java -Dcom.persistit.buffer.count.8192=10K -jar MyJar
938+
939+This is also true for substitution property values. For example, ``-Dcom.persistit.logpath=/tmp/`` will place the log files in the ``/tmp`` directory rather than ``/var/log/persistit`` as specified by the configuration file.
940
941=== removed file 'doc/Configuration.txt'
942--- doc/Configuration.txt 2012-04-30 22:09:31 +0000
943+++ doc/Configuration.txt 1970-01-01 00:00:00 +0000
944@@ -1,246 +0,0 @@
945-[[Configuration]]
946-= Configuration
947-
948-To initialize Akiban Persistit the embedding application defines a configuration and then invokes one of the +com.persistit.Persistit#initialize+ methods. The configuration defines parameters used to determine locations of files, sizes of buffer pool and journal files, policies and other elements required when Persistit starts up. These parameters are managed by the +com.persistit.Configuration+ class.
949-
950-An application can define the configuration in one of two equivalent ways:
951-
952-- Create a +com.persistit.Configuration+ instance and set its properties through methods such as +com.persistit.Configuration#setJournalPath+.
953-- Specify properties by name in a +java.util.Properties+ instance and then pass the +Properties+ to a +Configuration+ constructor.
954-
955-The following code samples show different ways of using the +com.persistit.Persistit#initialize+ method to configure and start Persistit:
956-
957-[source,java]
958-----
959-final Persistit db = new Persistit();
960-final Properties p = new Properties();
961-p.setProperty("buffer.count.16384", "1000");
962-p.setProperty("journalpath", "/home/akiban/data/journal");
963-...
964-db.initialize(p);
965-----
966-
967-[source,java]
968-----
969-final Persistit db = new Persistit();
970-db.initialize("/home/akiban/my_config.properties");
971-----
972-
973-[source,java]
974-----
975-final Persistit db = new Persistit();
976-final Configuration c = new Configuration();
977-c.getBufferPoolMap().get(16384).setCount(1000);
978-c.setJournalPath("/home/akiban/data/journal");
979-...
980-db.initialize(c);
981-----
982-
983-There are three essential elements in a Persistit configuration:
984-
985-- Memory for the buffer pool(s)
986-- Specifications for +com.persistit.Volume+ instances
987-- Journal file path
988-
989-== Configuring the Buffer Pool
990-
991-During initialization Persistit allocates a fixed amount of heap memory for use as buffers. Depending on the application, it is usually desirable to allocate most of a server’s physical memory to the JVM heap (using the +-Xmx+ and +-Xms+ JVM options) and then to allocate a large fraction of the heap to Persistit buffers. The buffer pool allocation is determined during initialization and remains constant until the embedding application calls +com.persistit.Persistit#close+ to release all resources.
992-
993-The number of buffers, and therefore the heap memory consumed, is determined during initialization by the available heap memory and configuration parameters. The heap memory size is obtained from the platform MemoryMXBean which in turn supplies the value given by the +-Xmx+ JVM property. Configuration parameters are specified by a collection of five +com.persistit.Configuration.BufferPoolConfiguration+ objects, one for each of the possible buffer sizes 1,024, 2,048, 4,096, 8,192 and 16,384 bytes. The method +com.persistit.Configuration#getBufferPoolMap(int)+ gets the +BufferPoolConfiguration+ for a specified buffer size.
994-
995-A +BufferPoolConfiguration+ contains the following attributes:
996-
997-[horizontal]
998-minimumCount:: lower bound on the number of buffers. (Default is zero.)
999-maximumCount:: upper bound on the number of buffers. (Default is zero.)
1000-minimumMemory:: lower bound on memory to allocate. (Default is zero bytes.)
1001-maximumMemory:: upper bound on memory to allocate. (Default is Long.MAX_VALUE bytes.)
1002-reservedMemory:: minimum number of bytes to reserve for use other than buffers. (Default is zero.)
1003-fraction:: floating point value between 0.0f and 1.0f indicating how much of available memory too allocate. (Default is 1.0f.)
1004-
1005-Persistit uses the following algorithm to determine the number of buffers to allocate for each buffer size:
1006-
1007-[source,java]
1008-----
1009-memoryToUse = fraction * (maxHeap - reservedMemory)
1010-memoryToUse = min(memoryToUse, maximumMemory)
1011-bufferCount = memoryToUse / bufferSizeWithOverhead
1012-bufferCount = max(minimumCount, min(maximumCount, count))
1013-if (bufferCount * bufferSize > maximumMemory) then FAIL
1014-if ((bufferCount + 1) * bufferSize < minimumMemory) then FAIL
1015-allocate bufferCount buffers
1016-----
1017-
1018-In other words, Persistit computes a buffer count based on the memory parameters, bounds it by +minimumCount+ and +maximumCount+ and then checks whether the resulting allocation fits within the memory constraints. Note that +bufferSizeWithOverhead+ is about 14% larger than the buffer size; the additional memory is reserved for indexing data and other overhead associated with the buffer.
1019-
1020-Typically an application uses a single buffer size, specifying either an absolute count or memory-based constraints for that size. This can be done by setting the attributes of the appropriate +BufferPoolConfiguration+ object directly, or using Property values.
1021-
1022-The property named +buffer.count._SSSS_+ where _SSSS_ is “1024”, “2048”, “4096”, “8192” or “16384” specifies an absolute count. For example,
1023-
1024-----
1025-buffer.count.8192 = 10000
1026-----
1027-
1028-causes Persistit to allocate 10,000 buffers of size 8192.
1029-
1030-The property +buffer.memory._SSSS_+ specifies memory constraints as shown in this example
1031-
1032-----
1033-buffer.memory.8192 = 512K,20M,4M,0.6
1034-----
1035-
1036-where 512K, 20M, 4M and 0.6 are the +minimumMemory+, +maximumMemory+, +reservedMemory+ and +fraction+, respectively.
1037-
1038-The MemoryMXBean supplies as its maximum heap size value the size given by the +-Xmx+ JVM parameter.
1039-
1040-=== Heap Tuning
1041-
1042-This section pertains to the Oracle HotSpot(tm) Java virtual machine.
1043-
1044-****
1045-Buffer instances are long-lived objects. To avoid severe garbage collector overhead it is important for all of them to fit in the heap’s tenured generation. This issue becomes especially significant with multi-gigabyte heaps.
1046-****
1047-
1048-By default the HotSpot server JVM allocates 1/3 of the heap to the new generation and 2/3 to the tenured generation, meaning that allocating more than 2/3 of the heap to buffers will result in bad performance.
1049-
1050-You can increase the fraction by specifying +-XX:NewRatio=_N_+ where _N_ indicates the ratio of tenured generation space to new generation space, or by using the +-Xmn+ parameter to specify an absolute amount of memory for the new generation. Also, setting +-Xms+ equal to +-Xmx+ will avoid numerous garbage collection cycles during the start-up process.
1051-
1052-See [http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html] for further information on tuning the heap and garbage collector for the HotSpot JVM.
1053-
1054-=== Multiple Buffer Pools
1055-
1056-In some cases it may be desirable to allocate two or more buffer pools having buffers of different sizes. For example, it may be beneficial to use a large number of small buffers to hold secondary index pages.
1057-
1058-When specifying multiple memory constraints for multiple buffer pools, the +fraction+ property applies to the available memory before any buffers are allocated. So, for example,
1059-
1060-
1061-----
1062-buffer.memory.2048=64M,512G,2G,.2
1063-buffer.memory.16384=64M,512G,2G,.5
1064-----
1065-
1066-results in two buffer pools having buffers of size 2,048 bytes and 16,384 bytes, respectively. Assuming that the +-Xmx+ value is 12G, then 2,048 byte buffers will be allocated to fill 20% of 10GByte, 16,384 byte buffers will be allocated to fill 50% of 10GByte, and approximately 5GByte (30% of 10GByte plus 2GByte reserved) will be available to application code.
1067-
1068-== Configuring Volumes
1069-
1070-Persistit creates and/or opens a set of database volume files during start-up. An application can create, open and close additional volumes, but it is often convenient for volumes to be defined in the confiuration, outside of application code.
1071-
1072-The +com.persistit.Configuration#getVolumeList+ method returns a List of +com.persistit.VolumeSpecification+ objects. An application can construct and add new +VolumeSpecification+ instances to this list before calling +com.persistit.Persistit#initialize(Configuration)+. Alternatively, the application can define volume specifications as property values using the syntax:
1073-
1074-+volume._N_ = _path_[,_attrname_[:_attrvalue_]]...+
1075-
1076-where _N_ is an arbitrary integer, _path_ is the path specification of the volume file, and _attrnames_ include:
1077-
1078-- +pageSize+: Fixed length unit representing one page. Value must be one of 1024, 2048, 4096, 8192 or 16384. To open and use the Volume, the buffer pool must have available buffers of the same size.
1079-
1080-- +create+: Persistit attempts to open an existing volume file with the specified _path_, or create a new one if the file does not exist.
1081-
1082-- +createOnly+: Persistit throw a VolumeAlreadyExistsException if the file specified by path already exists. Otherwise it creates a new file with the specified path.
1083-
1084-- +readOnly+: Opens a volume in read-only mode. An attempt to modify the volume results in a ReadOnlyVolumeException.
1085-
1086-- +initialPages+ or +initialSize+: Specifies the initial size of the newly created volume file, either as the count of pages or as the size in bytes.
1087-
1088-- +extensionPages+ or +extensionSize+: Specifies the extension size of the newly created volume, either as the count of pages or as the size in bytes. This is the size by which the volume file will expand when the volume needs to be enlarged.
1089-
1090-- +maximumPages+ or +maximumSize+: An upper limit on the number of pages this Volume may hold, either as the count of pages or as the size in bytes. An attempt to further enlarge the Volume will generate a VolumeFullException.
1091-
1092-- +alias+: The name of this Volume used in constructing +Exchange+ instances. If unspecified, the name is the simple file name given in the _path_, not including its dotted suffix.
1093-
1094-For example:
1095-
1096-----
1097-volume.1=/home/akiban/ffdemo,create,pageSize:16K,\
1098- initialSize:10M,extensionSize:10M,maximumSize:1G
1099-----
1100-
1101-specifies a volume having the name “ffdemo” in the /home/akiban directory. A new volume will be created if there is no existing volume file, and when created it will have the initial, extension and maximum sizes of 10MByte, 10MByte and 1GByte, respectively. Its page size will be 16KByte, meaning that the configuration must also have a buffer pool of 16KByte buffers.
1102-
1103-=== System Volume
1104-
1105-One volume in a Persistit configuration must be designated as the system volume. It contains class meta data for objects stored serialized in Persistit Values. When a configuration specifies only one volume, that volume implicitly becomes the system volume by default. However, when a configuration specifies multiple volumes, you must indicate which volume will serve as the system volume. There are two ways to do this. By default, Persistit looks for a unique volume named “_system”. You can simply create a volume whose file name is “_system”.
1106-
1107-Alternatively, you can specify a system volume name explicitly with the +sysvolume+ property (or +com.persistit.Configuration#setSysVolume+). The value is the name or alias of the selected volume.
1108-
1109-== Configuring the Journal Path
1110-
1111-The <<Journal>> consists of a series of sequentially numbered files located in directory specified by the configuration parameter +journalpath+. The application can set this property by calling +com.persistit.Configuration#setJournalPath+ prior to initializing Persistit or through the property
1112-
1113-----
1114-journalpath=/ssd/data/my_app_journal
1115-----
1116-
1117-The value specified can be either a
1118-
1119-- directory, in which case files named +persistit_journal._NNNNNNNNNNNN_+ will be created,
1120-
1121-- or a file name, in which case journal files will be created by appending the suffix +._NNNNNNNNNNNN_+.
1122-
1123-=== Recommendations for Physical Media
1124-
1125-The journal is written by appending records to the end of the highest-numbered file. Read operations occur while copying page images from the journal to their home volume files. While copying, Persistit attempts to perform large sequential read operations from the journal. Read operations also occur at random when Persistit needs to reload the image of a previously evicted page.
1126-
1127-Because of these characteristics a modern SSD (solid disk drive) is ideally suited for maintaining the journal. If no SSD is available in the server, placing the journal on a different physical disk drive than the volume file(s) can significantly improve performance.
1128-
1129-== Other Configuration Parameters
1130-
1131-The following additional properties are defined for Persistit. Other properties may also reside in the Properties object or its backing file; Persistit simply ignores any property not listed here.
1132-
1133-[horizontal]
1134-+journalsize+:: (+com.persistit.Configuration#setJournalSize+) Journal file block size. Default is 1,000,000,000 bytes. A new Persistit rolls over to a new journal file when this size is reached. Generally there is no reason to adjust this setting.
1135-
1136-+appendonly+:: (+com.persistit.Configuration#setAppendOnly+) True or false (default). When true, Persistit’s journal starts up in _append-only_ mode in which modified pages are only written to the journal and not copied to their home volumes. As a consequence, all existing journal files are preserved, and new modifications are written only to newly created journal files. The append-only flag can also be enabled or disabled by application code and through the JMX and RMI interfaces.
1137-
1138-+rmiport+:: (+com.persistit.Configuration#setRmiPort+) Specifies a port number on which Persistit will create a temporary Remote Method Invocation registry. If this property is specified, Persistit creates a registry and registers a +com.persistit.Management+ server on it. This allows remote access to management facilities within Persistit and permits the Swing-based administrative utility to attach to and manage a Persistit instance running on a headless server. The +rmihost+ and +rmiport+ properties are mutually exclusive.
1139-
1140-+rmihost+:: (+com.persistit.Configuration#setRmiHost+) Specifies the URL of an Remote Method Invocation registry. If present, Persistit registers its a server for its +com.persistit.Management+ interface at the specified external registry. The +rmihost+ and +rmiport+ properties are mutually exclusive.
1141-
1142-+jmx+:: (+com.persistit.Configuration#setJmxEnabled+) True or false (default). Specifies whether Persistit registers MXBeans with the platform MBean server. Set this value to +true+ to enable access from +jconsole+ and other management tools.
1143-
1144-+serialOverride+, +constructorOverride+:: (+com.persistit.Configuration#setSerialOverride+ +com.persistit.Configuration#setConstructorOverride+) Control aspects of object serialization. See <<Serialization>>.
1145-
1146-+showgui+:: ((+com.persistit.Configuration#setShowGUI+) True of False. If true, Persistit attempts to create and display an instance of the AdminUI utility panel within the current JVM. (Alternatively, AdminUI uses RMI and can be launched and run remotely if +rmiport+ or +rmihost+ has been specified.
1147-
1148-+logfile+:: (+com.persistit.Configuration#setLogFile+) Name of a log file to which Persistit’s default logger will write diagnostic log entries. Applications generally install a logging adapter to reroute messages through Log4J, SLF4J or other logger. The +logfile+ property is used only when no adapter has been installed.
1149-
1150-For all integer-valued properties, the suffix “K” may be used to represent kilo, “M” for mega, “G” for giga and “T” for tera. For example, “2M” represents the value 2,097,152.
1151-
1152-== A Configuration Example
1153-
1154-Following is an example of a Persistit configuration properties file:
1155-
1156-----
1157-datapath = /var/opt/persistit/data
1158-logpath = /var/log/persistit
1159-logfile = ${logpath}/${timestamp}.log
1160-
1161-buffer.count.16384 = 5000
1162-
1163-volume.1 = ${datapath}/demo_data, create, pageSize:16K, \
1164- initialSize:1M, extensionSize:1M, maximumSize:10G, alias:data
1165-
1166-volume.2 = ${datapath}/demo_system, create, pageSize:16K, \
1167- initialSize:100K, extensionSize:100K, maximumSize:1G
1168-
1169-sysvolume = demo_system
1170-
1171-journalpath = /ssd/persistit_journal
1172-----
1173-
1174-With this configuration there will be 5,000 16K buffers in the buffer pool consuming heap space of approximately 93MB including overhead. Persistit will open or create volume files named +/var/opt/persistit/data/demo_data+ and +/var/opt/persistit/data/demo_system+ and a journal file named +/ssd/persistit_journal.0000000000000000+. Persistit will write diagnostic logging output to a file such as +/var/log/persistit/20110523172213.log+.
1175-
1176-The +demo_data+ volume has the alias +data+. Application code uses the name "data" to refer to it. The +sysvolume+ property specifies that the +demo_system+ volume is designated to hold class meta data for serialized objects.
1177-
1178-=== Property Value Substitution
1179-
1180-This example also illustrates how property value substitution can be used within a Persistit configuration. The value of the +datapath+ replaces +$\{datapath\}+ in the volume specification. The property name +datapath+ is arbitrary; you may use any valid property name as a substitution variable. Similarly, the value of +logpath+ replaces +$\{logpath\}+ and the pseudo-property +$\{timestamp\}+ expands to a timestamp in the form +_yyyyMMddHHmm_+ to provides a unique time-based log file name.
1181-
1182-=== Incorporating Java System Properties
1183-
1184-You may also specify any configuration property as a Java system property with the prefix +com.persisit.+ System properties override values specified as properties. For example, you can override the value of +buffer.count.8192+ specifying
1185-
1186-----
1187-java -Dcom.persistit.buffer.count.8192=10K -jar MyJar
1188-----
1189-
1190-This is also true for substitution property values. For example, +-Dcom.persistit.logpath=/tmp/+ will place the log files in the +/tmp+ directory rather than +/var/log/persistit+ as specified by the configuration file.
1191
1192=== added file 'doc/GettingStarted.rst'
1193--- doc/GettingStarted.rst 1970-01-01 00:00:00 +0000
1194+++ doc/GettingStarted.rst 2012-05-30 18:23:19 +0000
1195@@ -0,0 +1,270 @@
1196+
1197+Getting Started with Akiban Persistit
1198+=====================================
1199+
1200+Welcome!
1201+
1202+We have worked hard to make Akiban Persistit(TM) exceptionally fast, reliable, simple and lightweight. We hope you will enjoy learning more about it and using it.
1203+
1204+Akiban Persistit is a key/value data storage library written in Java(TM). Key features include:
1205+
1206+- support for highly concurrent transaction processing with multi-version concurrency control
1207+- optimized serialization and deserialization mechanism for Java primitives and objects
1208+- multi-segment (compound) keys to enable a natural logical key hierarchy
1209+- support for long records (megabytes)
1210+- implementation of a persistent SortedMap
1211+- extensive management capability including command-line and GUI tools
1212+
1213+This chapter briefly and informally introduces and demonstrates various Persistit features through examples. Subsequent chapters and the Javadoc API documentation provides a detailed reference guide to the product.
1214+
1215+Download and Install
1216+--------------------
1217+
1218+Download ``akiban-persistit-3.xx.yy.zip`` from http://www.akiban.com/persistit/download.html.
1219+
1220+Unpack the distribution kit into a convenient directory using any unzip utility. For example, use ``jar`` to unpack the distribution kit to the current working directory as follows:
1221+.. code-block::
1222+
1223+ jar xvzf akiban-persistit-core-3.xx.yy.zip
1224+
1225+Review the ``LICENSE.html`` and ``README.html`` files located in the root of the installation directory. Persistit is licensed under the GNU Affero General Public License. By installing, copying or otherwise using the Software contained in the distribution kit, you agree to be bound by the terms of the license agreement. If you do not agree to these terms, remove and destroy all copies of the software in your possession immediately.
1226+
1227+Working with Persistit
1228+----------------------
1229+
1230+Add the ``akiban-persistit-core-3.xx.yy.jar`` from the ``lib`` directory of the distribution kit to your project's classpath. For example, copy it to ``jre/lib/ext`` in your Java Runtime Environment, or add it to your classpath environment variable.
1231+
1232+That's it. You are ready to work with Persistit.
1233+
1234+Examples
1235+^^^^^^^^
1236+
1237+Review the ``examples`` directory. Here you will find functional examples of varying complexity.
1238+
1239+ ``examples/HelloWorld``
1240+ source code for the example illustrating this chapter
1241+ ``examples/SimpleDemo``
1242+ short, simple program similar to HelloWorld
1243+ ``examples/SimpleBench``
1244+   a small micro-benchmark measuring the speed of insert, traversal, random updates, etc.
1245+ ``examples/SimpleTransaction``
1246+ example demonstrating use of Persisit’s multi-version currency control (MVCC) transactions
1247+ ``examples/FindFile``
1248+ a somewhat larger example that uses Persistit as the backing store for file finder utility
1249+ ``example/PersistitMapDemo``
1250+ demonstration of the PersistitMap interface
1251+
1252+HelloWorld
1253+----------
1254+
1255+Before going further let's honor tradition with a small program that stores, fetches and displays the phrase “Hello World.” In this program we will create a record with the key “Hello” and the value “World”.
1256+
1257+.. HelloWorld.java
1258+
1259+.. code-block:: java
1260+
1261+ import com.persistit.Exchange;
1262+ import com.persistit.Key;
1263+ import com.persistit.Persistit;
1264+
1265+ public class HelloWorld {
1266+ public static void main(String[] args) throws Exception {
1267+ Persistit db = new Persistit();
1268+ try {
1269+ // Read configuration from persistit.properties, allocate
1270+ // buffers, open Volume, and perform recovery processing
1271+ // if necessary.
1272+ //
1273+ db.initialize();
1274+ //
1275+ // Create an Exchange, which is a thread-private facade for
1276+ // accessing data in a Persistit Tree. This Exchange will
1277+ // access a Tree called "greetings" in a Volume called
1278+ // "hwdemo". It will create a new Tree by that name
1279+ // if one does not already exist.
1280+ //
1281+ Exchange dbex = db.getExchange("hwdemo", "greetings", true);
1282+ //
1283+ // Set up the Value field of the Exchange.
1284+ //
1285+ dbex.getValue().put("World");
1286+ //
1287+ // Set up the Key field of the Exchange.
1288+ //
1289+ dbex.getKey().append("Hello");
1290+ //
1291+ // Ask Persistit to put this key/value pair into the Tree.
1292+ // Until this point, the changes to the Exchange are local
1293+ // to this thread.
1294+ //
1295+ dbex.store();
1296+ //
1297+ // Prepare to traverse all the keys in the Tree (of which there
1298+ // is currently only one!) and for each key display its value.
1299+ //
1300+ dbex.getKey().to(Key.BEFORE);
1301+ while (dbex.next()) {
1302+ System.out.println(dbex.getKey().indexTo(0).decode() + " "
1303+ + dbex.getValue().get());
1304+ }
1305+ db.releaseExchange(dbex);
1306+ } finally {
1307+ // Always close Persistit. If the application does not do
1308+ // this, Persistit's background threads will keep the JVM from
1309+ // terminating.
1310+ //
1311+ db.close();
1312+ }
1313+ }
1314+ }
1315+
1316+Concepts
1317+--------
1318+
1319+Although ``HelloWorld.java`` is not very useful, it demonstrates several of the basic building blocks of the Persistit API.
1320+
1321+Initialization and Configuration
1322+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1323+
1324+Before accessing any data, ``HelloWorld.java`` calls one of the ``com.persistit.Persistit#initialize`` methods of ``com.persistit.Persistit``. This sets up the memory configuration for buffers and the path names of Persistit volume and journal files. Alternative versions of the initialize method accept configuration information from a ``java.util.Properties`` object, from a specified properties file, or by default from the file named ``persistit.properties``.
1325+
1326+In this example, ``persistit.properties`` looks like this::
1327+
1328+ datapath=.
1329+ buffer.count.8192=32
1330+ volume.1=${datapath}/hwdemo,create,pageSize:8192,\
1331+ initialPages:5,extensionPages:5,maximumPages:100000
1332+ journalpath=${datapath}/hwdemo_journal
1333+
1334+See :ref:`Configuration` for additional information about Persistit configuration properties.
1335+
1336+Volumes and Trees
1337+^^^^^^^^^^^^^^^^^
1338+
1339+A configuration defines one or more volume files that will contain stored Persistit data. Usually you will specify the ``create`` flag, which allows Persistit to create a new volume if the file does not already exist. Creating a new file also establishes the initial size and growth parameters for that volume.
1340+
1341+Each volume may contain an unlimited number of named trees. Each tree within a volume embodies a logically distinct B-Tree index structure. Think of a tree as simply a named key space within a volume.
1342+
1343+``HelloWorld.java`` stores its key/value pair in a tree called “greetings” in a volume named “hwdemo”. This is specified by constructing an Exchange.
1344+
1345+Exchanges
1346+---------
1347+
1348+The ``com.persistit.Exchange`` class is the primary facade for interacting with Persistit data. It is so-named because it allows an application to exchange information with the database. An Exchange provides methods for storing, deleting, fetching and traversing key/value pairs.
1349+
1350+The method
1351+
1352+.. code-block:: java
1353+
1354+ Exchange dbex = db.getExchange("hwdemo", "greetings", true);
1355+
1356+in ``HelloWorld.java`` finds a volume named "hwdemo" and attempts to find a tree in it named "greetings". If there is no such tree, ``getExchange`` creates it.
1357+
1358+Methods ``com.persistit.Persistit#getExchange`` and ``com.persistit.Persistit#releaseExchange`` maintain a pool of reusable Exchange objects designed for use by multi-threaded applications such as web applications. If a suitable exchange already exists, ``getExchange`` returns it; otherwise it constructs a new one.
1359+
1360+The Exchange looks up the volume name “hwdemo” by matching it against the volumes specified in the configuration. The match is based on the simple file name of the volume after removing its final dotted suffix. For example, the volume name “hwdemo” matches the volume specification ``${datapath}/hwdemo.v00``.
1361+
1362+Each Exchange is implicitly associated with a ``com.persistit.Key`` and a ``com.persistit.Value``. Typically you work with an Exchange in one of the following patterns:
1363+
1364+- Modify the Key, modify the Value and then perform a ``com.persistit.Exchange#store`` operation.
1365+- Modify the Key, perform a ``com.persistit.Exchange#fetch`` operation and then read the Value.
1366+- Modify the Key and then perform a ``com.persistit.Exchange#remove`` operation.
1367+- Optionally modify the Key, perform a ``com.persistit.Exchange#next``, ``com.persistit.Exchange#previous`` or ``com.persistit.Exchange#traverse`` operation, then read the resulting Key and/or Value.
1368+
1369+These methods and their variants provide the foundation for using Persistit.
1370+
1371+Records
1372+^^^^^^^
1373+
1374+In Persistit, a database record consists of a Key and a Value. The terms “record” and “key/value pair” are used interchangeably.
1375+
1376+When you store a record, Persistit searches for a previously stored record having the same key. If there is such a record, Persistit replaces its value. If there is no such record, Persistit inserts a new one. Like a Java Map, Persistit stores at most one value per key, and every record in a Tree has a unique key value.
1377+
1378+Keys
1379+^^^^
1380+
1381+A Key contains a unique identifier for key/value pair - or record - in a tree. The identifier consists of a sequence of one or more Java values encoded into an array of bytes stored in the volume file.
1382+
1383+Key instances are mutable. Your application typically changes an Exchange's Key in preparation for fetching or retrieving data. In particular, you can append, remove or replace one or more values in a Key. Each value you append is called a *key segment*. You append multiple key segments to implement concatenated keys. See ``com.persistit.Key`` for additional information on constructing keys and the ordering of key traversal within a tree.
1384+
1385+The ``HelloWorld.java`` example appends “Hello” to the Exchange’s Key object in this line:
1386+
1387+.. code-block:: java
1388+
1389+ dbex.getKey().append("Hello");
1390+
1391+The result is a key with a single key segment.
1392+
1393+Values
1394+^^^^^^
1395+
1396+A Value object represents the serialized state of a Java object or a primitive value. It is a staging area for data being transferred from or to the database by ``fetch``, ``traverse`` and ``store`` operations.
1397+
1398+Value instances are mutable. The ``fetch`` and ``traverse`` operations modify the state of an Exchange's Value instance to represent the value associated with some Key. Your application executes methods to modify the state of the Value instance in preparation for storing new data values into the database.
1399+
1400+Numerous methods allow you to serialize and deserialize primitives values and objects into and from a Value object. For example, in ``HelloWorld.java``, the statement
1401+
1402+.. code-block:: java
1403+
1404+ dbex.getValue().put("World");
1405+
1406+serializes the string “World” into the backing byte array of the Exchange’s Value object and
1407+
1408+.. code-block:: java
1409+
1410+ System.out.println(
1411+ dbex.getKey().indexTo(0).decode() + " " +
1412+ dbex.getValue().get());
1413+
1414+deserializes and prints an object value from the Key and another object value from the Value. Value also has methods such as ``getInt``, ``getLong``, ``getByteArray`` to decode primitive and array values directly.
1415+
1416+Storing and Fetching Data
1417+^^^^^^^^^^^^^^^^^^^^^^^^^
1418+
1419+Finally, it is these two methods in ``HelloWorld.java`` that cause the Exchange object to share data with the B-Tree, making it persistent and potentially available to other threads:
1420+
1421+.. code-block:: java
1422+
1423+ dbex.store();
1424+ ...
1425+ while (dbex.next()) { ... }
1426+
1427+Closing Persistit
1428+^^^^^^^^^^^^^^^^^
1429+
1430+Persistit creates one or more background threads that lazily write data to the Volume files and perform other maintenance activities. Be sure to invoke the ``com.persistit.Persistit#close`` method to allow these threads to finish their work and exit properly. The pattern illustrated in ``HelloWorld.java``, using a *try/finally* block to invoke ``close``, is strongly recommended.
1431+
1432+The ``com.persistit.Persistit#close(boolean)`` method optionally flushes all data to disk from the buffer pool before shutting down. Specifying the ``false`` option will close Persistit more quickly will lose recent updates if they were not performed inside of transactions, or will potentially require a longer recovery process during the next startup to reapply committed transactions.
1433+Additional Topics
1434+-----------------
1435+
1436+PersistitMap
1437+^^^^^^^^^^^^
1438+A particularly easy way to get started with Persistit is to use its built-in ``com.persistit.PersistitMap`` implementation. PersistitMap implements the ``java.util.SortedMap`` interface, so it can directly replace ``java.util.TreeMap`` or other kinds of Map in existing Java code.
1439+
1440+See :ref:`PersistitMap`.
1441+
1442+KeyFilters
1443+^^^^^^^^^^
1444+
1445+A ``com.persistit.KeyFilter`` can be supplied to restrict the results traversal operation in a convenient and
1446+
1447+Transactions
1448+^^^^^^^^^^^^
1449+
1450+Persistit provides ACID Transaction support with multi-version concurrency control (MCC) and adjustable durability policy.
1451+
1452+See :ref:`Transactions`.
1453+
1454+Managing Persistit
1455+^^^^^^^^^^^^^^^^^^
1456+
1457+Persistit provides several mechanisms for managing Persistit operation within an application. These include
1458+
1459+- JMX MXBeans
1460+- The ``com.persistit.Management`` object which provides programmatic access to many management operations
1461+- The ``com.persistit.CLI`` object which provides a command-line interface for various management operations
1462+- The AdminUI tool which provides a graphical client interface for examining records and other resources
1463+- Logging interface design for easy embedding in host applications
1464+
1465+See :ref:`Management`.
1466
1467=== removed file 'doc/GettingStarted.txt'
1468--- doc/GettingStarted.txt 2012-04-24 02:37:12 +0000
1469+++ doc/GettingStarted.txt 1970-01-01 00:00:00 +0000
1470@@ -1,255 +0,0 @@
1471-
1472-= Getting Started with Akiban Persistit
1473-
1474-
1475-Welcome!
1476-
1477-We have worked hard to make Akiban Persistit(TM) exceptionally fast, reliable, simple and lightweight. We hope you will enjoy learning more about it and using it.
1478-
1479-Akiban Persistit is a key/value data storage library written in Java(TM). Key features include:
1480-
1481-- support for highly concurrent transaction processing with multi-version concurrency control
1482-- optimized serialization and deserialization mechanism for Java primitives and objects
1483-- multi-segment (compound) keys to enable a natural logical key hierarchy
1484-- support for long records (megabytes)
1485-- implementation of a persistent SortedMap
1486-- extensive management capability including command-line and GUI tools
1487-
1488-This chapter briefly and informally introduces and demonstrates various Persistit features through examples. Subsequent chapters and the Javadoc API documentation provides a detailed reference guide to the product.
1489-
1490-== Download and Install
1491-
1492-Download +akiban-persistit-3.xx.yy.zip+ from http://www.akiban.com/persistit/download.html.
1493-
1494-Unpack the distribution kit into a convenient directory using any unzip utility. For example, use +jar+ to unpack the distribution kit to the current working directory as follows:
1495-----
1496-jar xvzf akiban-persistit-core-3.xx.yy.zip
1497-----
1498-
1499-Review the +LICENSE.html+ and +README.html+ files located in the root of the installation directory. Persistit is licensed under the XXXXXX XXXXXXX License. By installing, copying or otherwise using the Software contained in the distribution kit, you agree to be bound by the terms of the license agreement. If you do not agree to these terms, remove and destroy all copies of the software in your possession immediately.
1500-
1501-== Working with Persistit
1502-
1503-Add the +akiban-persistit-core-3.xx.yy.jar+ from the +lib+ directory of the distribution kit to your project's classpath. For example, copy it to +jre/lib/ext+ in your Java Runtime Environment, or add it to your classpath environment variable.
1504-
1505-That's it. You are ready to work with Persistit.
1506-
1507-=== Examples
1508-
1509-Review the +examples+ directory. Here you will find functional examples of varying complexity.
1510-
1511-[horizontal]
1512-+examples/HelloWorld+:: source code for the example illustrating this chapter
1513-+examples/SimpleDemo+:: short, simple program similar to HelloWorld
1514-+examples/SimpleBench+:: a small micro-benchmark measuring the speed of insert, traversal, random updates, etc.
1515-+examples/SimpleTransaction+:: example demonstrating use of Persisit’s multi-version currency control (MVCC) transactions
1516-+examples/FindFile+:: a somewhat larger example that uses Persistit as the backing store for file finder utility
1517-+example/PersistitMapDemo+:: demonstration of the PersistitMap interface
1518-
1519-== HelloWorld
1520-
1521-Before going further let's honor tradition with a small program that stores, fetches and displays the phrase “Hello World.” In this program we will create a record with the key “Hello” and the value “World”.
1522-
1523-.HelloWorld.java
1524-[source,java]
1525-----
1526-import com.persistit.Exchange;
1527-import com.persistit.Key;
1528-import com.persistit.Persistit;
1529-
1530-public class HelloWorld {
1531- public static void main(String[] args) throws Exception {
1532- Persistit db = new Persistit();
1533- try {
1534- // Read configuration from persistit.properties, allocate
1535- // buffers, open Volume, and perform recovery processing
1536- // if necessary.
1537- //
1538- db.initialize();
1539- //
1540- // Create an Exchange, which is a thread-private facade for
1541- // accessing data in a Persistit Tree. This Exchange will
1542- // access a Tree called "greetings" in a Volume called
1543- // "hwdemo". It will create a new Tree by that name
1544- // if one does not already exist.
1545- //
1546- Exchange dbex = db.getExchange("hwdemo", "greetings", true);
1547- //
1548- // Set up the Value field of the Exchange.
1549- //
1550- dbex.getValue().put("World");
1551- //
1552- // Set up the Key field of the Exchange.
1553- //
1554- dbex.getKey().append("Hello");
1555- //
1556- // Ask Persistit to put this key/value pair into the Tree.
1557- // Until this point, the changes to the Exchange are local
1558- // to this thread.
1559- //
1560- dbex.store();
1561- //
1562- // Prepare to traverse all the keys in the Tree (of which there
1563- // is currently only one!) and for each key display its value.
1564- //
1565- dbex.getKey().to(Key.BEFORE);
1566- while (dbex.next()) {
1567- System.out.println(dbex.getKey().indexTo(0).decode() + " "
1568- + dbex.getValue().get());
1569- }
1570- db.releaseExchange(dbex);
1571- } finally {
1572- // Always close Persistit. If the application does not do
1573- // this, Persistit's background threads will keep the JVM from
1574- // terminating.
1575- //
1576- db.close();
1577- }
1578- }
1579-}
1580-----
1581-
1582-== Concepts
1583-
1584-Although +HelloWorld.java+ is not very useful, it demonstrates several of the basic building blocks of the Persistit API.
1585-
1586-=== Initialization and Configuration
1587-
1588-Before accessing any data, +HelloWorld.java+ calls one of the +com.persistit.Persistit#initialize+ methods of +com.persistit.Persistit+. This sets up the memory configuration for buffers and the path names of Persistit volume and journal files. Alternative versions of the initialize method accept configuration information from a +java.util.Properties+ object, from a specified properties file, or by default from the file named +persistit.properties+.
1589-
1590-In this example, +persistit.properties+ looks like this:
1591-
1592-----
1593-datapath=.
1594-buffer.count.8192=32
1595-volume.1=${datapath}/hwdemo,create,pageSize:8192,\
1596- initialPages:5,extensionPages:5,maximumPages:100000
1597-journalpath=${datapath}/hwdemo_journal
1598-----
1599-
1600-See <<Configuration>> for additional information about Persistit configuration properties.
1601-
1602-=== Volumes and Trees
1603-
1604-A configuration defines one or more volume files that will contain stored Persistit data. Usually you will specify the +create+ flag, which allows Persistit to create a new volume if the file does not already exist. Creating a new file also establishes the initial size and growth parameters for that volume.
1605-
1606-Each volume may contain an unlimited number of named trees. Each tree within a volume embodies a logically distinct B-Tree index structure. Think of a tree as simply a named key space within a volume.
1607-
1608-+HelloWorld.java+ stores its key/value pair in a tree called “greetings” in a volume named “hwdemo”. This is specified by constructing an Exchange.
1609-
1610-=== Exchanges
1611-
1612-The +com.persistit.Exchange+ class is the primary facade for interacting with Persistit data. It is so-named because it allows an application to exchange information with the database. An Exchange provides methods for storing, deleting, fetching and traversing key/value pairs.
1613-
1614-The method
1615-
1616-[source,java]
1617-----
1618-Exchange dbex = db.getExchange("hwdemo", "greetings", true);
1619-----
1620-
1621-in +HelloWorld.java+ finds a volume named "hwdemo" and attempts to find a tree in it named "greetings". If there is no such tree, +getExchange+ creates it.
1622-
1623-Methods +com.persistit.Persistit#getExchange+ and +com.persistit.Persistit#releaseExchange+ maintain a pool of reusable Exchange objects designed for use by multi-threaded applications such as web applications. If a suitable exchange already exists, +getExchange+ returns it; otherwise it constructs a new one.
1624-
1625-The Exchange looks up the volume name “hwdemo” by matching it against the volumes specified in the configuration. The match is based on the simple file name of the volume after removing its final dotted suffix. For example, the volume name “hwdemo” matches the volume specification +${datapath}/hwdemo.v00+.
1626-
1627-Each Exchange is implicitly associated with a +com.persistit.Key+ and a +com.persistit.Value+. Typically you work with an Exchange in one of the following patterns:
1628-
1629-- Modify the Key, modify the Value and then perform a +com.persistit.Exchange#store+ operation.
1630-- Modify the Key, perform a +com.persistit.Exchange#fetch+ operation and then read the Value.
1631-- Modify the Key and then perform a +com.persistit.Exchange#remove+ operation.
1632-- Optionally modify the Key, perform a +com.persistit.Exchange#next+, +com.persistit.Exchange#previous+ or +com.persistit.Exchange#traverse+ operation, then read the resulting Key and/or Value.
1633-
1634-These methods and their variants provide the foundation for using Persistit.
1635-
1636-=== Records
1637-
1638-In Persistit, a database record consists of a Key and a Value. The terms “record” and “key/value pair” are used interchangeably.
1639-
1640-When you store a record, Persistit searches for a previously stored record having the same key. If there is such a record, Persistit replaces its value. If there is no such record, Persistit inserts a new one. Like a Java Map, Persistit stores at most one value per key, and every record in a Tree has a unique key value.
1641-
1642-=== Keys
1643-
1644-A Key contains a unique identifier for key/value pair - or record - in a tree. The identifier consists of a sequence of one or more Java values encoded into an array of bytes stored in the volume file.
1645-
1646-Key instances are mutable. Your application typically changes an Exchange's Key in preparation for fetching or retrieving data. In particular, you can append, remove or replace one or more values in a Key. Each value you append is called a _key segment_. You append multiple key segments to implement concatenated keys. See +com.persistit.Key+ for additional information on constructing keys and the ordering of key traversal within a tree.
1647-
1648-The +HelloWorld.java+ example appends “Hello” to the Exchange’s Key object in this line:
1649-
1650-[source,java]
1651-----
1652- dbex.getKey().append("Hello");
1653-----
1654-
1655-The result is a key with a single key segment.
1656-
1657-=== Values
1658-
1659-A Value object represents the serialized state of a Java object or a primitive value. It is a staging area for data being transferred from or to the database by +fetch+, +traverse+ and +store+ operations.
1660-
1661-Value instances are mutable. The +fetch+ and +traverse+ operations modify the state of an Exchange's Value instance to represent the value associated with some Key. Your application executes methods to modify the state of the Value instance in preparation for storing new data values into the database.
1662-
1663-Numerous methods allow you to serialize and deserialize primitives values and objects into and from a Value object. For example, in +HelloWorld.java+, the statement
1664-
1665-[source,java]
1666-----
1667- dbex.getValue().put("World");
1668-----
1669-serializes the string “World” into the backing byte array of the Exchange’s Value object and
1670-
1671-[source,java]
1672-----
1673- System.out.println(
1674- dbex.getKey().indexTo(0).decode() + " " +
1675- dbex.getValue().get());
1676-----
1677-deserializes and prints an object value from the Key and another object value from the Value. Value also has methods such as +getInt+, +getLong+, +getByteArray+ to decode primitive and array values directly.
1678-
1679-=== Storing and Fetching Data
1680-
1681-Finally, it is these two methods in +HelloWorld.java+ that cause the Exchange object to share data with the B-Tree, making it persistent and potentially available to other threads:
1682-
1683-[source,java]
1684-----
1685- dbex.store();
1686- ...
1687- while (dbex.next()) { ... }
1688-----
1689-
1690-=== Closing Persistit
1691-
1692-Persistit creates one or more background threads that lazily write data to the Volume files and perform other maintenance activities. Be sure to invoke the +com.persistit.Persistit.close+ method to allow these threads to finish their work and exit properly. The pattern illustrated in +HelloWorld.java+, using a _try/finally_ block to invoke +close+, is strongly recommended.
1693-
1694-The +close+ flushes all data from
1695-
1696-
1697-== Additional Topics
1698-
1699-=== PersistitMap
1700-
1701-A particularly easy way to get started with Persistit is to use its built-in +com.persistit.PersistitMap+ implementation. PersistitMap implements the +java.util.SortedMap+ interface, so it can directly replace +java.util.TreeMap+ or other kinds of Map in existing Java code.
1702-
1703-See <<PersistitMap>>.
1704-
1705-=== KeyFilters
1706-
1707-A +com.persistit.KeyFilter+ can be supplied to restrict the results traversal operation in a convenient and
1708-
1709-=== Transactions
1710-
1711-Persistit provides ACID Transaction support with multi-version concurrency control (MCC) and adjustable durability policy.
1712-
1713-See <<Transactions>>.
1714-
1715-=== Managing Persistit
1716-
1717-Persistit provides several mechanisms for managing Persistit operation within an application. These include
1718-
1719-- JMX MXBeans
1720-- The +com.persistit.Management+ object which provides programmatic access to many management operations
1721-- The +com.persistit.CLI+ object which provides a command-line interface for various management operations
1722-- The AdminUI tool which provides a graphical client interface for examining records and other resources
1723-- Logging interface design for easy embedding in host applications
1724-
1725-See <<Management>>.
1726
1727=== added file 'doc/Management.rst'
1728--- doc/Management.rst 1970-01-01 00:00:00 +0000
1729+++ doc/Management.rst 2012-05-30 18:23:19 +0000
1730@@ -0,0 +1,446 @@
1731+.. _Management:
1732+
1733+Management
1734+==========
1735+
1736+Akiban Persistit provides three main avenues for measuring and managing its internal resources: an RMI interface, a JMX interface and a command-line interface capable of launching various utility tasks.
1737+
1738+The RMI interface is primarily intended for the com.persistit.ui.AdminUI utility. AdminUI is a JFC/Swing program that runs on a device with graphical UI capabilities. For example, in Linux and Unix it requires an XServer. Since production servers are usually headless it is often necessary to run AdminUI remotely, via its RMI interface. To do this, the Persistit configuration must specify either the ``rmiport`` or ``rmihost`` property so that it can start an RMI server.
1739+
1740+Suppose a Persistit-based application is running on a host named “somehost” and has specified the configuration property ``rmiport=1099`` in its configuration. Then the AdminUI can be launched as follows to connect with it:
1741+
1742+.. code-block:: java
1743+
1744+ java -cp classpath com.persistit.ui.AdminUI somehost:1099
1745+
1746+where classpath includes the Persistit ``com.persistit.ui`` package.
1747+
1748+The JMX interface can be used by third-party management utilities, from applications such as ``jconsole`` and ``visualvm``, and from command-line JMX clients such as ``jmxterm``. To enable JMX access, the configuration must specify the property ``jmx=true``. This causes Persistit to register several MBeans with the platform MBean server during initialization.
1749+
1750+MXBeans
1751+-------
1752+The following JMX MXBeans are available:
1753+
1754+ ``com.persistit:type=Persistit``
1755+ See ``com.persistit.mxbeans.ManagementMXBean``
1756+ ``com.persistit:type=Persistit,class=AlertMonitorMXBean``
1757+ Accumulates, logs and emits notifications about abnormal events such as IOExceptions and measurements outside of
1758+ expected thresholds.
1759+ ``com.persistit:type=Persistit,class=CleanupManagerMXBean``
1760+ View current state of the Cleanup Manager. The Cleanup Manager performs background pruning and tree maintenance
1761+ activities.
1762+ ``com.persistit:type=Persistit,class=IOMeter``
1763+ Maintains statistics on file system I/O operations.
1764+ ``com.persistit.type=Persistit,class=JournalManager``
1765+ Views current journal status.
1766+ ``com.persistit.type=Persistit,class=RecoveryManager``
1767+ Views current status of the recovery process. Attributes of this MXBean change only during the recovery process.
1768+ ``com.persistit:type=Persistit,class=TransactionIndexMXBean``
1769+ View internal state of transaction index queues and tables.
1770+ ``com.persistit.type=Persistit,class=BufferPool.*SSSS*``
1771+ where *SSSS* is a buffer size (512, 1024, 2048, 4096 or 16394). View utilization statistics for buffers of the
1772+ selected size.
1773+
1774+
1775+For details see the JavaDoc API documentation for each MXBean interface.
1776+
1777+Management Tasks
1778+----------------
1779+
1780+Persistit provides several ways to launch and administer ``com.persistit.Task`` instances. A ``Task`` is a management operation that may take a significant amount of time and usually runs in a separate thread. For example, ``com.persistit.IntegrityCheck`` is a ``Task`` that verifies the internal structural integrity of one or more trees and can run for minutes to hours, depending on the size of the database. The :ref:`AdminUI` tool, ``com.persistit.mxbeans.ManagementMXBean`` and the command-line interface (:ref:`CLI`) provide mechanisms to launch, suspend or stop a task, and to monitor a task’s progress.
1781+
1782+Currently the following built-in Tasks are available:
1783+
1784+ ``icheck``
1785+ Check the integrity of one or more trees or volumes.
1786+ ``save``
1787+ Save selected key-value pairs from one or more trees to a flat file.
1788+ ``load``
1789+ Load selected key-value pairs from a flat file written by ``save``.
1790+ ``backup``
1791+ Control and/or perform a concurrent backup of one more more volumes.
1792+ ``stat``
1793+ Aggregate various performance statistics and either return them immediately, or write them periodically to a file.
1794+ ``task``
1795+ Check the status of an existing task. This task can also suspend, resume or stop an existing task. This task, which
1796+ immediately returns status information, can be used by external tools to poll the status of other tasks.
1797+ ``cliserver``
1798+ Start a simple command-line server on a specified port. This enables a client program to execute commands sending
1799+ them directly to that port.
1800+ *other tasks*
1801+ Various commands allow you to select and view pages and journal records.
1802+
1803+
1804+Executing a Task from an Application
1805+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1806+
1807+The ``com.persistit.mxbeans.ManagementMXBean#execute`` and ``com.persistit.mxbeans.ManagementMXBean#launch`` methods both take a single String-valued argument, parse it to set up a ``Task`` and return a String-valued result. For example:
1808+
1809+.. code-block:: java
1810+
1811+ String taskId = db.getManagement().launch(“backup -z file=/tmp/mybackup.zip”);
1812+ String status = db.getManagement().execute(“task -v -m -c taskId=” + taskId);
1813+
1814+launches the backup task and then queries its status.
1815+
1816+Executing a Task from a JMX Client
1817+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818+
1819+The ``com.persistit.mxbeans.ManagementMXBean#execute`` and ``com.persistit.mxbeans.ManagementMXBean#launch`` methods are exposed as operations on the ``com.persistit.mxbeans.ManagementMXBean``. You can invoke tasks
1820+
1821+- via ``jconsole`` by typing the desired command line as the argument of the ``execute`` operation.
1822+- via a third-party JMX client such as ``jmxterm``.
1823+- via the ``cliserver`` feature
1824+
1825+Executing a Task Using a Third-Party JMX client
1826+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1827+
1828+You can use the ``jmxterm`` program, for example, (see [http://www.cyclopsgroup.org/projects/jmxterm]) to execute commands with the following shell script::
1829+
1830+ #!/bin/sh
1831+ java -jar jmxterm-1.0-alpha-4-uber.jar --verbose silent --noninteract --url $1 <<EOF
1832+ run -d com.persistit -b com.persistit:type=Persistit execute $2
1833+ EOF
1834+
1835+To use this script, specify either the JMX URL or the process ID as the first command argument, and the command line as the second argument. Example::
1836+
1837+ peter:~/workspace/sandbox$ jmxterm-execute 1234 ‘stat\ -a’
1838+ hit=3942334 miss=14 new=7364 evict=0 jwrite=81810 jread=2 jcopy=63848 tcommit=0 troll=0 CC=0 RV=12 RJ=2 WJ=81810 EV=0 FJ=529 IOkbytes=1134487 TOTAL
1839+
1840+This command invokes the ``stat`` task with the flag ``-a`` on a JVM running with process id 1234. Note that with jxmterm white-space must be quoted by backslash (‘\’) even though the argument list is also enclosed in single-quotes. The backslash marshals the space character through ``jmxterm``’s parser. Commas and other delimiters also need to be quoted.
1841+
1842+.. _cliserver:
1843+
1844+Executing a Task Using the Built-In ``cliserver``
1845+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1846+
1847+``cliserver`` is a simple text-based server that receives a command line as a text string and emits the generated output as its response. To start it, enter the command::
1848+
1849+ cliserver port=9999
1850+
1851+programmatically or through JMX. (You may specify any valid, available port.) Then use a command-line client to send command lines to that port and display their results. Persistit includes a primitive command-line client within the ``com.persistit.CLI`` class itself. Create a script to invoke it as follows::
1852+
1853+ #!/bin/sh
1854+ java -cp classpath com.persistit.CLI localhost:9999 $*
1855+
1856+Where ``classpath`` includes the Persistit library. Assuming the name of the script is ``pcli`` you can then invoke commands from a shell as shown in this example::
1857+
1858+ /home/akiban:~$ pcli icheck -v -c "trees=*:Acc*"
1859+ Volume,Tree,Faults,IndexPages,IndexBytes,DataPages,DataBytes,LongRecordPages,LongRecordBytes,MvvPages,MvvRecords,MvvOverhead,MvvAntiValues,IndexHoles,PrunedPages
1860+ "persistit","AccumulatorRecoveryTest",0,3,24296,1519,15560788,0,0,1506,52192,721521,2397,0,0
1861+ "*","*",0,3,24296,1519,15560788,0,0,1506,52192,721521,2397,0,0
1862+ /home/akiban:~$
1863+
1864+Alternatively, you can use ``curl`` as follows::
1865+
1866+ #!/bin/sh
1867+ echo "$*" | curl --silent --show-error telnet://localhost:9999
1868+
1869+to issue commands.
1870+
1871+.. caution::
1872+
1873+ ``cliserver`` has no access control and sends potentially sensitive data in cleartext form. Therefore it should be used with care and only in a secure
1874+ network environment. Its primary mission is to allow easy inspection of internal data structures within Persistit.
1875+
1876+.. _CLI:
1877+
1878+The Command-Line Interface
1879+--------------------------
1880+
1881+The String value passed to the ``execute`` and ``launch`` operations specifies the name of a task and its arguments. The general form is::
1882+
1883+ commandname -flag -flag argname=value argname=value
1884+
1885+where the order of arguments and flags is not significant.
1886+
1887+
1888+Command: ``icheck``
1889+^^^^^^^^^^^^^^^^^^^
1890+
1891+Performs a com.persistit.IntegrityCheck task. Arguments:
1892+
1893+ ``trees``
1894+ Specifies volumes and/or trees to check. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
1895+ ``-r``
1896+ Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.
1897+ ``-u``
1898+ Don't freeze updates (Default is to freeze updates)
1899+ ``-h``
1900+ Fix index holes. An *index hole* is an anomaly that occurs rarely in normal operation such that a page does not have an index entry in the index page level
1901+ immediately above it
1902+ ``-p``
1903+ Prune obsolete MVV (multi-version value) instances while checking.
1904+ ``-P``
1905+ Prune obsolete MVV instances, and clear any remaining aborted TransactionStatus instances. Use with care.
1906+ ``-v``
1907+ Emit verbose output. For example, emit statistics for each tree.
1908+ ``-c``
1909+ Display tree statistics in comma-separated-variable format suitable for import into a spreadsheet program.
1910+
1911+Example::
1912+
1913+ icheck trees=vehicles/* -h
1914+
1915+Checks all trees in the ``vehicles`` volume and repairs index holes.
1916+
1917+Command: ``save``
1918+^^^^^^^^^^^^^^^^^
1919+
1920+Starts a com.persistit.StreamSaver task. Arguments:
1921+
1922+ ``file``
1923+ Name of file to save records to (required)
1924+ ``trees``
1925+ Specifies volumes and/or trees to save. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
1926+ ``-r``
1927+ Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
1928+ ``-v``
1929+ emit verbose output
1930+
1931+...‘*’ and ‘?’ are standard wildcards.
1932+
1933+Example::
1934+
1935+ save -v file=/home/akiban/save.dat trees=vehicles/*{[“Edsel”:”Yugo”]}
1936+
1937+Saves the records for “Edsel” through “Yugo”, inclusive, from any tree in the volume named ``vehicles``. See com.persistit.TreeSelector for selection syntax details.
1938+
1939+Command: ``load``
1940+^^^^^^^^^^^^^^^^^
1941+
1942+Starts a com.persistit.StreamLoader task. Arguments:
1943+
1944+ ``file``
1945+ Name of file to load records from
1946+ ``trees``
1947+ Specifies volumes and/or trees to load. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
1948+ ``-r``
1949+ Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
1950+ ``-n``
1951+ Don't create missing Volumes (Default is to create them)
1952+ ``-t``
1953+ Don't create missing Trees (Default is to create them)
1954+ ``-v``
1955+ Emit verbose output
1956+
1957+...‘*’ and ‘?’ are standard wildcards.
1958+
1959+Example::
1960+
1961+ load file=/home/akiban/save.dat trees=*/*{[“Falcon”:”Firebird”]}
1962+
1963+For any tree in any volume, this command loads all records having keys between “Falcon” and “Firebird”, inclusive.
1964+
1965+Command: ``backup``
1966+^^^^^^^^^^^^^^^^^^^
1967+
1968+Starts a ``com.persistit.BackupTask`` task to perform concurrent (hot) backup. Arguments:
1969+
1970+ ``file``
1971+ Archive file path. If this argument is specified, BackupTask will back up the database in .zip format to the specified file. This is intended only for small
1972+ databases. It is expected that ``backup`` will be used in conjunction with high-speed third-party data copying utilities for production use. The ``-a`` and
1973+ ``-e``
1974+ flags are incompatible with operation when the ``file`` argument is specified and are ignored.
1975+ ``-a``
1976+ Start appendOnly mode - for use with third-party backup tools. ``backup -a`` should be invoked before data copying begins.
1977+ ``-e``
1978+ End appendOnly mode - for use with third-party backup tools. ``backup -e`` should be invoked after data copying ends.
1979+ ``-c``
1980+ Request checkpoint before backup.
1981+ ``-z``
1982+ Compress output to ZIP format - meaningful only in conjunction with the ``file`` argument.
1983+ ``-f``
1984+ Emit a list of files that need to be copied. In this form the task immediately returns with a list of files currently comprising the Persistit database,
1985+ including Volume and journal files.
1986+ ``-y``
1987+ Copy pages from journal to Volumes before starting backup. This reduces the number of journal files in the backup set.
1988+
1989+Example::
1990+
1991+ backup -y -a -c -y -f
1992+ … invoke third-party backup tool to copy the database files
1993+ backup -e
1994+
1995+Uses the ``backup`` task twice, once to set *append-only* mode, checkpoint the journal and perform a full copy-back cycle (a process that attempts to shorten the journal), and then write out a list of files that need to be copied. The second call to ``backup`` restores normal operation. Between these two calls a third party backup tool is used to copy the data.
1996+
1997+Example::
1998+
1999+ backup -z file=/tmp/my_backup.zip
2000+
2001+Uses the built-in file copy feature with ZIP compression.
2002+
2003+Command: ``task``
2004+^^^^^^^^^^^^^^^^^
2005+
2006+Queries, stops, suspends or resumes a background task. Arguments:
2007+
2008+ ``taskId``
2009+ Task ID to to check, or -1 for all
2010+ ``-v``
2011+ Verbose - returns detailed status messages from the selected task(s)
2012+ ``-m``
2013+ Keep previously delivered messages. Default is to remove messages once reported.
2014+ ``-k``
2015+ Keep the selected task or tasks even if completed. Default is to remove tasks once reported.
2016+ ``-x``
2017+ Stop the selected task or tasks
2018+ ``-u``
2019+ Suspend the selected task or tasks
2020+ ``-r``
2021+ Resume the selected task or tasks
2022+
2023+Unlike other commands, the ``task`` command always runs immediately even if invoked through the ``launch`` method.
2024+
2025+You can use the ``task`` command to poll and display progress of long-running tasks. Invoke::
2026+
2027+ task -v -m -c taskId=nnn
2028+
2029+until the result is empty.
2030+
2031+Command: ``cliserver``
2032+^^^^^^^^^^^^^^^^^^^^^^
2033+
2034+Starts a simple text-based server that receives a command line as a text string and emits the generated output as its response. Argument:
2035+
2036+ ``port``
2037+ Port number on which to listen for commands.
2038+
2039+Command: ``exit``
2040+^^^^^^^^^^^^^^^^^
2041+
2042+Ends a running ``cliserver`` instance.
2043+
2044+Commands for Viewing Data
2045+^^^^^^^^^^^^^^^^^^^^^^^^^
2046+
2047+The following commands execute immediately, even if invoked through the ``launch`` method. They provide a mechanism to examine individual database pages or journal records.
2048+
2049+Command: ``select``
2050+^^^^^^^^^^^^^^^^^^^
2051+
2052+Selects a volume and optionally a tree for subsequent operations such as ``view``. Arguments:
2053+
2054+ ``tree``
2055+ Specifies volume and/or tree to select as context for subsequent operations. See com.persistit.TreeSelector for details syntax.
2056+ ``-r``
2057+ Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
2058+
2059+Command: ``list``
2060+^^^^^^^^^^^^^^^^^
2061+
2062+Lists volumes and trees. Arguments:
2063+
2064+ ``trees``
2065+ Specifies volumes and/or trees to list. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
2066+ ``-r``
2067+ Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.
2068+
2069+All volumes, and all trees within those volumes, that match the ``trees`` specification are listed. By default, this command lists all trees in all volumes.
2070+
2071+Command: ``pview``
2072+^^^^^^^^^^^^^^^^^^
2073+
2074+Displays contents of a database page. Arguments:
2075+
2076+ ``page``
2077+ page address
2078+ ``jaddr``
2079+ journal address - displays a page version stored at the specified journal address
2080+ ``key``
2081+ a key specified as a String defined in the com.persistit.Key class
2082+ ``level``
2083+ tree level of the desired page
2084+ ``find``
2085+ selected records in an index page surrounding a key that points to the specified page address
2086+ ``-a``
2087+ all records. If specified, all records in the page will be displayed. Otherwise the output is abbreviated to no more than 20 lines.
2088+ ``-s``
2089+ summary - only header information in the page is displayed
2090+
2091+The ``pview`` command identifies a page in one of three distinct ways: by page address, by journal address, or by key. Only one of the three parameters ``page``, ``jaddr`` or ``key`` (with ``level``) may be used.
2092+
2093+``page`` specifies the current version of a page having the specified address. If there is a copy of the page in the buffer pool, that copy is displayed even if it contains updates that are not yet written to disk.
2094+
2095+``jaddr`` specifies an address in the journal. Typical use is to invoke the ``jview`` command to view a list of journal records, and then to see a detailed view of one page record in the journal, invoke the ``pview`` command with its journal address.
2096+
2097+``key`` specifies a key. By default the data page associated with that key will be displayed. The data page is defined as level 0. The ``level`` parameter allows pages at various index levels to be viewed; for example ``level=1`` refers to the index page that points to the data page containing the specified key.
2098+
2099+When examining an index page with potentially hundreds of records it is sometimes convenient to find the record that points to a particular child page, and also the records immediately before and after. Specifying the ``find`` parameter when viewing an index page abbreviates the displayed records to include just the first and last records in the page, plus a small range of records surrounding the one that points to the specified page. This mechanism provides a convenient way to find sibling pages.
2100+
2101+
2102+Command: ``path``
2103+^^^^^^^^^^^^^^^^^
2104+
2105+For a specified key displays the sequence of pages from root of the tree to the data page containing they key. Argument:
2106+
2107+ ``key``
2108+ a key specified as a String defined in the com.persistit.Key class
2109+
2110+
2111+Command: ``jview``
2112+^^^^^^^^^^^^^^^^^^
2113+
2114+Displays journal records. Arguments:
2115+
2116+ ``start``
2117+ starting journal address (default = 0)
2118+ ``end``
2119+ end journal address (address = infinite)
2120+ ``timestamps``
2121+ range selection of timestamp values, e.g., “132466-132499” for records having timestamps between these two numbers, inclusive. Default is all timestamps.
2122+ ``types``
2123+ comma-delimted list of two-character record types, e.g., “JH,IV,IT,CP” to select only Journal Header, Identify Volume, Identify Tree and Check Point records
2124+ (see ``com.persistit.JournalRecord`` for definitions of all types.) Default value is all types.
2125+ ``pages``
2126+ range selection of page address for PA (Page) records, e.g., “1,2,13-16” to include pages, 1, 2, 13, 14, 15 or 16.
2127+ ``maxkey``
2128+ maximum display length of key values in the output. Default value is 42.
2129+ ``maxvalue``
2130+ maximum display length of values in the output. Default value is 42.
2131+ ``path``
2132+ journal file path. Default is the journal file path of the currently instantiated Persistit instance.
2133+ ``-v``
2134+ verbose format. If specified, causes PM (Page Map) and TM (TransactionMap) records to be be display all map elements.
2135+
2136+
2137+Note that the journal on a busy system contains a large number of records, so entering the ``journal`` command without constraining the address range or record types may result in extremely lengthy output.
2138+
2139+Command: ``open``
2140+^^^^^^^^^^^^^^^^^
2141+
2142+Opens a Persistit database for analysis. This task can only be used to examine a copy of a Persistit database that is not currently in use by an application. It works by attempting to open the volume and journal files using a synthesized configuration. It finds a collection of journal files and volume files specified by the ``datapath``, ``journalpath`` and ``volumepath`` arguments; from these it derives a set of properties that will allow it to examine those journals and volumes. By default all volumes are opened in read-only mode and cannot be changed by operations executed from the command-line interface.
2143+
2144+If there already is an open Persistit instance, this command detaches it. For example, if you start ``cliserver`` from a live Persistit instance and then issue the ``open`` command, the live instance will continue to operate but ``cliserver`` will no longer be attached to it.
2145+
2146+Note that you cannot ``open`` volumes that are already open in a running Persistit instance due to their file locks. However, you can copy open volumes and journal files to another location and ``open`` the copy. This is the primary use case for the ``open`` command: to analyze a copy of a database (for example a copy recovered from backup) without having to a launch the application software that embeds Persistit.
2147+
2148+Arguments:
2149+
2150+ ``datapath``
2151+ a directory path for volume and journal files to be analyzed
2152+ ``volumepath``
2153+ overrides ``datapath`` to specify an alternative location for volume files.
2154+ ``journalpath``
2155+ overrides ``datapath`` to specify an alternative location for journal files.
2156+ ``rmiport``
2157+ specifies an RMI port to which an instance of the AdminUI can attach.
2158+ ``-g``
2159+ launch a local copy of AdminUI
2160+ ``-y``
2161+ attempt to recover committed transactions .
2162+
2163+Note that even if you specify ``-y`` to recover transactions, the volume files will not be modified. But the ``open`` command will add a new journal file containing modifications caused by the recovery process. You can simply delete that file when done.
2164+
2165+Command: ``close``
2166+^^^^^^^^^^^^^^^^^^
2167+
2168+Detach and close the current Persistit instance. If the CLI was started with a live Persistit instance then this command merely detaches from it; if the instance was created with the ``open`` command then ``close`` closes it and releases all related file locks, buffers, etc.
2169+
2170+Command: ``source``
2171+^^^^^^^^^^^^^^^^^^^
2172+
2173+Execute command lines from a specified text file. Argument:
2174+
2175+ ``file``
2176+ file name of command input file
2177
2178=== removed file 'doc/Management.txt'
2179--- doc/Management.txt 2012-04-30 22:09:31 +0000
2180+++ doc/Management.txt 1970-01-01 00:00:00 +0000
2181@@ -1,360 +0,0 @@
2182-[[Management]]
2183-= Management
2184-
2185-Akiban Persistit provides three main avenues for measuring and managing its internal resources: an RMI interface, a JMX interface and a command-line interface capable of launching various utility tasks.
2186-
2187-The RMI interface is primarily intended for the com.persistit.ui.AdminUI utility. AdminUI is a JFC/Swing program that runs on a device with graphical UI capabilities. For example, in Linux and Unix it requires an XServer. Since production servers are usually headless it is often necessary to run AdminUI remotely, via its RMI interface. To do this, the Persistit configuration must specify either the +rmiport+ or +rmihost+ property so that it can start an RMI server.
2188-
2189-Suppose a Persistit-based application is running on a host named “somehost” and has specified the configuration property +rmiport=1099+ in its configuration. Then the AdminUI can be launched as follows to connect with it:
2190-
2191-----
2192-java -cp <classpath> com.persistit.ui.AdminUI somehost:1099
2193-----
2194-
2195-where <classpath> includes the Persistit com.persistit.ui package.
2196-
2197-The JMX interface can be used by third-party management utilities, from applications such as +jconsole+ and +visualvm+, and from command-line JMX clients such as +jmxterm+. To enable JMX access, the configuration must specify the property +jmx=true+. This causes Persistit to register several MBeans with the platform MBean server during initialization.
2198-
2199-== MXBeans
2200-
2201-The following JMX MXBeans are available:
2202-
2203-[horizontal]
2204-+com.persistit:type=Persistit+:: See +com.persistit.mxbeans.ManagementMXBean+
2205-+com.persistit:type=Persistit,class=AlertMonitorMXBean+:: Accumulates, logs and emits notifications about abnormal events such as IOExceptions and measurements outside of expected thresholds.
2206-+com.persistit:type=Persistit,class=CleanupManagerMXBean+:: View current state of the Cleanup Manager. The Cleanup Manager performs background pruning and tree maintenance activities.
2207-+com.persistit:type=Persistit,class=IOMeter+:: Maintains statistics on file system I/O operations.
2208-+com.persistit.type=Persistit,class=JournalManager+:: Views current journal status.
2209-+com.persistit.type=Persistit,class=RecoveryManager+:: Views current status of the recovery process. Attributes of this MXBean change only during the recovery process.
2210-+com.persistit:type=Persistit,class=TransactionIndexMXBean+:: View internal state of transaction index queues and tables.
2211-+com.persistit.type=Persistit,class=BufferPool._SSSS_+:: where _SSSS_ is a buffer size (512, 1024, 2048, 4096 or 16394). View utilization statistics for buffers of the selected size.
2212-
2213-
2214-For details see the JavaDoc API documentation for each MXBean interface.
2215-
2216-== Management Tasks
2217-
2218-Persistit provides several ways to launch and administer +com.persistit.Task+ instances. A +Task+ is a management operation that may take a significant amount of time and usually runs in a separate thread. For example, +com.persistit.IntegrityCheck+ is a +Task+ that verifies the internal structural integrity of one or more trees and can run for minutes to hours, depending on the size of the database. The <<AdminUI>> tool, +com.persistit.ManagementMXBean+ and the command-line interface (<<CLI>>) provide mechanisms to launch, suspend or stop a task, and to monitor a task’s progress.
2219-
2220-Currently the following built-in Tasks are available:
2221-
2222-[horizontal]
2223-+icheck+:: Check the integrity of one or more trees or volumes.
2224-+save+:: Save selected key-value pairs from one or more trees to a flat file.
2225-+load+:: Load selected key-value pairs from a flat file written by +save+.
2226-+backup+:: Control and/or perform a concurrent backup of one more more volumes.
2227-+stat+:: Aggregate various performance statistics and either return them immediately, or write them periodically to a file.
2228-+task+:: Check the status of an existing task. This task can also suspend, resume or stop an existing task. This task, which immediately returns status information, can be used by external tools to poll the status of other tasks.
2229-+cliserver+:: Start a simple command-line server on a specified port. This enables a client program to execute commands sending them directly to that port.
2230-+_other tasks_+:: Various commands allow you to select and view pages and journal records.
2231-
2232-
2233-=== Executing a Task from an Application
2234-
2235-The +com.persistit.mxbeans.ManagementMXBean#execute+ and +com.persistit.mxbeans.ManagementMXBean#launch+ methods both take a single String-valued argument, parse it to set up a +Task+ and return a String-valued result. For example:
2236-
2237-[source,java]
2238-----
2239-String taskId = db.getManagement().launch(“backup -z file=/tmp/mybackup.zip”);
2240-String status = db.getManagement().execute(“task -v -m -c taskId=” + taskId);
2241-----
2242-
2243-launches the backup task and then queries its status.
2244-
2245-=== Executing a Task from a JMX Client
2246-
2247-The +com.persistit.mxbeans.ManagementMXBean#execute+ and +com.persistit.mxbeans.ManagementMXBean#launch+ methods are exposed as operations on the +com.persistit.mxbeans.ManagementMXBean+. You can invoke tasks
2248-
2249-- via +jconsole+ by typing the desired command line as the argument of the +execute+ operation.
2250-- via a third-party JMX client such as +jmxterm+.
2251-- via the +cliserver+ feature
2252-
2253-==== Executing a Task Using a Third-Party JMX client.
2254-
2255-You can use the +jmxterm+ program, for example, (see [http://www.cyclopsgroup.org/projects/jmxterm]) to execute commands with the following shell script:
2256-
2257-[source,bash]
2258-----
2259-#!/bin/sh
2260-java -jar jmxterm-1.0-alpha-4-uber.jar --verbose silent --noninteract --url $1 <<EOF
2261-run -d com.persistit -b com.persistit:type=Persistit execute $2
2262-EOF
2263-----
2264-
2265-To use this script, specify either the JMX URL or the process ID as the first command argument, and the command line as the second argument. Example
2266-
2267-----
2268-peter:~/workspace/sandbox$ jmxterm-execute 1234 ‘stat\ -a’
2269-hit=3942334 miss=14 new=7364 evict=0 jwrite=81810 jread=2 jcopy=63848 tcommit=0 troll=0 CC=0 RV=12 RJ=2 WJ=81810 EV=0 FJ=529 IOkbytes=1134487 TOTAL
2270-----
2271-
2272-This command invokes the +stat+ task with the flag +-a+ on a JVM running with process id 1234. Note that with jxmterm white-space must be quoted by backslash (‘\’) even though the argument list is also enclosed in single-quotes. The backslash marshals the space character through +jmxterm+’s parser. Commas and other delimiters also need to be quoted.
2273-
2274-[[cliserver]]
2275-=== Executing a Task Using the Built-In +cliserver+
2276-
2277-+cliserver+ is a simple text-based server that receives a command line as a text string and emits the generated output as its response. To start it, enter the command
2278-----
2279-cliserver port=9999
2280-----
2281-programmatically or through JMX. (You may specify any valid, available port.) Then use a command-line client to send command lines to that port and display their results. Persistit includes a primitive command-line client within the +com.persistit.CLI+ class itself. Create a script to invoke it as follows:
2282-
2283-[source,bash]
2284-----
2285-#!/bin/sh
2286-java -cp <classpath> com.persistit.CLI localhost:9999 $*
2287-----
2288-
2289-Where +<classpath>+ includes the Persistit library. Assuming the name of the script is +pcli+ you can then invoke commands from a shell as shown in this example:
2290-
2291-----
2292-/home/akiban:~$ pcli icheck -v -c "trees=*:Acc*"
2293-Volume,Tree,Faults,IndexPages,IndexBytes,DataPages,DataBytes,LongRecordPages,LongRecordBytes,MvvPages,MvvRecords,MvvOverhead,MvvAntiValues,IndexHoles,PrunedPages
2294-"persistit","AccumulatorRecoveryTest",0,3,24296,1519,15560788,0,0,1506,52192,721521,2397,0,0
2295-"*","*",0,3,24296,1519,15560788,0,0,1506,52192,721521,2397,0,0
2296-/home/akiban:~$
2297-----
2298-
2299-Alternatively, you can use +curl+ as follows:
2300-
2301-[source,bash]
2302-----
2303-#!/bin/sh
2304-echo "$*" | curl --silent --show-error telnet://localhost:9999
2305-----
2306-to issue commands.
2307-
2308-CAUTION: Warning: +cliserver+ has no access control and sends potentially sensitive data in cleartext form. Therefore it should be used with care and only in a secure network environment. Its primary mission is to allow easy inspection of internal data structures within Persistit.
2309-
2310-[[CLI]]
2311-== The Command-Line Interface
2312-
2313-The String value passed to the +execute+ and +launch+ operations specifies the name of a task and its arguments. The general form is
2314-
2315-----
2316-commandname -flag -flag argname=value argname=value
2317-----
2318-
2319-where the order of arguments and flags is not significant.
2320-
2321-
2322-=== Command: +icheck+
2323-
2324-Performs a com.persistit.IntegrityCheck task. Arguments:
2325-
2326-[horizontal]
2327-+trees+:: Specifies volumes and/or trees to check. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
2328-+-r+:: Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.
2329-+-u+:: Don't freeze updates (Default is to freeze updates)
2330-+-h+:: Fix index holes. An _index hole_ is an anomaly that occurs rarely in normal operation such that a page does not have an index entry in the index page level immediately above it
2331-+-p+:: Prune obsolete MVV (multi-version value) instances while checking.
2332-+-P+:: Prune obsolete MVV instances, and clear any remaining aborted TransactionStatus instances. Use with care.
2333-+-v+:: Emit verbose output. For example, emit statistics for each tree.
2334-+-c+:: Display tree statistics in comma-separated-variable format suitable for import into a spreadsheet program.
2335-
2336-Example:
2337-----
2338-icheck trees=vehicles/* -h
2339-----
2340-Checks all trees in the +vehicles+ volume and repairs index holes.
2341-
2342-=== Command: +save+
2343-
2344-Starts a com.persistit.StreamSaver task. Arguments:
2345-
2346-[horizontal]
2347-+file+:: Name of file to save records to (required)
2348-+trees+:: Specifies volumes and/or trees to save. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
2349-+-r+:: Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
2350-+-v+:: emit verbose output
2351-‘*’ and ‘?’ as standard wildcards.)
2352-
2353-Example:
2354-----
2355-save -v file=/home/akiban/save.dat trees=vehicles/*{[“Edsel”:”Yugo”]}
2356-----
2357-
2358-Saves the records for “Edsel” through “Yugo”, inclusive, from any tree in the volume named +vehicles+. See com.persistit.TreeSelector for selection syntax details.
2359-
2360-=== Command: +load+
2361-
2362-Starts a com.persistit.StreamLoader task. Arguments:
2363-
2364-[horizontal]
2365-+file+:: Name of file to load records from
2366-+trees+:: Specifies volumes and/or trees to load. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
2367-+-r+:: Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
2368-+-n+:: Don't create missing Volumes (Default is to create them)
2369-+-t+:: Don't create missing Trees (Default is to create them)
2370-‘*’ and ‘?’ as standard wildcards.)
2371-+-v+:: emit verbose output
2372-
2373-Example:
2374-----
2375-load file=/home/akiban/save.dat trees=*/*{[“Falcon”:”Firebird”]}
2376-----
2377-
2378-For any tree in any volume, this command loads all records having keys between “Falcon” and “Firebird”, inclusive.
2379-
2380-=== Command: +backup+
2381-
2382-Starts a +com.persistit.BackupTask+ task to perform concurrent (hot) backup. Arguments:
2383-
2384-[horizontal]
2385-+file+:: Archive file path. If this argument is specified, BackupTask will back up the database in .zip format to the specified file. This is intended only for small databases. It is expected that +backup+ will be used in conjunction with high-speed third-party data copying utilities for production use. The +-a+ and +-e+ flags are incompatible with operation when the +file+ argument is specified and are ignored.
2386-+-a+:: Start appendOnly mode - for use with third-party backup tools. +backup -a+ should be invoked before data copying begins.
2387-+-e+:: End appendOnly mode - for use with third-party backup tools. +backup -e+ should be invoked after data copying ends.
2388-+-c+:: Request checkpoint before backup.
2389-+-z+:: Compress output to ZIP format - meaningful only in conjunction with the +file+ argument.
2390-+-f+:: Emit a list of files that need to be copied. In this form the task immediately returns with a list of files currently comprising the Persistit database, including Volume and journal files.
2391-+-y+:: Copy pages from journal to Volumes before starting backup. This reduces the number of journal files in the backup set.
2392-
2393-Examples:
2394-----
2395-backup -y -a -c -y -f
2396-… invoke third-party backup tool to copy the database files
2397-backup -e
2398-----
2399-Uses the +backup+ task twice, once to set _append-only_ mode, checkpoint the journal and perform a full copy-back cycle (a process that attempts to shorten the journal), and then write out a list of files that need to be copied. The second call to +backup+ restores normal operation. Between these two calls a third party backup tool is used to copy the data.
2400-
2401-----
2402-backup -z file=/tmp/my_backup.zip
2403-----
2404-Uses the built-in file copy feature with ZIP compression.
2405-
2406-=== Command: +task+
2407-
2408-Queries, stops, suspends or resumes a background task. Arguments:
2409-
2410-[horizontal]
2411-+taskId+:: Task ID to to check, or -1 for all
2412-+-v+:: Verbose - returns detailed status messages from the selected task(s)
2413-+-m+:: Keep previously delivered messages. Default is to remove messages once reported.
2414-+-k+:: Keep the selected task or tasks even if completed. Default is to remove tasks once reported.
2415-+-x+:: Stop the selected task or tasks
2416-+-u+:: Suspend the selected task or tasks
2417-+-r+:: Resume the selected task or tasks
2418-
2419-Unlike other commands, the +task+ command always runs immediately even if invoked through the +launch+ method.
2420-
2421-You can use the +task+ command to poll and display progress of long-running tasks. Invoke
2422-
2423-----
2424-task -v -m -c taskId=nnn
2425-----
2426-
2427-until the result is empty.
2428-
2429-=== Command: +cliserver+
2430-
2431-Starts a simple text-based server that receives a command line as a text string and emits the generated output as its response. Argument:
2432-
2433-[horizontal]
2434-+port+:: Port number on which to listen for commands.
2435-
2436-=== Command: +exit+
2437-
2438-Ends a running +cliserver+ instance.
2439-
2440-== Commands for Viewing Data
2441-
2442-The following commands execute immediately, even if invoked through the +launch+ method. They provide a mechanism to examine individual database pages or journal records.
2443-
2444-=== Command: +select+
2445-
2446-Selects a volume and optionally a tree for subsequent operations such as +view+. Arguments:
2447-
2448-[horizontal]
2449-+tree+:: Specifies volume and/or tree to select as context for subsequent operations. See com.persistit.TreeSelector for details syntax.
2450-+-r+:: Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
2451-
2452-=== Command: +list+
2453-
2454-Lists volumes and trees. Arguments:
2455-
2456-[horizontal]
2457-+trees+:: Specifies volumes and/or trees to list. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
2458-+-r+:: Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.
2459-
2460-All volumes, and all trees within those volumes, that match the +trees+ specification are listed. By default, this command lists all trees in all volumes.
2461-
2462-=== Command: +pview+
2463-
2464-Displays contents of a database page. Arguments:
2465-
2466-[horizontal]
2467-+page+:: page address
2468-+jaddr+:: journal address - displays a page version stored at the specified journal address
2469-+key+:: a key specified as a String defined in the com.persistit.Key class
2470-+level+:: tree level of the desired page
2471-+find+:: selected records in an index page surrounding a key that points to the specified page address
2472-+-a+:: all records. If specified, all records in the page will be displayed. Otherwise the output is abbreviated to no more than 20 lines.
2473-+-s+:: summary - only header information in the page is displayed
2474-
2475-The +pview+ command identifies a page in one of three distinct ways: by page address, by journal address, or by key. Only one of the three parameters +page+, +jaddr+ or +key+ (with +level+) may be used.
2476-
2477-+page+ specifies the current version of a page having the specified address. If there is a copy of the page in the buffer pool, that copy is displayed even if it contains updates that are not yet written to disk.
2478-
2479-+jaddr+ specifies an address in the journal. Typical use is to invoke the +jview+ command to view a list of journal records, and then to see a detailed view of one page record in the journal, invoke the +pview+ command with its journal address.
2480-
2481-+key+ specifies a key. By default the data page associated with that key will be displayed. The data page is defined as level 0. The +level+ parameter allows pages at various index levels to be viewed; for example +level=1+ refers to the index page that points to the data page containing the specified key.
2482-
2483-When examining an index page with potentially hundreds of records it is sometimes convenient to find the record that points to a particular child page, and also the records immediately before and after. Specifying the +find+ parameter when viewing an index page abbreviates the displayed records to include just the first and last records in the page, plus a small range of records surrounding the one that points to the specified page. This mechanism provides a convenient way to find sibling pages.
2484-
2485-
2486-=== Command: +path+
2487-
2488-For a specified key displays the sequence of pages from root of the tree to the data page containing they key. Argument:
2489-
2490-[horizontal]
2491-+key+:: a key specified as a String defined in the com.persistit.Key class
2492-
2493-
2494-=== Command: +jview+
2495-
2496-Displays journal records. Arguments:
2497-
2498-[horizontal]
2499-+start+:: starting journal address (default = 0)
2500-+end+:: end journal address (address = infinite)
2501-+timestamps+:: range selection of timestamp values, e.g., “132466-132499” for records having timestamps between these two numbers, inclusive. Default is all timestamps.
2502-+types+:: comma-delimted list of two-character record types, e.g., “JH,IV,IT,CP” to select only Journal Header, Identify Volume, Identify Tree and Check Point records (see com.persistit.JournalRecord for definitions of all types.) Default value is all types.
2503-+pages+:: range selection of page address for PA (Page) records, e.g., “1,2,13-16” to include pages, 1, 2, 13, 14, 15 or 16.
2504-+maxkey+:: maximum display length of key values in the output. Default value is 42.
2505-+maxvalue+:: maximum display length of values in the output. Default value is 42.
2506-+path+:: journal file path. Default is the journal file path of the currently instantiated Persistit instance.
2507-+-v+:: verbose format. If specified, causes PM (Page Map) and TM (TransactionMap) records to be be display all map elements.
2508-
2509-
2510-Note that the journal on a busy system contains a large number of records, so entering the +journal+ command without constraining the address range or record types may result in extremely lengthy output.
2511-
2512-=== Command: +open+
2513-
2514-Opens a Persistit database for analysis. This task can only be used to examine a copy of a Persistit database that is not currently in use by an application. It works by attempting to open the volume and journal files using a synthesized configuration. It finds a collection of journal files and volume files specified by the +datapath+, +journalpath+ and +volumepath+ arguments; from these it derives a set of properties that will allow it to examine those journals and volumes. By default all volumes are opened in read-only mode and cannot be changed by operations executed from the command-line interface.
2515-
2516-If there already is an open Persistit instance, this command detaches it. For example, if you start +cliserver+ from a live Persistit instance and then issue the +open+ command, the live instance will continue to operate but +cliserver+ will no longer be attached to it.
2517-
2518-Note that you cannot +open+ volumes that are already open in a running Persistit instance due to their file locks. However, you can copy open volumes and journal files to another location and +open+ the copy. This is the primary use case for the +open+ command: to analyze a copy of a database (for example a copy recovered from backup) without having to a launch the application software that embeds Persistit.
2519-
2520-Arguments:
2521-
2522-[horizontal]
2523-+datapath+:: a directory path for volume and journal files to be analyzed
2524-+volumepath+:: overrides +datapath+ to specify an alternative location for volume files.
2525-+journalpath+:: overrides +datapath+ to specify an alternative location for journal files.
2526-+rmiport+:: specifies an RMI port to which an instance of the AdminUI can attach.
2527-+-g+:: launch a local copy of AdminUI
2528-+-y+:: attempt to recover committed transactions .
2529-
2530-Note that even if you specify +-y+ to recover transactions, the volume files will not be modified. But the +open+ command will add a new journal file containing modifications caused by the recovery process. You can simply delete that file when done.
2531-
2532-=== Command: +close+
2533-
2534-Detach and close the current Persistit instance. If the CLI was started with a live Persistit instance then this command merely detaches from it; if the instance was created with the +open+ command then +close+ closes it and releases all related file locks, buffers, etc.
2535-
2536-=== Command: +source+
2537-
2538-Execute command lines from a specified text file. Argument:
2539-
2540-[horizontal]
2541-+file+:: file name of command input file
2542
2543=== added file 'doc/Miscellaneous.rst'
2544--- doc/Miscellaneous.rst 1970-01-01 00:00:00 +0000
2545+++ doc/Miscellaneous.rst 2012-05-30 18:23:19 +0000
2546@@ -0,0 +1,36 @@
2547+.. _Miscellaneous:
2548+
2549+Miscellaneous Topics
2550+====================
2551+
2552+Following are some short items you may find useful as you explore Akiban Persistit. Follow links to the API documentation for more details.
2553+
2554+Histograms
2555+----------
2556+
2557+The method ``com.persistit.Exchange#computeHistogram`` class provides a way to sample and summarize a set of keys in a ``Tree``. It works by traversing keys in index pages near the root of the tree. Because only a small fraction of all the keys in the tree are represented in the index, this can result in relatively small sample set of keys relatively quickly. The result can be used to estimate the actual number of keys.
2558+
2559+Temporary Volumes
2560+-----------------
2561+
2562+A Persistit temporary volume is a special kind of Volume that is deleted when Persistit is closed. The update mechanism for temporary volumes avoids writing to disk whenever possible, and its contents are not recoverable Persistit shuts down. Therefore in some cases database operations on temporary volumes are faster.
2563+
2564+The primary use case for a temporary volume is an application that needs the unlimited size, but not the persistence of normal Persistit volumes.
2565+
2566+See the ``com.persistit.Persistit#createTemporaryVolume`` method for additional details.
2567+
2568+Logging
2569+-------
2570+
2571+By default Persistit emits log messages to a file called persistit.log and also writes high level log messages to System.out. You can change this behavior by plugging in a different logging implementation. In particular, Persistit provides pluggable adapters for various other logging implementations, including Log4J, SLF4J, and the Java logging API introduced in JDK 1.4. For details see the API documentation for com.persistit.logging.AbstractPersistitLogger.
2572+
2573+Using one of these logging frameworks is simple. For example, the following code connects Persistit to an application-supplied SLF4J logger:
2574+
2575+.. code-block:: java
2576+
2577+ db.setPersistitLogger(new Slf4jAdapter(LOG))
2578+
2579+where ``db`` is the Persistit instance and ``LOG`` is a Logger supplied by SLF4J. This method should be called before the ``initialize`` method.
2580+
2581+
2582+
2583
2584=== removed file 'doc/Miscellaneous.txt'
2585--- doc/Miscellaneous.txt 2012-04-30 22:09:31 +0000
2586+++ doc/Miscellaneous.txt 1970-01-01 00:00:00 +0000
2587@@ -1,32 +0,0 @@
2588-[[Miscellaneous]]
2589-= Miscellaneous Topics
2590-
2591-Following are some short items you may find useful as you explore Akiban Persistit. Follow links to the API documentation for more details.
2592-
2593-== Histograms
2594-
2595-The method +com.persistit.Exchange#computeHistogram+ class provides a way to sample and summarize a set of keys in a +Tree+. It works by traversing keys in index pages near the root of the tree. Because only a small fraction of all the keys in the tree are represented in the index, this can result in relatively small sample set of keys relatively quickly. The result can be used to estimate the actual number of keys.
2596-
2597-== Temporary Volumes
2598-
2599-A Persistit temporary volume is a special kind of Volume that is deleted when Persistit is closed. The update mechanism for temporary volumes avoids writing to disk whenever possible, and its contents are not recoverable Persistit shuts down. Therefore in some cases database operations on temporary volumes are faster.
2600-
2601-The primary use case for a temporary volume is an application that needs the unlimited size, but not the persistence of normal Persistit volumes.
2602-
2603-See the +com.persistit.Persistit#createTemporaryVolume+ method for additional details.
2604-
2605-== Logging
2606-
2607-By default Persistit emits log messages to a file called persistit.log and also writes high level log messages to System.out. You can change this behavior by plugging in a different logging implementation. In particular, Persistit provides pluggable adapters for various other logging implementations, including Log4J, SLF4J, and the Java logging API introduced in JDK 1.4. For details see the API documentation for com.persistit.logging.AbstractPersistitLogger.
2608-
2609-Using one of these logging frameworks is simple. For example, the following code connects Persistit to an application-supplied SLF4J logger:
2610-
2611-[source,java]
2612-----
2613-db.setPersistitLogger(new Slf4jAdapter(LOG))
2614-----
2615-
2616-where +db+ is the Persistit instance and +LOG+ is a Logger supplied by SLF4J. This method should be called before the +initialize+ method.
2617-
2618-
2619-
2620
2621=== added file 'doc/PhysicalStorage.rst'
2622--- doc/PhysicalStorage.rst 1970-01-01 00:00:00 +0000
2623+++ doc/PhysicalStorage.rst 2012-05-30 18:23:19 +0000
2624@@ -0,0 +1,142 @@
2625+.. _PhysicalStorage:
2626+
2627+Physical B-Tree Representation
2628+==============================
2629+
2630+This chapter describes the physical structures used to represent Akiban Persistit records on disk and in memory.
2631+
2632+Files
2633+-----
2634+
2635+Following is a directory listing illustrating a working Persistit database::
2636+
2637+ -rw-r--r--. 1 demo demo 24G Feb 8 13:18 akiban_data
2638+ -rw-r--r--. 1 demo demo 48K Feb 8 13:19 akiban_system
2639+ -rw-r--r--. 1 demo demo 954M Feb 8 13:18 akiban_journal.000000000225
2640+ -rw-r--r--. 1 demo demo 954M Feb 8 13:19 akiban_journal.000000000226
2641+ -rw-r--r--. 1 demo demo 954M Feb 8 13:19 akiban_journal.000000000227
2642+ -rw-r--r--. 1 demo demo 662M Feb 8 13:19 akiban_journal.000000000228
2643+
2644+This database contains two *volume* files, ``akiban_data`` and ``akiban_system`` and four files that constitute part of the *journal*. As explained below, Persistit records are usually stored in a combination of volume and journal files.
2645+
2646+.. _Journal:
2647+
2648+The Journal
2649+-----------
2650+
2651+The *journal* is a set of files containing variable length records. The journal is append-only. New records are written only at the end; existing records are never overwritten. The journal consists of a numbered series of files having a configurable maximum size. When a journal file becomes full Persistit closes it and begins a new file with the next counter value. The maximum size of a journal file is determined by a configuration property called its block size. The default block size value is 1,000,000,000 bytes which works well with today’s standard server hardware.
2652+
2653+Every record in the journal has a 64-bit integer *journal address*. The journal address denotes which file contains the record and the record’s offset within that file. Journal addresses start at zero in a new database instance and grow perpetually. footnote:[Even on a system executing 1 million transactions per second the address space is large enough to last for hundreds of years.]
2654+
2655+Persistit writes two major types of records to journal files.
2656+
2657+- For each committed update transaction, Persistit writes a record containing sufficient information to replay the transaction during recovery. For example, when Persistit stores a key/value pair during a transaction, it writes a record to the journal containing the key and value.
2658+- Persistit also writes all updated page images to the journal. Some of these are eventually copied to volume files, as described below. This write/copy mechanism is critical to Persistit’s crash-recovery mechanism (see :ref:`Recovery`).
2659+
2660+As updates are applied, Persistit constantly appends new information- both transaction records and modified page images - to the end of the highest-numbered file. To prevent the aggregation of a large number of journal files Persistit also works to copy or remove information from older journal files so that they can be deleted. The background thread responsible for this activity is called the ``JOURNAL_COPIER`` thread. The JOURNAL_COPIER copies pages from the journal back into their home volume files, allowing old files to be deleted. Normally a Persistit system at rest gradually copies all update page images and perform checkpoints so that only one small journal file remains. Applications can accelerate that process by calling the ``com.persistit.Persistit#copyBackPages`` method.
2661+
2662+The journal is critical to ensuring Persistit can recover structurally intact B-Trees and apply all committed transactions after a system failure. For this reason, unless the JOURNAL_COPIER is entirely caught up, any attempt to save the state of a Persistit database must include both the volume and journal files.
2663+
2664+The journal also plays a critical role during concurrent backup. To back up a running Persistit database, the ``com.persistit.BackupTask`` does the following:
2665+
2666+- Enables ``appendOnly`` mode to suspend the copying of updated page images.
2667+- Copies the appropriate volume and journal files
2668+- Disables ``appendOnly`` mode to allow JOURNAL_COPIER to continue.
2669+
2670+For more details on the journal, checkpoints and transactions, see :ref:`Recovery`. For more information on concurrent backup and other management tasks, see :ref:`Management`.
2671+
2672+Pages and Volumes
2673+-----------------
2674+
2675+Persistit ultimately stores its data in one or more Volume files. Persistit manages volume files internally in sections called pages. Every page within one volume has the same size. The page size is configurable and may be 1,024, 2,048, 4,096, 8,192, or 16,384 (recommended) bytes long. Once the page size for a volume has been established, it cannot be changed. See :ref:`Configuration` for details of how to assign the page size for a new volume.
2676+
2677+Directory Tree
2678+^^^^^^^^^^^^^^
2679+
2680+Within a volume there can be an unlimited number of B-Trees. (B-Trees are also called simply “trees” in this document.) A tree consists of a set of pages including a *root page*, *index pages* and *data pages*. The root page can be data page if the tree is trivial and contains only small number of records. Usually the root page is an index page which contains references to other index pages which in turn may refer to data pages.
2681+
2682+Persistit manages a potentially large number of trees by maintaining a tree of trees called ``_directory``. The ``_directory`` tree contains the name, root page address, ``com.persistit.Accumulator`` data and ``com.persistit.TreeStatistics`` data for all the other trees in the volume. The tree name ``_directory`` is reserved and may not be used when creating an Exchange.
2683+
2684+Data Pages
2685+^^^^^^^^^^
2686+
2687+A data page contains a representation of one or more variable-length key/value pairs. The number of key/value pairs depends on the page size, and the sizes of the serialized keys and values. The first key in each data page is stored in its entirety, while subsequent keys are stored with *prefix compression* to reduce storage footprint and accelerate searches. Therefore the storage size of the second and subsequent keys in a data page depend on how many of the leading bytes of its serialized form match its predecessor. (See :ref:`Key` and :ref:`Value` for information on how Persistit encodes logical Java values into the byte arrays stored in a data page.)
2688+
2689+Index Pages
2690+^^^^^^^^^^^
2691+
2692+An index page has a structure similar to a data page except that instead of holding serialized value data, it instead contains page addresses of subordinate pages within the tree.
2693+
2694+.. TODO - diagram of B-Tree, page layouts, etc
2695+
2696+.. _Recovery:
2697+
2698+Recovery
2699+========
2700+
2701+Akiban Persistit is designed, implemented and tested to ensure that whether the application shuts down gracefully or crashes without cleanly closing the database, the database remains structurally intact and internally consistent after restart.
2702+
2703+To do this, Persistit performs a process called *recovery* every time it starts up. The recovery process is generally very fast after a normal shutdown. However, it can take a considerable amount of time after a crash because many committed transactions may need to be executed.
2704+
2705+Recovery performs two major activities:
2706+
2707+- Restores all B-Trees to an internally consistent state with a known timestamp.
2708+- Replays all transaction that committed after that timestamp.
2709+- Prunes multi-version values belonging to certain aborted transactions (see :ref:`Pruning`).
2710+
2711+To accomplish this, Persistit writes all updates first to the :ref:`Journal`. Persistit also periodically writes *checkpoint* records to the journal. During recovery, Persistit finds the last valid checkpoint written before shutdown or crash, restores B-Trees to state consistent with that checkpoint, and then replays transactions that committed after the checkpoint.
2712+
2713+Recovery depends on the availability of the volume and journal files as they existed prior to abrupt termination. If these are modified or destroyed outside of Persistit, successful recovery is unlikely.
2714+
2715+Timestamps and Checkpoints
2716+--------------------------
2717+
2718+Persistit maintains a universal counter called the *timestamp* counter. Every update operation assigns a new, larger timestamp, and every record in the journal includes the timestamp assigned to the operation writing the record. The timestamp counter is unrelated to clock time. It is merely a counter.
2719+
2720+A *checkpoint* is simply a timestamp for which a valid recovery is possible. Periodically Persistit chooses a timestamp to be a new checkpoint. Over time it then ensures that all pages updated before the checkpoint have been written to the journal, and then writes a checkpoint marker. By default checkpoints occur once every two minutes. Normal shutdown through ``com.persistit.Persistit#close`` writes a final checkpoint to the journal regardless of when the last checkpoint cycle occurred. That final checkpoint is what allows recovery after a normal shutdown to be very fast.
2721+
2722+Upon start-up Persistit starts by finding the last valid checkpoint timestamp, and then recovers only those page images from the journal that were written prior to it. The result is that all B-Trees are internally consistent and contain all the updates that were issued and committed to disk before the checkpoint timestamp and none the occurred after the checkpoint timestamp.
2723+
2724+Then Persistit locates and reapplies all transaction records in the journal for transactions that committed after the last valid checkpoint timestamp. These transactions are reapplied to the database, with the result that:
2725+
2726+- The B-Tree index and data structures are intact. All store, fetch, remove and traverse operations will complete successfully. footnote:[Persistit provides the utility class com.persistit.IntegrityCheck to verify the integrity of a Volume.]
2727+- All committed transactions are present in the recovered database. (See :ref:`Transactions` for durability determined by ``CommitPolicy``.)
2728+
2729+For updates occurring outside of a transaction the resulting state is identical to some consistent, reasonably recent state prior to the termination. (“Reasonably recent” depends on the checkpoint interval, which by default is set to two minutes.)
2730+
2731+Flush/Force/Checkpoint
2732+^^^^^^^^^^^^^^^^^^^^^^
2733+
2734+An application may require certainty at various points that all pending updates have been fully written to disk. The ``com.persistit.Persistit`` class provides three methods to ensure that updates have been written:
2735+
2736+ ``com.persistit.Persistit#flush``
2737+ causes Persistit to write all pending updates to the journal. Upon successful completion of flush any pages that needed writing prior to the call to flush are
2738+ guaranteed to have been written to their respective volume files.
2739+ ``com.persistit.Persistit#force``
2740+ forces the underlying operating system to write pending updates from the operating system’s write-behind cache to the actual disk. (This operation relies on
2741+ the underlying ``java.io.Filechannel#force(boolean)`` method.)
2742+ ``com.persistit.Persistit#checkpoint``
2743+ causes Persistit to allocate a new checkpoint timestamp and then wait for all updates that happened before that timestamp to be committed to disk.
2744+
2745+However, typical applications, especially those using :ref:`Transactions`, do not need to invoke these methods. Once a Transaction is durable, so are all other transactions that occurred at timestamps earlier than the transaction’s commit timestamp and no other method calls are required.
2746+
2747+
2748+The Buffer Pool
2749+---------------
2750+
2751+Persistit maintains a cache of page copies in memory called the *buffer pool*. The buffer pool is a critical resource in reducing disk I/O and providing good run-time performance. After performing a relatively expensive disk operation to read a copy of a page into the buffer pool, Persistit retains that copy to allow potentially many fetch and update operations to be performed against keys and values stored in that page.
2752+
2753+Persistit optimizes update operations by writing updated database pages lazily, generally a few seconds to minutes after the update has been performed on the in-memory copy of the page cached in the buffer pool. By writing lazily, Persistit allows many update operations to be completed on each page before incurring a relatively expensive disk I/O operation to write the updated version of the page to the Volume.
2754+
2755+In Persistit the buffer pool is a collection of buffers allocated from the heap for the duration of Persistit’s operation. The buffers are allocated by the ``com.persistit.Persistit#initialize`` method and are released when the application invokes close. Because buffers are allocated for the life of the Persistit instance, they impose no garbage collection overhead. (However, especially when using large buffer pool allocation in a JVM with a large heap, there are some special memory configuration issues to consider. See :ref:`Configuration` for details.)
2756+
2757+Persistit allocates buffers from the buffer pool in approximately least-recently-used (LRU) order. Most applications exhibit behavior in which data, having been accessed once, is read or updated several more times before the application moves to a different area of the database (locality of reference). LRU is an allocation strategy the yields reasonably good overall throughput by maintaining pages that are likely to be used again in the buffer pool in preference to pages that have not been used for a relatively long time.
2758+
2759+Generally, allocating more buffers in the buffer pool increases the likelihood that a page will be found in the pool rather than having to be reloaded from disk. Since disk I/O is relatively expensive, this means that enlarging the buffer pool is a good strategy for reducing disk I/O and thereby increasing throughput. Persistit is designed to manage extremely large buffer pools very efficiently, so if memory is available, it is generally a good strategy to maximum buffer pool size.
2760+
2761+Tools
2762+-----
2763+
2764+The command-line interface (see :ref:`CLI`) includes tools you can use to examine pages in volumes and records in the journal. Two of these include the ``jview`` and ``pview`` tasks. The ``jview`` command displays journal records selected within an address range, by type, by page address, and using other selection criteria in a readable form. The ``pview`` command displays the contents of pages selected by page address or key from a volume, or by journal address from the journal.
2765+
2766+
2767
2768=== removed file 'doc/PhysicalStorage.txt'
2769--- doc/PhysicalStorage.txt 2012-05-04 13:33:49 +0000
2770+++ doc/PhysicalStorage.txt 1970-01-01 00:00:00 +0000
2771@@ -1,126 +0,0 @@
2772-[[PhysicalStorage]]
2773-= Physical B-Tree Representation
2774-
2775-This chapter describes the physical structures used to represent Akiban Persistit records on disk and in memory.
2776-
2777-== Files
2778-
2779-Following is a directory listing illustrating a working Persistit database:
2780-
2781-----
2782--rw-r--r--. 1 demo demo 24G Feb 8 13:18 akiban_data
2783--rw-r--r--. 1 demo demo 48K Feb 8 13:19 akiban_system
2784--rw-r--r--. 1 demo demo 954M Feb 8 13:18 akiban_journal.000000000225
2785--rw-r--r--. 1 demo demo 954M Feb 8 13:19 akiban_journal.000000000226
2786--rw-r--r--. 1 demo demo 954M Feb 8 13:19 akiban_journal.000000000227
2787--rw-r--r--. 1 demo demo 662M Feb 8 13:19 akiban_journal.000000000228
2788-----
2789-
2790-This database contains two _volume_ files, +akiban_data+ and +akiban_system+ and four files that constitute part of the _journal_. As explained below, Persistit records are usually stored in a combination of volume and journal files.
2791-
2792-[[Journal]]
2793-== The Journal
2794-
2795-The _journal_ is a set of files containing variable length records. The journal is append-only. New records are written only at the end; existing records are never overwritten. The journal consists of a numbered series of files having a configurable maximum size. When a journal file becomes full Persistit closes it and begins a new file with the next counter value. The maximum size of a journal file is determined by a configuration property called its block size. The default block size value is 1,000,000,000 bytes which works well with today’s standard server hardware.
2796-
2797-Every record in the journal has a 64-bit integer _journal address_. The journal address denotes which file contains the record and the record’s offset within that file. Journal addresses start at zero in a new database instance and grow perpetually. footnote:[Even on a system executing 1 million transactions per second the address space is large enough to last for hundreds of years.]
2798-
2799-Persistit writes two major types of records to journal files.
2800-
2801-- For each committed update transaction, Persistit writes a record containing sufficient information to replay the transaction during recovery. For example, when Persistit stores a key/value pair during a transaction, it writes a record to the journal containing the key and value.
2802-- Persistit also writes all updated page images to the journal. Some of these are eventually copied to volume files, as described below. This write/copy mechanism is critical to Persistit’s crash-recovery mechanism (see <<Recovery>>).
2803-
2804-As updates are applied, Persistit constantly appends new information- both transaction records and modified page images - to the end of the highest-numbered file. To prevent the aggregation of a large number of journal files Persistit also works to copy or remove information from older journal files so that they can be deleted. The background thread responsible for this activity is called the +JOURNAL_COPIER+ thread. The JOURNAL_COPIER copies pages from the journal back into their home volume files, allowing old files to be deleted. Normally a Persistit system at rest gradually copies all update page images and perform checkpoints so that only one small journal file remains. Applications can accelerate that process by calling the +com.persistit.Persistit#copyBackPages+ method.
2805-
2806-The journal is critical to ensuring Persistit can recover structurally intact B-Trees and apply all committed transactions after a system failure. For this reason, unless the JOURNAL_COPIER is entirely caught up, any attempt to save the state of a Persistit database must include both the volume and journal files.
2807-
2808-The journal also plays a critical role during concurrent backup. To back up a running Persistit database, the +com.persistit.BackupTask+ does the following:
2809-
2810-- Enables +appendOnly+ mode to suspend the copying of updated page images.
2811-- Copies the appropriate volume and journal files
2812-- Disables +appendOnly+ mode to allow JOURNAL_COPIER to continue.
2813-
2814-For more details on the journal, checkpoints and transactions, see <<Recovery>>. For more information on concurrent backup and other management tasks, see <<Management>>.
2815-
2816-== Pages and Volumes
2817-
2818-Persistit ultimately stores its data in one or more Volume files. Persistit manages volume files internally in sections called pages. Every page within one volume has the same size. The page size is configurable and may be 1,024, 2,048, 4,096, 8,192, or 16,384 (recommended) bytes long. Once the page size for a volume has been established, it cannot be changed. See <<Configuration>> for details of how to assign the page size for a new volume.
2819-
2820-=== Directory Tree
2821-
2822-Within a volume there can be an unlimited number of B-Trees. (B-Trees are also called simply “trees” in this document.) A tree consists of a set of pages including a _root page_, _index pages_ and _data pages_. The root page can be data page if the tree is trivial and contains only small number of records. Usually the root page is an index page which contains references to other index pages which in turn may refer to data pages.
2823-
2824-Persistit manages a potentially large number of trees by maintaining a tree of trees called +_directory+. The +_directory+ tree contains the name, root page address, +com.persistit.Accumulator+ data and +com.persistit.TreeStatistics+ data for all the other trees in the volume. The tree name +_directory+ is reserved and may not be used when creating an Exchange.
2825-
2826-=== Data Pages
2827-
2828-A data page contains a representation of one or more variable-length key/value pairs. The number of key/value pairs depends on the page size, and the sizes of the serialized keys and values. The first key in each data page is stored in its entirety, while subsequent keys are stored with _prefix compression_ to reduce storage footprint and accelerate searches. Therefore the storage size of the second and subsequent keys in a data page depend on how many of the leading bytes of its serialized form match its predecessor. (See <<Key>> and <<Value>> for information on how Persistit encodes logical Java values into the byte arrays stored in a data page.)
2829-
2830-=== Index Pages
2831-
2832-An index page has a structure similar to a data page except that instead of holding serialized value data, it instead contains page addresses of subordinate pages within the tree.
2833-
2834-****
2835-TODO - diagram of B-Tree, page layouts, etc
2836-****
2837-[[Recovery]]
2838-== Recovery
2839-
2840-Akiban Persistit is designed, implemented and tested to ensure that whether the application shuts down gracefully or crashes without cleanly closing the database, the database remains structurally intact and internally consistent after restart.
2841-
2842-To do this, Persistit performs a process called _recovery_ every time it starts up. The recovery process is generally very fast after a normal shutdown. However, it can take a considerable amount of time after a crash because many committed transactions may need to be executed.
2843-
2844-Recovery performs two major activities:
2845-
2846-- Restores all B-Trees to an internally consistent state with a known timestamp.
2847-- Replays all transaction that committed after that timestamp.
2848-- Prunes multi-version values belonging to certain aborted transactions (see <<Pruning>>).
2849-
2850-To accomplish this, Persistit writes all updates first to the <<Journal>>. Persistit also periodically writes _checkpoint_ records to the journal. During recovery, Persistit finds the last valid checkpoint written before shutdown or crash, restores B-Trees to state consistent with that checkpoint, and then replays transactions that committed after the checkpoint.
2851-
2852-Recovery depends on the availability of the volume and journal files as they existed prior to abrupt termination. If these are modified or destroyed outside of Persistit, successful recovery is unlikely.
2853-
2854-=== Timestamps and Checkpoints
2855-
2856-Persistit maintains a universal counter called the _timestamp_ counter. Every update operation assigns a new, larger timestamp, and every record in the journal includes the timestamp assigned to the operation writing the record. The timestamp counter is unrelated to clock time. It is merely a counter.
2857-
2858-A _checkpoint_ is simply a timestamp for which a valid recovery is possible. Periodically Persistit chooses a timestamp to be a new checkpoint. Over time it then ensures that all pages updated before the checkpoint have been written to the journal, and then writes a checkpoint marker. By default checkpoints occur once every two minutes. Normal shutdown through +com.persistit.Persistit#close+ writes a final checkpoint to the journal regardless of when the last checkpoint cycle occurred. That final checkpoint is what allows recovery after a normal shutdown to be very fast.
2859-
2860-Upon start-up Persistit starts by finding the last valid checkpoint timestamp, and then recovers only those page images from the journal that were written prior to it. The result is that all B-Trees are internally consistent and contain all the updates that were issued and committed to disk before the checkpoint timestamp and none the occurred after the checkpoint timestamp.
2861-
2862-Then Persistit locates and reapplies all transaction records in the journal for transactions that committed after the last valid checkpoint timestamp. These transactions are reapplied to the database, with the result that:
2863-
2864-- The B-Tree index and data structures are intact. All store, fetch, remove and traverse operations will complete successfully. footnote:[Persistit provides the utility class com.persistit.IntegrityCheck to verify the integrity of a Volume.]
2865-- All committed transactions are present in the recovered database. (See <<Transactions>> for durability determined by +CommitPolicy+.)
2866-
2867-For updates occurring outside of a transaction the resulting state is identical to some consistent, reasonably recent state prior to the termination. (“Reasonably recent” depends on the checkpoint interval, which by default is set to two minutes.)
2868-
2869-=== Flush/Force/Checkpoint
2870-
2871-An application may require certainty at various points that all pending updates have been fully written to disk. The +com.persistit.Persistit+ class provides three methods to ensure that updates have been written:
2872-
2873-[horizontal]
2874-+com.persistit.Persistit#flush+:: causes Persistit to write all pending updates to the journal. Upon successful completion of flush any pages that needed writing prior to the call to flush are guaranteed to have been written to their respective volume files.
2875-+com.persistit.Persistit#force+:: forces the underlying operating system to write pending updates from the operating system’s write-behind cache to the actual disk. (This operation relies on the underlying +java.io.Filechannel#force(boolean)+ method.)
2876-+com.persistit.Persistit#checkpoint+:: causes Persistit to allocate a new checkpoint timestamp and then wait for all updates that happened before that timestamp to be committed to disk.
2877-
2878-However, typical applications, especially those using <<Transactions>>, do not need to invoke these methods. Once a Transaction is durable, so are all other transactions that occurred at timestamps earlier than the transaction’s commit timestamp and no other method calls are required.
2879-
2880-
2881-== The Buffer Pool
2882-
2883-Persistit maintains a cache of page copies in memory called the _buffer pool_. The buffer pool is a critical resource in reducing disk I/O and providing good run-time performance. After performing a relatively expensive disk operation to read a copy of a page into the buffer pool, Persistit retains that copy to allow potentially many fetch and update operations to be performed against keys and values stored in that page.
2884-
2885-Persistit optimizes update operations by writing updated database pages lazily, generally a few seconds to minutes after the update has been performed on the in-memory copy of the page cached in the buffer pool. By writing lazily, Persistit allows many update operations to be completed on each page before incurring a relatively expensive disk I/O operation to write the updated version of the page to the Volume.
2886-
2887-In Persistit the buffer pool is a collection of buffers allocated from the heap for the duration of Persistit’s operation. The buffers are allocated by the +com.persistit.Persistit#initialize+ method and are released when the application invokes close. Because buffers are allocated for the life of the Persistit instance, they impose no garbage collection overhead. (However, especially when using large buffer pool allocation in a JVM with a large heap, there are some special memory configuration issues to consider. See <<Configuration>> for details.)
2888-
2889-Persistit allocates buffers from the buffer pool in approximately least-recently-used (LRU) order. Most applications exhibit behavior in which data, having been accessed once, is read or updated several more times before the application moves to a different area of the database (locality of reference). LRU is an allocation strategy the yields reasonably good overall throughput by maintaining pages that are likely to be used again in the buffer pool in preference to pages that have not been used for a relatively long time.
2890-
2891-Generally, allocating more buffers in the buffer pool increases the likelihood that a page will be found in the pool rather than having to be reloaded from disk. Since disk I/O is relatively expensive, this means that enlarging the buffer pool is a good strategy for reducing disk I/O and thereby increasing throughput. Persistit is designed to manage extremely large buffer pools very efficiently, so if memory is available, it is generally a good strategy to maximum buffer pool size.
2892-
2893-== Tools
2894-
2895-The command-line interface (see <<CLI>>) includes tools you can use to examine pages in volumes and records in the journal. Two of these include the +jview+ and +pview+ tasks. The +jview+ command displays journal records selected within an address range, by type, by page address, and using other selection criteria in a readable form. The +pview+ command displays the contents of pages selected by page address or key from a volume, or by journal address from the journal.
2896-
2897-
2898
2899=== added file 'doc/ReleaseNotes.rst'
2900--- doc/ReleaseNotes.rst 1970-01-01 00:00:00 +0000
2901+++ doc/ReleaseNotes.rst 2012-05-30 18:23:19 +0000
2902@@ -0,0 +1,84 @@
2903+************************************
2904+Akiban-Persistit 3.1.1 Release Notes
2905+************************************
2906+
2907+Release Date
2908+============
2909+May 25, 2012
2910+
2911+Overview
2912+========
2913+This is the first open source release of the Persistit project (https://launchpad.net/akiban-persistit).
2914+
2915+See http://www.akiban.com/akiban-persistit for a summary of features and benefits, licensing information and how to get support.
2916+
2917+Documentation
2918+=============
2919+Users Guide (http://www.akiban.com/ak-docs/admin/persistit)
2920+JavaDoc (http://www.akiban.com/ak-docs/admin/persistit/apidocs)
2921+
2922+Building Akiban-Persistit
2923+=========================
2924+Use Maven (maven.apache.org) to build Persistit.
2925+
2926+To build::
2927+
2928+ mvn install
2929+
2930+The resulting jar files are in the ``target`` directory. To build the Javadoc::
2931+
2932+ mvn javadoc:javadoc
2933+
2934+The resulting Javadoc HTML files are in ``target/site/apidocs``.
2935+
2936+Building and Running the Examples
2937+---------------------------------
2938+
2939+Small examples are located in the ``examples`` directory. Each has a short README file describing the example, and an Ant build script (http://ant.apache.org). After building the main akiban-persisit jar file using Maven, you may run::
2940+
2941+ ant run
2942+
2943+in each of the examples subdirectories to build and run the examples.
2944+
2945+Known Issues
2946+============
2947+
2948+Transactional Tree Management
2949+-----------------------------
2950+
2951+All operations within Trees such as store, fetch, remove and traverse are correctly supported within transactions. However, the operations to create and delete Tree instances currently do not respect transaction boundaries. For example, if a transaction creates a new Tree, it is immediately visible within other Transactions and will continue to exist even if the original transaction aborts. (However, records inserted or modified by the original transaction will not be visible until the transaction commits.) Prior to creating/removing trees, transaction processing should be quiesced and allowed to complete.
2952+
2953+Problems with Disk Full - Bug 916071
2954+------------------------------------
2955+
2956+There are rare cases where Persistit will generate exceptions other than java.io.IOException: No space left on device when a disk volume containing the journal or volume file fills up. The database will be intact upon recovery, but the application may receive unexpected exceptions.
2957+
2958+Out of Memory Error, Direct Memory Buffer - Bug 985117
2959+------------------------------------------------------
2960+
2961+Out of Memory Error, Direct Memory Buffer. Can cause failed transactions under extreme load conditions as a result of threads getting backed up writing to the journal file. However, this error is transient and recoverable by by retrying the failed transaction.
2962+
2963+* Workaround: Ensure your application has the ability to retry failed transactions
2964+
2965+
2966+Tree#getChangeCount may return inaccurate result - Bug 986465
2967+-------------------------------------------------------------
2968+
2969+The getChangeCount method may return inaccurate results as its not currently transactional. The primary consumer is the PersistitMap. As a result of this bug Persistit may not generate java.util.ConcurrentModiciationException when it is supposed to.
2970+
2971+Multi-Version-Values sometimes not fully pruned - Bug 1000331
2972+-------------------------------------------------------------
2973+
2974+Multi-version values are not always pruned properly causing volume growth. The number of MVV records and their overhead size can be obtaining by running the IntegrityCheck task.
2975+
2976+* Workaround 1: Run the IntegrityCheck task (CLI command icheck) with the -P option which will prune the MVVs. This will remove obsolete MVV instances and in many cases free up pages in which new data can be stored. However, it will not reduce the actual size of the volume file.
2977+
2978+* Workaround 2: To reduce the size of the volume you can use the CLI commands save and load to offload and then reload the data into a newly created volume file. See http://www.akiban.com/ak-docs/admin/persistit/Management.html#management for more information about these operations.
2979+
2980+
2981+Buffer Pool Configuration
2982+=========================
2983+For optimal performance, proper configuration of the Persistit buffer pool is required. See section "Configuring the Buffer Pool" in the configuration document http://www.akiban.com/ak-docs/admin/persistit/Configuration.html
2984+
2985+.. note:: Especially when used with multi-gigabyte heaps, the default Hotspot JVM server heuristics are be suboptimal for Persistit applications. Persistit is usually configured to allocate a large fraction of the heap to Buffer instances that are allocated at startup and held for the duration of the Persistit instance. For efficient operation, all of the Buffer instances must fit in the tenured (old) generation of the heap to avoid very significant garbage collector overhead. Use either -XX:NewSize or -Xmn to adjust the relative sizes of the new and old generations.
2986+
2987
2988=== added file 'doc/Security.rst'
2989--- doc/Security.rst 1970-01-01 00:00:00 +0000
2990+++ doc/Security.rst 2012-05-30 18:23:19 +0000
2991@@ -0,0 +1,93 @@
2992+.. _Security:
2993+
2994+Security Notes
2995+==============
2996+
2997+Akiban Persistit provides no built-in data access control because it is intended for embedded use in applications that provide their own logical access control. Security-conscious applications must also prevent unauthorized access to Persistit's physical files and to the Persistit API. The following resources must be protected from unauthorized access:
2998+
2999+- Persistit volume files
3000+- configuration properties file, if one is used
3001+- access by unauthorized code to the API exposed by the Persistit library
3002+- the port opened and exposed by Persistit when either the ``com.persistit.rmiport`` or ``com.persistit.rmihost`` property is set. If you are using Persistit's remote administration feature, be sure to block unauthorized access to the RMI port.
3003+- the :ref:`cliserver` if instantiated
3004+
3005+In addition to these general deployment considerations, Persistit requires certain permissions in an environment controlled by a security manager.
3006+
3007+Java programs run from the command line typically do not install a security manager, and therefore implicitly grant all permissions. However, when Persistit is used within an Applet, or within any framework that installs a security manager, it is important to understand what permissions are required.
3008+
3009+Security Domains
3010+----------------
3011+
3012+This section assumes a basic understanding of the Java security model. See http://download.oracle.com/javase/1.5.0/docs/guide/security/spec/security-spec.doc2.html[New Protection Mechanisms - Overview of Basic Concepts] for further information.
3013+
3014+Note that when Java is started from the command line, as is often the case in server applications, all security privileges are granted by default. The information in this section is intended for cases where security privileges need to be controlled.
3015+
3016+Akiban Persistit performs various security-sensitive operations: it reads and writes files, it reads system properties, it optionally opens a TCP/IP socket, and it performs various security-sensitive operations related to reflection and serialization. These operations are divided into two categories: those required only by the Persistit library itself, and those required by the application that is using Persistit. For example, the application code must have permission to read and write files, but it does not require permission to access private fields through reflection; only the Persistit library itself needs this permission. The latter operation is called a “privileged” operation because Persistit invokes the access controller's doPrivileged method to establish its permission to perform the privileged operation.
3017+
3018+At a practical level, this means you can create two separate security domains for applications embedding Persistit. One domain is specific to the Persistit library itself, and grants all the permissions required by Persistit, including the privileged permissions. The other domain includes the application, and grants only the non-privileged permissions.
3019+
3020+Using the default java.lang.SecurityManager implementation, you define domains and the permissions available to them in a policy file stored in the user's home directory. For those already familiar with the policy file format, here is a security policy file that illustrates these concepts:
3021+
3022+.. code-block:: java
3023+
3024+ grant codeBase "file:/appdir/myapplication.jar" {
3025+ permission java.io.FilePermission "e:\\data\\*", "read, write, delete";
3026+ permission java.io.FilePermission "e:\\logs\\*", "read, write, delete";
3027+ permission java.net.SocketPermission "localhost",
3028+ "accept, connect, listen, resolve";
3029+ };
3030+
3031+ grant codeBase "file:/lib/akiban-persistit.jar" {
3032+ permission java.io.FilePermission "<<ALL FILES>>", "read, write, delete";
3033+ permission java.net.SocketPermission "*:1099-",
3034+ "accept, connect, listen, resolve";
3035+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
3036+ permission java.io.SerializablePermission "enableSubclassImplementation";
3037+ permission java.util.PropertyPermission "com.persistit.*", "read";
3038+ permission java.lang.RuntimePermission "accessDeclaredMembers";
3039+ };
3040+
3041+This policy file sets up two security domains. One covers the application code in ``myapplication.jar`` and grants just the restricted set of permissions needed by the application, while the other grants additional permissions to the Persistit library.
3042+
3043+Although the file and socket permissions granted by the privileged domain are less restrictive than those granted to ``myapplication.jar``, the actual permission granted to running code is the intersection of these two and is therefore restricted to just the set of files and sockets granted to myapplication.jar.
3044+
3045+Permissions Required for DefaultValueCoder
3046+------------------------------------------
3047+
3048+DefaultValueCoder performs three security-sensitive operations:
3049+
3050+- It enumerates the declared fields of the class being serialized,
3051+- It reads and writes data from and to those fields using reflection even if they are private, and
3052+- It overrides the default implementations of java.io.ObjectInputStream and java.io.ObjectOutputStream.
3053+
3054+If a SecurityManager is installed then three permissions must be granted to enable this new mechanism::
3055+
3056+ java.lang.RuntimePermission "accessDeclaredMembers";
3057+ java.lang.reflect.ReflectPermission("suppressAccessChecks")
3058+ java.io.SerializablePermission("enableSubclassImplementation")
3059+
3060+Persistit acquires these permissions through privileged operations, meaning that only the Persistit library domain needs to have them – they do not need to be and should not be granted to the application domain.
3061+
3062+Permission Required for Reading System Properties
3063+-------------------------------------------------
3064+
3065+Persistit attempts to read system properties whose names begin with “com.persistit.” Specific permission to do this is granted by the line::
3066+
3067+ permission java.util.PropertyPermission "com.persistit.*", "read";
3068+
3069+Again, only the Persistit library domain needs to have this permission. If this permission is not granted, Persistit ignores all system properties.
3070+
3071+Permissions Required for File and Socket I/O
3072+--------------------------------------------
3073+
3074+Persistit needs permission to read and write its volume and journal files, to read a configuration properties file and (optionally) write to a log file. File I/O permissions also apply to the source and destination files specified for Import and Export tasks available within the AdminUI utility. In addition, if you specify either the rmihost or rmiport property to enable remote administration, Persistit needs permission to create RMI connections.
3075+
3076+These are not privileged operations, meaning that if the policy establishes separate domains for the application and the Persistit library, both domains must grant permission for all I/O operations. (If they were privileged operations, an untrusted application code could use the Persistit library as a proxy to perform malicious file I/O.) As is defined by the Java security mechanism, when Persistit attempts to open a file, permissions of both the application domain and the Persistit library domains are checked; if the operation is denied by either domain then the attempt fails with a java.security.AccessControlException.
3077+
3078+As specified in the sample policy file above, the Persistit library domain has been granted permissions on `<<ALL FILES>>`. This means that the application domain controls what subset of the file system is accessible. In the example, files may only be read and written to the e:\data and e:\logs directories on a Windows box. (See the Java documentation on Permissions for details on how to construct File and Socket permissions.)
3079+
3080+Deploying Persistit as an Installed Optional Package
3081+----------------------------------------------------
3082+
3083+A convenient way to grant Persistit the permissions required to perform its privileged operations is to install it as an optional package. The Sun Java Runtime Environment treats JAR files located in the <jre-home>/lib/ext directory as optional Java extension classes, and by default grants them the same privileges as Java system classes. If the Persistit library is loaded from this directory then only the application File and Socket privileges need to be granted explicitly through a security policy. To deploy Persistit in this manner simply copy the Persistit library jar file to the appropriate ``*jre-home*/lib/ext`` directory.
3084+
3085
3086=== removed file 'doc/Security.txt'
3087--- doc/Security.txt 2012-04-30 22:09:31 +0000
3088+++ doc/Security.txt 1970-01-01 00:00:00 +0000
3089@@ -1,91 +0,0 @@
3090-[[Security]]
3091-= Security Notes
3092-
3093-Akiban Persistit provides no built-in data access control because it is intended for embedded use in applications that provide their own logical access control. Security-conscious applications must also prevent unauthorized access to Persistit's physical files and to the Persistit API. The following resources must be protected from unauthorized access:
3094-
3095-- Persistit volume files
3096-- configuration properties file, if one is used
3097-- access by unauthorized code to the API exposed by the Persistit library
3098-- the port opened and exposed by Persistit when either the +com.persistit.rmiport+ or +com.persistit.rmihost+ property is set. If you are using Persistit's remote administration feature, be sure to block unauthorized access to the RMI port.
3099-- the <<cliserver>> if instantiated
3100-
3101-In addition to these general deployment considerations, Persistit requires certain permissions in an environment controlled by a security manager.
3102-
3103-Java programs run from the command line typically do not install a security manager, and therefore implicitly grant all permissions. However, when Persistit is used within an Applet, or within any framework that installs a security manager, it is important to understand what permissions are required.
3104-
3105-== Security Domains
3106-
3107-This section assumes a basic understanding of the Java security model. See http://download.oracle.com/javase/1.5.0/docs/guide/security/spec/security-spec.doc2.html[New Protection Mechanisms - Overview of Basic Concepts] for further information.
3108-
3109-Note that when Java is started from the command line, as is often the case in server applications, all security privileges are granted by default. The information in this section is intended for cases where security privileges need to be controlled.
3110-
3111-Akiban Persistit performs various security-sensitive operations: it reads and writes files, it reads system properties, it optionally opens a TCP/IP socket, and it performs various security-sensitive operations related to reflection and serialization. These operations are divided into two categories: those required only by the Persistit library itself, and those required by the application that is using Persistit. For example, the application code must have permission to read and write files, but it does not require permission to access private fields through reflection; only the Persistit library itself needs this permission. The latter operation is called a “privileged” operation because Persistit invokes the access controller's doPrivileged method to establish its permission to perform the privileged operation.
3112-
3113-At a practical level, this means you can create two separate security domains for applications embedding Persistit. One domain is specific to the Persistit library itself, and grants all the permissions required by Persistit, including the privileged permissions. The other domain includes the application, and grants only the non-privileged permissions.
3114-
3115-Using the default java.lang.SecurityManager implementation, you define domains and the permissions available to them in a policy file stored in the user's home directory. For those already familiar with the policy file format, here is a security policy file that illustrates these concepts:
3116-
3117-.Example .java.policy File
3118-----
3119-grant codeBase "file:/appdir/myapplication.jar" {
3120- permission java.io.FilePermission "e:\\data\\*", "read, write, delete";
3121- permission java.io.FilePermission "e:\\logs\\*", "read, write, delete";
3122- permission java.net.SocketPermission "localhost",
3123- "accept, connect, listen, resolve";
3124-};
3125-
3126-grant codeBase "file:/lib/akiban-persistit.jar" {
3127- permission java.io.FilePermission "<<ALL FILES>>", "read, write, delete";
3128- permission java.net.SocketPermission "*:1099-",
3129- "accept, connect, listen, resolve";
3130- permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
3131- permission java.io.SerializablePermission "enableSubclassImplementation";
3132- permission java.util.PropertyPermission "com.persistit.*", "read";
3133- permission java.lang.RuntimePermission "accessDeclaredMembers";
3134-};
3135-----
3136-
3137-This policy file sets up two security domains. One covers the application code in +myapplication.jar+ and grants just the restricted set of permissions needed by the application, while the other grants additional permissions to the Persistit library.
3138-
3139-Although the file and socket permissions granted by the privileged domain are less restrictive than those granted to +myapplication.jar+, the actual permission granted to running code is the intersection of these two and is therefore restricted to just the set of files and sockets granted to myapplication.jar.
3140-
3141-== Permissions Required for DefaultValueCoder
3142-
3143-DefaultValueCoder performs three security-sensitive operations:
3144-
3145-- It enumerates the declared fields of the class being serialized,
3146-- It reads and writes data from and to those fields using reflection even if they are private, and
3147-- It overrides the default implementations of java.io.ObjectInputStream and java.io.ObjectOutputStream.
3148-
3149-If a SecurityManager is installed then three permissions must be granted to enable this new mechanism:
3150-
3151-----
3152-java.lang.RuntimePermission "accessDeclaredMembers";
3153-java.lang.reflect.ReflectPermission("suppressAccessChecks")
3154-java.io.SerializablePermission("enableSubclassImplementation")
3155-----
3156-
3157-Persistit acquires these permissions through privileged operations, meaning that only the Persistit library domain needs to have them – they do not need to be and should not be granted to the application domain.
3158-
3159-== Permission Required for Reading System Properties
3160-
3161-Persistit attempts to read system properties whose names begin with “com.persistit.” Specific permission to do this is granted by the line
3162-
3163-----
3164- permission java.util.PropertyPermission "com.persistit.*", "read";
3165-----
3166-
3167-Again, only the Persistit library domain needs to have this permission. If this permission is not granted, Persistit ignores all system properties.
3168-
3169-== Permissions Required for File and Socket I/O
3170-
3171-Persistit needs permission to read and write its volume and journal files, to read a configuration properties file and (optionally) write to a log file. File I/O permissions also apply to the source and destination files specified for Import and Export tasks available within the AdminUI utility. In addition, if you specify either the rmihost or rmiport property to enable remote administration, Persistit needs permission to create RMI connections.
3172-
3173-These are not privileged operations, meaning that if the policy establishes separate domains for the application and the Persistit library, both domains must grant permission for all I/O operations. (If they were privileged operations, an untrusted application code could use the Persistit library as a proxy to perform malicious file I/O.) As is defined by the Java security mechanism, when Persistit attempts to open a file, permissions of both the application domain and the Persistit library domains are checked; if the operation is denied by either domain then the attempt fails with a java.security.AccessControlException.
3174-
3175-As specified in the sample policy file above, the Persistit library domain has been granted permissions on `<<ALL FILES>>`. This means that the application domain controls what subset of the file system is accessible. In the example, files may only be read and written to the e:\data and e:\logs directories on a Windows box. (See the Java documentation on Permissions for details on how to construct File and Socket permissions.)
3176-
3177-== Deploying Persistit as an Installed Optional Package
3178-
3179-A convenient way to grant Persistit the permissions required to perform its privileged operations is to install it as an optional package. The Sun Java Runtime Environment treats JAR files located in the <jre-home>/lib/ext directory as optional Java extension classes, and by default grants them the same privileges as Java system classes. If the Persistit library is loaded from this directory then only the application File and Socket privileges need to be granted explicitly through a security policy. To deploy Persistit in this manner simply copy the Persistit library jar file to the appropriate +_jre-home_/lib/ext+ directory.
3180-
3181
3182=== added file 'doc/Serialization.rst'
3183--- doc/Serialization.rst 1970-01-01 00:00:00 +0000
3184+++ doc/Serialization.rst 2012-05-30 18:23:19 +0000
3185@@ -0,0 +1,250 @@
3186+.. _Serialization:
3187+
3188+Serializing Object Values
3189+=========================
3190+
3191+Akiban Persistit uses one of several mechanisms to serialize a Java Object into a ``com.persistit.Value``.
3192+
3193+* For the following classes, Persistit provides built-in optimized serialization logic that cannot be overridden:
3194+
3195+ * ``java.lang.String``
3196+ * ``java.util.Date``
3197+ * ``java.math.BigInteger``
3198+ * ``java.math.BigDecimal``
3199+ * Wrapper classes for primitive values (``Boolean``, ``Byte``, ``Short``, etc.)
3200+ * All arrays (however, the mechanisms described here apply to array elements).
3201+
3202+* An application can register a custom ``com.persistit.encoding.ValueCoder`` to handle serialization of a particular class
3203+* Default serialization using Persistit's built-in serialization mechanism described below, or
3204+* Standard Java serialization as described in http://download.oracle.com/javase/1.5.0/docs/guide/serialization/spec/serial-arch.html[Java Object Serialization Specification].
3205+
3206+Persistit's default serialization method serializes objects into approximately 33% fewer bytes, and depending on the structure of objects being serialized, is about 40% faster than Java serialization.
3207+
3208+Storing Objects in Persistit
3209+----------------------------
3210+
3211+To store an object value into a Persistit database, you put the object into the Value field of an Exchange, and then invoke the Exchange's store method as shown in this code fragment:
3212+
3213+.. code-block:: java
3214+
3215+ exchange.getValue().put(myObject);
3216+ exchange.store();
3217+
3218+Of course, Persistit cannot actually store a live object on disk. Instead it creates and stores a byte array containing state information about the object. Subsequently you fetch an object from Persistit as follows:
3219+
3220+.. code-block:: java
3221+
3222+ exchange.fetch();
3223+ MyClass myObject = (MyClass)exchange.getValue().get();
3224+
3225+The resulting MyClass instance is a newly constructed object instance that is equivalent - subject to the accuracy of the serialization code - to the original object. This process is equivalent to the serialization and deserialization capabilities provided by java.io.ObjectOutputStream and java.io.ObjectInputStream.
3226+
3227+Persistit makes use of helper classes called “coders” to marshal data between live objects and their stored byte-array representations. Value coders, which implement ``com.persistit.encoding.ValueCoder``, marshal data to and from Value objects; ``com.persistit.encoding.KeyCoder`` implementations do the same for ``com.persistit.Key``s. A value coder provides capability somewhat like the custom serialization logic implemented through ``readObject``, ``writeObject``, ``readExternal`` and ``writeExternal``. However, a value coder can provide this logic for any class without modifying the class itself, which may be important if the class is part of a closed library.
3228+
3229+You may create and register a value coder for almost any class, including classes that are not marked Serializable. The exceptions are those listed which have built-in, non-overridable serialization logic.
3230+
3231+DefaultValueCoder and SerialValueCoder
3232+--------------------------------------
3233+
3234+When required to serialize or deserialize class with no explicitly defined ``ValueCoder``, Persistit automatically creates and registers one of the following two default ``ValueCoder`` implementations:
3235+
3236+``com.persistit.DefaultValueCoder``:: uses introspection to determine which fields to serialize, and reflection to access and update the fields
3237+``com.persistit.encoding.SerialValueCoder``:: creates instances of ObjectInputStream and ObjectOutputStream to serialize and deserialize the object.
3238+
3239+DefaultValueCoder uses a more compact storage format and is significantly faster than standard Java serialization; however, it imposes certain limitations and trade-offs described below. By default, Persistit will use a DefaultValueCoder. However, you can identify classes that should instead be serialized and deserialized by ``SerialValueCoder`` by specifying the ``serialOverride`` configuration property, which is described below.
3240+
3241+DefaultValueCoder
3242+-----------------
3243+
3244+A DefaultValueCoder uses Java reflection to access and update the fields of an arbitrary object. The set of fields is defined by the Java Object Serialization Specification. By default, these include all non-static, non-transient fields of the current class and its Serializable superclasses. A class may override this default set by specifying an array of ``java.io.ObjectStreamField`` objects in a private final static field named ``serialPersistentFields``, as described in the specification.
3245+
3246+``DefaultValueCoder`` invokes the special methods ``readResolve``, ``writeReplace``, ``readObject`` and ``writeObject``, (or for Externalizable classes, ``writeExternal`` and ``readExternal``) to provide the compatible custom serialization support. To support the ``readObject``/``readExternal`` and ``writeObject``/``writeExternal`` methods, Persistit creates extended implementations of ``java.io.ObjectOutputStream`` and ``java.io.ObjectInputStream``. These use a custom serialization format optimized for writing to a Value's backing byte array. For example, they do not organize data into 1,024-byte blocks, and they factor meta data about classes into a separate class information database so that this information is not repeated in multiple records containing instances of the same class.
3247+
3248+Currently, ``DefaultValueCoder`` does not support the following elements of the serialization API:
3249+
3250+- the ``readObjectNoData`` custom serialization method
3251+- the ``PutFields``/``GetFields`` API of ``ObjectOutputStream`` and ``ObjectInputStream``
3252+- the ``readLine`` method of ``ObjectInputStream``.
3253+
3254+Constructing Objects upon Deserialization
3255+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3256+
3257+When deserializing a value, ``DefaultValueCoder`` combines information about the original object's class and the stored field data to reconstruct an object equivalent to the original. To do so it must first construct a new instance of class and then decode and set its serialized fields.
3258+
3259+For compatibility with standard Java serialization, ``DefaultValueCoder`` constructs new object instances of Serializable classes using the same logic as ``ObjectInputStream``, namely:
3260+
3261+If the class is Externalizable, ``DefaultValueCoder`` invokes its public no-argument constructor. (The specification for Externalizable requires the class to have such a constructor.)
3262+
3263+Otherwise, if the class is Serializable, ``DefaultValueCoder`` invokes the no-argument constructor of its nearest non-serializable superclass.
3264+
3265+``DefaultValueCoder`` must use platform-specific logic when constructing instances of Serializable classes: specifically, it invokes the same internal, non-public method as ``ObjectInputStream``. We have verified correct behavior on a wide range of Java runtime environments, but because the implementation uses private methods within various JRE versions, it is possible (though unlikely) that a future JRE will not provide a comparable capability.
3266+
3267+To avoid using platform-specific API calls, you can specify the configuration property::
3268+
3269+ constructorOverride=true
3270+
3271+When this property is ``true``, ``DefaultValueCoder`` requires each object being serialized or deserialized to have a no-argument constructor through which instances will be constructed during deserialization. Unless the class implements Externalizable, that constructor may be private, package-private, protected or public.
3272+
3273+Extending DefaultValueCoder
3274+^^^^^^^^^^^^^^^^^^^^^^^^^^^
3275+
3276+You can register an extended ``DefaultValueCoder`` to provide custom behavior, including custom logic for constructing instances of a class, as shown here:
3277+
3278+.. code-block:: java
3279+
3280+ Persistit.getInstance().getCoderManager().registerValueCoder(MyClass.class, new DefaultValueCoder(MyClass.class) {
3281+ public Object get(Value value, Class clazz, CoderContext context) throws ConversionException {
3282+
3283+ // Construct the object being deserialized.
3284+ Object instance = new MyClass(...custom arguments...);
3285+
3286+ // See "registering objects while deserializing" below
3287+ value.registerEncodedObject(instance);
3288+
3289+ // Load the non-transient, non-static fields
3290+ render(value, instance, clazz, context);
3291+
3292+ return instance;
3293+ }
3294+ });
3295+
3296+
3297+
3298+Security Policy Requirements for DefaultValueCoder
3299+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3300+
3301+DefaultValueCoder performs security-sensitive operations: (a) it reads and writes data from and to private fields using reflection, and (b) it overrides the default implementations of java.io.ObjectInputStream and java.io.ObjectOutputStream. If a SecurityManager is installed then three permissions must be granted to enable the new mechanism::
3302+
3303+ java.lang.RuntimePermission "accessDeclaredMembers";
3304+ java.lang.reflect.ReflectPermission("suppressAccessChecks")
3305+ java.io.SerializablePermission("enableSubclassImplementation")
3306+
3307+See :ref:`Security` for an extended discussion on security policy issues for Persistit.
3308+
3309+SerialValueCoder
3310+----------------
3311+
3312+``SerialValueCoder`` uses standard Java serialization to store and retrieve object values. Typically this results in slower performance and a more verbose storage format than ``DefaultValueCoder``, but there are a number of reasons why a particular application might require standard Java serialization, including:
3313+
3314+- the security context into which the application will be deployed does not grant the permissions noted above that are required for ``DefaultValueCoder``,
3315+- to avoid Persistit's use of private API calls to construct object instances during deserialization,
3316+- a preference for the use of a standard format defined within the Java platform rather than Persistit's custom format,
3317+- limitations documented above on the API elements available during custom deserialization within DefaultValueCoder, for example non-support of GetField and PutField.
3318+
3319+Your application can specify ``SerialValueCoders`` for specific classes either by explicitly creating and registering them, or by naming them in the com.persistit.serialOverride property.
3320+
3321+To explicitly register a ``SerialValueCoder`` for the class ``MyClass``, do this:
3322+
3323+.. code-block:: java
3324+
3325+ ...
3326+ Persistit.getInstance().getCoderManager().registerValueCoder(
3327+ MyClass.class,
3328+ new SerialValueCoder(MyClass.class));
3329+ ...
3330+
3331+
3332+The ``com.persistit.serialOverride`` Configuration Property
3333+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3334+
3335+The ``serialOverride`` property specifies classes that are to be serialized by ``SerialValueCoder`` rather than ``DefaultValueCoder``. This property affects how Persistit assigns a value coder when none has previously been registered. It does not override or affect explicitly registered coders.
3336+
3337+Names are separated by commas and may contain wild cards.
3338+
3339+The following are valid patterns:
3340+
3341+ ``java.io.File``
3342+ Just the File class.
3343+ ``java.io.*``
3344+ All classes in the java.io package.
3345+ ``java.awt.**``
3346+ All classes in the java.awt package and its sub-packages
3347+ ``java.util.*Map``
3348+ All of the Map classes in the java.util.
3349+ ``**``
3350+ All classes in all packages
3351+
3352+More precisely, ``serialOverride`` specifies a comma-delimited list of zero or more patterns, each of which is either a fully-qualified class name or pattern that has within it exactly one wild card. The wild card “\*” replaces any sequence of characters other than a period (“.”), while “\*\*” replaces any sequence of characters including periods. For example::
3353+
3354+ ``serialOverride=org.apache.**,com.mypkg.serialstuff.*,com.mypkg.MyClass``
3355+
3356+Like all configuration properties, you may specify this in the persistit.properties file or as a system property through a Java command-line argument in the form::
3357+
3358+ ``-Dcom.persistit.serialOverride=...``
3359+
3360+Registering Objects in a Custom ``ValueCoder``
3361+----------------------------------------------
3362+
3363+In a custom ``ValueCoder`` implementation, the ``get`` method is responsible for constructing and populating an instance of an object. The following pattern should be used when implementing the get method:
3364+
3365+.. code-block:: java
3366+
3367+ public void get(Value value, Class clazz, CoderContext context) throws ConversionException {
3368+ // Construct the object being deserialized.
3369+ //
3370+ Object instance = ...constructor for the object...
3371+
3372+ // Associate a handle with the newly
3373+ // created instance.
3374+ //
3375+ value.registerEncodedObject(instance);
3376+
3377+ // Populate the object's internal state
3378+ //
3379+ ... load the fields – for example, by calling render...
3380+
3381+ return instance;
3382+ }
3383+
3384+The purpose of the ``registerEncodedObject`` method is to record the association between the newly created object and an internal integer-valued handle that may be used subsequently in the serialization stream to refer to that object. This mechanism supports objects that may have fields that refer either indirectly or indirectly back to the same object – i.e., that participate in a cyclical reference graph.
3385+
3386+As a concrete example, consider a Person class with a spouse field such that for married couple p and q, p.spouse is q and q.spouse is p. When Persistit serializes p it also serializes q, but when it serializes q's spouse field, it records a reference handle associated with the already-serialized instance of p rather than writing a new copy of p in the serialization stream. Upon deserializing q, Persistit looks up the object for the recorded handle to correctly associate the already-deserialized p instance with q.
3387+
3388+Whenever you implement a custom ``get()`` method in any ``ValueCoder``, you must notify the underlying Value object about the newly created object by calling registerEncodedObject before deserializing its fields so that any back-references made within serialized fields of that object can find the object correctly.
3389+
3390+``Value.toString()`` and ``decodeDisplayable``
3391+----------------------------------------------
3392+
3393+In many cases it is not very useful simply to display the result of evaluating ``toString()`` on an object. The default toString method inherited from Object conveys just a class name and a memory handle. In addition, for remote operations of AdminUI, it may not even be feasible to construct a deserialized object for each record. Therefore, ``com.persistit.Value`` provides a specialized ``toString()`` method to render an arbitrary object value into a legible string. The AdminUI utility uses this facility to summarize the data contained in a Tree.
3394+
3395+Persistit creates a String value loading the object's class, using the following algorithm:
3396+
3397+- If the state represented by this Value is undefined, then return "undefined".
3398+- If the state is null or a boolean, return "null" "false", or "true".
3399+- If the value represents a primitive type, return the string representation of the value, prefixed by "(byte)", "(short)", "(char)", "(long)", or "(float)" for the corresponding types. Values of type int and double are presented without prefix to reduce clutter.
3400+- If the value represents a String, return a modified form of the string enclosed in double quotes. For each character of the string, if it is a double quote replace it by "\"", otherwise if it is outside of the printable ASCII character set replace the character in the modified string by "\b", "\t", "\n", "\r" or "\uNNNN" such that the modified string would be a valid Java string constant.
3401+- If the value represents a wrapper for a primitive value (i.e., a java.lang.Boolean, java.lang.Byte, etc.) return the string representation of the value prefixed by "(Boolean)", "(Byte)", "(Short)", "(Character)", "(Integer)", "(Long)", "(Float)" or "(Double)". The package name java.lang is removed to reduce clutter.
3402+- If the value represents a java.util.Date, return a formatted representation of the date using the format specified by Key.SDF. This is a readable format that displays the date with full precision, including milliseconds.
3403+- If the value represents an array, return a list of comma-separated element values surrounded by square brackets.
3404+- If the value represents one of the standard Collection implementations in the java.util package, then return a comma-separated list of values surrounded by square brackets.
3405+- If the value represents one of the standard Map implementations in the java.util package, then return a comma-separated list of key/value pairs surrounded by square brackets. Each key/value pair is represented by a string in the form key->value.
3406+- If the value represents an object of a class for which there is a registered com.persistit.encoding.ValueDisplayer, invoke the displayer's display method to format a displayable representation of the object.
3407+- If the value represents an object that has been stored using the version default serialization mechanism described above, return the class name of the object followed by a comma-separated tuple, enclosed within curly brace characters, representing the value of each field of the object.
3408+- If the value represents an object encoded through standard Java serialization, return the string "(Serialized-object)" followed by a sequence of hex digits representing the serialized bytes. Note that this process does not attempt to deserialize the object.
3409+- If the value represents an object that has already been represented within the formatted result - for example, if a Collection contains two references to the same object - then instead of creating an additional string representing the second or subsequent instance, emit a back reference pointer in the form @NNN where NNN is the character offset within the displayable string where the first instance was found. (This does not apply to strings and the primitive wrapper classes.)
3410+
3411+For example, consider a Person having for date of birth, first name, last name, salary and friends, an array of other Person objects. The result returned by toString() on a Value representing Mary Smith who has a friend John Smith, might appear as follows::
3412+
3413+ (Person){(Date)19490826000000.000-0400,"Mary","Jones",(long)75000,[
3414+ (Person){(Date)19550522000000.000-0400,"John","Smith",(long)68000,[@0]}]}
3415+
3416+In this example, John Smith's friends array contains a back reference to Mary Jones in the form "@0" because Mary's displayable reference starts at the beginning of the string.
3417+
3418+
3419+PersistitReference
3420+------------------
3421+
3422+In general, serializing an object that contains references to other objects requires all the referenced objects also to be serialized. For an object connected to a large reference graph, it may be impractical or even semantically incorrect to serialize the entire graph.
3423+
3424+One way to control the serialization graph for such an object is to write a custom ValueCoder; the custom ValueCoder can store key values for looking up the referenced object, rather than the object itself. The ValueCoderDemo.java program demonstrates how this can be done.
3425+
3426+The ``com.persistit.ref.PersistitReference`` interface, and its abstract subclasses, provide an alternative mechanism for breaking up an object reference graph. It requires no custom ValueCoder, but does impact the design of application classes. In addition, you will need to write a concrete implementation of either com.persistit.ref.AbstractReference or com.persistit.ref.AbstractWeakReference based on the actual storage structure of your object graph.
3427+
3428+ObjectCache
3429+-----------
3430+
3431+A ``com.persistit.Value`` object holds the serialized, encoded state of a primitive value of an object. Each time you invoke the get method on a Value, Persistit generates a new copy of the object deserialized from this Value. Persistit does not implicitly cache deserialized objects. However, the ``com.persistit.encoding.ObjectCache`` class provides a simple mechanism for applications that need to maintain an in-memory cache of of objects from Persistit. ``ObjectCache`` works somewhat like a specialized version of java.util.WeakHashMap.
3432+
3433+``ObjectCache`` has ``put``, ``get`` and ``remove`` methods much like a normal Map implementation. However, when storing an object value with the supplied ``com.persistit.Key``, ``ObjectCache`` constructs a new, immutable ``com.persistit.KeyState`` object to hold as an internal key. This is necessary because ``Key`` objects change value as they are used.
3434+
3435+Each ``ObjectCache`` entry holds its object value as a ``SoftReference``, making it available for garbage collection when space is needed.
3436
3437=== removed file 'doc/Serialization.txt'
3438--- doc/Serialization.txt 2012-04-30 22:09:31 +0000
3439+++ doc/Serialization.txt 1970-01-01 00:00:00 +0000
3440@@ -1,246 +0,0 @@
3441-[[Serialization]]
3442-= Serializing Object Values
3443-
3444-Akiban Persistit uses one of several mechanisms to serialize a Java Object into a +com.persistit.Value+.
3445-
3446-- For the following classes, Persistit provides built-in optimized serialization logic that cannot be overridden:
3447-
3448-* +java.lang.String+
3449-* +java.util.Date+
3450-* +java.math.BigInteger+
3451-* +java.math.BigDecimal+
3452-* Wrapper classes for primitive values (+Boolean+, +Byte+, +Short+, etc.)
3453-* All arrays (however, the mechanisms described here apply to array elements).
3454-
3455-- An application can register a custom +com.persistit.encoding.ValueCoder+ to handle serialization of a particular class
3456-- Default serialization using Persistit's built-in serialization mechanism described below, or
3457-- Standard Java serialization as described in http://download.oracle.com/javase/1.5.0/docs/guide/serialization/spec/serial-arch.html[Java Object Serialization Specification].
3458-
3459-Persistit's default serialization method serializes objects into approximately 33% fewer bytes, and depending on the structure of objects being serialized, is about 40% faster than Java serialization.
3460-
3461-== Storing Objects in Persistit
3462-
3463-To store an object value into a Persistit database, you put the object into the Value field of an Exchange, and then invoke the Exchange's store method as shown in this code fragment:
3464-
3465-[source,java]
3466-----
3467- exchange.getValue().put(myObject);
3468- exchange.store();
3469-----
3470-
3471-Of course, Persistit cannot actually store a live object on disk. Instead it creates and stores a byte array containing state information about the object. Subsequently you fetch an object from Persistit as follows:
3472-
3473-[source,java]
3474-----
3475- exchange.fetch();
3476- MyClass myObject = (MyClass)exchange.getValue().get();
3477-----
3478-
3479-The resulting MyClass instance is a newly constructed object instance that is equivalent - subject to the accuracy of the serialization code - to the original object. This process is equivalent to the serialization and deserialization capabilities provided by java.io.ObjectOutputStream and java.io.ObjectInputStream.
3480-
3481-Persistit makes use of helper classes called “coders” to marshal data between live objects and their stored byte-array representations. Value coders, which implement +com.persistit.encoding.ValueCoder+, marshal data to and from Value objects; +com.persistit.encoding.KeyCoder+ implementations do the same for +com.persistit.Key+ s. A value coder provides capability somewhat like the custom serialization logic implemented through +readObject+, +writeObject+, +readExternal+ and +writeExternal+. However, a value coder can provide this logic for any class without modifying the class itself, which may be important if the class is part of a closed library.
3482-
3483-You may create and register a value coder for almost any class, including classes that are not marked Serializable. The exceptions are those listed which have built-in, non-overridable serialization logic.
3484-
3485-=== DefaultValueCoder and SerialValueCoder
3486-
3487-When required to serialize or deserialize class with no explicitly defined +ValueCoder+, Persistit automatically creates and registers one of the following two default +ValueCoder+ implementations:
3488-
3489-+com.persistit.DefaultValueCoder+:: uses introspection to determine which fields to serialize, and reflection to access and update the fields
3490-+com.persistit.encoding.SerialValueCoder+:: creates instances of ObjectInputStream and ObjectOutputStream to serialize and deserialize the object.
3491-
3492-DefaultValueCoder uses a more compact storage format and is significantly faster than standard Java serialization; however, it imposes certain limitations and trade-offs described below. By default, Persistit will use a DefaultValueCoder. However, you can identify classes that should instead be serialized and deserialized by +SerialValueCoder+ by specifying the +serialOverride+ configuration property, which is described below.
3493-
3494-== DefaultValueCoder
3495-
3496-A DefaultValueCoder uses Java reflection to access and update the fields of an arbitrary object. The set of fields is defined by the Java Object Serialization Specification. By default, these include all non-static, non-transient fields of the current class and its Serializable superclasses. A class may override this default set by specifying an array of +java.io.ObjectStreamField+ objects in a private final static field named +serialPersistentFields+, as described in the specification.
3497-
3498-+DefaultValueCoder+ invokes the special methods +readResolve+, +writeReplace+, +readObject+ and +writeObject+, (or for Externalizable classes, +writeExternal+ and +readExternal+) to provide the compatible custom serialization support. To support the +readObject+/+readExternal+ and +writeObject+/+writeExternal+ methods, Persistit creates extended implementations of +java.io.ObjectOutputStream+ and +java.io.ObjectInputStream+. These use a custom serialization format optimized for writing to a Value's backing byte array. For example, they do not organize data into 1,024-byte blocks, and they factor meta data about classes into a separate class information database so that this information is not repeated in multiple records containing instances of the same class.
3499-
3500-Currently, +DefaultValueCoder+ does not support the following elements of the serialization API:
3501-
3502-- the +readObjectNoData+ custom serialization method
3503-- the +PutFields+/+GetFields+ API of +ObjectOutputStream+ and +ObjectInputStream+
3504-- the +readLine+ method of +ObjectInputStream+.
3505-
3506-=== Constructing Objects upon Deserialization
3507-
3508-When deserializing a value, +DefaultValueCoder+ combines information about the original object's class and the stored field data to reconstruct an object equivalent to the original. To do so it must first construct a new instance of class and then decode and set its serialized fields.
3509-
3510-For compatibility with standard Java serialization, +DefaultValueCoder+ constructs new object instances of Serializable classes using the same logic as +ObjectInputStream+, namely:
3511-
3512-If the class is Externalizable, +DefaultValueCoder+ invokes its public no-argument constructor. (The specification for Externalizable requires the class to have such a constructor.)
3513-
3514-Otherwise, if the class is Serializable, +DefaultValueCoder+ invokes the no-argument constructor of its nearest non-serializable superclass.
3515-
3516-+DefaultValueCoder+ must use platform-specific logic when constructing instances of Serializable classes: specifically, it invokes the same internal, non-public method as +ObjectInputStream+. We have verified correct behavior on a wide range of Java runtime environments, but because the implementation uses private methods within various JRE versions, it is possible (though unlikely) that a future JRE will not provide a comparable capability.
3517-
3518-To avoid using platform-specific API calls, you can specify the configuration property
3519-
3520-----
3521- constructorOverride=true
3522-----
3523-
3524-When this property is +true+, +DefaultValueCoder+ requires each object being serialized or deserialized to have a no-argument constructor through which instances will be constructed during deserialization. Unless the class implements Externalizable, that constructor may be private, package-private, protected or public.
3525-
3526-=== Extending DefaultValueCoder
3527-
3528-You can register an extended +DefaultValueCoder+ to provide custom behavior, including custom logic for constructing instances of a class, as shown here:
3529-
3530-[source,java]
3531------
3532- Persistit.getInstance().getCoderManager().registerValueCoder(MyClass.class, new DefaultValueCoder(MyClass.class) {
3533- public Object get(Value value, Class clazz, CoderContext context) throws ConversionException {
3534-
3535- // Construct the object being deserialized.
3536- Object instance = new MyClass(...custom arguments...);
3537-
3538- // See "registering objects while deserializing" below
3539- value.registerEncodedObject(instance);
3540-
3541- // Load the non-transient, non-static fields
3542- render(value, instance, clazz, context);
3543-
3544- return instance;
3545- }
3546- });
3547-----
3548-
3549-
3550-
3551-=== Security Policy Requirements for DefaultValueCoder
3552-
3553-DefaultValueCoder performs security-sensitive operations: (a) it reads and writes data from and to private fields using reflection, and (b) it overrides the default implementations of java.io.ObjectInputStream and java.io.ObjectOutputStream. If a SecurityManager is installed then three permissions must be granted to enable the new mechanism:
3554-
3555-----
3556-java.lang.RuntimePermission "accessDeclaredMembers";
3557-java.lang.reflect.ReflectPermission("suppressAccessChecks")
3558-java.io.SerializablePermission("enableSubclassImplementation")
3559-----
3560-
3561-See <<Security>> for an extended discussion on security policy issues for Persistit.
3562-
3563-== SerialValueCoder
3564-
3565-+SerialValueCoder+ uses standard Java serialization to store and retrieve object values. Typically this results in slower performance and a more verbose storage format than +DefaultValueCoder+, but there are a number of reasons why a particular application might require standard Java serialization, including:
3566-
3567-- the security context into which the application will be deployed does not grant the permissions noted above that are required for +DefaultValueCoder+,
3568-- to avoid Persistit's use of private API calls to construct object instances during deserialization,
3569-- a preference for the use of a standard format defined within the Java platform rather than Persistit's custom format,
3570-- limitations documented above on the API elements available during custom deserialization within DefaultValueCoder, for example non-support of GetField and PutField.
3571-
3572-Your application can specify +SerialValueCoders+ for specific classes either by explicitly creating and registering them, or by naming them in the com.persistit.serialOverride property.
3573-
3574-To explicitly register a +SerialValueCoder+ for the class +MyClass+, do this:
3575-
3576-[source,java]
3577-----
3578- ...
3579- Persistit.getInstance().getCoderManager().registerValueCoder(
3580- MyClass.class,
3581- new SerialValueCoder(MyClass.class));
3582- ...
3583-----
3584-
3585-
3586-=== The +com.persistit.serialOverride+ Configuration Property
3587-
3588-The +serialOverride+ property specifies classes that are to be serialized by +SerialValueCoder+ rather than +DefaultValueCoder+. This property affects how Persistit assigns a value coder when none has previously been registered. It does not override or affect explicitly registered coders.
3589-
3590-Names are separated by commas and may contain wild cards.
3591-
3592-The following are valid patterns:
3593-
3594-+java.io.File+:: Just the File class.
3595-+java.io.*+:: All classes in the java.io package.
3596-+java.awt.**+:: All classes in the java.awt package and its sub-packages
3597-+java.util.*Map+:: All of the Map classes in the java.util.
3598-+**+:: All classes in all packages
3599-
3600-More precisely, +serialOverride+ specifies a comma-delimited list of zero or more patterns, each of which is either a fully-qualified class name or pattern that has within it exactly one wild card. The wild card “\*” replaces any sequence of characters other than a period (“.”), while “\*\*” replaces any sequence of characters including periods. For example:
3601-
3602-----
3603-+serialOverride=org.apache.**,com.mypkg.serialstuff.*,com.mypkg.MyClass+
3604-----
3605-
3606-Like all configuration properties, you may specify this in the persistit.properties file or as a system property through a Java command-line argument in the form:
3607-
3608-----
3609-+-Dcom.persistit.serialOverride=...+
3610-----
3611-
3612-== Registering Objects in a Custom +ValueCoder+
3613-
3614-In a custom +ValueCoder+ implementation, the +get+ method is responsible for constructing and populating an instance of an object. The following pattern should be used when implementing the get method:
3615-
3616-[source,java]
3617-----
3618-public void get(Value value, Class clazz, CoderContext context) throws ConversionException {
3619- // Construct the object being deserialized.
3620- //
3621- Object instance = ...constructor for the object...
3622-
3623- // Associate a handle with the newly
3624- // created instance.
3625- //
3626- value.registerEncodedObject(instance);
3627-
3628- // Populate the object's internal state
3629- //
3630- ... load the fields – for example, by calling render...
3631-
3632- return instance;
3633-}
3634-----
3635-
3636-The purpose of the +registerEncodedObject+ method is to record the association between the newly created object and an internal integer-valued handle that may be used subsequently in the serialization stream to refer to that object. This mechanism supports objects that may have fields that refer either indirectly or indirectly back to the same object – i.e., that participate in a cyclical reference graph.
3637-
3638-As a concrete example, consider a Person class with a spouse field such that for married couple p and q, p.spouse is q and q.spouse is p. When Persistit serializes p it also serializes q, but when it serializes q's spouse field, it records a reference handle associated with the already-serialized instance of p rather than writing a new copy of p in the serialization stream. Upon deserializing q, Persistit looks up the object for the recorded handle to correctly associate the already-deserialized p instance with q.
3639-
3640-Whenever you implement a custom +get()+ method in any +ValueCoder+, you must notify the underlying Value object about the newly created object by calling registerEncodedObject before deserializing its fields so that any back-references made within serialized fields of that object can find the object correctly.
3641-
3642-== +Value.toString()+ and +decodeDisplayable+
3643-
3644-In many cases it is not very useful simply to display the result of evaluating +toString()+ on an object. The default toString method inherited from Object conveys just a class name and a memory handle. In addition, for remote operations of AdminUI, it may not even be feasible to construct a deserialized object for each record. Therefore, +com.persistit.Value+ provides a specialized +toString()+ method to render an arbitrary object value into a legible string. The AdminUI utility uses this facility to summarize the data contained in a Tree.
3645-
3646-Persistit creates a String value loading the object's class, using the following algorithm:
3647-
3648-- If the state represented by this Value is undefined, then return "undefined".
3649-- If the state is null or a boolean, return "null" "false", or "true".
3650-- If the value represents a primitive type, return the string representation of the value, prefixed by "(byte)", "(short)", "(char)", "(long)", or "(float)" for the corresponding types. Values of type int and double are presented without prefix to reduce clutter.
3651-- If the value represents a String, return a modified form of the string enclosed in double quotes. For each character of the string, if it is a double quote replace it by "\"", otherwise if it is outside of the printable ASCII character set replace the character in the modified string by "\b", "\t", "\n", "\r" or "\uNNNN" such that the modified string would be a valid Java string constant.
3652-- If the value represents a wrapper for a primitive value (i.e., a java.lang.Boolean, java.lang.Byte, etc.) return the string representation of the value prefixed by "(Boolean)", "(Byte)", "(Short)", "(Character)", "(Integer)", "(Long)", "(Float)" or "(Double)". The package name java.lang is removed to reduce clutter.
3653-- If the value represents a java.util.Date, return a formatted representation of the date using the format specified by Key.SDF. This is a readable format that displays the date with full precision, including milliseconds.
3654-- If the value represents an array, return a list of comma-separated element values surrounded by square brackets.
3655-- If the value represents one of the standard Collection implementations in the java.util package, then return a comma-separated list of values surrounded by square brackets.
3656-- If the value represents one of the standard Map implementations in the java.util package, then return a comma-separated list of key/value pairs surrounded by square brackets. Each key/value pair is represented by a string in the form key->value.
3657-- If the value represents an object of a class for which there is a registered com.persistit.encoding.ValueDisplayer, invoke the displayer's display method to format a displayable representation of the object.
3658-- If the value represents an object that has been stored using the version default serialization mechanism described above, return the class name of the object followed by a comma-separated tuple, enclosed within curly brace characters, representing the value of each field of the object.
3659-- If the value represents an object encoded through standard Java serialization, return the string "(Serialized-object)" followed by a sequence of hex digits representing the serialized bytes. Note that this process does not attempt to deserialize the object.
3660-- If the value represents an object that has already been represented within the formatted result - for example, if a Collection contains two references to the same object - then instead of creating an additional string representing the second or subsequent instance, emit a back reference pointer in the form @NNN where NNN is the character offset within the displayable string where the first instance was found. (This does not apply to strings and the primitive wrapper classes.)
3661-
3662-For example, consider a Person having for date of birth, first name, last name, salary and friends, an array of other Person objects. The result returned by toString() on a Value representing Mary Smith who has a friend John Smith, might appear as follows:
3663-
3664-----
3665- (Person){(Date)19490826000000.000-0400,"Mary","Jones",(long)75000,[
3666- (Person){(Date)19550522000000.000-0400,"John","Smith",(long)68000,[@0]}]}
3667-----
3668-
3669-In this example, John Smith's friends array contains a back reference to Mary Jones in the form "@0" because Mary's displayable reference starts at the beginning of the string.
3670-
3671-
3672-== PersistitReference
3673-
3674-In general, serializing an object that contains references to other objects requires all the referenced objects also to be serialized. For an object connected to a large reference graph, it may be impractical or even semantically incorrect to serialize the entire graph.
3675-
3676-One way to control the serialization graph for such an object is to write a custom ValueCoder; the custom ValueCoder can store key values for looking up the referenced object, rather than the object itself. The ValueCoderDemo.java program demonstrates how this can be done.
3677-
3678-The +com.persistit.ref.PersistitReference+ interface, and its abstract subclasses, provide an alternative mechanism for breaking up an object reference graph. It requires no custom ValueCoder, but does impact the design of application classes. In addition, you will need to write a concrete implementation of either com.persistit.ref.AbstractReference or com.persistit.ref.AbstractWeakReference based on the actual storage structure of your object graph.
3679-
3680-== ObjectCache
3681-
3682-A +com.persistit.Value+ object holds the serialized, encoded state of a primitive value of an object. Each time you invoke the get method on a Value, Persistit generates a new copy of the object deserialized from this Value. Persistit does not implicitly cache deserialized objects. However, the +com.persistit.encoding.ObjectCache+ class provides a simple mechanism for applications that need to maintain an in-memory cache of of objects from Persistit. +ObjectCache+ works somewhat like a specialized version of java.util.WeakHashMap.
3683-
3684-+ObjectCache+ has +put+, +get+ and +remove+ methods much like a normal Map implementation. However, when storing an object value with the supplied +com.persistit.Key+, +ObjectCache+ constructs a new, immutable +com.persistit.KeyState+ object to hold as an internal key. This is necessary because +Key+ objects change value as they are used.
3685-
3686-Each +ObjectCache+ entry holds its object value as a +SoftReference+, making it available for garbage collection when space is needed.
3687
3688=== removed file 'doc/TOC.txt'
3689--- doc/TOC.txt 2012-04-25 18:13:07 +0000
3690+++ doc/TOC.txt 1970-01-01 00:00:00 +0000
3691@@ -1,19 +0,0 @@
3692-Akiban Persistit User Guide
3693-===========================
3694-Peter Beaman <pbeaman@akiban.com>
3695-:toc:
3696-:doctype: book
3697-:icons:
3698-:numbered:
3699-:website: http://www.akiban.com/persistit/
3700-
3701-@GettingStarted.txt
3702-@BasicAPI.txt
3703-@Transactions.txt
3704-@PhysicalStorage.txt
3705-@Configuration.txt
3706-@Management.txt
3707-@Security.txt
3708-@Serialization.txt
3709-@Miscellaneous.txt
3710-
3711
3712=== added file 'doc/Transactions.rst'
3713--- doc/Transactions.rst 1970-01-01 00:00:00 +0000
3714+++ doc/Transactions.rst 2012-05-30 18:23:19 +0000
3715@@ -0,0 +1,200 @@
3716+.. _Transactions:
3717+
3718+Transactions
3719+============
3720+
3721+Akiban Persistit supports transactions with multi-version concurrency control (MVCC) using a protocol called Snapshot Isolation (SI). An application calls ``com.persistit.Transaction#begin``, ``com.persistit.Transaction#commit``, ``com.persistit.Transaction#rollback# and ``com.persistit.Transaction#end`` methods to control the current transaction scope explicitly. A Transaction allows an application to execute multiple database operations in an atomic, consistent, isolated and durable (ACID) manner.
3722+
3723+Applications manage transactions through an instance of a ``com.persistit.Transaction`` object. ``Transaction`` does not represent a single transaction, but is instead a context in which a thread may perform many sequential transactions. The general pattern is that the application gets the current thread’s ``Transaction`` instance, calls its ``begin`` method, performs work, calls ``commit`` and finally ``end``. The thread uses the same ``Transaction`` instance repeatedly. Generally each thread has one ``Transaction`` that lasts for the entire life of the thread (but see com.persistit.Transaction#_threadManagement for a mechanism that allows a transaction to be serviced by multiple threads).
3724+
3725+Using Transactions
3726+------------------
3727+
3728+The following code fragment performs two store operations within the scope of a transaction:
3729+
3730+.. code-block:: java
3731+
3732+ //
3733+ // Get the transaction context for the current thread.
3734+ //
3735+ Transaction txn = myExchange.getTransaction();
3736+ int remainingRetries = RETRY_COUNT;
3737+ for (;;) {
3738+ txn.begin();
3739+ try {
3740+ myExchange.getValue().put("First value");
3741+ myExchange.clear().append(1).store();
3742+ myExchange.getValue().put("Second value");
3743+ myExchange.clear().append(2).store();
3744+ // Required to commit the transaction
3745+ txn.commit();
3746+ break;
3747+ } catch (RollbackException re) {
3748+ // perform any special rollback handling
3749+ // allow loop to repeat until commit succeeds or retries
3750+ // too many times.
3751+ if (--remainingRetries < 0) {
3752+ throw new TransactionFailedException();
3753+ }
3754+ } catch (PersistitException pe) {
3755+ // handle other Persistit exception
3756+ } finally {
3757+ // Required to end the scope of a transaction.
3758+ txn.end();
3759+ }
3760+ }
3761+
3762+This example catches ``com.persistit.exception.RollbackException`` which can be thrown by any Persistit operation within the scope of a transaction, including ``commit``. Any code explicitly running within the scope of a transaction should be designed to handle rollbacks.
3763+
3764+This example also uses a *try/finally* block to ensure every call to ``begin`` has a matching call to ``end``. This code pattern is mandatory: it is critical to correct transaction nesting behavior.
3765+
3766+One convenient way to do this is to encapsulate the logic of a transaction in an implementation of ``com.persisitit.TransactionRunnable`` interface. The ``com.persistit.Transaction#run`` method automatically provides logic to begin the transaction, execute the TransactionRunnable and commit the transaction, repeating the process until no rollback is thrown or a maximum retry count is reached. For example, the code fragment shown above can be rewritten as:
3767+
3768+.. code-block:: java
3769+
3770+ //
3771+ // Get the transaction context for the current thread.
3772+ //
3773+ Transaction txn = myExchange.getTransaction();
3774+ //
3775+ // Perform the transaction with the following parameters:
3776+ // - try to commit it up to 10 times
3777+ // - delay 2 milliseconds before each retry
3778+ // - use the group commit durability policy
3779+ //
3780+ txn.run(new TransactionRunnable() {
3781+ public void run() throws PersistitException {
3782+ myExchange.getValue().put("First value");
3783+ myExchange.clear().append(1).store();
3784+ myExchange.getValue().put("Second value");
3785+ myExchange.clear().append(2).store();
3786+ }
3787+ }, 10, 2, CommitPolicy.GROUP);
3788+
3789+Mixing Transactional and Non-Transactional Operations
3790+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3791+
3792+Database operations running outside the scope of an explicitly defined transaction are never subject to rollback and therefore do not require retry logic. However, such operations are also not guaranteed to be durable in the event of a system crash. Further, such operations are not isolated. Read operations performed outside of a transaction can read uncommitted updates, and updates performed outside of a transaction are visible within transactions. In other words, non-transactional reads and writes may break both the durability and isolation of concurrently executing transactions. Therefore it is strongly recommended that in an application that relies on transactions, all interactions with the database should use transactions.
3793+
3794+Optimistic Transaction Scheduling
3795+---------------------------------
3796+
3797+To achieve high performance and scalability, Persistit supports an optimistic transaction scheduling protocol called MVCC with http://wikipedia.org/wiki/Snapshot_isolation[Snapshot Isolation]. Under this protocol multiple threads are permitted to execute transactions at full speed without blocking until a potentially inconsistent state is recognized. At that point a transaction suspected of causing the inconsistent state is automatically forced to roll back.
3798+
3799+Optimistic scheduling works because transactions usually do not collide, especially when individual database operations are fast, and so in practice transactions are seldom rolled back. But because any transaction may be rolled back at any point, applications must be designed carefully to avoid unintended side-effects. For example, a transaction should never perform non-repeatable or externally visible operations such as file or network I/O within its scope.
3800+
3801+Snapshot Isolation
3802+^^^^^^^^^^^^^^^^^^
3803+
3804+Persistit schedules concurrently executing transactions optimistically, without locking any database records. Instead, Persistit uses the well-known Snapshot Isolation protocol to achieve atomicity and isolation. While transactions are modifying data, Persistit maintains multiple versions of values being modified. Each version is labeled with the commit timestamp of the transaction that modified it. Whenever a transaction reads a value that has been modified by other transactions, it gets the latest version that was committed before its own start timestamp. In other words, all read operations are performed as if from a "snapshot" of the state of the database made at the transaction's start timestamp - hence the name "Snapshot Isolation."
3805+
3806+.. _Pruning:
3807+
3808+Pruning
3809+^^^^^^^
3810+
3811+Given that all updates written through transactions are created as versions within the MVCC scheme, a large number of versions can accumulate over time. Persistit reduces this proliferation through an activity called "pruning." Pruning resolves the final state of each version by removing any versions created by aborted transactions and removing obsolete versions no longer needed by other transactions. If a value contains only one version and the commit timestamp of the transaction that created it is before the start of any currently running transaction, that value is called *primordial*. The goal of pruning is to reduce most or all values in the database to their primordial states because updating and reading primordial values is more efficient than than managing multiple version values. Pruning happens automatically and is generally not visible to the application.
3812+
3813+Rollbacks
3814+^^^^^^^^^
3815+
3816+Usually Snapshot Isolation allows concurrent transactions to commit without interference but this is not always the case. Two concurrent transactions that attempt to modify the same Persistit key/value pair before they commit are said to have a "write-write dependency". To avoid anomalous results one of them must abort, rolling back any other updates it may also have created, and retry. Persistit implements a "first updater wins" policy in which if two transactions attempt to update the same record, the first transaction "wins" by being allowed to continue, while the second transaction "loses" and is required to abort.
3817+
3818+Once a transaction has aborted, any subsequent database operation it attempts throws a ``RollbackException``. Application code should catch and handle this Exception. Usually the correct and desired behavior is simply to retry the transaction as shown in the code samples above.
3819+
3820+A transaction can also voluntarily roll back. For example, transaction logic could detect an error condition that it chooses to handle by throwing an exception back to the application. In this case the transaction should invoke the ``rollback`` method to explicitly declare its intent to abort the transaction.
3821+
3822+Read-Only Transactions
3823+^^^^^^^^^^^^^^^^^^^^^^
3824+
3825+Under Snapshot Isolation, transactions that read but do not modify data cannot generate any write-write dependencies and are therefore not subject to being rolled back because of the actions of other transactions. However, even though it modifies no data, a long-running read-only transaction can force Persistit to retain old value versions from other transactions for its duration in order to provide a snapshot view. This behavior can cause congestion and performance degradation by preventing very old values from being pruned. The degree to which this is a problem depends on the volume of update transactions being processed and the duration of long-running transactions.
3826+
3827+Snapshot Isolation is not Serializable
3828+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3829+
3830+It is well-known that transactions executing under SI are not necessarily serializable. Under SI, so-called *write-skew* anomalies can happen with transactions that have certain kinds of interactions. Write-skew can be avoided by (a) explicit application-level locking or (b) structuring transactions to add write-write dependencies where write-skew otherwise could occur.
3831+
3832+Note that many common transaction patterns, including those defined by the TPC-C benchmark, do not experience write-skew and therefore *are* serializable under SI.
3833+
3834+Durability Options: ``CommitPolicy``
3835+------------------------------------
3836+
3837+Persistit provides three policies that determine the durability of a transaction after it has executed the ``com.persistit.Transaction#commit`` method. These are:
3838+
3839+ ``HARD``
3840+ The ``commit`` method does not return until all updates created by the transaction have been written to non-volatile storage (e.g., disk storage).
3841+ ``GROUP``
3842+ The ``commit`` method does not return until all updates created by the transaction have been written to non-volatile storage. In addition, the committing
3843+ transaction waits briefly in an attempt to recruit other transactions running in other threads to write their updates with the same physical I/O operation.
3844+ ``SOFT``
3845+ The ``commit`` method returns *before* the updates have been recorded on non-volatile storage. Persistit attempts to write them within 100 milliseconds, but
3846+ this interval is not guaranteed.
3847+
3848+You can specify a default policy in the Persistit initialization properties using the ``txnpolicy`` property or under program control using ``com.persistit.Persistit#setDefaultTransactionCommitPolicy``. The default policy applies whenever the application calls the ``commit()`` method. You can override the default policy using ``commit(CommitPolicy)``.
3849+
3850+HARD and GROUP ensure each transaction is written durably to non-volatile storage before the ``commit`` method returns. The difference is that GROUP can improve throughput in multi-threaded applications because the average number of I/O operations needed to commit *N* transactions can be smaller than *N*. However, for one or a small number of concurrent threads, GROUP reduces throughput because it works by introducing a delay to allow other concurrent transactions to commit within a single I/O operation.
3851+
3852+SOFT commits are generally much faster than HARD or GROUP commits, especially for single-threaded applications, because the results of numerous transactions committed from a single thread can be aggregated and written to disk in a single I/O operation. However, transactions written with the SOFT commit policy are not immediately durable and it is possible that the recovered state of a database will be missing transactions that reported they were committed shortly before a crash.
3853+
3854+For SOFT commits, the state of the database after restart is such that for any committed transaction T, either all or none of its modifications will be present in the recovered database. Further, if a transaction T2 reads or updates data that was written by any other transaction T1, and if T2 is present in the recovered database, then so is T1. Any transaction that was in progress, but had not been committed at the time of the failure, is guaranteed not to be present in the recovered database. SOFT commits are designed to be durable within 100 milliseconds after ``commit`` returns. However, this interval is determined by computing the average duration of recent I/O operations to predict the completion time of the I/O that will write the transaction to disk, and therefore the interval cannot be guaranteed.
3855+
3856+Nested Transactions
3857+-------------------
3858+
3859+A nested transaction occurs when code that is already executing within the scope of a transaction executes the ``begin`` method to start a new transaction. This might happen, for example, if an application’s transaction logic calls a method that also uses transactions. In this case, the commit processing of the inner transaction scope is deferred until the outermost transaction commits. At that point, all the updates performed within the inner and outer transaction scopes are committed to the database. Similarly, a rollback initiated by the inner transaction causes both it and the outermost transaction to roll back.
3860+
3861+Accumulators
3862+------------
3863+
3864+Consider an application in which concurrently running transactions share a counter. For example, suppose each transaction is responsible for allocating a unique integer as a primary key for a database record. One way to do this would be to store the counter in a Persistit key/value pair, reading the value at the start of each transaction and committing an update at the end.
3865+
3866+The problem with this approach is that under SI, concurrent transactions running in a multi-threaded application would experience very frequent write-write dependencies on the counter value; in fact, the only way to complete any transactions would be serially, one at a time.
3867+
3868+Persistit provides the ``com.persistit.Accumulator`` class to avoid this problem. An accumulator is designed to manage contributions from multiple concurrent transactions without causing write-write dependencies. Accumulators are durable in the sense that each transaction’s contribution is made durable with the transaction itself, and Persistit automatically recovers a correct state for each Accumulator in the event of a system crash.
3869+
3870+There are four types of accumulator in Persistit. Each a concrete subclass of the abstract ``com.persistit.Accumulator`` class:
3871+
3872+ ``SUM``
3873+ Tallies a count or sum of contributions by each transaction
3874+ ``MIN``
3875+ Finds the minimum value contributed by all transactions
3876+ ``MAX``
3877+ Finds the maximum value contributed by all transactions
3878+ ``SEQ``
3879+ Special case of the SUM accumulator used to generate sequence numbers
3880+
3881+Accumulator instances are associated with a ``com.persistit.Tree``. Each ``Tree`` may have up to 64 accumulators. The following code fragment creates and/or acquires a ``SumAccumulator``, reads its snapshot value and then adds one to it:
3882+
3883+.. code-block:: java
3884+
3885+ final Exchange ex = _persistit.getExchange(volume, treeName, true);
3886+ final Transaction txn = ex.getTransaction();
3887+ txn.begin();
3888+ try {
3889+ final Accumulator acc =
3890+ ex.getTree().getAccumulator(Accumulator.Type.SUM, 17);
3891+ long snap = acc.getSnapshotValue(txn);
3892+ acc.update(1, txn);
3893+ txn.commit();
3894+ } finally {
3895+ txn.end();
3896+ }
3897+
3898+The value 17 is simply an arbitrary index number between 0 and 63, inclusive. The application is responsible for allocating and managing accumulator indexes.
3899+
3900+The snapshot value of an accumulator obtained through ``com.persistit.Accumulator#getSnapshotValue()`` is the value computed from all updates contributed by transactions that had committed at the time the current transaction started, plus the transaction’s own as-yet uncommitted updates. In other words, the snapshot value of the accumulator is consistent with the snapshot view of all other data visible within the transaction.
3901+
3902+An accumulator has two ways of accessing its accumulated value:
3903+
3904+ ``getSnapshotValue()``
3905+ Is a value computed from updates that were committed at the start of the current transaction. This method may be called only within the scope of a
3906+ Transaction.
3907+ ``getLiveValue()``
3908+ Is an ephemeral value reflecting all updates performed by all transactions, including concurrent and aborted transactions.
3909+
3910+The snapshot value is a precise, consistent tally, while the live value is approximate. For a ``SumAccumulator``, ``MaxAccumulator`` or ``SeqAccumulator``, if all updates are have non-negative arguments, then the live value is always greater than or equal to the snapshot value.
3911+
3912+SeqAccumulator
3913+^^^^^^^^^^^^^^
3914+
3915+The ``SeqAccumulator`` class has a special role in allocating unique identifier numbers, e.g., synthetic primary keys. The goal of the ``SeqAccumulator`` is to ensure that every committed transaction has received a unique value integer in all circumstances, including after recovery from a crash. See ``com.persistit.Accumulator`` for details.
3916
3917=== removed file 'doc/Transactions.txt'
3918--- doc/Transactions.txt 2012-04-30 22:09:31 +0000
3919+++ doc/Transactions.txt 1970-01-01 00:00:00 +0000
3920@@ -1,179 +0,0 @@
3921-[[Transactions]]
3922-= Transactions
3923-
3924-Akiban Persistit supports transactions with multi-version concurrency control (MVCC) using a protocol called Snapshot Isolation (SI). An application calls +com.persistit.Transaction#begin+, +com.persistit.Transaction#commit+, +com.persistit.Transaction#rollback# and +com.persistit.Transaction#end+ methods to control the current transaction scope explicitly. A Transaction allows an application to execute multiple database operations in an atomic, consistent, isolated and durable (ACID) manner.
3925-
3926-Applications manage transactions through an instance of a +com.persistit.Transaction+ object. +Transaction+ does not represent a single transaction, but is instead a context in which a thread may perform many sequential transactions. The general pattern is that the application gets the current thread’s +Transaction+ instance, calls its +begin+ method, performs work, calls +commit+ and finally +end+. The thread uses the same +Transaction+ instance repeatedly. Generally each thread has one +Transaction+ that lasts for the entire life of the thread (but see com.persistit.Transaction#_threadManagement[Thread Management] for a mechanism that allows a transaction to be serviced by multiple threads).
3927-
3928-== Using Transactions
3929-
3930-The following code fragment performs two store operations within the scope of a transaction:
3931-
3932-[source,java]
3933-----
3934-//
3935-// Get the transaction context for the current thread.
3936-//
3937-Transaction txn = myExchange.getTransaction();
3938-int remainingRetries = RETRY_COUNT;
3939-for (;;) {
3940- txn.begin();
3941- try {
3942- myExchange.getValue().put("First value");
3943- myExchange.clear().append(1).store();
3944- myExchange.getValue().put("Second value");
3945- myExchange.clear().append(2).store();
3946- // Required to commit the transaction
3947- txn.commit();
3948- break;
3949- } catch (RollbackException re) {
3950- // perform any special rollback handling
3951- // allow loop to repeat until commit succeeds or retries
3952- // too many times.
3953- if (--remainingRetries < 0) {
3954- throw new TransactionFailedException();
3955- }
3956- } catch (PersistitException pe) {
3957- // handle other Persistit exception
3958- } finally {
3959- // Required to end the scope of a transaction.
3960- txn.end();
3961- }
3962-}
3963-----
3964-
3965-This example catches +com.persistit.exception.RollbackException+ which can be thrown by any Persistit operation within the scope of a transaction, including +commit+. Any code explicitly running within the scope of a transaction should be designed to handle rollbacks.
3966-
3967-This example also uses a _try/finally_ block to ensure every call to +begin+ has a matching call to +end+. This code pattern is mandatory: it is critical to correct transaction nesting behavior.
3968-
3969-One convenient way to do this is to encapsulate the logic of a transaction in an implementation of +com.persisitit.TransactionRunnable+ interface. The +com.persistit.Transaction#run+ method automatically provides logic to begin the transaction, execute the TransactionRunnable and commit the transaction, repeating the process until no rollback is thrown or a maximum retry count is reached. For example, the code fragment shown above can be rewritten as:
3970-
3971-[source,java]
3972-----
3973-//
3974-// Get the transaction context for the current thread.
3975-//
3976-Transaction txn = myExchange.getTransaction();
3977-//
3978-// Perform the transaction with the following parameters:
3979-// - try to commit it up to 10 times
3980-// - delay 2 milliseconds before each retry
3981-// - use the group commit durability policy
3982-//
3983-txn.run(new TransactionRunnable() {
3984- public void run() throws PersistitException {
3985- myExchange.getValue().put("First value");
3986- myExchange.clear().append(1).store();
3987- myExchange.getValue().put("Second value");
3988- myExchange.clear().append(2).store();
3989- }
3990-}, 10, 2, CommitPolicy.GROUP);
3991-----
3992-
3993-=== Mixing Transactional and Non-Transactional Operations
3994-
3995-Database operations running outside the scope of an explicitly defined transaction are never subject to rollback and therefore do not require retry logic. However, such operations are also not guaranteed to be durable in the event of a system crash. Further, such operations are not isolated. Read operations performed outside of a transaction can read uncommitted updates, and updates performed outside of a transaction are visible within transactions. In other words, non-transactional reads and writes may break both the durability and isolation of concurrently executing transactions. Therefore it is strongly recommended that in an application that relies on transactions, all interactions with the database should use transactions.
3996-
3997-== Optimistic Transaction Scheduling
3998-
3999-To achieve high performance and scalability, Persistit supports an optimistic transaction scheduling protocol called MVCC with http://wikipedia.org/wiki/Snapshot_isolation[Snapshot Isolation]. Under this protocol multiple threads are permitted to execute transactions at full speed without blocking until a potentially inconsistent state is recognized. At that point a transaction suspected of causing the inconsistent state is automatically forced to roll back.
4000-
4001-Optimistic scheduling works because transactions usually do not collide, especially when individual database operations are fast, and so in practice transactions are seldom rolled back. But because any transaction may be rolled back at any point, applications must be designed carefully to avoid unintended side-effects. For example, a transaction should never perform non-repeatable or externally visible operations such as file or network I/O within its scope.
4002-
4003-=== Snapshot Isolation
4004-
4005-Persistit schedules concurrently executing transactions optimistically, without locking any database records. Instead, Persistit uses the well-known Snapshot Isolation protocol to achieve atomicity and isolation. While transactions are modifying data, Persistit maintains multiple versions of values being modified. Each version is labeled with the commit timestamp of the transaction that modified it. Whenever a transaction reads a value that has been modified by other transactions, it gets the latest version that was committed before its own start timestamp. In other words, all read operations are performed as if from a "snapshot" of the state of the database made at the transaction's start timestamp - hence the name "Snapshot Isolation."
4006-
4007-[[Pruning]]
4008-=== Pruning
4009-
4010-Given that all updates written through transactions are created as versions within the MVCC scheme, a large number of versions can accumulate over time. Persistit reduces this proliferation through an activity called "pruning." Pruning resolves the final state of each version by removing any versions created by aborted transactions and removing obsolete versions no longer needed by other transactions. If a value contains only one version and the commit timestamp of the transaction that created it is before the start of any currently running transaction, that value is called _primordial_. The goal of pruning is to reduce most or all values in the database to their primordial states because updating and reading primordial values is more efficient than than managing multiple version values. Pruning happens automatically and is generally not visible to the application.
4011-
4012-=== Rollbacks
4013-
4014-Usually Snapshot Isolation allows concurrent transactions to commit without interference but this is not always the case. Two concurrent transactions that attempt to modify the same Persistit key/value pair before they commit are said to have a "write-write dependency". To avoid anomalous results one of them must abort, rolling back any other updates it may also have created, and retry. Persistit implements a "first updater wins" policy in which if two transactions attempt to update the same record, the first transaction "wins" by being allowed to continue, while the second transaction "loses" and is required to abort.
4015-
4016-Once a transaction has aborted, any subsequent database operation it attempts throws a +RollbackException+. Application code should catch and handle this Exception. Usually the correct and desired behavior is simply to retry the transaction as shown in the code samples above.
4017-
4018-A transaction can also voluntarily roll back. For example, transaction logic could detect an error condition that it chooses to handle by throwing an exception back to the application. In this case the transaction should invoke the +rollback+ method to explicitly declare its intent to abort the transaction.
4019-
4020-=== Read-Only Transactions
4021-
4022-Under Snapshot Isolation, transactions that read but do not modify data cannot generate any write-write dependencies and are therefore not subject to being rolled back because of the actions of other transactions. However, even though it modifies no data, a long-running read-only transaction can force Persistit to retain old value versions from other transactions for its duration in order to provide a snapshot view. This behavior can cause congestion and performance degradation by preventing very old values from being pruned. The degree to which this is a problem depends on the volume of update transactions being processed and the duration of long-running transactions.
4023-
4024-=== Snapshot Isolation is not Serializable
4025-
4026-It is well-known that transactions executing under SI are not necessarily serializable. Under SI, so-called _write-skew_ anomalies can happen with transactions that have certain kinds of interactions. Write-skew can be avoided by (a) explicit application-level locking or (b) structuring transactions to add write-write dependencies where write-skew otherwise could occur.
4027-
4028-Note that many common transaction patterns, including those defined by the TPC-C benchmark, do not experience write-skew and therefore _are_ serializable under SI.
4029-
4030-== Durability Options: +CommitPolicy+
4031-
4032-Persistit provides three policies that determine the durability of a transaction after it has executed the +com.persistit.Transaction#commit+ method. These are:
4033-
4034-[horizontal]
4035-+HARD+:: The +commit+ method does not return until all updates created by the transaction have been written to non-volatile storage (e.g., disk storage).
4036-+GROUP+:: The +commit+ method does not return until all updates created by the transaction have been written to non-volatile storage. In addition, the committing transaction waits briefly in an attempt to recruit other transactions running in other threads to write their updates with the same physical I/O operation.
4037-+SOFT+:: The +commit+ method returns _before_ the updates have been recorded on non-volatile storage. Persistit attempts to write them within 100 milliseconds, but this interval is not guaranteed.
4038-
4039-You can specify a default policy in the Persistit initialization properties using the +txnpolicy+ property or under program control using +com.persistit.Persistit#setDefaultTransactionCommitPolicy+. The default policy applies whenever the application calls the +commit()+ method. You can override the default policy using +commit(CommitPolicy)+.
4040-
4041-HARD and GROUP ensure each transaction is written durably to non-volatile storage before the +commit+ method returns. The difference is that GROUP can improve throughput in multi-threaded applications because the average number of I/O operations needed to commit _N_ transactions can be smaller than _N_. However, for one or a small number of concurrent threads, GROUP reduces throughput because it works by introducing a delay to allow other concurrent transactions to commit within a single I/O operation.
4042-
4043-SOFT commits are generally much faster than HARD or GROUP commits, especially for single-threaded applications, because the results of numerous transactions committed from a single thread can be aggregated and written to disk in a single I/O operation. However, transactions written with the SOFT commit policy are not immediately durable and it is possible that the recovered state of a database will be missing transactions that reported they were committed shortly before a crash.
4044-
4045-For SOFT commits, the state of the database after restart is such that for any committed transaction T, either all or none of its modifications will be present in the recovered database. Further, if a transaction T2 reads or updates data that was written by any other transaction T1, and if T2 is present in the recovered database, then so is T1. Any transaction that was in progress, but had not been committed at the time of the failure, is guaranteed not to be present in the recovered database. SOFT commits are designed to be durable within 100 milliseconds after +commit+ returns. However, this interval is determined by computing the average duration of recent I/O operations to predict the completion time of the I/O that will write the transaction to disk, and therefore the interval cannot be guaranteed.
4046-
4047-== Nested Transactions
4048-
4049-A nested transaction occurs when code that is already executing within the scope of a transaction executes the +begin+ method to start a new transaction. This might happen, for example, if an application’s transaction logic calls a method that also uses transactions. In this case, the commit processing of the inner transaction scope is deferred until the outermost transaction commits. At that point, all the updates performed within the inner and outer transaction scopes are committed to the database. Similarly, a rollback initiated by the inner transaction causes both it and the outermost transaction to roll back.
4050-
4051-== Accumulators
4052-
4053-Consider an application in which concurrently running transactions share a counter. For example, suppose each transaction is responsible for allocating a unique integer as a primary key for a database record. One way to do this would be to store the counter in a Persistit key/value pair, reading the value at the start of each transaction and committing an update at the end.
4054-
4055-The problem with this approach is that under SI, concurrent transactions running in a multi-threaded application would experience very frequent write-write dependencies on the counter value; in fact, the only way to complete any transactions would be serially, one at a time.
4056-
4057-Persistit provides the +com.persistit.Accumulator+ class to avoid this problem. An accumulator is designed to manage contributions from multiple concurrent transactions without causing write-write dependencies. Accumulators are durable in the sense that each transaction’s contribution is made durable with the transaction itself, and Persistit automatically recovers a correct state for each Accumulator in the event of a system crash.
4058-
4059-There are four types of accumulator in Persistit. Each a concrete subclass of the abstract +com.persistit.Accumulator+ class:
4060-
4061-[horizontal]
4062-+SUM+:: Tallies a count or sum of contributions by each transaction
4063-+MIN+:: Finds the minimum value contributed by all transactions
4064-+MAX+:: Finds the maximum value contributed by all transactions
4065-+SEQ+:: Special case of the SUM accumulator used to generate sequence numbers
4066-
4067-Accumulator instances are associated with a +com.persistit.Tree+. Each +Tree+ may have up to 64 accumulators. The following code fragment creates and/or acquires a +SumAccumulator+, reads its snapshot value and then adds one to it:
4068-
4069-[source,java]
4070-----
4071-final Exchange ex = _persistit.getExchange(volume, treeName, true);
4072-final Transaction txn = ex.getTransaction();
4073-txn.begin();
4074-try {
4075- final Accumulator acc =
4076- ex.getTree().getAccumulator(Accumulator.Type.SUM, 17);
4077- long snap = acc.getSnapshotValue(txn);
4078- acc.update(1, txn);
4079- txn.commit();
4080-} finally {
4081- txn.end();
4082-}
4083-----
4084-
4085-The value 17 is simply an arbitrary index number between 0 and 63, inclusive. The application is responsible for allocating and managing accumulator indexes.
4086-
4087-The snapshot value of an accumulator obtained through +com.persistit.Accumulator#getSnapshotValue()+ is the value computed from all updates contributed by transactions that had committed at the time the current transaction started, plus the transaction’s own as-yet uncommitted updates. In other words, the snapshot value of the accumulator is consistent with the snapshot view of all other data visible within the transaction.
4088-
4089-An accumulator has two ways of accessing its accumulated value:
4090-
4091-[horizontal]
4092-+getSnapshotValue()+:: Is a value computed from updates that were committed at the start of the current transaction. This method may be called only within the scope of a Transaction.
4093-+getLiveValue()+:: Is an ephemeral value reflecting all updates performed by all transactions, including concurrent and aborted transactions.
4094-
4095-The snapshot value is a precise, consistent tally, while the live value is approximate. For a +SumAccumulator+, +MaxAccumulator+ or +SeqAccumulator+, if all updates are have non-negative arguments, then the live value is always greater than or equal to the snapshot value.
4096-
4097-=== SeqAccumulator
4098-
4099-The +SeqAccumulator+ class has a special role in allocating unique identifier numbers, e.g., synthetic primary keys. The goal of the +SeqAccumulator+ is to ensure that every committed transaction has received a unique value integer in all circumstances, including after recovery from a crash. See +com.persistit.Accumulator+ for details.
4100
4101=== modified file 'doc/build/build-doc.sh'
4102--- doc/build/build-doc.sh 2012-05-25 18:50:59 +0000
4103+++ doc/build/build-doc.sh 2012-05-30 18:23:19 +0000
4104@@ -37,12 +37,29 @@
4105 # The end-product files, user_guide.html and user_guide.xml are written
4106 # there.
4107 #
4108-rm -rf /tmp/akiban-persistit-doc
4109-mkdir /tmp/akiban-persistit-doc
4110-javac -d /tmp/akiban-persistit-doc -cp ../../core/target/classes/ src/*.java
4111-java -cp /tmp/akiban-persistit-doc:../../core/target/classes AsciiDocPrep in=../TOC.txt out=/tmp/akiban-persistit-doc/doc.txt base=apidocs index=../../core/target/site/apidocs/index-all.html
4112-asciidoc -a toc -n -d book -b xhtml11 -o /tmp/akiban-persistit-doc/doc.html /tmp/akiban-persistit-doc/doc.txt
4113-asciidoc -a toc -n -d book -b docbook -o /tmp/akiban-persistit-doc/doc.xml /tmp/akiban-persistit-doc/doc.txt
4114-sed s/\`/\ / /tmp/akiban-persistit-doc/doc.html > /tmp/akiban-persistit-doc/user_guide.html
4115-sed s/\`/\ / /tmp/akiban-persistit-doc/doc.xml > /tmp/akiban-persistit-doc/user_guide.xml
4116+rm -rf ../../target/sphinx/source
4117+mkdir -p ../../target/sphinx/source
4118+mkdir -p ../../target/sphinx/classes
4119+mkdir -p ../../target/sphinx/html
4120+mkdir -p ../../target/sphinx/text
4121+
4122+cp ../index.rst ../../target/sphinx/source
4123+cp ../conf.py ../../target/sphinx/source
4124+
4125+javac -d ../../target/sphinx/classes -cp ../../target/classes/ src/*.java
4126+
4127+java -cp ../../target/sphinx/classes:../../target/classes SphinxDocPrep in=../ReleaseNotes.rst out=../../target/sphinx/source/ReleaseNotes.rst base=http://www.akiban.com/ak-docs/admin/persistit/apidocs index=../../target/site/apidocs/index-all.html
4128+java -cp ../../target/sphinx/classes:../../target/classes SphinxDocPrep in=../BasicAPI.rst out=../../target/sphinx/source/BasicAPI.rst base=http://www.akiban.com/ak-docs/admin/persistit/apidocs index=../../target/site/apidocs/index-all.html
4129+java -cp ../../target/sphinx/classes:../../target/classes SphinxDocPrep in=../Configuration.rst out=../../target/sphinx/source/Configuration.rst base=http://www.akiban.com/ak-docs/admin/persistit/apidocs index=../../target/site/apidocs/index-all.html
4130+java -cp ../../target/sphinx/classes:../../target/classes SphinxDocPrep in=../GettingStarted.rst out=../../target/sphinx/source/GettingStarted.rst base=http://www.akiban.com/ak-docs/admin/persistit/apidocs index=../../target/site/apidocs/index-all.html
4131+java -cp ../../target/sphinx/classes:../../target/classes SphinxDocPrep in=../Management.rst out=../../target/sphinx/source/Management.rst base=http://www.akiban.com/ak-docs/admin/persistit/apidocs index=../../target/site/apidocs/index-all.html
4132+java -cp ../../target/sphinx/classes:../../target/classes SphinxDocPrep in=../Miscellaneous.rst out=../../target/sphinx/source/Miscellaneous.rst base=http://www.akiban.com/ak-docs/admin/persistit/apidocs index=../../target/site/apidocs/index-all.html
4133+java -cp ../../target/sphinx/classes:../../target/classes SphinxDocPrep in=../PhysicalStorage.rst out=../../target/sphinx/source/PhysicalStorage.rst base=http://www.akiban.com/ak-docs/admin/persistit/apidocs index=../../target/site/apidocs/index-all.html
4134+java -cp ../../target/sphinx/classes:../../target/classes SphinxDocPrep in=../Security.rst out=../../target/sphinx/source/Security.rst base=http://www.akiban.com/ak-docs/admin/persistit/apidocs index=../../target/site/apidocs/index-all.html
4135+java -cp ../../target/sphinx/classes:../../target/classes SphinxDocPrep in=../Serialization.rst out=../../target/sphinx/source/Serialization.rst base=http://www.akiban.com/ak-docs/admin/persistit/apidocs index=../../target/site/apidocs/index-all.html
4136+java -cp ../../target/sphinx/classes:../../target/classes SphinxDocPrep in=../Transactions.rst out=../../target/sphinx/source/Transactions.rst base=http://www.akiban.com/ak-docs/admin/persistit/apidocs index=../../target/site/apidocs/index-all.html
4137+
4138+sphinx-build -a ../../target/sphinx/source ../../target/sphinx/html
4139+
4140+fold -s ../../target/sphinx/source/ReleaseNotes.rst | sed 's/``//g' | sed 's/\.\. note:/NOTE/' | sed 's/::/:/' > ../../target/sphinx/text/ReleaseNotes
4141
4142
4143=== added file 'doc/build/build-doc.sh.orig'
4144--- doc/build/build-doc.sh.orig 1970-01-01 00:00:00 +0000
4145+++ doc/build/build-doc.sh.orig 2012-05-30 18:23:19 +0000
4146@@ -0,0 +1,48 @@
4147+#/bin/sh
4148+#
4149+# Copyright © 2011-2012 Akiban Technologies, Inc. All rights reserved.
4150+#
4151+# This program is free software: you can redistribute it and/or modify
4152+# it under the terms of the GNU Affero General Public License as
4153+# published by the Free Software Foundation, version 3 (only) of the
4154+# License.
4155+#
4156+# This program is distributed in the hope that it will be useful,
4157+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4158+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4159+# GNU Affero General Public License for more details.
4160+#
4161+# You should have received a copy of the GNU Affero General Public License
4162+# along with this program. If not, see <http://www.gnu.org/licenses/>.
4163+#
4164+# This program may also be available under different license terms. For more
4165+# information, see www.akiban.com or contact licensing@akiban.com.
4166+#
4167+
4168+# ---------------------
4169+#
4170+# Builds the Akiban Persistit doc set. Currently this process is based on
4171+# the asciidoc tool (http://www.methods.co.nz/asciidoc/).
4172+#
4173+# Here are the steps:
4174+# 1. Run a Java program AsciiDocPrep to prepare a text asciidoc file.
4175+# Among other things, AsciiDocPrep fills in JavaDoc hyperlinks.
4176+# 2. Run asciidoc to generate an html file.
4177+# 3. Use sed to replace some characters. Turns out asciidoc doesn't like
4178+# to link to URLs having spaces, so AsciDocPrep replaces those spaces
4179+# with the "`" character. This step converts those back to spaces.
4180+#
4181+# Run this script from the root of the persistit source directory. This
4182+# script writes changes only into a directory /tmp/akiban-persistit-doc.
4183+# The end-product files, user_guide.html and user_guide.xml are written
4184+# there.
4185+#
4186+rm -rf /tmp/akiban-persistit-doc
4187+mkdir /tmp/akiban-persistit-doc
4188+javac -d /tmp/akiban-persistit-doc -cp ../../core/target/classes/ src/*.java
4189+java -cp /tmp/akiban-persistit-doc:../../core/target/classes AsciiDocPrep in=../TOC.txt out=/tmp/akiban-persistit-doc/doc.txt base=apidocs index=../../core/target/site/apidocs/index-all.html
4190+asciidoc -a toc -n -d book -b xhtml11 -o /tmp/akiban-persistit-doc/doc.html /tmp/akiban-persistit-doc/doc.txt
4191+asciidoc -a toc -n -d book -b docbook -o /tmp/akiban-persistit-doc/doc.xml /tmp/akiban-persistit-doc/doc.txt
4192+sed s/\`/\ / /tmp/akiban-persistit-doc/doc.html > /tmp/akiban-persistit-doc/user_guide.html
4193+sed s/\`/\ / /tmp/akiban-persistit-doc/doc.xml > /tmp/akiban-persistit-doc/user_guide.xml
4194+
4195
4196=== added file 'doc/build/src/SphinxDocPrep.java'
4197--- doc/build/src/SphinxDocPrep.java 1970-01-01 00:00:00 +0000
4198+++ doc/build/src/SphinxDocPrep.java 2012-05-30 18:23:19 +0000
4199@@ -0,0 +1,147 @@
4200+import java.io.BufferedReader;
4201+import java.io.File;
4202+import java.io.FileReader;
4203+import java.io.FileWriter;
4204+import java.io.PrintWriter;
4205+import java.util.SortedMap;
4206+import java.util.regex.Matcher;
4207+import java.util.regex.Pattern;
4208+
4209+import com.persistit.util.ArgParser;
4210+
4211+public class SphinxDocPrep {
4212+
4213+ private final static Pattern PERSISTIT_PATTERN = Pattern
4214+ .compile("(``)?(com\\.persistit(?:\\.[a-z]\\w*)*(?:\\.[A-Z]\\w*)+)(?:#(\\w+(?:[\\(\\)\\,a-zA-Z]*)))?(``)?");
4215+
4216+ private final static String[] ARG_TEMPLATE = { "in|string:|Input file", "out|string:|Output file",
4217+ "index|string:|Pathname of index-all.html file", "base|string:|Base of generated URLs", };
4218+
4219+ enum BlockState {
4220+ OUT, WAIT_FIRST_BLANK_LINE, WAIT_SECOND_BLANK_LINE
4221+ }
4222+
4223+ private AsciiDocIndex index;
4224+ private BlockState block = BlockState.OUT;
4225+ private PrintWriter writer;
4226+ private String base;
4227+ private String indexPath;
4228+
4229+ private void prepare(final String[] args) throws Exception {
4230+ ArgParser ap = new ArgParser("SphinxDocPrep", args, ARG_TEMPLATE);
4231+ final String inPath = ap.getStringValue("in");
4232+ final String outPath = ap.getStringValue("out");
4233+
4234+ writer = outPath.isEmpty() ? new PrintWriter(System.out) : new PrintWriter(new FileWriter(outPath));
4235+
4236+ base = ap.getStringValue("base");
4237+ if (base.isEmpty()) {
4238+ base = "http://akiban.com/persistit/doc/apidocs";
4239+ }
4240+ indexPath = ap.getStringValue("index");
4241+ if (indexPath.isEmpty()) {
4242+ indexPath = "/home/peter/website/apidocs/index-all.html";
4243+ }
4244+
4245+ index = new AsciiDocIndex();
4246+ System.out.print("Building JavaDoc index..");
4247+ index.buildIndex(indexPath, base);
4248+ System.out.println("done");
4249+
4250+ processFile(new File(inPath), 0);
4251+ writer.close();
4252+ }
4253+
4254+ public void processFile(final File file, final int level) throws Exception {
4255+ BufferedReader reader = new BufferedReader(new FileReader(file));
4256+ System.out.print("Processing file " + file);
4257+ String line;
4258+ while ((line = reader.readLine()) != null) {
4259+ if (line.startsWith("@")) {
4260+ processFile(new File(file.getParentFile(), line.substring(1)), level + 1);
4261+ } else {
4262+ processLine(line);
4263+ }
4264+ }
4265+ writer.println();
4266+ System.out.println(" - done");
4267+ }
4268+
4269+ private void processLine(final String line) throws Exception {
4270+ if (line.contains(".. code-block:")) {
4271+ block = BlockState.WAIT_FIRST_BLANK_LINE;
4272+ } else if (line.isEmpty()) {
4273+ switch (block) {
4274+ case WAIT_FIRST_BLANK_LINE:
4275+ block = BlockState.WAIT_SECOND_BLANK_LINE;
4276+ break;
4277+
4278+ case WAIT_SECOND_BLANK_LINE:
4279+ block = BlockState.OUT;
4280+ break;
4281+
4282+ default:
4283+ // no change
4284+ }
4285+ }
4286+
4287+ if (block == BlockState.OUT) {
4288+ final StringBuffer sb = new StringBuffer();
4289+ if (line.startsWith("=")) {
4290+ sb.append("=");
4291+ }
4292+ final Matcher matcher = PERSISTIT_PATTERN.matcher(line);
4293+ while (matcher.find()) {
4294+ processMatch(matcher, sb);
4295+ }
4296+ matcher.appendTail(sb);
4297+ writer.println(sb.toString());
4298+ } else {
4299+ writer.println(line);
4300+ writer.flush();
4301+ }
4302+ }
4303+
4304+ private void processMatch(final Matcher matcher, final StringBuffer sb) {
4305+ String className = matcher.group(2);
4306+ String methodName = matcher.group(3);
4307+
4308+ String replacement;
4309+ if (methodName == null) {
4310+ String url = index.getClassMap().get(className);
4311+ if (url == null || url.isEmpty()) {
4312+ replacement = "<<<Missing class: " + className + ">>>";
4313+ } else {
4314+ replacement = "`" + className + " <" + url + ">`_";
4315+ }
4316+ } else {
4317+ String from = className + "#" + methodName.split("\\(")[0];
4318+ final SortedMap<String, String> map = index.getMethodMap().tailMap(from);
4319+ String url;
4320+ if (map.isEmpty()) {
4321+ replacement = "<<<Missing method: " + methodName + ">>>";
4322+ } else {
4323+ final String first = map.firstKey();
4324+ url = map.get(first);
4325+ url = url.replace(" ", "%20");
4326+ String text = first.split("#")[1];
4327+ text = text.replace("com.persistit.encoding.", "");
4328+ text = text.replace("com.persistit.exception.", "");
4329+ text = text.replace("com.persistit.logging.", "");
4330+ text = text.replace("com.persistit.mxbeans.", "");
4331+ text = text.replace("com.persistit.ref.", "");
4332+ text = text.replace("com.persistit.ui.", "");
4333+ text = text.replace("com.persistit.", "");
4334+ text = text.replace("java.lang.", "");
4335+ text = text.replace("java.util.", "");
4336+ replacement= "`" + text + " <" + url + ">`_";
4337+ }
4338+ }
4339+
4340+ matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
4341+ }
4342+
4343+ public static void main(final String[] args) throws Exception {
4344+ new SphinxDocPrep().prepare(args);
4345+ }
4346+}
4347
4348=== added file 'doc/conf.py'
4349--- doc/conf.py 1970-01-01 00:00:00 +0000
4350+++ doc/conf.py 2012-05-30 18:23:19 +0000
4351@@ -0,0 +1,285 @@
4352+# -*- coding: utf-8 -*-
4353+#
4354+# PersistitDoc documentation build configuration file, created by
4355+# sphinx-quickstart on Fri May 18 15:19:04 2012.
4356+#
4357+# This file is execfile()d with the current directory set to its containing dir.
4358+#
4359+# Note that not all possible configuration values are present in this
4360+# autogenerated file.
4361+#
4362+# All configuration values have a default; values that are commented out
4363+# serve to show the default.
4364+
4365+import sys, os
4366+
4367+# If extensions (or modules to document with autodoc) are in another directory,
4368+# add these directories to sys.path here. If the directory is relative to the
4369+# documentation root, use os.path.abspath to make it absolute, like shown here.
4370+#sys.path.insert(0, os.path.abspath('.'))
4371+
4372+# -- General configuration -----------------------------------------------------
4373+
4374+# If your documentation needs a minimal Sphinx version, state it here.
4375+#needs_sphinx = '1.0'
4376+
4377+# Add any Sphinx extension module names here, as strings. They can be extensions
4378+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
4379+extensions = ['sphinx.ext.todo']
4380+
4381+# Add any paths that contain templates here, relative to this directory.
4382+templates_path = ['_templates']
4383+
4384+# The suffix of source filenames.
4385+source_suffix = '.rst'
4386+
4387+# The encoding of source files.
4388+#source_encoding = 'utf-8-sig'
4389+
4390+# The master toctree document.
4391+master_doc = 'index'
4392+
4393+# General information about the project.
4394+project = u'PersistitDoc'
4395+copyright = u'2012, Akiban Technologies'
4396+
4397+# The version info for the project you're documenting, acts as replacement for
4398+# |version| and |release|, also used in various other places throughout the
4399+# built documents.
4400+#
4401+# The short X.Y version.
4402+version = '1'
4403+# The full version, including alpha/beta/rc tags.
4404+release = '1'
4405+
4406+# The language for content autogenerated by Sphinx. Refer to documentation
4407+# for a list of supported languages.
4408+#language = None
4409+
4410+# There are two options for replacing |today|: either, you set today to some
4411+# non-false value, then it is used:
4412+#today = ''
4413+# Else, today_fmt is used as the format for a strftime call.
4414+#today_fmt = '%B %d, %Y'
4415+
4416+# List of patterns, relative to source directory, that match files and
4417+# directories to ignore when looking for source files.
4418+exclude_patterns = []
4419+
4420+# The reST default role (used for this markup: `text`) to use for all documents.
4421+#default_role = None
4422+
4423+# If true, '()' will be appended to :func: etc. cross-reference text.
4424+#add_function_parentheses = True
4425+
4426+# If true, the current module name will be prepended to all description
4427+# unit titles (such as .. function::).
4428+#add_module_names = True
4429+
4430+# If true, sectionauthor and moduleauthor directives will be shown in the
4431+# output. They are ignored by default.
4432+#show_authors = False
4433+
4434+# The name of the Pygments (syntax highlighting) style to use.
4435+pygments_style = 'sphinx'
4436+
4437+# A list of ignored prefixes for module index sorting.
4438+#modindex_common_prefix = []
4439+
4440+
4441+# -- Options for HTML output ---------------------------------------------------
4442+
4443+# The theme to use for HTML and HTML Help pages. See the documentation for
4444+# a list of builtin themes.
4445+html_theme = 'default'
4446+
4447+# Theme options are theme-specific and customize the look and feel of a theme
4448+# further. For a list of options available for each theme, see the
4449+# documentation.
4450+#html_theme_options = {}
4451+
4452+# Add any paths that contain custom themes here, relative to this directory.
4453+#html_theme_path = []
4454+
4455+# The name for this set of Sphinx documents. If None, it defaults to
4456+# "<project> v<release> documentation".
4457+#html_title = None
4458+
4459+# A shorter title for the navigation bar. Default is the same as html_title.
4460+#html_short_title = None
4461+
4462+# The name of an image file (relative to this directory) to place at the top
4463+# of the sidebar.
4464+#html_logo = None
4465+
4466+# The name of an image file (within the static path) to use as favicon of the
4467+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
4468+# pixels large.
4469+#html_favicon = None
4470+
4471+# Add any paths that contain custom static files (such as style sheets) here,
4472+# relative to this directory. They are copied after the builtin static files,
4473+# so a file named "default.css" will overwrite the builtin "default.css".
4474+html_static_path = ['_static']
4475+
4476+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
4477+# using the given strftime format.
4478+#html_last_updated_fmt = '%b %d, %Y'
4479+
4480+# If true, SmartyPants will be used to convert quotes and dashes to
4481+# typographically correct entities.
4482+#html_use_smartypants = True
4483+
4484+# Custom sidebar templates, maps document names to template names.
4485+#html_sidebars = {}
4486+
4487+# Additional templates that should be rendered to pages, maps page names to
4488+# template names.
4489+#html_additional_pages = {}
4490+
4491+# If false, no module index is generated.
4492+#html_domain_indices = True
4493+
4494+# If false, no index is generated.
4495+#html_use_index = True
4496+
4497+# If true, the index is split into individual pages for each letter.
4498+#html_split_index = False
4499+
4500+# If true, links to the reST sources are added to the pages.
4501+#html_show_sourcelink = True
4502+
4503+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
4504+#html_show_sphinx = True
4505+
4506+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
4507+#html_show_copyright = True
4508+
4509+# If true, an OpenSearch description file will be output, and all pages will
4510+# contain a <link> tag referring to it. The value of this option must be the
4511+# base URL from which the finished HTML is served.
4512+#html_use_opensearch = ''
4513+
4514+# This is the file name suffix for HTML files (e.g. ".xhtml").
4515+#html_file_suffix = None
4516+
4517+# Output file base name for HTML help builder.
4518+htmlhelp_basename = 'PersistitDocdoc'
4519+
4520+
4521+# -- Options for LaTeX output --------------------------------------------------
4522+
4523+latex_elements = {
4524+# The paper size ('letterpaper' or 'a4paper').
4525+#'papersize': 'letterpaper',
4526+
4527+# The font size ('10pt', '11pt' or '12pt').
4528+#'pointsize': '10pt',
4529+
4530+# Additional stuff for the LaTeX preamble.
4531+#'preamble': '',
4532+}
4533+
4534+# Grouping the document tree into LaTeX files. List of tuples
4535+# (source start file, target name, title, author, documentclass [howto/manual]).
4536+latex_documents = [
4537+ ('index', 'PersistitDoc.tex', u'PersistitDoc Documentation',
4538+ u'Akiban Technologies', 'manual'),
4539+]
4540+
4541+# The name of an image file (relative to this directory) to place at the top of
4542+# the title page.
4543+#latex_logo = None
4544+
4545+# For "manual" documents, if this is true, then toplevel headings are parts,
4546+# not chapters.
4547+#latex_use_parts = False
4548+
4549+# If true, show page references after internal links.
4550+#latex_show_pagerefs = False
4551+
4552+# If true, show URL addresses after external links.
4553+#latex_show_urls = False
4554+
4555+# Documents to append as an appendix to all manuals.
4556+#latex_appendices = []
4557+
4558+# If false, no module index is generated.
4559+#latex_domain_indices = True
4560+
4561+
4562+# -- Options for manual page output --------------------------------------------
4563+
4564+# One entry per manual page. List of tuples
4565+# (source start file, name, description, authors, manual section).
4566+man_pages = [
4567+ ('index', 'persistitdoc', u'PersistitDoc Documentation',
4568+ [u'Akiban Technologies'], 1)
4569+]
4570+
4571+# If true, show URL addresses after external links.
4572+#man_show_urls = False
4573+
4574+
4575+# -- Options for Texinfo output ------------------------------------------------
4576+
4577+# Grouping the document tree into Texinfo files. List of tuples
4578+# (source start file, target name, title, author,
4579+# dir menu entry, description, category)
4580+texinfo_documents = [
4581+ ('index', 'PersistitDoc', u'PersistitDoc Documentation',
4582+ u'Akiban Technologies', 'PersistitDoc', 'One line description of project.',
4583+ 'Miscellaneous'),
4584+]
4585+
4586+# Documents to append as an appendix to all manuals.
4587+#texinfo_appendices = []
4588+
4589+# If false, no module index is generated.
4590+#texinfo_domain_indices = True
4591+
4592+# How to display URL addresses: 'footnote', 'no', or 'inline'.
4593+#texinfo_show_urls = 'footnote'
4594+
4595+
4596+# -- Options for Epub output ---------------------------------------------------
4597+
4598+# Bibliographic Dublin Core info.
4599+epub_title = u'PersistitDoc'
4600+epub_author = u'Akiban Technologies'
4601+epub_publisher = u'Akiban Technologies'
4602+epub_copyright = u'2012, Akiban Technologies'
4603+
4604+# The language of the text. It defaults to the language option
4605+# or en if the language is not set.
4606+#epub_language = ''
4607+
4608+# The scheme of the identifier. Typical schemes are ISBN or URL.
4609+#epub_scheme = ''
4610+
4611+# The unique identifier of the text. This can be a ISBN number
4612+# or the project homepage.
4613+#epub_identifier = ''
4614+
4615+# A unique identification for the text.
4616+#epub_uid = ''
4617+
4618+# A tuple containing the cover image and cover page html template filenames.
4619+#epub_cover = ()
4620+
4621+# HTML files that should be inserted before the pages created by sphinx.
4622+# The format is a list of tuples containing the path and title.
4623+#epub_pre_files = []
4624+
4625+# HTML files shat should be inserted after the pages created by sphinx.
4626+# The format is a list of tuples containing the path and title.
4627+#epub_post_files = []
4628+
4629+# A list of files that should not be packed into the epub file.
4630+#epub_exclude_files = []
4631+
4632+# The depth of the table of contents in toc.ncx.
4633+#epub_tocdepth = 3
4634+
4635+# Allow duplicate toc entries.
4636+#epub_tocdup = True
4637
4638=== added file 'doc/index.rst'
4639--- doc/index.rst 1970-01-01 00:00:00 +0000
4640+++ doc/index.rst 2012-05-30 18:23:19 +0000
4641@@ -0,0 +1,15 @@
4642+Akiban Persistit User Guide
4643+===========================
4644+.. toctree::
4645+ :maxdepth: 1
4646+
4647+ GettingStarted
4648+ BasicAPI
4649+ Transactions
4650+ PhysicalStorage
4651+ Configuration
4652+ Management
4653+ Security
4654+ Serialization
4655+ Miscellaneous
4656+
4657
4658=== removed file 'doc/overview-summary.txt'
4659--- doc/overview-summary.txt 2011-04-26 02:10:48 +0000
4660+++ doc/overview-summary.txt 1970-01-01 00:00:00 +0000
4661@@ -1,107 +0,0 @@
4662-
4663-Persistit 2.2
4664-=============
4665-
4666-Persistit(TM) is a small, lightweight Java(TM) library that provides simple, fast and reliable data persistence for Java applications. It is designed to be embedded in Java application programs and to operate free of administration by the end-user.
4667-
4668-This section provides a brief overview. See http://com.akiban.com/persistit/documentation/ for complete documentation.
4669-
4670-== API Overview
4671-
4672-Persistit stores data as key-value pairs in highly optimized B-Tree structures. Much like a Java Map implementation, Persistit associates at most one value with each unique instance of a key.
4673-
4674-Persistit provides interfaces to access and modify keys and their associated values. The developer writes code to construct key and value instances and to store, fetch, traverse and remove keys and records to and from the database. Persistit permits efficient multi-threaded concurrent access to database volumes. It is designed to minimize contention for critical resources and to maximize throughput on multi-processor machines.
4675-
4676-In addition to low-level access methods on keys and values, Persistit provides com.persistit.PersistitMap, which implements the java.util.SortedMap interface. PersistitMap uses the Persistit database as a backing store so that key/value pairs are persistent, potentially shared with all threads, and limited in number only by disk storage. (See PersistitMap.)
4677-
4678-Within Persistit, key values are _segmented_ and _ordered_. Segmented means that you can append multiple primitive values or Strings to construct a concatenated key. Ordered means that the methods that enumerate key values within a Persistit database do so in a specified natural order. (See Keys).
4679-
4680-A Persistit value may be any primitive value, any Serializable Java object, or an object of any class supported by a custom serialization helper class. When stored in the B-Tree, keys and values are represented by sequences of bytes. The byte sequence that represents a value may be of arbitrary length, bounded only by available heap memory. (See Values.)
4681-
4682-=== Access Methods
4683-
4684-The primary low-level interface for interacting with Persistit is +com.persistit.Exchange+. The Exchange class provides all methods for storing, deleting, fetching and traversing key/value pairs. These methods are summarized here and described in detail in the API documentation.
4685-
4686-Although the underlying Persistit database is designed for highly concurrent multi-threaded operation, the Exchange object itself is not thread-safe. Each thread should create and use its own Exchange object(s) when accessing the database.
4687-
4688-To create an Exchange you provide a Volume name (or alias) and a tree name in its constructor. The constructor will optionally create a new tree in that Volume if a tree having the specified name is not found. An application may construct an arbitrary number of Exchange objects. Creating a new Exchange has no effect on the database if the specified tree already exists. Tree creation is thread-safe: multiple threads concurrently constructing Exchanges using the same Tree name will safely result in the creation of only one new tree.
4689-
4690-An Exchange is a moderately complex object that requires several thousand bytes of heap space. Memory-constrained applications should construct Exchanges in moderate numbers. An Exchange internally maintains some optimization information such that references to nearby Keys within a tree are accelerated. Performance may benefit from using a different Exchange for each area of the Tree being accessed.
4691-
4692-Persistit offers Exchange pooling to avoid rapidly creating and destroying Exchange objects in multi-threaded applications. In particular, web applications may benefit from using the Exchange pool.
4693-
4694-An Exchange is always associated with a com.persistit.Key and a com.persistit.Value. Typically you work with an Exchange in one of the following patterns:
4695-. Modify the Key, perform a +fetch+ operation, and extract the Value.
4696-. Modify the Key, modify the Value, and then perform a +store+ operation.
4697-. Modify the Key, and then perform a +remove+ operation.
4698-. Optionally modify the Key, perform a +traverse+ operation, then read the resulting Key and/or Value.
4699-
4700-These four methods, plus a few other methods listed here, are the primary low-level interface to the database. Semantics are as follows:
4701-
4702-[horizontal]
4703-+fetch+:: Reads the stored value associated with this Exchange's Key and modifies the Exchange’s Value to reflect that value.
4704-+store+:: Inserts or replaces the key/value pair for the specified key in the Tree either by replacing the former value, if there was one, or inserting a new value.
4705-+fetchAndStore+:: Fetches and then replaces the stored value. Upon completion, Value reflects the formerly stored value for the current Key. This operation is atomic, as opposed to sequential calls to fetch and store.
4706-+remove+, +removeAll+, +removeKeyRange+:: Removes key/value pairs from the Tree. Versions of this method specify either a single key or a range of keys to be removed.
4707-+fetchAndRemove+:: Fetches and then removes the stored value. Upon completion, Value reflects the formerly stored value for the current Key. This operation is atomic, as opposed to sequential calls to fetch and remove.
4708-+traverse+, +next+, +previous+:: Modifies the Exchange’s Key and Value to reflect a successor or predecessor key within the tree. (See API documentation for com.persistit.Key for information on the order of traversal.)
4709-+incrementValue+:: Atomically increments or decrements a long (64-bit integer) value associated with the current Key, and returns the modified value. If there is currently no value associated with the key then incrementValue creates one and assigns an initial value to it. This operation provides a convenient way for concurrent threads to safely allocate unique long integers without an explicit transaction scope.
4710-+hasNext+, +hasPrevious+:: Indicates, without modifying the Exchange’s Value or Key objects, whether there is a successor or predecessor key in the Tree.
4711-+getChangeCount+:: Number of times the Tree for this Exchange has changed. This count may be used as a reliable indicator of whether the Tree has changed since some earlier instant in time. For example, it is used to detect concurrent modifications by PersistitMap.
4712-
4713-Because Persistit permits concurrent operations by multiple threads, there is no guarantee that the underlying database will remain unchanged after any of these operations is completed. However, each of these methods operates atomically. That is, the inputs and outputs of each method are consistent with some valid state of the underlying Persistit backing store at some instant in time. The Value and Key objects for the Exchange represent that consistent state even if some other thread subsequently modifies the underlying database.
4714-
4715-=== PersistitMap
4716-
4717-Persistit provides an implementation of the java.util.SortedMap interface called com.persistit.PersistitMap. PersistitMap uses Persistit as its backing store, permitting large maps to be stored efficiently on disk using constant heap memory space.
4718-
4719-Keys for PersistitMap must conform to the constraints described above under Keys. Values must conform to the constraints described for Values.
4720-
4721-The constructor for PersistitMap takes an Exchange as its sole parameter. All key/value pairs of the Map are stored within the tree identified by this Exchange. The Key supplied by the Exchange becomes the root of a logical tree. For example:
4722-
4723-[source,java]
4724-----
4725-Exchange ex = new Exchange("myVolume", "myTree", true);
4726-ex.append("USA").append("MA");
4727-PersistitMap<String, String> map = new PersistitMap<String, String>(ex);
4728-map.put("Boston", "Hub");
4729-----
4730-
4731-places a key/value pair into the myTree with the concatenated key +{"USA ","MA","Boston"}+ and a value of +"Hub"+.
4732-
4733-Because Persistit is designed for concurrent operation it is possible (and often intended) for the backing store of PersistitMap to be changed by other threads while a java.util.Iterator is in use. Generally the expected behavior for an Iterator on a Map collection view is to throw a ConcurrentModificationException if the underlying collection changes. This is known as fail-fast behavior. PersistitMap implements this behavior by throwing a ConcurrentModificationException in the event the Tree containing the map changes. An application can detect that the map may have changed due to a programming error in case the design contract calls for it to remain unchanged by catching this exception.
4734-
4735-However, sometimes it may be desirable to use PersistitMap and its collections view interfaces to iterate across changing data. Internally, Persistit uses the traverse method to retrieve the next highest key in the key sort order in order to implement the Iterator’s hasNext and next methods. The result will depend on the content of the database at the instant these operations are performed. PersistitMap provides the method setAllowConcurrentModification to enable this behavior. By default, concurrent modifications are not allowed.
4736-=== KeyFilter
4737-
4738-A +com.persistit.KeyFilter+ defines a subset of all possible key values. You can supply a KeyFilter to the traverse methods of an Exchange. You can also specify a KeyFilter for any Iterator returned by the collection views of a PersistitMap. In either case, the key/value pairs covered by traversing the database or iterating over the collection view are restricted to those selected by the KeyFilter.
4739-
4740-Use of a KeyFilter is illustrated by the following code fragment:
4741-
4742-[source,java]
4743-----
4744-Exchange ex = new Exchange("myVolume", "myTree", true);
4745-KeyFilter kf = new KeyFilter("{\"Bellini\":\"Busoni\"}");
4746-ex.append(Key.BEFORE);
4747-while (ex.next(kf))
4748-{
4749- System.out.println(ex.getKey().reset().decodeString());
4750-}
4751-----
4752-
4753-This simple example emits the string-valued keys within myTree whose values fall alphabetically between “Bellini” and “Busoni”, inclusive.
4754-
4755-
4756-== Transactions
4757-
4758-Persistit supports transactions with full isolation and optimistic concurrency control. An application may begin, commit or roll back the current transaction scope explicitly, executing multiple database operations in an atomic, consistent, isolated and (optionally) durable (ACID) manner. If the application does not explicitly define the scope of a transaction, each database operation implicitly runs within the scope of a separate transaction. Each Persistit transaction may optionally be committed to either memory or disk. Transactions committed to memory are much faster, but are not immediately durable. (See Transactions.)
4759-
4760-== Configuration
4761-
4762-To initialize Persistit the embedding application invokes one of the initialize methods of +com.persistit.Persistit+, passing either a +java.util.Properties+ object or the name of a properties file from which the Properties object derives its content. The following properties are defined for Persistit. Other properties may also reside in the Properties object or its backing file; Persistit simply ignores any property not listed here.
4763-
4764-== Logging API
4765-
4766-Persistit is writes various diagnostic and informational messages to a log. By default, the log is written as text to the file +persistit.log+ in the current working directory. However, a container application will usually have a logging architecture already in place, and Persistit provides a simple way to redirect its log output to the container application’s log. Adapters for Log4J and the Java Logging API are included; other logging systems are easy to adapt.
4767-
4768-

Subscribers

People subscribed via source and target branches