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
=== added file 'doc/BasicAPI.rst'
--- doc/BasicAPI.rst 1970-01-01 00:00:00 +0000
+++ doc/BasicAPI.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,332 @@
1.. _Basic-API:
2
3Basic API
4=========
5
6Akiban 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.
7
8Persistit 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.
9
10Persistit 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).
11
12The Persistit Instance
13----------------------
14
15To 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:
16
17.. code-block:: java
18
19 final Persistit db = new Persistit();
20 //
21 // register any Coder and Renderer instances before initialization
22 //
23 db.initialize(configProperties);
24 try {
25 // do application work
26 } finally {
27 db.close();
28 }
29
30The ``configProperties`` describe the memory allocation, initial set of volumes, the journal, and other settings needed to get Persistit started. See :ref:`Configuration` for details.
31
32The ``com.persistit.Persistit#close`` method gracefully flushes all modified data to disk, stops background threads and unregisters JMX MBeans.
33
34.. note::
35
36 The Persistit background threads are not daemon threads, so if your application returns
37 from its static main method without calling ``close``, the JVM will not automatically exit.
38
39Although 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`.
40
41.. _Key:
42
43Key
44---
45
46The 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*.
47
48The following value types are implicitly supported in keys::
49
50 null
51 boolean (and Boolean)
52 byte (and Byte)
53 short (and Short)
54 char (and Character)
55 int (and Integer)
56 long (and Long)
57 float (and Float)
58 double (and Double)
59 java.lang.String
60 java.math.BigInteger
61 java.math.BigDecimal
62 java.util.Date
63 byte[]
64
65In 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.
66
67Appending and Decoding Key Segments
68^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
69
70The ``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
71
72.. code-block:: java
73
74 public void append(long v)
75 public void to(long v)
76 public long decodeLong()
77
78The ``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``).
79
80For example:
81
82.. code-block:: java
83
84 key.clear(); // clear any previous key segments
85 key.append("Atlantic"); // append segment "Atlantic"
86 key.to("Pacific"); // replace "Atlantic" with "Pacific"
87 key.reset(); // reset index to beginning
88 String s = key.decode(); // s contains "Pacific"
89
90The 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.
91
92.. code-block:: java
93
94 key.clear(); // clear any previous key segments
95 key.append(new Integer(1234));
96 key.append("Atlantic");
97 key.append(1.23d);
98 key.reset(); // reset index to beginning for decoding
99 int v = key.decodeInt(); // v will be 1234
100 String s = (String)key.decode(); // s will be "Atlantic"
101 Double d = (Double)decode(); // d will be 1.23d as a Double
102
103In 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.
104
105The maximum size of a serialized ``Key`` is 2,047 bytes.
106
107For further information, see ``com.persistit.Key``.
108
109
110.. _Value:
111
112Value
113-----
114
115A ``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.
116
117The 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.
118
119For example, in ``HelloWorld.java``, the line
120
121.. code-block:: java
122
123 dbex.getValue().put("World");
124
125serializes the String “World”, and the expression
126
127.. code-block:: java
128
129 dbex.getValue().get()
130
131decodes 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.
132
133Value Types
134^^^^^^^^^^^
135
136``Value`` provides optimized predefined representations for the following types::
137
138 null
139 all primitive types
140 all arrays
141 java.math.BigInteger
142 java.math.BigDecimal
143 java.lang.String
144 java.util.Date
145
146In general, Persistit uses one of four mechanisms to encode a Java value into a Value object:
147
148- If the value is one of the predefined types listed above, Persistit uses its own internal serialization logic.
149- If there is a registered ``com.persistit.encoding.ValueCoder`` for the object's class, Persistit delegates to it.
150- If enabled, Persistit uses an accelerated serialization/deserialization mechanism to encode and decode objects.
151- Otherwise, for classes that implement java.io.Serializable, Persistit attempts to perform default Java serialization and deserialization.
152
153A 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.
154
155See :ref:`Serialization` for additional information.
156
157Large Values
158^^^^^^^^^^^^
159
160Persistit 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.
161
162The 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.
163
164On 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.
165
166.. _Exchange:
167
168Exchange
169--------
170
171The 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.
172
173An Exchange instance contains references to a ``Key`` and a ``Value``. The methods ``com.persistit.Exchange.getKey()`` and ``com.persistit.Exchange.getValue()`` access these instances.
174
175To 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.
176
177An 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.
178
179Persistit 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.
180
181An 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.
182
183Concurrent Operations on Exchanges
184^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
185
186Although 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.
187
188Because 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.
189
190Exchange API
191^^^^^^^^^^^^
192
193An 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:
194
195- Modify the Key, perform a ``fetch`` operation, and extract the Value.
196- Modify the Key, modify the Value, and then perform a ``store`` operation.
197- Modify the Key, and then perform a ``remove`` operation.
198- Optionally modify the Key, perform a ``traverse`` operation, then read the resulting Key and/or Value.
199
200These four methods, plus a few other methods listed here, are the primary low-level interface to the database. Semantics are as follows:
201
202``fetch``
203 Reads the stored value associated with this Exchange's Key and modifies the Exchange’s Value to reflect that value.
204``store``
205 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.
206``fetchAndStore``
207 Reads and then replaces the stored value. Upon completion, Value reflects the formerly stored value for the current Key. This operation is atomic.
208``remove``, ``removeAll``, ``removeKeyRange``
209 Removes key/value pairs from the Tree. Versions of this method specify either a single key or a range of keys to be removed.
210``fetchAndRemove``
211 Fetches and then removes the stored value. Upon completion, Value reflects the formerly stored value for the current Key. This operation is atomic.
212``traverse``, ``next``, ``previous``
213 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.
214``hasNext``, ``hasPrevious``
215 Indicates, without modifying the Exchange’s Value or Key objects, whether there is a successor or predecessor key in the Tree.
216``hasChildren``
217 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*.
218
219For 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 :
220
221.. code-block:: java
222
223 public Exchange append(long v)
224 public Exchange append(String v)
225 ...
226
227To allow code call-chaining these methods of Exchange return the same Exchange. For example, it is valid to write code such as
228
229.. code-block:: java
230
231 exchange.clear().append(" Pacific").append("Ocean").append(123).fetch();
232
233This example fetches the value associated with the concatenated key
234``{“Pacific”, ”Ocean”, 123}``.
235
236Exchange also delegates other key manipulation methods. (See ``com.persistit.Exchange`` for detailed API documentation.)
237
238Traversing and Querying Collections of Data
239-------------------------------------------
240
241An 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.
242
243For example, this code from ``HelloWorld.java`` prints out the key and value of each record in a tree:
244
245.. code-block:: java
246
247 dbex.getKey().to(Key.BEFORE);
248 while (dbex.next())
249 {
250 System.out.println(
251 dbex.getKey().indexTo(0).decode() + " " +
252 dbex.getValue().get());
253 }
254
255In 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.
256
257You 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.
258
259.. _KeyFilter:
260
261Selecting key values with a KeyFilter
262^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
263
264A ``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.
265
266You 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.
267
268Use of a KeyFilter is illustrated by the following code fragment:
269
270.. code-block:: java
271
272 Exchange ex = new Exchange("myVolume", "myTree", true);
273 KeyFilter kf = new KeyFilter("{\"Bellini\":\"Britten\"}");
274 ex.append(Key.BEFORE);
275 while (ex.next(kf)){
276 System.out.println(ex.getKey().reset().decodeString());
277 }
278
279This simple example emits the string-valued keys within Tree “myTree” whose values fall alphabetically between “Bellini” and “Britten”, inclusive.
280
281
282You will find an example with a KeyFilter in the examples/FindFileDemo directory.
283
284.. _PersistitMap:
285
286PersistitMap
287------------
288
289In 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.
290
291Keys and Values for PersistitMap must conform to the constraints described above under :ref:`Key` and :ref:`Value`.
292
293The 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:
294
295.. code-block:: java
296
297 Exchange ex = new Exchange("myVolume", "myTree", true);
298 ex.append("USA").append("MA");
299 PersistitMap<String, String> map = new PersistitMap<String, String>(ex);
300 map.put("Boston", "Hub");
301
302places a key/value pair into Tree “myTree” with the concatenated key ``{"USA ","MA","Boston"}`` and a value ``"Hub"``.
303
304Generally 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.
305
306However, 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.
307
308.. note:: When ``PersistitMap`` is used within a transaction updates generated by other concurrent transactions are not visible and
309 therefore cannot cause a ConcurrentModificationException. However, to avoid unpredictable results an Iterator created within the scope
310 of a transaction must be used only within that transaction.
311
312
313Exceptions in PersistitMap
314^^^^^^^^^^^^^^^^^^^^^^^^^^
315
316Persistit 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.
317
318Applying a KeyFilter to a PersistitMap Iterator
319^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
320
321You 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:
322
323.. code-block:: java
324
325 PersistitMap map = new PersistitMap(exchange);
326 PersistitMap.ExchangeIterator iterator =
327 (PersistitMap.ExchangeIterator)map.entrySet().iterator();
328 iterator.setFilterTerm(KeyFilter.rangeTerm("A", "M"));
329
330In this example, the iterator will only access String-valued keys between “A” and “M”.
331
332
0333
=== removed file 'doc/BasicAPI.txt'
--- doc/BasicAPI.txt 2012-04-30 22:09:31 +0000
+++ doc/BasicAPI.txt 1970-01-01 00:00:00 +0000
@@ -1,320 +0,0 @@
1[[BasicAPI]]
2= Basic API
3
4Akiban 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.
5
6Persistit 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.
7
8Persistit 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).
9
10== The Persistit Instance
11
12To 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:
13
14[source,java]
15----
16final Persistit db = new Persistit();
17//
18// register any Coder and Renderer instances before initialization
19//
20db.initialize(configProperties);
21try {
22 // do application work
23} finally {
24 db.close();
25}
26----
27
28The +configProperties+ describe the memory allocation, initial set of volumes, the journal, and other settings needed to get Persistit started. See <<Configuration>> for details.
29
30The +com.persistit.Persistit#close+ method gracefully flushes all modified data to disk, stops background threads and unregisters JMX MBeans.
31****
32The 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.
33****
34
35Although 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>>.
36
37[[Key]]
38== Key
39
40The 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_.
41
42The following value types are implicitly supported in keys:
43
44.Types Supported in +com.persistit.Key+
45----
46null
47boolean (and Boolean)
48byte (and Byte)
49short (and Short)
50char (and Character)
51int (and Integer)
52long (and Long)
53float (and Float)
54double (and Double)
55java.lang.String
56java.math.BigInteger
57java.math.BigDecimal
58java.util.Date
59byte[]
60----
61
62In 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.
63****
64TODO: Collation
65****
66
67=== Appending and Decoding Key Segments
68
69The +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
70
71[source,java]
72----
73public void append(long v)
74public void to(long v)
75public long decodeLong()
76----
77
78The +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+).
79
80For example:
81
82[source,java]
83----
84key.clear(); // clear any previous key segments
85key.append("Atlantic"); // append segment "Atlantic"
86key.to("Pacific"); // replace "Atlantic" with "Pacific"
87key.reset(); // reset index to beginning
88String s = key.decode(); // s contains "Pacific"
89----
90
91The 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.
92
93[source,java]
94----
95key.clear(); // clear any previous key segments
96key.append(new Integer(1234));
97key.append("Atlantic");
98key.append(1.23d);
99key.reset(); // reset index to beginning for decoding
100int v = key.decodeInt(); // v will be 1234
101String s = (String)key.decode(); // s will be "Atlantic"
102Double d = (Double)decode(); // d will be 1.23d as a Double
103----
104
105In 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.
106
107The maximum size of a serialized +Key+ is 2,047 bytes.
108
109For further information, see +com.persistit.Key+.
110
111
112[[Value]]
113== Value
114
115A +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.
116
117The 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.
118
119For example, in +HelloWorld.java+, the line
120
121[source,java]
122----
123dbex.getValue().put("World");
124----
125
126serializes the String “World”, and the expression
127
128[source,java]
129----
130dbex.getValue().get()
131----
132
133decodes 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.
134
135=== Value Types
136
137+Value+ provides optimized predefined representations for the following types:
138
139.Types Implicitly Supported by +com.persistit.Value+
140----
141null
142all primitive types
143all arrays
144java.math.BigInteger
145java.math.BigDecimal
146java.lang.String
147java.util.Date
148----
149In general, Persistit uses one of four mechanisms to encode a Java value into a Value object:
150
151- If the value is one of the predefined types listed above, Persistit uses its own internal serialization logic.
152- If there is a registered +com.persistit.encoding.ValueCoder+ for the object's class, Persistit delegates to it.
153- If enabled, Persistit uses an accelerated serialization/deserialization mechanism to encode and decode objects.
154- Otherwise, for classes that implement java.io.Serializable, Persistit attempts to perform default Java serialization and deserialization.
155
156A 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.
157
158See <<Serialization>> for additional information.
159
160=== Large Values
161
162Persistit 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.
163
164The 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.
165
166On 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.
167
168[[Exchange]]
169== Exchange
170
171The 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.
172
173An Exchange instance contains references to a +Key+ and a +Value+. The methods +com.persistit.Exchange.getKey()+ and +com.persistit.Exchange.getValue()+ access these instances.
174
175To 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.
176
177An 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.
178
179Persistit 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.
180
181An 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.
182
183=== Concurrent Operations on Exchanges
184
185Although 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.
186
187Because 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.
188
189=== Exchange API
190
191An 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:
192
193- Modify the Key, perform a +fetch+ operation, and extract the Value.
194- Modify the Key, modify the Value, and then perform a +store+ operation.
195- Modify the Key, and then perform a +remove+ operation.
196- Optionally modify the Key, perform a +traverse+ operation, then read the resulting Key and/or Value.
197
198These four methods, plus a few other methods listed here, are the primary low-level interface to the database. Semantics are as follows:
199
200[horizontal]
201+fetch+:: Reads the stored value associated with this Exchange's Key and modifies the Exchange’s Value to reflect that value.
202+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.
203+fetchAndStore+:: Reads and then replaces the stored value. Upon completion, Value reflects the formerly stored value for the current Key. This operation is atomic.
204+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.
205+fetchAndRemove+:: Fetches and then removes the stored value. Upon completion, Value reflects the formerly stored value for the current Key. This operation is atomic.
206+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.
207+hasNext+, +hasPrevious+:: Indicates, without modifying the Exchange’s Value or Key objects, whether there is a successor or predecessor key in the Tree.
208+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_.
209
210
211For 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 :
212
213[source,java]
214----
215public Exchange append(long v)
216public Exchange append(String v)
217...
218----
219To allow code call-chaining these methods of Exchange return the same Exchange. For example, it is valid to write code such as
220
221[source,java]
222----
223exchange.clear().append(" Pacific").append("Ocean").append(123).fetch();
224----
225
226This example fetches the value associated with the concatenated key
227+{“Pacific”, ”Ocean”, 123}+.
228
229Exchange also delegates other key manipulation methods. (See +com.persistit.Exchange+ for detailed API documentation.)
230
231=== Traversing and Querying Collections of Data
232
233An 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.
234
235For example, this code from +HelloWorld.java+ prints out the key and value of each record in a tree:
236
237[source,java]
238----
239 dbex.getKey().to(Key.BEFORE);
240 while (dbex.next())
241 {
242 System.out.println(
243 dbex.getKey().indexTo(0).decode() + " " +
244 dbex.getValue().get());
245 }
246----
247
248In 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.
249
250You 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.
251
252[[KeyFilter]]
253=== Selecting key values with a KeyFilter
254
255A +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.
256
257You 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.
258
259Use of a KeyFilter is illustrated by the following code fragment:
260
261[source,java]
262----
263Exchange ex = new Exchange("myVolume", "myTree", true);
264KeyFilter kf = new KeyFilter("{\"Bellini\":\"Britten\"}");
265ex.append(Key.BEFORE);
266while (ex.next(kf)){
267 System.out.println(ex.getKey().reset().decodeString());
268}
269----
270
271This simple example emits the string-valued keys within Tree “myTree” whose values fall alphabetically between “Bellini” and “Britten”, inclusive.
272
273
274You will find an example with a KeyFilter in the examples/FindFileDemo directory.
275
276[[PersistitMap]]
277=== PersistitMap
278
279In 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.
280
281Keys and Values for PersistitMap must conform to the constraints described above under <<Key>> and <<Value>>.
282
283The 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:
284
285[source,java]
286----
287Exchange ex = new Exchange("myVolume", "myTree", true);
288ex.append("USA").append("MA");
289PersistitMap<String, String> map = new PersistitMap<String, String>(ex);
290map.put("Boston", "Hub");
291----
292
293places a key/value pair into Tree “myTree” with the concatenated key +{"USA ","MA","Boston"}+ and a value +"Hub"+.
294
295Generally 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.
296
297However, 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.
298
299NOTE: 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.
300
301
302=== Exceptions in PersistitMap
303
304Persistit 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.
305
306=== Applying a KeyFilter to a PersistitMap Iterator
307
308You 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:
309
310[source,java]
311----
312 PersistitMap map = new PersistitMap(exchange);
313 PersistitMap.ExchangeIterator iterator =
314 (PersistitMap.ExchangeIterator)map.entrySet().iterator();
315 iterator.setFilterTerm(KeyFilter.rangeTerm("A", "M"));
316----
317
318In this example, the iterator will only access String-valued keys between “A” and “M”.
319
320
3210
=== added file 'doc/Configuration.rst'
--- doc/Configuration.rst 1970-01-01 00:00:00 +0000
+++ doc/Configuration.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,273 @@
1.. _Configuration:
2
3Configuration
4=============
5
6To 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.
7
8An application can define the configuration in one of two equivalent ways:
9
10- Create a ``com.persistit.Configuration`` instance and set its properties through methods such as ``com.persistit.Configuration#setJournalPath``.
11- Specify properties by name in a ``java.util.Properties`` instance and then pass the ``Properties`` to a ``Configuration`` constructor.
12
13The following code samples show different ways of using the ``com.persistit.Persistit#initialize`` method to configure and start Persistit:
14
15.. code-block:: java
16
17 final Persistit db = new Persistit();
18 final Properties p = new Properties();
19 p.setProperty("buffer.count.16384", "1000");
20 p.setProperty("journalpath", "/home/akiban/data/journal");
21 ...
22 db.initialize(p);
23
24.. code-block:: java
25
26 final Persistit db = new Persistit();
27 db.initialize("/home/akiban/my_config.properties");
28
29.. code-block:: java
30
31 final Persistit db = new Persistit();
32 final Configuration c = new Configuration();
33 c.getBufferPoolMap().get(16384).setCount(1000);
34 c.setJournalPath("/home/akiban/data/journal");
35 ...
36 db.initialize(c);
37
38There are three essential elements in a Persistit configuration:
39
40- Memory for the buffer pool(s)
41- Specifications for ``com.persistit.Volume`` instances
42- Journal file path
43
44Configuring the Buffer Pool
45---------------------------
46
47During 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.
48
49The 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.
50
51A ``BufferPoolConfiguration`` contains the following attributes:
52
53 ``minimumCount``
54 lower bound on the number of buffers. (Default is zero.)
55 ``maximumCount``
56 upper bound on the number of buffers. (Default is zero.)
57 ``minimumMemory``
58 lower bound on memory to allocate. (Default is zero bytes.)
59 ``maximumMemory``
60 upper bound on memory to allocate. (Default is Long.MAX_VALUE bytes.)
61 ``reservedMemory``
62 minimum number of bytes to reserve for use other than buffers. (Default is zero.)
63 ``fraction``
64 floating point value between 0.0f and 1.0f indicating how much of available memory too allocate. (Default is 1.0f.)
65
66Persistit uses the following algorithm to determine the number of buffers to allocate for each buffer size:
67
68.. code-block:: java
69
70 memoryToUse = fraction * (maxHeap - reservedMemory)
71 memoryToUse = min(memoryToUse, maximumMemory)
72 bufferCount = memoryToUse / bufferSizeWithOverhead
73 bufferCount = max(minimumCount, min(maximumCount, count))
74 if (bufferCount * bufferSize > maximumMemory) then FAIL
75 if ((bufferCount + 1) * bufferSize < minimumMemory) then FAIL
76 allocate bufferCount buffers
77
78In 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.
79
80Typically 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.
81
82The property named ``buffer.count.SSSS`` where ``SSSS`` is “1024”, “2048”, “4096”, “8192” or “16384” specifies an absolute count. For example,
83
84.. code-block:: java
85
86 buffer.count.8192 = 10000
87
88causes Persistit to allocate 10,000 buffers of size 8192.
89
90The property ``buffer.memory.SSSS`` specifies memory constraints as shown in this example
91
92.. code-block:: java
93
94 buffer.memory.8192 = 512K,20M,4M,0.6
95
96where 512K, 20M, 4M and 0.6 are the ``minimumMemory``, ``maximumMemory``, ``reservedMemory`` and ``fraction``, respectively.
97
98The MemoryMXBean supplies as its maximum heap size value the size given by the ``-Xmx`` JVM parameter.
99
100Heap Tuning
101-----------
102
103This section pertains to the Oracle HotSpot(tm) Java virtual machine.
104
105.. note::
106
107 Buffer instances are long-lived objects. To avoid severe garbage collector overhead it is important for all of them
108 to fit in the heap’s tenured generation. This issue becomes especially significant with multi-gigabyte heaps.
109
110By 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.
111
112You 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.
113
114See [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.
115
116Multiple Buffer Pools
117---------------------
118
119In 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.
120
121When specifying multiple memory constraints for multiple buffer pools, the ``fraction`` property applies to the available memory before any buffers are allocated. So, for example,
122
123.. code-block:: java
124
125 buffer.memory.2048=64M,512G,2G,.2
126 buffer.memory.16384=64M,512G,2G,.5
127
128results 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.
129
130Configuring Volumes
131-------------------
132
133Persistit 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.
134
135The ``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:
136
137``volume.N = path[,attrname[:attrvalue]]...``
138
139where ``N`` is an arbitrary integer, ``path`` is the path specification of the volume file, and ``attrnames`` include:
140
141- ``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.
142
143- ``create``: Persistit attempts to open an existing volume file with the specified *path*, or create a new one if the file does not exist.
144
145- ``createOnly``: Persistit throw a VolumeAlreadyExistsException if the file specified by path already exists. Otherwise it creates a new file with the specified path.
146
147- ``readOnly``: Opens a volume in read-only mode. An attempt to modify the volume results in a ReadOnlyVolumeException.
148
149- ``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.
150
151- ``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.
152
153- ``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.
154
155- ``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.
156
157For example::
158
159 volume.1=/home/akiban/ffdemo,create,pageSize:16K,\
160 initialSize:10M,extensionSize:10M,maximumSize:1G
161
162specifies 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.
163
164System Volume
165-------------
166
167One 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”.
168
169Alternatively, 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.
170
171Configuring the Journal Path
172----------------------------
173
174The :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::
175
176 journalpath=/ssd/data/my_app_journal
177
178The value specified can be either a
179
180- directory, in which case files named ``persistit_journal.NNNNNNNNNNNN`` will be created,
181- or a file name, in which case journal files will be created by appending the suffix ``.NNNNNNNNNNNN``.
182
183Recommendations for Physical Media
184----------------------------------
185
186The 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.
187
188Because 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.
189
190Other Configuration Parameters
191------------------------------
192
193The 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.
194
195 ``journalsize``: (``com.persistit.Configuration#setJournalSize``)
196 Journal file block size. Default is 1,000,000,000 bytes. A new Persistit rolls over to a new journal file when this
197 size is reached. Generally there is no reason to adjust this setting.
198
199 ``appendonly``: (``com.persistit.Configuration#setAppendOnly``), True or false (default).
200 When true, Persistit’s journal starts up in *append-only* mode in which modified pages are only written to the
201 journal and not copied to their home volumes. As a consequence, all existing journal files are preserved, and new
202 modifications are written only to newly created journal files. The append-only flag can also be enabled or disabled
203 by application code and through the JMX and RMI interfaces.
204
205 ``rmiport``: (``com.persistit.Configuration#setRmiPort``)
206 Specifies a port number on which Persistit will create a temporary Remote Method Invocation registry. If this
207 property is specified, Persistit creates a registry and registers a ``com.persistit.Management`` server on it. This
208 allows remote access to management facilities within Persistit and permits the Swing-based administrative utility to
209 attach to and manage a Persistit instance running on a headless server. The ``rmihost`` and ``rmiport`` properties
210 are mutually exclusive.
211
212 ``rmihost``: (``com.persistit.Configuration#setRmiHost``)
213 Specifies the URL of an Remote Method Invocation registry. If present, Persistit registers its a server for its
214 ``com.persistit.Management`` interface at the specified external registry. The ``rmihost`` and ``rmiport``
215 properties are mutually exclusive.
216
217 ``jmx``: (``com.persistit.Configuration#setJmxEnabled``), True or false (default).
218 Specifies whether Persistit registers MXBeans with the platform MBean server. Set this value to ``true`` to enable
219 access from ``jconsole`` and other management tools.
220
221 ``serialOverride``, ``constructorOverride``: (``com.persistit.Configuration#setSerialOverride`` ``com.persistit.Configuration#setConstructorOverride``)
222 Control aspects of object serialization. See :ref:`Serialization`.
223
224 ``showgui``: (``com.persistit.Configuration#setShowGUI``), True of False.
225 If true, Persistit attempts to create and display an instance of the AdminUI utility panel within the current JVM.
226 Alternatively, AdminUI uses RMI and can be launched and run remotely if ``rmiport`` or ``rmihost`` has been
227 specified.
228
229 ``logfile``: (``com.persistit.Configuration#setLogFile``)
230 Name of a log file to which Persistit’s default logger will write diagnostic log entries. Applications generally
231 install a logging adapter to reroute messages through Log4J, SLF4J or other logger. The ``logfile`` property is used
232 only when no adapter has been installed.
233
234For 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.
235
236A Configuration Example
237-----------------------
238
239Following is an example of a Persistit configuration properties file::
240
241 datapath = /var/opt/persistit/data
242 logpath = /var/log/persistit
243 logfile = ${logpath}/${timestamp}.log
244
245 buffer.count.16384 = 5000
246
247 volume.1 = ${datapath}/demo_data, create, pageSize:16K, \
248 initialSize:1M, extensionSize:1M, maximumSize:10G, alias:data
249
250 volume.2 = ${datapath}/demo_system, create, pageSize:16K, \
251 initialSize:100K, extensionSize:100K, maximumSize:1G
252
253 sysvolume = demo_system
254
255 journalpath = /ssd/persistit_journal
256
257With 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``.
258
259The ``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.
260
261Property Value Substitution
262---------------------------
263
264This 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.
265
266Incorporating Java System Properties
267------------------------------------
268
269You 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::
270
271 java -Dcom.persistit.buffer.count.8192=10K -jar MyJar
272
273This 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.
0274
=== removed file 'doc/Configuration.txt'
--- doc/Configuration.txt 2012-04-30 22:09:31 +0000
+++ doc/Configuration.txt 1970-01-01 00:00:00 +0000
@@ -1,246 +0,0 @@
1[[Configuration]]
2= Configuration
3
4To 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.
5
6An application can define the configuration in one of two equivalent ways:
7
8- Create a +com.persistit.Configuration+ instance and set its properties through methods such as +com.persistit.Configuration#setJournalPath+.
9- Specify properties by name in a +java.util.Properties+ instance and then pass the +Properties+ to a +Configuration+ constructor.
10
11The following code samples show different ways of using the +com.persistit.Persistit#initialize+ method to configure and start Persistit:
12
13[source,java]
14----
15final Persistit db = new Persistit();
16final Properties p = new Properties();
17p.setProperty("buffer.count.16384", "1000");
18p.setProperty("journalpath", "/home/akiban/data/journal");
19...
20db.initialize(p);
21----
22
23[source,java]
24----
25final Persistit db = new Persistit();
26db.initialize("/home/akiban/my_config.properties");
27----
28
29[source,java]
30----
31final Persistit db = new Persistit();
32final Configuration c = new Configuration();
33c.getBufferPoolMap().get(16384).setCount(1000);
34c.setJournalPath("/home/akiban/data/journal");
35...
36db.initialize(c);
37----
38
39There are three essential elements in a Persistit configuration:
40
41- Memory for the buffer pool(s)
42- Specifications for +com.persistit.Volume+ instances
43- Journal file path
44
45== Configuring the Buffer Pool
46
47During 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.
48
49The 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.
50
51A +BufferPoolConfiguration+ contains the following attributes:
52
53[horizontal]
54minimumCount:: lower bound on the number of buffers. (Default is zero.)
55maximumCount:: upper bound on the number of buffers. (Default is zero.)
56minimumMemory:: lower bound on memory to allocate. (Default is zero bytes.)
57maximumMemory:: upper bound on memory to allocate. (Default is Long.MAX_VALUE bytes.)
58reservedMemory:: minimum number of bytes to reserve for use other than buffers. (Default is zero.)
59fraction:: floating point value between 0.0f and 1.0f indicating how much of available memory too allocate. (Default is 1.0f.)
60
61Persistit uses the following algorithm to determine the number of buffers to allocate for each buffer size:
62
63[source,java]
64----
65memoryToUse = fraction * (maxHeap - reservedMemory)
66memoryToUse = min(memoryToUse, maximumMemory)
67bufferCount = memoryToUse / bufferSizeWithOverhead
68bufferCount = max(minimumCount, min(maximumCount, count))
69if (bufferCount * bufferSize > maximumMemory) then FAIL
70if ((bufferCount + 1) * bufferSize < minimumMemory) then FAIL
71allocate bufferCount buffers
72----
73
74In 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.
75
76Typically 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.
77
78The property named +buffer.count._SSSS_+ where _SSSS_ is “1024”, “2048”, “4096”, “8192” or “16384” specifies an absolute count. For example,
79
80----
81buffer.count.8192 = 10000
82----
83
84causes Persistit to allocate 10,000 buffers of size 8192.
85
86The property +buffer.memory._SSSS_+ specifies memory constraints as shown in this example
87
88----
89buffer.memory.8192 = 512K,20M,4M,0.6
90----
91
92where 512K, 20M, 4M and 0.6 are the +minimumMemory+, +maximumMemory+, +reservedMemory+ and +fraction+, respectively.
93
94The MemoryMXBean supplies as its maximum heap size value the size given by the +-Xmx+ JVM parameter.
95
96=== Heap Tuning
97
98This section pertains to the Oracle HotSpot(tm) Java virtual machine.
99
100****
101Buffer 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.
102****
103
104By 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.
105
106You 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.
107
108See [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.
109
110=== Multiple Buffer Pools
111
112In 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.
113
114When specifying multiple memory constraints for multiple buffer pools, the +fraction+ property applies to the available memory before any buffers are allocated. So, for example,
115
116
117----
118buffer.memory.2048=64M,512G,2G,.2
119buffer.memory.16384=64M,512G,2G,.5
120----
121
122results 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.
123
124== Configuring Volumes
125
126Persistit 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.
127
128The +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:
129
130+volume._N_ = _path_[,_attrname_[:_attrvalue_]]...+
131
132where _N_ is an arbitrary integer, _path_ is the path specification of the volume file, and _attrnames_ include:
133
134- +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.
135
136- +create+: Persistit attempts to open an existing volume file with the specified _path_, or create a new one if the file does not exist.
137
138- +createOnly+: Persistit throw a VolumeAlreadyExistsException if the file specified by path already exists. Otherwise it creates a new file with the specified path.
139
140- +readOnly+: Opens a volume in read-only mode. An attempt to modify the volume results in a ReadOnlyVolumeException.
141
142- +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.
143
144- +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.
145
146- +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.
147
148- +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.
149
150For example:
151
152----
153volume.1=/home/akiban/ffdemo,create,pageSize:16K,\
154 initialSize:10M,extensionSize:10M,maximumSize:1G
155----
156
157specifies 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.
158
159=== System Volume
160
161One 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”.
162
163Alternatively, 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.
164
165== Configuring the Journal Path
166
167The <<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
168
169----
170journalpath=/ssd/data/my_app_journal
171----
172
173The value specified can be either a
174
175- directory, in which case files named +persistit_journal._NNNNNNNNNNNN_+ will be created,
176
177- or a file name, in which case journal files will be created by appending the suffix +._NNNNNNNNNNNN_+.
178
179=== Recommendations for Physical Media
180
181The 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.
182
183Because 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.
184
185== Other Configuration Parameters
186
187The 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.
188
189[horizontal]
190+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.
191
192+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.
193
194+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.
195
196+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.
197
198+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.
199
200+serialOverride+, +constructorOverride+:: (+com.persistit.Configuration#setSerialOverride+ +com.persistit.Configuration#setConstructorOverride+) Control aspects of object serialization. See <<Serialization>>.
201
202+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.
203
204+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.
205
206For 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.
207
208== A Configuration Example
209
210Following is an example of a Persistit configuration properties file:
211
212----
213datapath = /var/opt/persistit/data
214logpath = /var/log/persistit
215logfile = ${logpath}/${timestamp}.log
216
217buffer.count.16384 = 5000
218
219volume.1 = ${datapath}/demo_data, create, pageSize:16K, \
220 initialSize:1M, extensionSize:1M, maximumSize:10G, alias:data
221
222volume.2 = ${datapath}/demo_system, create, pageSize:16K, \
223 initialSize:100K, extensionSize:100K, maximumSize:1G
224
225sysvolume = demo_system
226
227journalpath = /ssd/persistit_journal
228----
229
230With 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+.
231
232The +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.
233
234=== Property Value Substitution
235
236This 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.
237
238=== Incorporating Java System Properties
239
240You 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
241
242----
243java -Dcom.persistit.buffer.count.8192=10K -jar MyJar
244----
245
246This 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.
2470
=== added file 'doc/GettingStarted.rst'
--- doc/GettingStarted.rst 1970-01-01 00:00:00 +0000
+++ doc/GettingStarted.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,270 @@
1
2Getting Started with Akiban Persistit
3=====================================
4
5Welcome!
6
7We 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.
8
9Akiban Persistit is a key/value data storage library written in Java(TM). Key features include:
10
11- support for highly concurrent transaction processing with multi-version concurrency control
12- optimized serialization and deserialization mechanism for Java primitives and objects
13- multi-segment (compound) keys to enable a natural logical key hierarchy
14- support for long records (megabytes)
15- implementation of a persistent SortedMap
16- extensive management capability including command-line and GUI tools
17
18This 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.
19
20Download and Install
21--------------------
22
23Download ``akiban-persistit-3.xx.yy.zip`` from http://www.akiban.com/persistit/download.html.
24
25Unpack 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:
26.. code-block::
27
28 jar xvzf akiban-persistit-core-3.xx.yy.zip
29
30Review 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.
31
32Working with Persistit
33----------------------
34
35Add 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.
36
37That's it. You are ready to work with Persistit.
38
39Examples
40^^^^^^^^
41
42Review the ``examples`` directory. Here you will find functional examples of varying complexity.
43
44 ``examples/HelloWorld``
45 source code for the example illustrating this chapter
46 ``examples/SimpleDemo``
47 short, simple program similar to HelloWorld
48 ``examples/SimpleBench``
49   a small micro-benchmark measuring the speed of insert, traversal, random updates, etc.
50 ``examples/SimpleTransaction``
51 example demonstrating use of Persisit’s multi-version currency control (MVCC) transactions
52 ``examples/FindFile``
53 a somewhat larger example that uses Persistit as the backing store for file finder utility
54 ``example/PersistitMapDemo``
55 demonstration of the PersistitMap interface
56
57HelloWorld
58----------
59
60Before 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”.
61
62.. HelloWorld.java
63
64.. code-block:: java
65
66 import com.persistit.Exchange;
67 import com.persistit.Key;
68 import com.persistit.Persistit;
69
70 public class HelloWorld {
71 public static void main(String[] args) throws Exception {
72 Persistit db = new Persistit();
73 try {
74 // Read configuration from persistit.properties, allocate
75 // buffers, open Volume, and perform recovery processing
76 // if necessary.
77 //
78 db.initialize();
79 //
80 // Create an Exchange, which is a thread-private facade for
81 // accessing data in a Persistit Tree. This Exchange will
82 // access a Tree called "greetings" in a Volume called
83 // "hwdemo". It will create a new Tree by that name
84 // if one does not already exist.
85 //
86 Exchange dbex = db.getExchange("hwdemo", "greetings", true);
87 //
88 // Set up the Value field of the Exchange.
89 //
90 dbex.getValue().put("World");
91 //
92 // Set up the Key field of the Exchange.
93 //
94 dbex.getKey().append("Hello");
95 //
96 // Ask Persistit to put this key/value pair into the Tree.
97 // Until this point, the changes to the Exchange are local
98 // to this thread.
99 //
100 dbex.store();
101 //
102 // Prepare to traverse all the keys in the Tree (of which there
103 // is currently only one!) and for each key display its value.
104 //
105 dbex.getKey().to(Key.BEFORE);
106 while (dbex.next()) {
107 System.out.println(dbex.getKey().indexTo(0).decode() + " "
108 + dbex.getValue().get());
109 }
110 db.releaseExchange(dbex);
111 } finally {
112 // Always close Persistit. If the application does not do
113 // this, Persistit's background threads will keep the JVM from
114 // terminating.
115 //
116 db.close();
117 }
118 }
119 }
120
121Concepts
122--------
123
124Although ``HelloWorld.java`` is not very useful, it demonstrates several of the basic building blocks of the Persistit API.
125
126Initialization and Configuration
127^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
128
129Before 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``.
130
131In this example, ``persistit.properties`` looks like this::
132
133 datapath=.
134 buffer.count.8192=32
135 volume.1=${datapath}/hwdemo,create,pageSize:8192,\
136 initialPages:5,extensionPages:5,maximumPages:100000
137 journalpath=${datapath}/hwdemo_journal
138
139See :ref:`Configuration` for additional information about Persistit configuration properties.
140
141Volumes and Trees
142^^^^^^^^^^^^^^^^^
143
144A 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.
145
146Each 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.
147
148``HelloWorld.java`` stores its key/value pair in a tree called “greetings” in a volume named “hwdemo”. This is specified by constructing an Exchange.
149
150Exchanges
151---------
152
153The ``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.
154
155The method
156
157.. code-block:: java
158
159 Exchange dbex = db.getExchange("hwdemo", "greetings", true);
160
161in ``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.
162
163Methods ``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.
164
165The 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``.
166
167Each 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:
168
169- Modify the Key, modify the Value and then perform a ``com.persistit.Exchange#store`` operation.
170- Modify the Key, perform a ``com.persistit.Exchange#fetch`` operation and then read the Value.
171- Modify the Key and then perform a ``com.persistit.Exchange#remove`` operation.
172- 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.
173
174These methods and their variants provide the foundation for using Persistit.
175
176Records
177^^^^^^^
178
179In Persistit, a database record consists of a Key and a Value. The terms “record” and “key/value pair” are used interchangeably.
180
181When 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.
182
183Keys
184^^^^
185
186A 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.
187
188Key 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.
189
190The ``HelloWorld.java`` example appends “Hello” to the Exchange’s Key object in this line:
191
192.. code-block:: java
193
194 dbex.getKey().append("Hello");
195
196The result is a key with a single key segment.
197
198Values
199^^^^^^
200
201A 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.
202
203Value 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.
204
205Numerous methods allow you to serialize and deserialize primitives values and objects into and from a Value object. For example, in ``HelloWorld.java``, the statement
206
207.. code-block:: java
208
209 dbex.getValue().put("World");
210
211serializes the string “World” into the backing byte array of the Exchange’s Value object and
212
213.. code-block:: java
214
215 System.out.println(
216 dbex.getKey().indexTo(0).decode() + " " +
217 dbex.getValue().get());
218
219deserializes 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.
220
221Storing and Fetching Data
222^^^^^^^^^^^^^^^^^^^^^^^^^
223
224Finally, 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:
225
226.. code-block:: java
227
228 dbex.store();
229 ...
230 while (dbex.next()) { ... }
231
232Closing Persistit
233^^^^^^^^^^^^^^^^^
234
235Persistit 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.
236
237The ``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.
238Additional Topics
239-----------------
240
241PersistitMap
242^^^^^^^^^^^^
243A 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.
244
245See :ref:`PersistitMap`.
246
247KeyFilters
248^^^^^^^^^^
249
250A ``com.persistit.KeyFilter`` can be supplied to restrict the results traversal operation in a convenient and
251
252Transactions
253^^^^^^^^^^^^
254
255Persistit provides ACID Transaction support with multi-version concurrency control (MCC) and adjustable durability policy.
256
257See :ref:`Transactions`.
258
259Managing Persistit
260^^^^^^^^^^^^^^^^^^
261
262Persistit provides several mechanisms for managing Persistit operation within an application. These include
263
264- JMX MXBeans
265- The ``com.persistit.Management`` object which provides programmatic access to many management operations
266- The ``com.persistit.CLI`` object which provides a command-line interface for various management operations
267- The AdminUI tool which provides a graphical client interface for examining records and other resources
268- Logging interface design for easy embedding in host applications
269
270See :ref:`Management`.
0271
=== removed file 'doc/GettingStarted.txt'
--- doc/GettingStarted.txt 2012-04-24 02:37:12 +0000
+++ doc/GettingStarted.txt 1970-01-01 00:00:00 +0000
@@ -1,255 +0,0 @@
1
2= Getting Started with Akiban Persistit
3
4
5Welcome!
6
7We 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.
8
9Akiban Persistit is a key/value data storage library written in Java(TM). Key features include:
10
11- support for highly concurrent transaction processing with multi-version concurrency control
12- optimized serialization and deserialization mechanism for Java primitives and objects
13- multi-segment (compound) keys to enable a natural logical key hierarchy
14- support for long records (megabytes)
15- implementation of a persistent SortedMap
16- extensive management capability including command-line and GUI tools
17
18This 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.
19
20== Download and Install
21
22Download +akiban-persistit-3.xx.yy.zip+ from http://www.akiban.com/persistit/download.html.
23
24Unpack 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:
25----
26jar xvzf akiban-persistit-core-3.xx.yy.zip
27----
28
29Review 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.
30
31== Working with Persistit
32
33Add 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.
34
35That's it. You are ready to work with Persistit.
36
37=== Examples
38
39Review the +examples+ directory. Here you will find functional examples of varying complexity.
40
41[horizontal]
42+examples/HelloWorld+:: source code for the example illustrating this chapter
43+examples/SimpleDemo+:: short, simple program similar to HelloWorld
44+examples/SimpleBench+:: a small micro-benchmark measuring the speed of insert, traversal, random updates, etc.
45+examples/SimpleTransaction+:: example demonstrating use of Persisit’s multi-version currency control (MVCC) transactions
46+examples/FindFile+:: a somewhat larger example that uses Persistit as the backing store for file finder utility
47+example/PersistitMapDemo+:: demonstration of the PersistitMap interface
48
49== HelloWorld
50
51Before 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”.
52
53.HelloWorld.java
54[source,java]
55----
56import com.persistit.Exchange;
57import com.persistit.Key;
58import com.persistit.Persistit;
59
60public class HelloWorld {
61 public static void main(String[] args) throws Exception {
62 Persistit db = new Persistit();
63 try {
64 // Read configuration from persistit.properties, allocate
65 // buffers, open Volume, and perform recovery processing
66 // if necessary.
67 //
68 db.initialize();
69 //
70 // Create an Exchange, which is a thread-private facade for
71 // accessing data in a Persistit Tree. This Exchange will
72 // access a Tree called "greetings" in a Volume called
73 // "hwdemo". It will create a new Tree by that name
74 // if one does not already exist.
75 //
76 Exchange dbex = db.getExchange("hwdemo", "greetings", true);
77 //
78 // Set up the Value field of the Exchange.
79 //
80 dbex.getValue().put("World");
81 //
82 // Set up the Key field of the Exchange.
83 //
84 dbex.getKey().append("Hello");
85 //
86 // Ask Persistit to put this key/value pair into the Tree.
87 // Until this point, the changes to the Exchange are local
88 // to this thread.
89 //
90 dbex.store();
91 //
92 // Prepare to traverse all the keys in the Tree (of which there
93 // is currently only one!) and for each key display its value.
94 //
95 dbex.getKey().to(Key.BEFORE);
96 while (dbex.next()) {
97 System.out.println(dbex.getKey().indexTo(0).decode() + " "
98 + dbex.getValue().get());
99 }
100 db.releaseExchange(dbex);
101 } finally {
102 // Always close Persistit. If the application does not do
103 // this, Persistit's background threads will keep the JVM from
104 // terminating.
105 //
106 db.close();
107 }
108 }
109}
110----
111
112== Concepts
113
114Although +HelloWorld.java+ is not very useful, it demonstrates several of the basic building blocks of the Persistit API.
115
116=== Initialization and Configuration
117
118Before 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+.
119
120In this example, +persistit.properties+ looks like this:
121
122----
123datapath=.
124buffer.count.8192=32
125volume.1=${datapath}/hwdemo,create,pageSize:8192,\
126 initialPages:5,extensionPages:5,maximumPages:100000
127journalpath=${datapath}/hwdemo_journal
128----
129
130See <<Configuration>> for additional information about Persistit configuration properties.
131
132=== Volumes and Trees
133
134A 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.
135
136Each 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.
137
138+HelloWorld.java+ stores its key/value pair in a tree called “greetings” in a volume named “hwdemo”. This is specified by constructing an Exchange.
139
140=== Exchanges
141
142The +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.
143
144The method
145
146[source,java]
147----
148Exchange dbex = db.getExchange("hwdemo", "greetings", true);
149----
150
151in +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.
152
153Methods +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.
154
155The 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+.
156
157Each 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:
158
159- Modify the Key, modify the Value and then perform a +com.persistit.Exchange#store+ operation.
160- Modify the Key, perform a +com.persistit.Exchange#fetch+ operation and then read the Value.
161- Modify the Key and then perform a +com.persistit.Exchange#remove+ operation.
162- 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.
163
164These methods and their variants provide the foundation for using Persistit.
165
166=== Records
167
168In Persistit, a database record consists of a Key and a Value. The terms “record” and “key/value pair” are used interchangeably.
169
170When 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.
171
172=== Keys
173
174A 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.
175
176Key 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.
177
178The +HelloWorld.java+ example appends “Hello” to the Exchange’s Key object in this line:
179
180[source,java]
181----
182 dbex.getKey().append("Hello");
183----
184
185The result is a key with a single key segment.
186
187=== Values
188
189A 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.
190
191Value 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.
192
193Numerous methods allow you to serialize and deserialize primitives values and objects into and from a Value object. For example, in +HelloWorld.java+, the statement
194
195[source,java]
196----
197 dbex.getValue().put("World");
198----
199serializes the string “World” into the backing byte array of the Exchange’s Value object and
200
201[source,java]
202----
203 System.out.println(
204 dbex.getKey().indexTo(0).decode() + " " +
205 dbex.getValue().get());
206----
207deserializes 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.
208
209=== Storing and Fetching Data
210
211Finally, 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:
212
213[source,java]
214----
215 dbex.store();
216 ...
217 while (dbex.next()) { ... }
218----
219
220=== Closing Persistit
221
222Persistit 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.
223
224The +close+ flushes all data from
225
226
227== Additional Topics
228
229=== PersistitMap
230
231A 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.
232
233See <<PersistitMap>>.
234
235=== KeyFilters
236
237A +com.persistit.KeyFilter+ can be supplied to restrict the results traversal operation in a convenient and
238
239=== Transactions
240
241Persistit provides ACID Transaction support with multi-version concurrency control (MCC) and adjustable durability policy.
242
243See <<Transactions>>.
244
245=== Managing Persistit
246
247Persistit provides several mechanisms for managing Persistit operation within an application. These include
248
249- JMX MXBeans
250- The +com.persistit.Management+ object which provides programmatic access to many management operations
251- The +com.persistit.CLI+ object which provides a command-line interface for various management operations
252- The AdminUI tool which provides a graphical client interface for examining records and other resources
253- Logging interface design for easy embedding in host applications
254
255See <<Management>>.
2560
=== added file 'doc/Management.rst'
--- doc/Management.rst 1970-01-01 00:00:00 +0000
+++ doc/Management.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,446 @@
1.. _Management:
2
3Management
4==========
5
6Akiban 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.
7
8The 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.
9
10Suppose 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:
11
12.. code-block:: java
13
14 java -cp classpath com.persistit.ui.AdminUI somehost:1099
15
16where classpath includes the Persistit ``com.persistit.ui`` package.
17
18The 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.
19
20MXBeans
21-------
22The following JMX MXBeans are available:
23
24 ``com.persistit:type=Persistit``
25 See ``com.persistit.mxbeans.ManagementMXBean``
26 ``com.persistit:type=Persistit,class=AlertMonitorMXBean``
27 Accumulates, logs and emits notifications about abnormal events such as IOExceptions and measurements outside of
28 expected thresholds.
29 ``com.persistit:type=Persistit,class=CleanupManagerMXBean``
30 View current state of the Cleanup Manager. The Cleanup Manager performs background pruning and tree maintenance
31 activities.
32 ``com.persistit:type=Persistit,class=IOMeter``
33 Maintains statistics on file system I/O operations.
34 ``com.persistit.type=Persistit,class=JournalManager``
35 Views current journal status.
36 ``com.persistit.type=Persistit,class=RecoveryManager``
37 Views current status of the recovery process. Attributes of this MXBean change only during the recovery process.
38 ``com.persistit:type=Persistit,class=TransactionIndexMXBean``
39 View internal state of transaction index queues and tables.
40 ``com.persistit.type=Persistit,class=BufferPool.*SSSS*``
41 where *SSSS* is a buffer size (512, 1024, 2048, 4096 or 16394). View utilization statistics for buffers of the
42 selected size.
43
44
45For details see the JavaDoc API documentation for each MXBean interface.
46
47Management Tasks
48----------------
49
50Persistit 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.
51
52Currently the following built-in Tasks are available:
53
54 ``icheck``
55 Check the integrity of one or more trees or volumes.
56 ``save``
57 Save selected key-value pairs from one or more trees to a flat file.
58 ``load``
59 Load selected key-value pairs from a flat file written by ``save``.
60 ``backup``
61 Control and/or perform a concurrent backup of one more more volumes.
62 ``stat``
63 Aggregate various performance statistics and either return them immediately, or write them periodically to a file.
64 ``task``
65 Check the status of an existing task. This task can also suspend, resume or stop an existing task. This task, which
66 immediately returns status information, can be used by external tools to poll the status of other tasks.
67 ``cliserver``
68 Start a simple command-line server on a specified port. This enables a client program to execute commands sending
69 them directly to that port.
70 *other tasks*
71 Various commands allow you to select and view pages and journal records.
72
73
74Executing a Task from an Application
75^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
76
77The ``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:
78
79.. code-block:: java
80
81 String taskId = db.getManagement().launch(“backup -z file=/tmp/mybackup.zip”);
82 String status = db.getManagement().execute(“task -v -m -c taskId=” + taskId);
83
84launches the backup task and then queries its status.
85
86Executing a Task from a JMX Client
87^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
88
89The ``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
90
91- via ``jconsole`` by typing the desired command line as the argument of the ``execute`` operation.
92- via a third-party JMX client such as ``jmxterm``.
93- via the ``cliserver`` feature
94
95Executing a Task Using a Third-Party JMX client
96^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
97
98You can use the ``jmxterm`` program, for example, (see [http://www.cyclopsgroup.org/projects/jmxterm]) to execute commands with the following shell script::
99
100 #!/bin/sh
101 java -jar jmxterm-1.0-alpha-4-uber.jar --verbose silent --noninteract --url $1 <<EOF
102 run -d com.persistit -b com.persistit:type=Persistit execute $2
103 EOF
104
105To 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::
106
107 peter:~/workspace/sandbox$ jmxterm-execute 1234 ‘stat\ -a’
108 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
109
110This 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.
111
112.. _cliserver:
113
114Executing a Task Using the Built-In ``cliserver``
115^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
116
117``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::
118
119 cliserver port=9999
120
121programmatically 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::
122
123 #!/bin/sh
124 java -cp classpath com.persistit.CLI localhost:9999 $*
125
126Where ``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::
127
128 /home/akiban:~$ pcli icheck -v -c "trees=*:Acc*"
129 Volume,Tree,Faults,IndexPages,IndexBytes,DataPages,DataBytes,LongRecordPages,LongRecordBytes,MvvPages,MvvRecords,MvvOverhead,MvvAntiValues,IndexHoles,PrunedPages
130 "persistit","AccumulatorRecoveryTest",0,3,24296,1519,15560788,0,0,1506,52192,721521,2397,0,0
131 "*","*",0,3,24296,1519,15560788,0,0,1506,52192,721521,2397,0,0
132 /home/akiban:~$
133
134Alternatively, you can use ``curl`` as follows::
135
136 #!/bin/sh
137 echo "$*" | curl --silent --show-error telnet://localhost:9999
138
139to issue commands.
140
141.. caution::
142
143 ``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
144 network environment. Its primary mission is to allow easy inspection of internal data structures within Persistit.
145
146.. _CLI:
147
148The Command-Line Interface
149--------------------------
150
151The String value passed to the ``execute`` and ``launch`` operations specifies the name of a task and its arguments. The general form is::
152
153 commandname -flag -flag argname=value argname=value
154
155where the order of arguments and flags is not significant.
156
157
158Command: ``icheck``
159^^^^^^^^^^^^^^^^^^^
160
161Performs a com.persistit.IntegrityCheck task. Arguments:
162
163 ``trees``
164 Specifies volumes and/or trees to check. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
165 ``-r``
166 Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.
167 ``-u``
168 Don't freeze updates (Default is to freeze updates)
169 ``-h``
170 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
171 immediately above it
172 ``-p``
173 Prune obsolete MVV (multi-version value) instances while checking.
174 ``-P``
175 Prune obsolete MVV instances, and clear any remaining aborted TransactionStatus instances. Use with care.
176 ``-v``
177 Emit verbose output. For example, emit statistics for each tree.
178 ``-c``
179 Display tree statistics in comma-separated-variable format suitable for import into a spreadsheet program.
180
181Example::
182
183 icheck trees=vehicles/* -h
184
185Checks all trees in the ``vehicles`` volume and repairs index holes.
186
187Command: ``save``
188^^^^^^^^^^^^^^^^^
189
190Starts a com.persistit.StreamSaver task. Arguments:
191
192 ``file``
193 Name of file to save records to (required)
194 ``trees``
195 Specifies volumes and/or trees to save. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
196 ``-r``
197 Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
198 ``-v``
199 emit verbose output
200
201...‘*’ and ‘?’ are standard wildcards.
202
203Example::
204
205 save -v file=/home/akiban/save.dat trees=vehicles/*{[“Edsel”:”Yugo”]}
206
207Saves the records for “Edsel” through “Yugo”, inclusive, from any tree in the volume named ``vehicles``. See com.persistit.TreeSelector for selection syntax details.
208
209Command: ``load``
210^^^^^^^^^^^^^^^^^
211
212Starts a com.persistit.StreamLoader task. Arguments:
213
214 ``file``
215 Name of file to load records from
216 ``trees``
217 Specifies volumes and/or trees to load. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
218 ``-r``
219 Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
220 ``-n``
221 Don't create missing Volumes (Default is to create them)
222 ``-t``
223 Don't create missing Trees (Default is to create them)
224 ``-v``
225 Emit verbose output
226
227...‘*’ and ‘?’ are standard wildcards.
228
229Example::
230
231 load file=/home/akiban/save.dat trees=*/*{[“Falcon”:”Firebird”]}
232
233For any tree in any volume, this command loads all records having keys between “Falcon” and “Firebird”, inclusive.
234
235Command: ``backup``
236^^^^^^^^^^^^^^^^^^^
237
238Starts a ``com.persistit.BackupTask`` task to perform concurrent (hot) backup. Arguments:
239
240 ``file``
241 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
242 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
243 ``-e``
244 flags are incompatible with operation when the ``file`` argument is specified and are ignored.
245 ``-a``
246 Start appendOnly mode - for use with third-party backup tools. ``backup -a`` should be invoked before data copying begins.
247 ``-e``
248 End appendOnly mode - for use with third-party backup tools. ``backup -e`` should be invoked after data copying ends.
249 ``-c``
250 Request checkpoint before backup.
251 ``-z``
252 Compress output to ZIP format - meaningful only in conjunction with the ``file`` argument.
253 ``-f``
254 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,
255 including Volume and journal files.
256 ``-y``
257 Copy pages from journal to Volumes before starting backup. This reduces the number of journal files in the backup set.
258
259Example::
260
261 backup -y -a -c -y -f
262 … invoke third-party backup tool to copy the database files
263 backup -e
264
265Uses 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.
266
267Example::
268
269 backup -z file=/tmp/my_backup.zip
270
271Uses the built-in file copy feature with ZIP compression.
272
273Command: ``task``
274^^^^^^^^^^^^^^^^^
275
276Queries, stops, suspends or resumes a background task. Arguments:
277
278 ``taskId``
279 Task ID to to check, or -1 for all
280 ``-v``
281 Verbose - returns detailed status messages from the selected task(s)
282 ``-m``
283 Keep previously delivered messages. Default is to remove messages once reported.
284 ``-k``
285 Keep the selected task or tasks even if completed. Default is to remove tasks once reported.
286 ``-x``
287 Stop the selected task or tasks
288 ``-u``
289 Suspend the selected task or tasks
290 ``-r``
291 Resume the selected task or tasks
292
293Unlike other commands, the ``task`` command always runs immediately even if invoked through the ``launch`` method.
294
295You can use the ``task`` command to poll and display progress of long-running tasks. Invoke::
296
297 task -v -m -c taskId=nnn
298
299until the result is empty.
300
301Command: ``cliserver``
302^^^^^^^^^^^^^^^^^^^^^^
303
304Starts a simple text-based server that receives a command line as a text string and emits the generated output as its response. Argument:
305
306 ``port``
307 Port number on which to listen for commands.
308
309Command: ``exit``
310^^^^^^^^^^^^^^^^^
311
312Ends a running ``cliserver`` instance.
313
314Commands for Viewing Data
315^^^^^^^^^^^^^^^^^^^^^^^^^
316
317The following commands execute immediately, even if invoked through the ``launch`` method. They provide a mechanism to examine individual database pages or journal records.
318
319Command: ``select``
320^^^^^^^^^^^^^^^^^^^
321
322Selects a volume and optionally a tree for subsequent operations such as ``view``. Arguments:
323
324 ``tree``
325 Specifies volume and/or tree to select as context for subsequent operations. See com.persistit.TreeSelector for details syntax.
326 ``-r``
327 Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
328
329Command: ``list``
330^^^^^^^^^^^^^^^^^
331
332Lists volumes and trees. Arguments:
333
334 ``trees``
335 Specifies volumes and/or trees to list. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
336 ``-r``
337 Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.
338
339All volumes, and all trees within those volumes, that match the ``trees`` specification are listed. By default, this command lists all trees in all volumes.
340
341Command: ``pview``
342^^^^^^^^^^^^^^^^^^
343
344Displays contents of a database page. Arguments:
345
346 ``page``
347 page address
348 ``jaddr``
349 journal address - displays a page version stored at the specified journal address
350 ``key``
351 a key specified as a String defined in the com.persistit.Key class
352 ``level``
353 tree level of the desired page
354 ``find``
355 selected records in an index page surrounding a key that points to the specified page address
356 ``-a``
357 all records. If specified, all records in the page will be displayed. Otherwise the output is abbreviated to no more than 20 lines.
358 ``-s``
359 summary - only header information in the page is displayed
360
361The ``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.
362
363``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.
364
365``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.
366
367``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.
368
369When 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.
370
371
372Command: ``path``
373^^^^^^^^^^^^^^^^^
374
375For a specified key displays the sequence of pages from root of the tree to the data page containing they key. Argument:
376
377 ``key``
378 a key specified as a String defined in the com.persistit.Key class
379
380
381Command: ``jview``
382^^^^^^^^^^^^^^^^^^
383
384Displays journal records. Arguments:
385
386 ``start``
387 starting journal address (default = 0)
388 ``end``
389 end journal address (address = infinite)
390 ``timestamps``
391 range selection of timestamp values, e.g., “132466-132499” for records having timestamps between these two numbers, inclusive. Default is all timestamps.
392 ``types``
393 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
394 (see ``com.persistit.JournalRecord`` for definitions of all types.) Default value is all types.
395 ``pages``
396 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.
397 ``maxkey``
398 maximum display length of key values in the output. Default value is 42.
399 ``maxvalue``
400 maximum display length of values in the output. Default value is 42.
401 ``path``
402 journal file path. Default is the journal file path of the currently instantiated Persistit instance.
403 ``-v``
404 verbose format. If specified, causes PM (Page Map) and TM (TransactionMap) records to be be display all map elements.
405
406
407Note 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.
408
409Command: ``open``
410^^^^^^^^^^^^^^^^^
411
412Opens 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.
413
414If 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.
415
416Note 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.
417
418Arguments:
419
420 ``datapath``
421 a directory path for volume and journal files to be analyzed
422 ``volumepath``
423 overrides ``datapath`` to specify an alternative location for volume files.
424 ``journalpath``
425 overrides ``datapath`` to specify an alternative location for journal files.
426 ``rmiport``
427 specifies an RMI port to which an instance of the AdminUI can attach.
428 ``-g``
429 launch a local copy of AdminUI
430 ``-y``
431 attempt to recover committed transactions .
432
433Note 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.
434
435Command: ``close``
436^^^^^^^^^^^^^^^^^^
437
438Detach 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.
439
440Command: ``source``
441^^^^^^^^^^^^^^^^^^^
442
443Execute command lines from a specified text file. Argument:
444
445 ``file``
446 file name of command input file
0447
=== removed file 'doc/Management.txt'
--- doc/Management.txt 2012-04-30 22:09:31 +0000
+++ doc/Management.txt 1970-01-01 00:00:00 +0000
@@ -1,360 +0,0 @@
1[[Management]]
2= Management
3
4Akiban 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.
5
6The 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.
7
8Suppose 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:
9
10----
11java -cp <classpath> com.persistit.ui.AdminUI somehost:1099
12----
13
14where <classpath> includes the Persistit com.persistit.ui package.
15
16The 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.
17
18== MXBeans
19
20The following JMX MXBeans are available:
21
22[horizontal]
23+com.persistit:type=Persistit+:: See +com.persistit.mxbeans.ManagementMXBean+
24+com.persistit:type=Persistit,class=AlertMonitorMXBean+:: Accumulates, logs and emits notifications about abnormal events such as IOExceptions and measurements outside of expected thresholds.
25+com.persistit:type=Persistit,class=CleanupManagerMXBean+:: View current state of the Cleanup Manager. The Cleanup Manager performs background pruning and tree maintenance activities.
26+com.persistit:type=Persistit,class=IOMeter+:: Maintains statistics on file system I/O operations.
27+com.persistit.type=Persistit,class=JournalManager+:: Views current journal status.
28+com.persistit.type=Persistit,class=RecoveryManager+:: Views current status of the recovery process. Attributes of this MXBean change only during the recovery process.
29+com.persistit:type=Persistit,class=TransactionIndexMXBean+:: View internal state of transaction index queues and tables.
30+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.
31
32
33For details see the JavaDoc API documentation for each MXBean interface.
34
35== Management Tasks
36
37Persistit 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.
38
39Currently the following built-in Tasks are available:
40
41[horizontal]
42+icheck+:: Check the integrity of one or more trees or volumes.
43+save+:: Save selected key-value pairs from one or more trees to a flat file.
44+load+:: Load selected key-value pairs from a flat file written by +save+.
45+backup+:: Control and/or perform a concurrent backup of one more more volumes.
46+stat+:: Aggregate various performance statistics and either return them immediately, or write them periodically to a file.
47+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.
48+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.
49+_other tasks_+:: Various commands allow you to select and view pages and journal records.
50
51
52=== Executing a Task from an Application
53
54The +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:
55
56[source,java]
57----
58String taskId = db.getManagement().launch(“backup -z file=/tmp/mybackup.zip”);
59String status = db.getManagement().execute(“task -v -m -c taskId=” + taskId);
60----
61
62launches the backup task and then queries its status.
63
64=== Executing a Task from a JMX Client
65
66The +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
67
68- via +jconsole+ by typing the desired command line as the argument of the +execute+ operation.
69- via a third-party JMX client such as +jmxterm+.
70- via the +cliserver+ feature
71
72==== Executing a Task Using a Third-Party JMX client.
73
74You can use the +jmxterm+ program, for example, (see [http://www.cyclopsgroup.org/projects/jmxterm]) to execute commands with the following shell script:
75
76[source,bash]
77----
78#!/bin/sh
79java -jar jmxterm-1.0-alpha-4-uber.jar --verbose silent --noninteract --url $1 <<EOF
80run -d com.persistit -b com.persistit:type=Persistit execute $2
81EOF
82----
83
84To 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
85
86----
87peter:~/workspace/sandbox$ jmxterm-execute 1234 ‘stat\ -a’
88hit=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
89----
90
91This 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.
92
93[[cliserver]]
94=== Executing a Task Using the Built-In +cliserver+
95
96+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
97----
98cliserver port=9999
99----
100programmatically 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:
101
102[source,bash]
103----
104#!/bin/sh
105java -cp <classpath> com.persistit.CLI localhost:9999 $*
106----
107
108Where +<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:
109
110----
111/home/akiban:~$ pcli icheck -v -c "trees=*:Acc*"
112Volume,Tree,Faults,IndexPages,IndexBytes,DataPages,DataBytes,LongRecordPages,LongRecordBytes,MvvPages,MvvRecords,MvvOverhead,MvvAntiValues,IndexHoles,PrunedPages
113"persistit","AccumulatorRecoveryTest",0,3,24296,1519,15560788,0,0,1506,52192,721521,2397,0,0
114"*","*",0,3,24296,1519,15560788,0,0,1506,52192,721521,2397,0,0
115/home/akiban:~$
116----
117
118Alternatively, you can use +curl+ as follows:
119
120[source,bash]
121----
122#!/bin/sh
123echo "$*" | curl --silent --show-error telnet://localhost:9999
124----
125to issue commands.
126
127CAUTION: 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.
128
129[[CLI]]
130== The Command-Line Interface
131
132The String value passed to the +execute+ and +launch+ operations specifies the name of a task and its arguments. The general form is
133
134----
135commandname -flag -flag argname=value argname=value
136----
137
138where the order of arguments and flags is not significant.
139
140
141=== Command: +icheck+
142
143Performs a com.persistit.IntegrityCheck task. Arguments:
144
145[horizontal]
146+trees+:: Specifies volumes and/or trees to check. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
147+-r+:: Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.
148+-u+:: Don't freeze updates (Default is to freeze updates)
149+-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
150+-p+:: Prune obsolete MVV (multi-version value) instances while checking.
151+-P+:: Prune obsolete MVV instances, and clear any remaining aborted TransactionStatus instances. Use with care.
152+-v+:: Emit verbose output. For example, emit statistics for each tree.
153+-c+:: Display tree statistics in comma-separated-variable format suitable for import into a spreadsheet program.
154
155Example:
156----
157icheck trees=vehicles/* -h
158----
159Checks all trees in the +vehicles+ volume and repairs index holes.
160
161=== Command: +save+
162
163Starts a com.persistit.StreamSaver task. Arguments:
164
165[horizontal]
166+file+:: Name of file to save records to (required)
167+trees+:: Specifies volumes and/or trees to save. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
168+-r+:: Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
169+-v+:: emit verbose output
170‘*’ and ‘?’ as standard wildcards.)
171
172Example:
173----
174save -v file=/home/akiban/save.dat trees=vehicles/*{[“Edsel”:”Yugo”]}
175----
176
177Saves the records for “Edsel” through “Yugo”, inclusive, from any tree in the volume named +vehicles+. See com.persistit.TreeSelector for selection syntax details.
178
179=== Command: +load+
180
181Starts a com.persistit.StreamLoader task. Arguments:
182
183[horizontal]
184+file+:: Name of file to load records from
185+trees+:: Specifies volumes and/or trees to load. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
186+-r+:: Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
187+-n+:: Don't create missing Volumes (Default is to create them)
188+-t+:: Don't create missing Trees (Default is to create them)
189‘*’ and ‘?’ as standard wildcards.)
190+-v+:: emit verbose output
191
192Example:
193----
194load file=/home/akiban/save.dat trees=*/*{[“Falcon”:”Firebird”]}
195----
196
197For any tree in any volume, this command loads all records having keys between “Falcon” and “Firebird”, inclusive.
198
199=== Command: +backup+
200
201Starts a +com.persistit.BackupTask+ task to perform concurrent (hot) backup. Arguments:
202
203[horizontal]
204+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.
205+-a+:: Start appendOnly mode - for use with third-party backup tools. +backup -a+ should be invoked before data copying begins.
206+-e+:: End appendOnly mode - for use with third-party backup tools. +backup -e+ should be invoked after data copying ends.
207+-c+:: Request checkpoint before backup.
208+-z+:: Compress output to ZIP format - meaningful only in conjunction with the +file+ argument.
209+-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.
210+-y+:: Copy pages from journal to Volumes before starting backup. This reduces the number of journal files in the backup set.
211
212Examples:
213----
214backup -y -a -c -y -f
215… invoke third-party backup tool to copy the database files
216backup -e
217----
218Uses 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.
219
220----
221backup -z file=/tmp/my_backup.zip
222----
223Uses the built-in file copy feature with ZIP compression.
224
225=== Command: +task+
226
227Queries, stops, suspends or resumes a background task. Arguments:
228
229[horizontal]
230+taskId+:: Task ID to to check, or -1 for all
231+-v+:: Verbose - returns detailed status messages from the selected task(s)
232+-m+:: Keep previously delivered messages. Default is to remove messages once reported.
233+-k+:: Keep the selected task or tasks even if completed. Default is to remove tasks once reported.
234+-x+:: Stop the selected task or tasks
235+-u+:: Suspend the selected task or tasks
236+-r+:: Resume the selected task or tasks
237
238Unlike other commands, the +task+ command always runs immediately even if invoked through the +launch+ method.
239
240You can use the +task+ command to poll and display progress of long-running tasks. Invoke
241
242----
243task -v -m -c taskId=nnn
244----
245
246until the result is empty.
247
248=== Command: +cliserver+
249
250Starts a simple text-based server that receives a command line as a text string and emits the generated output as its response. Argument:
251
252[horizontal]
253+port+:: Port number on which to listen for commands.
254
255=== Command: +exit+
256
257Ends a running +cliserver+ instance.
258
259== Commands for Viewing Data
260
261The following commands execute immediately, even if invoked through the +launch+ method. They provide a mechanism to examine individual database pages or journal records.
262
263=== Command: +select+
264
265Selects a volume and optionally a tree for subsequent operations such as +view+. Arguments:
266
267[horizontal]
268+tree+:: Specifies volume and/or tree to select as context for subsequent operations. See com.persistit.TreeSelector for details syntax.
269+-r+:: Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.)
270
271=== Command: +list+
272
273Lists volumes and trees. Arguments:
274
275[horizontal]
276+trees+:: Specifies volumes and/or trees to list. See com.persistit.TreeSelector for details syntax. Default is all trees in all volumes.
277+-r+:: Tree specification uses Java RegEx syntax (Default is to treat ‘*’ and ‘?’ as standard single-character and multi-character wildcards.
278
279All volumes, and all trees within those volumes, that match the +trees+ specification are listed. By default, this command lists all trees in all volumes.
280
281=== Command: +pview+
282
283Displays contents of a database page. Arguments:
284
285[horizontal]
286+page+:: page address
287+jaddr+:: journal address - displays a page version stored at the specified journal address
288+key+:: a key specified as a String defined in the com.persistit.Key class
289+level+:: tree level of the desired page
290+find+:: selected records in an index page surrounding a key that points to the specified page address
291+-a+:: all records. If specified, all records in the page will be displayed. Otherwise the output is abbreviated to no more than 20 lines.
292+-s+:: summary - only header information in the page is displayed
293
294The +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.
295
296+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.
297
298+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.
299
300+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.
301
302When 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.
303
304
305=== Command: +path+
306
307For a specified key displays the sequence of pages from root of the tree to the data page containing they key. Argument:
308
309[horizontal]
310+key+:: a key specified as a String defined in the com.persistit.Key class
311
312
313=== Command: +jview+
314
315Displays journal records. Arguments:
316
317[horizontal]
318+start+:: starting journal address (default = 0)
319+end+:: end journal address (address = infinite)
320+timestamps+:: range selection of timestamp values, e.g., “132466-132499” for records having timestamps between these two numbers, inclusive. Default is all timestamps.
321+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.
322+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.
323+maxkey+:: maximum display length of key values in the output. Default value is 42.
324+maxvalue+:: maximum display length of values in the output. Default value is 42.
325+path+:: journal file path. Default is the journal file path of the currently instantiated Persistit instance.
326+-v+:: verbose format. If specified, causes PM (Page Map) and TM (TransactionMap) records to be be display all map elements.
327
328
329Note 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.
330
331=== Command: +open+
332
333Opens 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.
334
335If 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.
336
337Note 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.
338
339Arguments:
340
341[horizontal]
342+datapath+:: a directory path for volume and journal files to be analyzed
343+volumepath+:: overrides +datapath+ to specify an alternative location for volume files.
344+journalpath+:: overrides +datapath+ to specify an alternative location for journal files.
345+rmiport+:: specifies an RMI port to which an instance of the AdminUI can attach.
346+-g+:: launch a local copy of AdminUI
347+-y+:: attempt to recover committed transactions .
348
349Note 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.
350
351=== Command: +close+
352
353Detach 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.
354
355=== Command: +source+
356
357Execute command lines from a specified text file. Argument:
358
359[horizontal]
360+file+:: file name of command input file
3610
=== added file 'doc/Miscellaneous.rst'
--- doc/Miscellaneous.rst 1970-01-01 00:00:00 +0000
+++ doc/Miscellaneous.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,36 @@
1.. _Miscellaneous:
2
3Miscellaneous Topics
4====================
5
6Following are some short items you may find useful as you explore Akiban Persistit. Follow links to the API documentation for more details.
7
8Histograms
9----------
10
11The 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.
12
13Temporary Volumes
14-----------------
15
16A 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.
17
18The primary use case for a temporary volume is an application that needs the unlimited size, but not the persistence of normal Persistit volumes.
19
20See the ``com.persistit.Persistit#createTemporaryVolume`` method for additional details.
21
22Logging
23-------
24
25By 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.
26
27Using one of these logging frameworks is simple. For example, the following code connects Persistit to an application-supplied SLF4J logger:
28
29.. code-block:: java
30
31 db.setPersistitLogger(new Slf4jAdapter(LOG))
32
33where ``db`` is the Persistit instance and ``LOG`` is a Logger supplied by SLF4J. This method should be called before the ``initialize`` method.
34
35
36
037
=== removed file 'doc/Miscellaneous.txt'
--- doc/Miscellaneous.txt 2012-04-30 22:09:31 +0000
+++ doc/Miscellaneous.txt 1970-01-01 00:00:00 +0000
@@ -1,32 +0,0 @@
1[[Miscellaneous]]
2= Miscellaneous Topics
3
4Following are some short items you may find useful as you explore Akiban Persistit. Follow links to the API documentation for more details.
5
6== Histograms
7
8The 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.
9
10== Temporary Volumes
11
12A 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.
13
14The primary use case for a temporary volume is an application that needs the unlimited size, but not the persistence of normal Persistit volumes.
15
16See the +com.persistit.Persistit#createTemporaryVolume+ method for additional details.
17
18== Logging
19
20By 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.
21
22Using one of these logging frameworks is simple. For example, the following code connects Persistit to an application-supplied SLF4J logger:
23
24[source,java]
25----
26db.setPersistitLogger(new Slf4jAdapter(LOG))
27----
28
29where +db+ is the Persistit instance and +LOG+ is a Logger supplied by SLF4J. This method should be called before the +initialize+ method.
30
31
32
330
=== added file 'doc/PhysicalStorage.rst'
--- doc/PhysicalStorage.rst 1970-01-01 00:00:00 +0000
+++ doc/PhysicalStorage.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,142 @@
1.. _PhysicalStorage:
2
3Physical B-Tree Representation
4==============================
5
6This chapter describes the physical structures used to represent Akiban Persistit records on disk and in memory.
7
8Files
9-----
10
11Following is a directory listing illustrating a working Persistit database::
12
13 -rw-r--r--. 1 demo demo 24G Feb 8 13:18 akiban_data
14 -rw-r--r--. 1 demo demo 48K Feb 8 13:19 akiban_system
15 -rw-r--r--. 1 demo demo 954M Feb 8 13:18 akiban_journal.000000000225
16 -rw-r--r--. 1 demo demo 954M Feb 8 13:19 akiban_journal.000000000226
17 -rw-r--r--. 1 demo demo 954M Feb 8 13:19 akiban_journal.000000000227
18 -rw-r--r--. 1 demo demo 662M Feb 8 13:19 akiban_journal.000000000228
19
20This 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.
21
22.. _Journal:
23
24The Journal
25-----------
26
27The *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.
28
29Every 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.]
30
31Persistit writes two major types of records to journal files.
32
33- 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.
34- 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`).
35
36As 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.
37
38The 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.
39
40The journal also plays a critical role during concurrent backup. To back up a running Persistit database, the ``com.persistit.BackupTask`` does the following:
41
42- Enables ``appendOnly`` mode to suspend the copying of updated page images.
43- Copies the appropriate volume and journal files
44- Disables ``appendOnly`` mode to allow JOURNAL_COPIER to continue.
45
46For more details on the journal, checkpoints and transactions, see :ref:`Recovery`. For more information on concurrent backup and other management tasks, see :ref:`Management`.
47
48Pages and Volumes
49-----------------
50
51Persistit 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.
52
53Directory Tree
54^^^^^^^^^^^^^^
55
56Within 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.
57
58Persistit 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.
59
60Data Pages
61^^^^^^^^^^
62
63A 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.)
64
65Index Pages
66^^^^^^^^^^^
67
68An 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.
69
70.. TODO - diagram of B-Tree, page layouts, etc
71
72.. _Recovery:
73
74Recovery
75========
76
77Akiban 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.
78
79To 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.
80
81Recovery performs two major activities:
82
83- Restores all B-Trees to an internally consistent state with a known timestamp.
84- Replays all transaction that committed after that timestamp.
85- Prunes multi-version values belonging to certain aborted transactions (see :ref:`Pruning`).
86
87To 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.
88
89Recovery 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.
90
91Timestamps and Checkpoints
92--------------------------
93
94Persistit 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.
95
96A *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.
97
98Upon 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.
99
100Then 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:
101
102- 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.]
103- All committed transactions are present in the recovered database. (See :ref:`Transactions` for durability determined by ``CommitPolicy``.)
104
105For 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.)
106
107Flush/Force/Checkpoint
108^^^^^^^^^^^^^^^^^^^^^^
109
110An 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:
111
112 ``com.persistit.Persistit#flush``
113 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
114 guaranteed to have been written to their respective volume files.
115 ``com.persistit.Persistit#force``
116 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
117 the underlying ``java.io.Filechannel#force(boolean)`` method.)
118 ``com.persistit.Persistit#checkpoint``
119 causes Persistit to allocate a new checkpoint timestamp and then wait for all updates that happened before that timestamp to be committed to disk.
120
121However, 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.
122
123
124The Buffer Pool
125---------------
126
127Persistit 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.
128
129Persistit 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.
130
131In 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.)
132
133Persistit 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.
134
135Generally, 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.
136
137Tools
138-----
139
140The 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.
141
142
0143
=== removed file 'doc/PhysicalStorage.txt'
--- doc/PhysicalStorage.txt 2012-05-04 13:33:49 +0000
+++ doc/PhysicalStorage.txt 1970-01-01 00:00:00 +0000
@@ -1,126 +0,0 @@
1[[PhysicalStorage]]
2= Physical B-Tree Representation
3
4This chapter describes the physical structures used to represent Akiban Persistit records on disk and in memory.
5
6== Files
7
8Following is a directory listing illustrating a working Persistit database:
9
10----
11-rw-r--r--. 1 demo demo 24G Feb 8 13:18 akiban_data
12-rw-r--r--. 1 demo demo 48K Feb 8 13:19 akiban_system
13-rw-r--r--. 1 demo demo 954M Feb 8 13:18 akiban_journal.000000000225
14-rw-r--r--. 1 demo demo 954M Feb 8 13:19 akiban_journal.000000000226
15-rw-r--r--. 1 demo demo 954M Feb 8 13:19 akiban_journal.000000000227
16-rw-r--r--. 1 demo demo 662M Feb 8 13:19 akiban_journal.000000000228
17----
18
19This 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.
20
21[[Journal]]
22== The Journal
23
24The _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.
25
26Every 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.]
27
28Persistit writes two major types of records to journal files.
29
30- 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.
31- 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>>).
32
33As 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.
34
35The 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.
36
37The journal also plays a critical role during concurrent backup. To back up a running Persistit database, the +com.persistit.BackupTask+ does the following:
38
39- Enables +appendOnly+ mode to suspend the copying of updated page images.
40- Copies the appropriate volume and journal files
41- Disables +appendOnly+ mode to allow JOURNAL_COPIER to continue.
42
43For more details on the journal, checkpoints and transactions, see <<Recovery>>. For more information on concurrent backup and other management tasks, see <<Management>>.
44
45== Pages and Volumes
46
47Persistit 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.
48
49=== Directory Tree
50
51Within 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.
52
53Persistit 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.
54
55=== Data Pages
56
57A 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.)
58
59=== Index Pages
60
61An 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.
62
63****
64TODO - diagram of B-Tree, page layouts, etc
65****
66[[Recovery]]
67== Recovery
68
69Akiban 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.
70
71To 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.
72
73Recovery performs two major activities:
74
75- Restores all B-Trees to an internally consistent state with a known timestamp.
76- Replays all transaction that committed after that timestamp.
77- Prunes multi-version values belonging to certain aborted transactions (see <<Pruning>>).
78
79To 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.
80
81Recovery 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.
82
83=== Timestamps and Checkpoints
84
85Persistit 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.
86
87A _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.
88
89Upon 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.
90
91Then 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:
92
93- 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.]
94- All committed transactions are present in the recovered database. (See <<Transactions>> for durability determined by +CommitPolicy+.)
95
96For 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.)
97
98=== Flush/Force/Checkpoint
99
100An 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:
101
102[horizontal]
103+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.
104+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.)
105+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.
106
107However, 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.
108
109
110== The Buffer Pool
111
112Persistit 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.
113
114Persistit 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.
115
116In 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.)
117
118Persistit 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.
119
120Generally, 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.
121
122== Tools
123
124The 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.
125
126
1270
=== added file 'doc/ReleaseNotes.rst'
--- doc/ReleaseNotes.rst 1970-01-01 00:00:00 +0000
+++ doc/ReleaseNotes.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,84 @@
1************************************
2Akiban-Persistit 3.1.1 Release Notes
3************************************
4
5Release Date
6============
7May 25, 2012
8
9Overview
10========
11This is the first open source release of the Persistit project (https://launchpad.net/akiban-persistit).
12
13See http://www.akiban.com/akiban-persistit for a summary of features and benefits, licensing information and how to get support.
14
15Documentation
16=============
17Users Guide (http://www.akiban.com/ak-docs/admin/persistit)
18JavaDoc (http://www.akiban.com/ak-docs/admin/persistit/apidocs)
19
20Building Akiban-Persistit
21=========================
22Use Maven (maven.apache.org) to build Persistit.
23
24To build::
25
26 mvn install
27
28The resulting jar files are in the ``target`` directory. To build the Javadoc::
29
30 mvn javadoc:javadoc
31
32The resulting Javadoc HTML files are in ``target/site/apidocs``.
33
34Building and Running the Examples
35---------------------------------
36
37Small 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::
38
39 ant run
40
41in each of the examples subdirectories to build and run the examples.
42
43Known Issues
44============
45
46Transactional Tree Management
47-----------------------------
48
49All 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.
50
51Problems with Disk Full - Bug 916071
52------------------------------------
53
54There 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.
55
56Out of Memory Error, Direct Memory Buffer - Bug 985117
57------------------------------------------------------
58
59Out 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.
60
61* Workaround: Ensure your application has the ability to retry failed transactions
62
63
64Tree#getChangeCount may return inaccurate result - Bug 986465
65-------------------------------------------------------------
66
67The 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.
68
69Multi-Version-Values sometimes not fully pruned - Bug 1000331
70-------------------------------------------------------------
71
72Multi-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.
73
74* 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.
75
76* 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.
77
78
79Buffer Pool Configuration
80=========================
81For 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
82
83.. 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.
84
085
=== added file 'doc/Security.rst'
--- doc/Security.rst 1970-01-01 00:00:00 +0000
+++ doc/Security.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,93 @@
1.. _Security:
2
3Security Notes
4==============
5
6Akiban 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:
7
8- Persistit volume files
9- configuration properties file, if one is used
10- access by unauthorized code to the API exposed by the Persistit library
11- 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.
12- the :ref:`cliserver` if instantiated
13
14In addition to these general deployment considerations, Persistit requires certain permissions in an environment controlled by a security manager.
15
16Java 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.
17
18Security Domains
19----------------
20
21This 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.
22
23Note 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.
24
25Akiban 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.
26
27At 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.
28
29Using 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:
30
31.. code-block:: java
32
33 grant codeBase "file:/appdir/myapplication.jar" {
34 permission java.io.FilePermission "e:\\data\\*", "read, write, delete";
35 permission java.io.FilePermission "e:\\logs\\*", "read, write, delete";
36 permission java.net.SocketPermission "localhost",
37 "accept, connect, listen, resolve";
38 };
39
40 grant codeBase "file:/lib/akiban-persistit.jar" {
41 permission java.io.FilePermission "<<ALL FILES>>", "read, write, delete";
42 permission java.net.SocketPermission "*:1099-",
43 "accept, connect, listen, resolve";
44 permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
45 permission java.io.SerializablePermission "enableSubclassImplementation";
46 permission java.util.PropertyPermission "com.persistit.*", "read";
47 permission java.lang.RuntimePermission "accessDeclaredMembers";
48 };
49
50This 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.
51
52Although 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.
53
54Permissions Required for DefaultValueCoder
55------------------------------------------
56
57DefaultValueCoder performs three security-sensitive operations:
58
59- It enumerates the declared fields of the class being serialized,
60- It reads and writes data from and to those fields using reflection even if they are private, and
61- It overrides the default implementations of java.io.ObjectInputStream and java.io.ObjectOutputStream.
62
63If a SecurityManager is installed then three permissions must be granted to enable this new mechanism::
64
65 java.lang.RuntimePermission "accessDeclaredMembers";
66 java.lang.reflect.ReflectPermission("suppressAccessChecks")
67 java.io.SerializablePermission("enableSubclassImplementation")
68
69Persistit 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.
70
71Permission Required for Reading System Properties
72-------------------------------------------------
73
74Persistit attempts to read system properties whose names begin with “com.persistit.” Specific permission to do this is granted by the line::
75
76 permission java.util.PropertyPermission "com.persistit.*", "read";
77
78Again, only the Persistit library domain needs to have this permission. If this permission is not granted, Persistit ignores all system properties.
79
80Permissions Required for File and Socket I/O
81--------------------------------------------
82
83Persistit 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.
84
85These 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.
86
87As 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.)
88
89Deploying Persistit as an Installed Optional Package
90----------------------------------------------------
91
92A 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.
93
094
=== removed file 'doc/Security.txt'
--- doc/Security.txt 2012-04-30 22:09:31 +0000
+++ doc/Security.txt 1970-01-01 00:00:00 +0000
@@ -1,91 +0,0 @@
1[[Security]]
2= Security Notes
3
4Akiban 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:
5
6- Persistit volume files
7- configuration properties file, if one is used
8- access by unauthorized code to the API exposed by the Persistit library
9- 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.
10- the <<cliserver>> if instantiated
11
12In addition to these general deployment considerations, Persistit requires certain permissions in an environment controlled by a security manager.
13
14Java 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.
15
16== Security Domains
17
18This 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.
19
20Note 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.
21
22Akiban 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.
23
24At 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.
25
26Using 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:
27
28.Example .java.policy File
29----
30grant codeBase "file:/appdir/myapplication.jar" {
31 permission java.io.FilePermission "e:\\data\\*", "read, write, delete";
32 permission java.io.FilePermission "e:\\logs\\*", "read, write, delete";
33 permission java.net.SocketPermission "localhost",
34 "accept, connect, listen, resolve";
35};
36
37grant codeBase "file:/lib/akiban-persistit.jar" {
38 permission java.io.FilePermission "<<ALL FILES>>", "read, write, delete";
39 permission java.net.SocketPermission "*:1099-",
40 "accept, connect, listen, resolve";
41 permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
42 permission java.io.SerializablePermission "enableSubclassImplementation";
43 permission java.util.PropertyPermission "com.persistit.*", "read";
44 permission java.lang.RuntimePermission "accessDeclaredMembers";
45};
46----
47
48This 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.
49
50Although 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.
51
52== Permissions Required for DefaultValueCoder
53
54DefaultValueCoder performs three security-sensitive operations:
55
56- It enumerates the declared fields of the class being serialized,
57- It reads and writes data from and to those fields using reflection even if they are private, and
58- It overrides the default implementations of java.io.ObjectInputStream and java.io.ObjectOutputStream.
59
60If a SecurityManager is installed then three permissions must be granted to enable this new mechanism:
61
62----
63java.lang.RuntimePermission "accessDeclaredMembers";
64java.lang.reflect.ReflectPermission("suppressAccessChecks")
65java.io.SerializablePermission("enableSubclassImplementation")
66----
67
68Persistit 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.
69
70== Permission Required for Reading System Properties
71
72Persistit attempts to read system properties whose names begin with “com.persistit.” Specific permission to do this is granted by the line
73
74----
75 permission java.util.PropertyPermission "com.persistit.*", "read";
76----
77
78Again, only the Persistit library domain needs to have this permission. If this permission is not granted, Persistit ignores all system properties.
79
80== Permissions Required for File and Socket I/O
81
82Persistit 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.
83
84These 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.
85
86As 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.)
87
88== Deploying Persistit as an Installed Optional Package
89
90A 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.
91
920
=== added file 'doc/Serialization.rst'
--- doc/Serialization.rst 1970-01-01 00:00:00 +0000
+++ doc/Serialization.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,250 @@
1.. _Serialization:
2
3Serializing Object Values
4=========================
5
6Akiban Persistit uses one of several mechanisms to serialize a Java Object into a ``com.persistit.Value``.
7
8* For the following classes, Persistit provides built-in optimized serialization logic that cannot be overridden:
9
10 * ``java.lang.String``
11 * ``java.util.Date``
12 * ``java.math.BigInteger``
13 * ``java.math.BigDecimal``
14 * Wrapper classes for primitive values (``Boolean``, ``Byte``, ``Short``, etc.)
15 * All arrays (however, the mechanisms described here apply to array elements).
16
17* An application can register a custom ``com.persistit.encoding.ValueCoder`` to handle serialization of a particular class
18* Default serialization using Persistit's built-in serialization mechanism described below, or
19* 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].
20
21Persistit'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.
22
23Storing Objects in Persistit
24----------------------------
25
26To 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:
27
28.. code-block:: java
29
30 exchange.getValue().put(myObject);
31 exchange.store();
32
33Of 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:
34
35.. code-block:: java
36
37 exchange.fetch();
38 MyClass myObject = (MyClass)exchange.getValue().get();
39
40The 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.
41
42Persistit 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.
43
44You 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.
45
46DefaultValueCoder and SerialValueCoder
47--------------------------------------
48
49When required to serialize or deserialize class with no explicitly defined ``ValueCoder``, Persistit automatically creates and registers one of the following two default ``ValueCoder`` implementations:
50
51``com.persistit.DefaultValueCoder``:: uses introspection to determine which fields to serialize, and reflection to access and update the fields
52``com.persistit.encoding.SerialValueCoder``:: creates instances of ObjectInputStream and ObjectOutputStream to serialize and deserialize the object.
53
54DefaultValueCoder 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.
55
56DefaultValueCoder
57-----------------
58
59A 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.
60
61``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.
62
63Currently, ``DefaultValueCoder`` does not support the following elements of the serialization API:
64
65- the ``readObjectNoData`` custom serialization method
66- the ``PutFields``/``GetFields`` API of ``ObjectOutputStream`` and ``ObjectInputStream``
67- the ``readLine`` method of ``ObjectInputStream``.
68
69Constructing Objects upon Deserialization
70^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
71
72When 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.
73
74For compatibility with standard Java serialization, ``DefaultValueCoder`` constructs new object instances of Serializable classes using the same logic as ``ObjectInputStream``, namely:
75
76If the class is Externalizable, ``DefaultValueCoder`` invokes its public no-argument constructor. (The specification for Externalizable requires the class to have such a constructor.)
77
78Otherwise, if the class is Serializable, ``DefaultValueCoder`` invokes the no-argument constructor of its nearest non-serializable superclass.
79
80``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.
81
82To avoid using platform-specific API calls, you can specify the configuration property::
83
84 constructorOverride=true
85
86When 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.
87
88Extending DefaultValueCoder
89^^^^^^^^^^^^^^^^^^^^^^^^^^^
90
91You can register an extended ``DefaultValueCoder`` to provide custom behavior, including custom logic for constructing instances of a class, as shown here:
92
93.. code-block:: java
94
95 Persistit.getInstance().getCoderManager().registerValueCoder(MyClass.class, new DefaultValueCoder(MyClass.class) {
96 public Object get(Value value, Class clazz, CoderContext context) throws ConversionException {
97
98 // Construct the object being deserialized.
99 Object instance = new MyClass(...custom arguments...);
100
101 // See "registering objects while deserializing" below
102 value.registerEncodedObject(instance);
103
104 // Load the non-transient, non-static fields
105 render(value, instance, clazz, context);
106
107 return instance;
108 }
109 });
110
111
112
113Security Policy Requirements for DefaultValueCoder
114^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
115
116DefaultValueCoder 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::
117
118 java.lang.RuntimePermission "accessDeclaredMembers";
119 java.lang.reflect.ReflectPermission("suppressAccessChecks")
120 java.io.SerializablePermission("enableSubclassImplementation")
121
122See :ref:`Security` for an extended discussion on security policy issues for Persistit.
123
124SerialValueCoder
125----------------
126
127``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:
128
129- the security context into which the application will be deployed does not grant the permissions noted above that are required for ``DefaultValueCoder``,
130- to avoid Persistit's use of private API calls to construct object instances during deserialization,
131- a preference for the use of a standard format defined within the Java platform rather than Persistit's custom format,
132- limitations documented above on the API elements available during custom deserialization within DefaultValueCoder, for example non-support of GetField and PutField.
133
134Your application can specify ``SerialValueCoders`` for specific classes either by explicitly creating and registering them, or by naming them in the com.persistit.serialOverride property.
135
136To explicitly register a ``SerialValueCoder`` for the class ``MyClass``, do this:
137
138.. code-block:: java
139
140 ...
141 Persistit.getInstance().getCoderManager().registerValueCoder(
142 MyClass.class,
143 new SerialValueCoder(MyClass.class));
144 ...
145
146
147The ``com.persistit.serialOverride`` Configuration Property
148^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
149
150The ``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.
151
152Names are separated by commas and may contain wild cards.
153
154The following are valid patterns:
155
156 ``java.io.File``
157 Just the File class.
158 ``java.io.*``
159 All classes in the java.io package.
160 ``java.awt.**``
161 All classes in the java.awt package and its sub-packages
162 ``java.util.*Map``
163 All of the Map classes in the java.util.
164 ``**``
165 All classes in all packages
166
167More 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::
168
169 ``serialOverride=org.apache.**,com.mypkg.serialstuff.*,com.mypkg.MyClass``
170
171Like 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::
172
173 ``-Dcom.persistit.serialOverride=...``
174
175Registering Objects in a Custom ``ValueCoder``
176----------------------------------------------
177
178In 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:
179
180.. code-block:: java
181
182 public void get(Value value, Class clazz, CoderContext context) throws ConversionException {
183 // Construct the object being deserialized.
184 //
185 Object instance = ...constructor for the object...
186
187 // Associate a handle with the newly
188 // created instance.
189 //
190 value.registerEncodedObject(instance);
191
192 // Populate the object's internal state
193 //
194 ... load the fields – for example, by calling render...
195
196 return instance;
197 }
198
199The 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.
200
201As 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.
202
203Whenever 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.
204
205``Value.toString()`` and ``decodeDisplayable``
206----------------------------------------------
207
208In 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.
209
210Persistit creates a String value loading the object's class, using the following algorithm:
211
212- If the state represented by this Value is undefined, then return "undefined".
213- If the state is null or a boolean, return "null" "false", or "true".
214- 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.
215- 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.
216- 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.
217- 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.
218- If the value represents an array, return a list of comma-separated element values surrounded by square brackets.
219- 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.
220- 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.
221- 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.
222- 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.
223- 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.
224- 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.)
225
226For 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::
227
228 (Person){(Date)19490826000000.000-0400,"Mary","Jones",(long)75000,[
229 (Person){(Date)19550522000000.000-0400,"John","Smith",(long)68000,[@0]}]}
230
231In 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.
232
233
234PersistitReference
235------------------
236
237In 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.
238
239One 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.
240
241The ``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.
242
243ObjectCache
244-----------
245
246A ``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.
247
248``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.
249
250Each ``ObjectCache`` entry holds its object value as a ``SoftReference``, making it available for garbage collection when space is needed.
0251
=== removed file 'doc/Serialization.txt'
--- doc/Serialization.txt 2012-04-30 22:09:31 +0000
+++ doc/Serialization.txt 1970-01-01 00:00:00 +0000
@@ -1,246 +0,0 @@
1[[Serialization]]
2= Serializing Object Values
3
4Akiban Persistit uses one of several mechanisms to serialize a Java Object into a +com.persistit.Value+.
5
6- For the following classes, Persistit provides built-in optimized serialization logic that cannot be overridden:
7
8* +java.lang.String+
9* +java.util.Date+
10* +java.math.BigInteger+
11* +java.math.BigDecimal+
12* Wrapper classes for primitive values (+Boolean+, +Byte+, +Short+, etc.)
13* All arrays (however, the mechanisms described here apply to array elements).
14
15- An application can register a custom +com.persistit.encoding.ValueCoder+ to handle serialization of a particular class
16- Default serialization using Persistit's built-in serialization mechanism described below, or
17- 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].
18
19Persistit'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.
20
21== Storing Objects in Persistit
22
23To 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:
24
25[source,java]
26----
27 exchange.getValue().put(myObject);
28 exchange.store();
29----
30
31Of 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:
32
33[source,java]
34----
35 exchange.fetch();
36 MyClass myObject = (MyClass)exchange.getValue().get();
37----
38
39The 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.
40
41Persistit 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.
42
43You 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.
44
45=== DefaultValueCoder and SerialValueCoder
46
47When required to serialize or deserialize class with no explicitly defined +ValueCoder+, Persistit automatically creates and registers one of the following two default +ValueCoder+ implementations:
48
49+com.persistit.DefaultValueCoder+:: uses introspection to determine which fields to serialize, and reflection to access and update the fields
50+com.persistit.encoding.SerialValueCoder+:: creates instances of ObjectInputStream and ObjectOutputStream to serialize and deserialize the object.
51
52DefaultValueCoder 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.
53
54== DefaultValueCoder
55
56A 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.
57
58+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.
59
60Currently, +DefaultValueCoder+ does not support the following elements of the serialization API:
61
62- the +readObjectNoData+ custom serialization method
63- the +PutFields+/+GetFields+ API of +ObjectOutputStream+ and +ObjectInputStream+
64- the +readLine+ method of +ObjectInputStream+.
65
66=== Constructing Objects upon Deserialization
67
68When 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.
69
70For compatibility with standard Java serialization, +DefaultValueCoder+ constructs new object instances of Serializable classes using the same logic as +ObjectInputStream+, namely:
71
72If the class is Externalizable, +DefaultValueCoder+ invokes its public no-argument constructor. (The specification for Externalizable requires the class to have such a constructor.)
73
74Otherwise, if the class is Serializable, +DefaultValueCoder+ invokes the no-argument constructor of its nearest non-serializable superclass.
75
76+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.
77
78To avoid using platform-specific API calls, you can specify the configuration property
79
80----
81 constructorOverride=true
82----
83
84When 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.
85
86=== Extending DefaultValueCoder
87
88You can register an extended +DefaultValueCoder+ to provide custom behavior, including custom logic for constructing instances of a class, as shown here:
89
90[source,java]
91-----
92 Persistit.getInstance().getCoderManager().registerValueCoder(MyClass.class, new DefaultValueCoder(MyClass.class) {
93 public Object get(Value value, Class clazz, CoderContext context) throws ConversionException {
94
95 // Construct the object being deserialized.
96 Object instance = new MyClass(...custom arguments...);
97
98 // See "registering objects while deserializing" below
99 value.registerEncodedObject(instance);
100
101 // Load the non-transient, non-static fields
102 render(value, instance, clazz, context);
103
104 return instance;
105 }
106 });
107----
108
109
110
111=== Security Policy Requirements for DefaultValueCoder
112
113DefaultValueCoder 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:
114
115----
116java.lang.RuntimePermission "accessDeclaredMembers";
117java.lang.reflect.ReflectPermission("suppressAccessChecks")
118java.io.SerializablePermission("enableSubclassImplementation")
119----
120
121See <<Security>> for an extended discussion on security policy issues for Persistit.
122
123== SerialValueCoder
124
125+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:
126
127- the security context into which the application will be deployed does not grant the permissions noted above that are required for +DefaultValueCoder+,
128- to avoid Persistit's use of private API calls to construct object instances during deserialization,
129- a preference for the use of a standard format defined within the Java platform rather than Persistit's custom format,
130- limitations documented above on the API elements available during custom deserialization within DefaultValueCoder, for example non-support of GetField and PutField.
131
132Your application can specify +SerialValueCoders+ for specific classes either by explicitly creating and registering them, or by naming them in the com.persistit.serialOverride property.
133
134To explicitly register a +SerialValueCoder+ for the class +MyClass+, do this:
135
136[source,java]
137----
138 ...
139 Persistit.getInstance().getCoderManager().registerValueCoder(
140 MyClass.class,
141 new SerialValueCoder(MyClass.class));
142 ...
143----
144
145
146=== The +com.persistit.serialOverride+ Configuration Property
147
148The +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.
149
150Names are separated by commas and may contain wild cards.
151
152The following are valid patterns:
153
154+java.io.File+:: Just the File class.
155+java.io.*+:: All classes in the java.io package.
156+java.awt.**+:: All classes in the java.awt package and its sub-packages
157+java.util.*Map+:: All of the Map classes in the java.util.
158+**+:: All classes in all packages
159
160More 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:
161
162----
163+serialOverride=org.apache.**,com.mypkg.serialstuff.*,com.mypkg.MyClass+
164----
165
166Like 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:
167
168----
169+-Dcom.persistit.serialOverride=...+
170----
171
172== Registering Objects in a Custom +ValueCoder+
173
174In 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:
175
176[source,java]
177----
178public void get(Value value, Class clazz, CoderContext context) throws ConversionException {
179 // Construct the object being deserialized.
180 //
181 Object instance = ...constructor for the object...
182
183 // Associate a handle with the newly
184 // created instance.
185 //
186 value.registerEncodedObject(instance);
187
188 // Populate the object's internal state
189 //
190 ... load the fields – for example, by calling render...
191
192 return instance;
193}
194----
195
196The 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.
197
198As 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.
199
200Whenever 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.
201
202== +Value.toString()+ and +decodeDisplayable+
203
204In 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.
205
206Persistit creates a String value loading the object's class, using the following algorithm:
207
208- If the state represented by this Value is undefined, then return "undefined".
209- If the state is null or a boolean, return "null" "false", or "true".
210- 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.
211- 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.
212- 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.
213- 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.
214- If the value represents an array, return a list of comma-separated element values surrounded by square brackets.
215- 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.
216- 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.
217- 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.
218- 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.
219- 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.
220- 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.)
221
222For 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:
223
224----
225 (Person){(Date)19490826000000.000-0400,"Mary","Jones",(long)75000,[
226 (Person){(Date)19550522000000.000-0400,"John","Smith",(long)68000,[@0]}]}
227----
228
229In 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.
230
231
232== PersistitReference
233
234In 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.
235
236One 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.
237
238The +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.
239
240== ObjectCache
241
242A +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.
243
244+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.
245
246Each +ObjectCache+ entry holds its object value as a +SoftReference+, making it available for garbage collection when space is needed.
2470
=== removed file 'doc/TOC.txt'
--- doc/TOC.txt 2012-04-25 18:13:07 +0000
+++ doc/TOC.txt 1970-01-01 00:00:00 +0000
@@ -1,19 +0,0 @@
1Akiban Persistit User Guide
2===========================
3Peter Beaman <pbeaman@akiban.com>
4:toc:
5:doctype: book
6:icons:
7:numbered:
8:website: http://www.akiban.com/persistit/
9
10@GettingStarted.txt
11@BasicAPI.txt
12@Transactions.txt
13@PhysicalStorage.txt
14@Configuration.txt
15@Management.txt
16@Security.txt
17@Serialization.txt
18@Miscellaneous.txt
19
200
=== added file 'doc/Transactions.rst'
--- doc/Transactions.rst 1970-01-01 00:00:00 +0000
+++ doc/Transactions.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,200 @@
1.. _Transactions:
2
3Transactions
4============
5
6Akiban 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.
7
8Applications 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).
9
10Using Transactions
11------------------
12
13The following code fragment performs two store operations within the scope of a transaction:
14
15.. code-block:: java
16
17 //
18 // Get the transaction context for the current thread.
19 //
20 Transaction txn = myExchange.getTransaction();
21 int remainingRetries = RETRY_COUNT;
22 for (;;) {
23 txn.begin();
24 try {
25 myExchange.getValue().put("First value");
26 myExchange.clear().append(1).store();
27 myExchange.getValue().put("Second value");
28 myExchange.clear().append(2).store();
29 // Required to commit the transaction
30 txn.commit();
31 break;
32 } catch (RollbackException re) {
33 // perform any special rollback handling
34 // allow loop to repeat until commit succeeds or retries
35 // too many times.
36 if (--remainingRetries < 0) {
37 throw new TransactionFailedException();
38 }
39 } catch (PersistitException pe) {
40 // handle other Persistit exception
41 } finally {
42 // Required to end the scope of a transaction.
43 txn.end();
44 }
45 }
46
47This 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.
48
49This 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.
50
51One 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:
52
53.. code-block:: java
54
55 //
56 // Get the transaction context for the current thread.
57 //
58 Transaction txn = myExchange.getTransaction();
59 //
60 // Perform the transaction with the following parameters:
61 // - try to commit it up to 10 times
62 // - delay 2 milliseconds before each retry
63 // - use the group commit durability policy
64 //
65 txn.run(new TransactionRunnable() {
66 public void run() throws PersistitException {
67 myExchange.getValue().put("First value");
68 myExchange.clear().append(1).store();
69 myExchange.getValue().put("Second value");
70 myExchange.clear().append(2).store();
71 }
72 }, 10, 2, CommitPolicy.GROUP);
73
74Mixing Transactional and Non-Transactional Operations
75^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
76
77Database 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.
78
79Optimistic Transaction Scheduling
80---------------------------------
81
82To 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.
83
84Optimistic 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.
85
86Snapshot Isolation
87^^^^^^^^^^^^^^^^^^
88
89Persistit 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."
90
91.. _Pruning:
92
93Pruning
94^^^^^^^
95
96Given 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.
97
98Rollbacks
99^^^^^^^^^
100
101Usually 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.
102
103Once 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.
104
105A 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.
106
107Read-Only Transactions
108^^^^^^^^^^^^^^^^^^^^^^
109
110Under 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.
111
112Snapshot Isolation is not Serializable
113^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
114
115It 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.
116
117Note that many common transaction patterns, including those defined by the TPC-C benchmark, do not experience write-skew and therefore *are* serializable under SI.
118
119Durability Options: ``CommitPolicy``
120------------------------------------
121
122Persistit provides three policies that determine the durability of a transaction after it has executed the ``com.persistit.Transaction#commit`` method. These are:
123
124 ``HARD``
125 The ``commit`` method does not return until all updates created by the transaction have been written to non-volatile storage (e.g., disk storage).
126 ``GROUP``
127 The ``commit`` method does not return until all updates created by the transaction have been written to non-volatile storage. In addition, the committing
128 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.
129 ``SOFT``
130 The ``commit`` method returns *before* the updates have been recorded on non-volatile storage. Persistit attempts to write them within 100 milliseconds, but
131 this interval is not guaranteed.
132
133You 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)``.
134
135HARD 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.
136
137SOFT 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.
138
139For 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.
140
141Nested Transactions
142-------------------
143
144A 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.
145
146Accumulators
147------------
148
149Consider 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.
150
151The 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.
152
153Persistit 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.
154
155There are four types of accumulator in Persistit. Each a concrete subclass of the abstract ``com.persistit.Accumulator`` class:
156
157 ``SUM``
158 Tallies a count or sum of contributions by each transaction
159 ``MIN``
160 Finds the minimum value contributed by all transactions
161 ``MAX``
162 Finds the maximum value contributed by all transactions
163 ``SEQ``
164 Special case of the SUM accumulator used to generate sequence numbers
165
166Accumulator 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:
167
168.. code-block:: java
169
170 final Exchange ex = _persistit.getExchange(volume, treeName, true);
171 final Transaction txn = ex.getTransaction();
172 txn.begin();
173 try {
174 final Accumulator acc =
175 ex.getTree().getAccumulator(Accumulator.Type.SUM, 17);
176 long snap = acc.getSnapshotValue(txn);
177 acc.update(1, txn);
178 txn.commit();
179 } finally {
180 txn.end();
181 }
182
183The value 17 is simply an arbitrary index number between 0 and 63, inclusive. The application is responsible for allocating and managing accumulator indexes.
184
185The 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.
186
187An accumulator has two ways of accessing its accumulated value:
188
189 ``getSnapshotValue()``
190 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
191 Transaction.
192 ``getLiveValue()``
193 Is an ephemeral value reflecting all updates performed by all transactions, including concurrent and aborted transactions.
194
195The 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.
196
197SeqAccumulator
198^^^^^^^^^^^^^^
199
200The ``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.
0201
=== removed file 'doc/Transactions.txt'
--- doc/Transactions.txt 2012-04-30 22:09:31 +0000
+++ doc/Transactions.txt 1970-01-01 00:00:00 +0000
@@ -1,179 +0,0 @@
1[[Transactions]]
2= Transactions
3
4Akiban 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.
5
6Applications 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).
7
8== Using Transactions
9
10The following code fragment performs two store operations within the scope of a transaction:
11
12[source,java]
13----
14//
15// Get the transaction context for the current thread.
16//
17Transaction txn = myExchange.getTransaction();
18int remainingRetries = RETRY_COUNT;
19for (;;) {
20 txn.begin();
21 try {
22 myExchange.getValue().put("First value");
23 myExchange.clear().append(1).store();
24 myExchange.getValue().put("Second value");
25 myExchange.clear().append(2).store();
26 // Required to commit the transaction
27 txn.commit();
28 break;
29 } catch (RollbackException re) {
30 // perform any special rollback handling
31 // allow loop to repeat until commit succeeds or retries
32 // too many times.
33 if (--remainingRetries < 0) {
34 throw new TransactionFailedException();
35 }
36 } catch (PersistitException pe) {
37 // handle other Persistit exception
38 } finally {
39 // Required to end the scope of a transaction.
40 txn.end();
41 }
42}
43----
44
45This 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.
46
47This 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.
48
49One 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:
50
51[source,java]
52----
53//
54// Get the transaction context for the current thread.
55//
56Transaction txn = myExchange.getTransaction();
57//
58// Perform the transaction with the following parameters:
59// - try to commit it up to 10 times
60// - delay 2 milliseconds before each retry
61// - use the group commit durability policy
62//
63txn.run(new TransactionRunnable() {
64 public void run() throws PersistitException {
65 myExchange.getValue().put("First value");
66 myExchange.clear().append(1).store();
67 myExchange.getValue().put("Second value");
68 myExchange.clear().append(2).store();
69 }
70}, 10, 2, CommitPolicy.GROUP);
71----
72
73=== Mixing Transactional and Non-Transactional Operations
74
75Database 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.
76
77== Optimistic Transaction Scheduling
78
79To 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.
80
81Optimistic 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.
82
83=== Snapshot Isolation
84
85Persistit 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."
86
87[[Pruning]]
88=== Pruning
89
90Given 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.
91
92=== Rollbacks
93
94Usually 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.
95
96Once 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.
97
98A 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.
99
100=== Read-Only Transactions
101
102Under 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.
103
104=== Snapshot Isolation is not Serializable
105
106It 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.
107
108Note that many common transaction patterns, including those defined by the TPC-C benchmark, do not experience write-skew and therefore _are_ serializable under SI.
109
110== Durability Options: +CommitPolicy+
111
112Persistit provides three policies that determine the durability of a transaction after it has executed the +com.persistit.Transaction#commit+ method. These are:
113
114[horizontal]
115+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).
116+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.
117+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.
118
119You 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)+.
120
121HARD 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.
122
123SOFT 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.
124
125For 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.
126
127== Nested Transactions
128
129A 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.
130
131== Accumulators
132
133Consider 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.
134
135The 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.
136
137Persistit 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.
138
139There are four types of accumulator in Persistit. Each a concrete subclass of the abstract +com.persistit.Accumulator+ class:
140
141[horizontal]
142+SUM+:: Tallies a count or sum of contributions by each transaction
143+MIN+:: Finds the minimum value contributed by all transactions
144+MAX+:: Finds the maximum value contributed by all transactions
145+SEQ+:: Special case of the SUM accumulator used to generate sequence numbers
146
147Accumulator 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:
148
149[source,java]
150----
151final Exchange ex = _persistit.getExchange(volume, treeName, true);
152final Transaction txn = ex.getTransaction();
153txn.begin();
154try {
155 final Accumulator acc =
156 ex.getTree().getAccumulator(Accumulator.Type.SUM, 17);
157 long snap = acc.getSnapshotValue(txn);
158 acc.update(1, txn);
159 txn.commit();
160} finally {
161 txn.end();
162}
163----
164
165The value 17 is simply an arbitrary index number between 0 and 63, inclusive. The application is responsible for allocating and managing accumulator indexes.
166
167The 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.
168
169An accumulator has two ways of accessing its accumulated value:
170
171[horizontal]
172+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.
173+getLiveValue()+:: Is an ephemeral value reflecting all updates performed by all transactions, including concurrent and aborted transactions.
174
175The 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.
176
177=== SeqAccumulator
178
179The +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.
1800
=== modified file 'doc/build/build-doc.sh'
--- doc/build/build-doc.sh 2012-05-25 18:50:59 +0000
+++ doc/build/build-doc.sh 2012-05-30 18:23:19 +0000
@@ -37,12 +37,29 @@
37# The end-product files, user_guide.html and user_guide.xml are written37# The end-product files, user_guide.html and user_guide.xml are written
38# there.38# there.
39#39#
40rm -rf /tmp/akiban-persistit-doc40rm -rf ../../target/sphinx/source
41mkdir /tmp/akiban-persistit-doc41mkdir -p ../../target/sphinx/source
42javac -d /tmp/akiban-persistit-doc -cp ../../core/target/classes/ src/*.java42mkdir -p ../../target/sphinx/classes
43java -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.html43mkdir -p ../../target/sphinx/html
44asciidoc -a toc -n -d book -b xhtml11 -o /tmp/akiban-persistit-doc/doc.html /tmp/akiban-persistit-doc/doc.txt44mkdir -p ../../target/sphinx/text
45asciidoc -a toc -n -d book -b docbook -o /tmp/akiban-persistit-doc/doc.xml /tmp/akiban-persistit-doc/doc.txt45
46sed s/\`/\ / /tmp/akiban-persistit-doc/doc.html > /tmp/akiban-persistit-doc/user_guide.html46cp ../index.rst ../../target/sphinx/source
47sed s/\`/\ / /tmp/akiban-persistit-doc/doc.xml > /tmp/akiban-persistit-doc/user_guide.xml47cp ../conf.py ../../target/sphinx/source
48
49javac -d ../../target/sphinx/classes -cp ../../target/classes/ src/*.java
50
51java -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
52java -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
53java -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
54java -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
55java -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
56java -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
57java -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
58java -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
59java -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
60java -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
61
62sphinx-build -a ../../target/sphinx/source ../../target/sphinx/html
63
64fold -s ../../target/sphinx/source/ReleaseNotes.rst | sed 's/``//g' | sed 's/\.\. note:/NOTE/' | sed 's/::/:/' > ../../target/sphinx/text/ReleaseNotes
4865
4966
=== added file 'doc/build/build-doc.sh.orig'
--- doc/build/build-doc.sh.orig 1970-01-01 00:00:00 +0000
+++ doc/build/build-doc.sh.orig 2012-05-30 18:23:19 +0000
@@ -0,0 +1,48 @@
1#/bin/sh
2#
3# Copyright © 2011-2012 Akiban Technologies, Inc. All rights reserved.
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Affero General Public License as
7# published by the Free Software Foundation, version 3 (only) of the
8# License.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17#
18# This program may also be available under different license terms. For more
19# information, see www.akiban.com or contact licensing@akiban.com.
20#
21
22# ---------------------
23#
24# Builds the Akiban Persistit doc set. Currently this process is based on
25# the asciidoc tool (http://www.methods.co.nz/asciidoc/).
26#
27# Here are the steps:
28# 1. Run a Java program AsciiDocPrep to prepare a text asciidoc file.
29# Among other things, AsciiDocPrep fills in JavaDoc hyperlinks.
30# 2. Run asciidoc to generate an html file.
31# 3. Use sed to replace some characters. Turns out asciidoc doesn't like
32# to link to URLs having spaces, so AsciDocPrep replaces those spaces
33# with the "`" character. This step converts those back to spaces.
34#
35# Run this script from the root of the persistit source directory. This
36# script writes changes only into a directory /tmp/akiban-persistit-doc.
37# The end-product files, user_guide.html and user_guide.xml are written
38# there.
39#
40rm -rf /tmp/akiban-persistit-doc
41mkdir /tmp/akiban-persistit-doc
42javac -d /tmp/akiban-persistit-doc -cp ../../core/target/classes/ src/*.java
43java -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
44asciidoc -a toc -n -d book -b xhtml11 -o /tmp/akiban-persistit-doc/doc.html /tmp/akiban-persistit-doc/doc.txt
45asciidoc -a toc -n -d book -b docbook -o /tmp/akiban-persistit-doc/doc.xml /tmp/akiban-persistit-doc/doc.txt
46sed s/\`/\ / /tmp/akiban-persistit-doc/doc.html > /tmp/akiban-persistit-doc/user_guide.html
47sed s/\`/\ / /tmp/akiban-persistit-doc/doc.xml > /tmp/akiban-persistit-doc/user_guide.xml
48
049
=== added file 'doc/build/src/SphinxDocPrep.java'
--- doc/build/src/SphinxDocPrep.java 1970-01-01 00:00:00 +0000
+++ doc/build/src/SphinxDocPrep.java 2012-05-30 18:23:19 +0000
@@ -0,0 +1,147 @@
1import java.io.BufferedReader;
2import java.io.File;
3import java.io.FileReader;
4import java.io.FileWriter;
5import java.io.PrintWriter;
6import java.util.SortedMap;
7import java.util.regex.Matcher;
8import java.util.regex.Pattern;
9
10import com.persistit.util.ArgParser;
11
12public class SphinxDocPrep {
13
14 private final static Pattern PERSISTIT_PATTERN = Pattern
15 .compile("(``)?(com\\.persistit(?:\\.[a-z]\\w*)*(?:\\.[A-Z]\\w*)+)(?:#(\\w+(?:[\\(\\)\\,a-zA-Z]*)))?(``)?");
16
17 private final static String[] ARG_TEMPLATE = { "in|string:|Input file", "out|string:|Output file",
18 "index|string:|Pathname of index-all.html file", "base|string:|Base of generated URLs", };
19
20 enum BlockState {
21 OUT, WAIT_FIRST_BLANK_LINE, WAIT_SECOND_BLANK_LINE
22 }
23
24 private AsciiDocIndex index;
25 private BlockState block = BlockState.OUT;
26 private PrintWriter writer;
27 private String base;
28 private String indexPath;
29
30 private void prepare(final String[] args) throws Exception {
31 ArgParser ap = new ArgParser("SphinxDocPrep", args, ARG_TEMPLATE);
32 final String inPath = ap.getStringValue("in");
33 final String outPath = ap.getStringValue("out");
34
35 writer = outPath.isEmpty() ? new PrintWriter(System.out) : new PrintWriter(new FileWriter(outPath));
36
37 base = ap.getStringValue("base");
38 if (base.isEmpty()) {
39 base = "http://akiban.com/persistit/doc/apidocs";
40 }
41 indexPath = ap.getStringValue("index");
42 if (indexPath.isEmpty()) {
43 indexPath = "/home/peter/website/apidocs/index-all.html";
44 }
45
46 index = new AsciiDocIndex();
47 System.out.print("Building JavaDoc index..");
48 index.buildIndex(indexPath, base);
49 System.out.println("done");
50
51 processFile(new File(inPath), 0);
52 writer.close();
53 }
54
55 public void processFile(final File file, final int level) throws Exception {
56 BufferedReader reader = new BufferedReader(new FileReader(file));
57 System.out.print("Processing file " + file);
58 String line;
59 while ((line = reader.readLine()) != null) {
60 if (line.startsWith("@")) {
61 processFile(new File(file.getParentFile(), line.substring(1)), level + 1);
62 } else {
63 processLine(line);
64 }
65 }
66 writer.println();
67 System.out.println(" - done");
68 }
69
70 private void processLine(final String line) throws Exception {
71 if (line.contains(".. code-block:")) {
72 block = BlockState.WAIT_FIRST_BLANK_LINE;
73 } else if (line.isEmpty()) {
74 switch (block) {
75 case WAIT_FIRST_BLANK_LINE:
76 block = BlockState.WAIT_SECOND_BLANK_LINE;
77 break;
78
79 case WAIT_SECOND_BLANK_LINE:
80 block = BlockState.OUT;
81 break;
82
83 default:
84 // no change
85 }
86 }
87
88 if (block == BlockState.OUT) {
89 final StringBuffer sb = new StringBuffer();
90 if (line.startsWith("=")) {
91 sb.append("=");
92 }
93 final Matcher matcher = PERSISTIT_PATTERN.matcher(line);
94 while (matcher.find()) {
95 processMatch(matcher, sb);
96 }
97 matcher.appendTail(sb);
98 writer.println(sb.toString());
99 } else {
100 writer.println(line);
101 writer.flush();
102 }
103 }
104
105 private void processMatch(final Matcher matcher, final StringBuffer sb) {
106 String className = matcher.group(2);
107 String methodName = matcher.group(3);
108
109 String replacement;
110 if (methodName == null) {
111 String url = index.getClassMap().get(className);
112 if (url == null || url.isEmpty()) {
113 replacement = "<<<Missing class: " + className + ">>>";
114 } else {
115 replacement = "`" + className + " <" + url + ">`_";
116 }
117 } else {
118 String from = className + "#" + methodName.split("\\(")[0];
119 final SortedMap<String, String> map = index.getMethodMap().tailMap(from);
120 String url;
121 if (map.isEmpty()) {
122 replacement = "<<<Missing method: " + methodName + ">>>";
123 } else {
124 final String first = map.firstKey();
125 url = map.get(first);
126 url = url.replace(" ", "%20");
127 String text = first.split("#")[1];
128 text = text.replace("com.persistit.encoding.", "");
129 text = text.replace("com.persistit.exception.", "");
130 text = text.replace("com.persistit.logging.", "");
131 text = text.replace("com.persistit.mxbeans.", "");
132 text = text.replace("com.persistit.ref.", "");
133 text = text.replace("com.persistit.ui.", "");
134 text = text.replace("com.persistit.", "");
135 text = text.replace("java.lang.", "");
136 text = text.replace("java.util.", "");
137 replacement= "`" + text + " <" + url + ">`_";
138 }
139 }
140
141 matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
142 }
143
144 public static void main(final String[] args) throws Exception {
145 new SphinxDocPrep().prepare(args);
146 }
147}
0148
=== added file 'doc/conf.py'
--- doc/conf.py 1970-01-01 00:00:00 +0000
+++ doc/conf.py 2012-05-30 18:23:19 +0000
@@ -0,0 +1,285 @@
1# -*- coding: utf-8 -*-
2#
3# PersistitDoc documentation build configuration file, created by
4# sphinx-quickstart on Fri May 18 15:19:04 2012.
5#
6# This file is execfile()d with the current directory set to its containing dir.
7#
8# Note that not all possible configuration values are present in this
9# autogenerated file.
10#
11# All configuration values have a default; values that are commented out
12# serve to show the default.
13
14import sys, os
15
16# If extensions (or modules to document with autodoc) are in another directory,
17# add these directories to sys.path here. If the directory is relative to the
18# documentation root, use os.path.abspath to make it absolute, like shown here.
19#sys.path.insert(0, os.path.abspath('.'))
20
21# -- General configuration -----------------------------------------------------
22
23# If your documentation needs a minimal Sphinx version, state it here.
24#needs_sphinx = '1.0'
25
26# Add any Sphinx extension module names here, as strings. They can be extensions
27# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
28extensions = ['sphinx.ext.todo']
29
30# Add any paths that contain templates here, relative to this directory.
31templates_path = ['_templates']
32
33# The suffix of source filenames.
34source_suffix = '.rst'
35
36# The encoding of source files.
37#source_encoding = 'utf-8-sig'
38
39# The master toctree document.
40master_doc = 'index'
41
42# General information about the project.
43project = u'PersistitDoc'
44copyright = u'2012, Akiban Technologies'
45
46# The version info for the project you're documenting, acts as replacement for
47# |version| and |release|, also used in various other places throughout the
48# built documents.
49#
50# The short X.Y version.
51version = '1'
52# The full version, including alpha/beta/rc tags.
53release = '1'
54
55# The language for content autogenerated by Sphinx. Refer to documentation
56# for a list of supported languages.
57#language = None
58
59# There are two options for replacing |today|: either, you set today to some
60# non-false value, then it is used:
61#today = ''
62# Else, today_fmt is used as the format for a strftime call.
63#today_fmt = '%B %d, %Y'
64
65# List of patterns, relative to source directory, that match files and
66# directories to ignore when looking for source files.
67exclude_patterns = []
68
69# The reST default role (used for this markup: `text`) to use for all documents.
70#default_role = None
71
72# If true, '()' will be appended to :func: etc. cross-reference text.
73#add_function_parentheses = True
74
75# If true, the current module name will be prepended to all description
76# unit titles (such as .. function::).
77#add_module_names = True
78
79# If true, sectionauthor and moduleauthor directives will be shown in the
80# output. They are ignored by default.
81#show_authors = False
82
83# The name of the Pygments (syntax highlighting) style to use.
84pygments_style = 'sphinx'
85
86# A list of ignored prefixes for module index sorting.
87#modindex_common_prefix = []
88
89
90# -- Options for HTML output ---------------------------------------------------
91
92# The theme to use for HTML and HTML Help pages. See the documentation for
93# a list of builtin themes.
94html_theme = 'default'
95
96# Theme options are theme-specific and customize the look and feel of a theme
97# further. For a list of options available for each theme, see the
98# documentation.
99#html_theme_options = {}
100
101# Add any paths that contain custom themes here, relative to this directory.
102#html_theme_path = []
103
104# The name for this set of Sphinx documents. If None, it defaults to
105# "<project> v<release> documentation".
106#html_title = None
107
108# A shorter title for the navigation bar. Default is the same as html_title.
109#html_short_title = None
110
111# The name of an image file (relative to this directory) to place at the top
112# of the sidebar.
113#html_logo = None
114
115# The name of an image file (within the static path) to use as favicon of the
116# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
117# pixels large.
118#html_favicon = None
119
120# Add any paths that contain custom static files (such as style sheets) here,
121# relative to this directory. They are copied after the builtin static files,
122# so a file named "default.css" will overwrite the builtin "default.css".
123html_static_path = ['_static']
124
125# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
126# using the given strftime format.
127#html_last_updated_fmt = '%b %d, %Y'
128
129# If true, SmartyPants will be used to convert quotes and dashes to
130# typographically correct entities.
131#html_use_smartypants = True
132
133# Custom sidebar templates, maps document names to template names.
134#html_sidebars = {}
135
136# Additional templates that should be rendered to pages, maps page names to
137# template names.
138#html_additional_pages = {}
139
140# If false, no module index is generated.
141#html_domain_indices = True
142
143# If false, no index is generated.
144#html_use_index = True
145
146# If true, the index is split into individual pages for each letter.
147#html_split_index = False
148
149# If true, links to the reST sources are added to the pages.
150#html_show_sourcelink = True
151
152# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
153#html_show_sphinx = True
154
155# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
156#html_show_copyright = True
157
158# If true, an OpenSearch description file will be output, and all pages will
159# contain a <link> tag referring to it. The value of this option must be the
160# base URL from which the finished HTML is served.
161#html_use_opensearch = ''
162
163# This is the file name suffix for HTML files (e.g. ".xhtml").
164#html_file_suffix = None
165
166# Output file base name for HTML help builder.
167htmlhelp_basename = 'PersistitDocdoc'
168
169
170# -- Options for LaTeX output --------------------------------------------------
171
172latex_elements = {
173# The paper size ('letterpaper' or 'a4paper').
174#'papersize': 'letterpaper',
175
176# The font size ('10pt', '11pt' or '12pt').
177#'pointsize': '10pt',
178
179# Additional stuff for the LaTeX preamble.
180#'preamble': '',
181}
182
183# Grouping the document tree into LaTeX files. List of tuples
184# (source start file, target name, title, author, documentclass [howto/manual]).
185latex_documents = [
186 ('index', 'PersistitDoc.tex', u'PersistitDoc Documentation',
187 u'Akiban Technologies', 'manual'),
188]
189
190# The name of an image file (relative to this directory) to place at the top of
191# the title page.
192#latex_logo = None
193
194# For "manual" documents, if this is true, then toplevel headings are parts,
195# not chapters.
196#latex_use_parts = False
197
198# If true, show page references after internal links.
199#latex_show_pagerefs = False
200
201# If true, show URL addresses after external links.
202#latex_show_urls = False
203
204# Documents to append as an appendix to all manuals.
205#latex_appendices = []
206
207# If false, no module index is generated.
208#latex_domain_indices = True
209
210
211# -- Options for manual page output --------------------------------------------
212
213# One entry per manual page. List of tuples
214# (source start file, name, description, authors, manual section).
215man_pages = [
216 ('index', 'persistitdoc', u'PersistitDoc Documentation',
217 [u'Akiban Technologies'], 1)
218]
219
220# If true, show URL addresses after external links.
221#man_show_urls = False
222
223
224# -- Options for Texinfo output ------------------------------------------------
225
226# Grouping the document tree into Texinfo files. List of tuples
227# (source start file, target name, title, author,
228# dir menu entry, description, category)
229texinfo_documents = [
230 ('index', 'PersistitDoc', u'PersistitDoc Documentation',
231 u'Akiban Technologies', 'PersistitDoc', 'One line description of project.',
232 'Miscellaneous'),
233]
234
235# Documents to append as an appendix to all manuals.
236#texinfo_appendices = []
237
238# If false, no module index is generated.
239#texinfo_domain_indices = True
240
241# How to display URL addresses: 'footnote', 'no', or 'inline'.
242#texinfo_show_urls = 'footnote'
243
244
245# -- Options for Epub output ---------------------------------------------------
246
247# Bibliographic Dublin Core info.
248epub_title = u'PersistitDoc'
249epub_author = u'Akiban Technologies'
250epub_publisher = u'Akiban Technologies'
251epub_copyright = u'2012, Akiban Technologies'
252
253# The language of the text. It defaults to the language option
254# or en if the language is not set.
255#epub_language = ''
256
257# The scheme of the identifier. Typical schemes are ISBN or URL.
258#epub_scheme = ''
259
260# The unique identifier of the text. This can be a ISBN number
261# or the project homepage.
262#epub_identifier = ''
263
264# A unique identification for the text.
265#epub_uid = ''
266
267# A tuple containing the cover image and cover page html template filenames.
268#epub_cover = ()
269
270# HTML files that should be inserted before the pages created by sphinx.
271# The format is a list of tuples containing the path and title.
272#epub_pre_files = []
273
274# HTML files shat should be inserted after the pages created by sphinx.
275# The format is a list of tuples containing the path and title.
276#epub_post_files = []
277
278# A list of files that should not be packed into the epub file.
279#epub_exclude_files = []
280
281# The depth of the table of contents in toc.ncx.
282#epub_tocdepth = 3
283
284# Allow duplicate toc entries.
285#epub_tocdup = True
0286
=== added file 'doc/index.rst'
--- doc/index.rst 1970-01-01 00:00:00 +0000
+++ doc/index.rst 2012-05-30 18:23:19 +0000
@@ -0,0 +1,15 @@
1Akiban Persistit User Guide
2===========================
3.. toctree::
4 :maxdepth: 1
5
6 GettingStarted
7 BasicAPI
8 Transactions
9 PhysicalStorage
10 Configuration
11 Management
12 Security
13 Serialization
14 Miscellaneous
15
016
=== removed file 'doc/overview-summary.txt'
--- doc/overview-summary.txt 2011-04-26 02:10:48 +0000
+++ doc/overview-summary.txt 1970-01-01 00:00:00 +0000
@@ -1,107 +0,0 @@
1
2Persistit 2.2
3=============
4
5Persistit(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.
6
7This section provides a brief overview. See http://com.akiban.com/persistit/documentation/ for complete documentation.
8
9== API Overview
10
11Persistit 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.
12
13Persistit 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.
14
15In 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.)
16
17Within 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).
18
19A 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.)
20
21=== Access Methods
22
23The 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.
24
25Although 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.
26
27To 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.
28
29An 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.
30
31Persistit 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.
32
33An 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:
34. Modify the Key, perform a +fetch+ operation, and extract the Value.
35. Modify the Key, modify the Value, and then perform a +store+ operation.
36. Modify the Key, and then perform a +remove+ operation.
37. Optionally modify the Key, perform a +traverse+ operation, then read the resulting Key and/or Value.
38
39These four methods, plus a few other methods listed here, are the primary low-level interface to the database. Semantics are as follows:
40
41[horizontal]
42+fetch+:: Reads the stored value associated with this Exchange's Key and modifies the Exchange’s Value to reflect that value.
43+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.
44+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.
45+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.
46+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.
47+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.)
48+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.
49+hasNext+, +hasPrevious+:: Indicates, without modifying the Exchange’s Value or Key objects, whether there is a successor or predecessor key in the Tree.
50+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.
51
52Because 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.
53
54=== PersistitMap
55
56Persistit 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.
57
58Keys for PersistitMap must conform to the constraints described above under Keys. Values must conform to the constraints described for Values.
59
60The 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:
61
62[source,java]
63----
64Exchange ex = new Exchange("myVolume", "myTree", true);
65ex.append("USA").append("MA");
66PersistitMap<String, String> map = new PersistitMap<String, String>(ex);
67map.put("Boston", "Hub");
68----
69
70places a key/value pair into the myTree with the concatenated key +{"USA ","MA","Boston"}+ and a value of +"Hub"+.
71
72Because 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.
73
74However, 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.
75=== KeyFilter
76
77A +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.
78
79Use of a KeyFilter is illustrated by the following code fragment:
80
81[source,java]
82----
83Exchange ex = new Exchange("myVolume", "myTree", true);
84KeyFilter kf = new KeyFilter("{\"Bellini\":\"Busoni\"}");
85ex.append(Key.BEFORE);
86while (ex.next(kf))
87{
88 System.out.println(ex.getKey().reset().decodeString());
89}
90----
91
92This simple example emits the string-valued keys within myTree whose values fall alphabetically between “Bellini” and “Busoni”, inclusive.
93
94
95== Transactions
96
97Persistit 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.)
98
99== Configuration
100
101To 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.
102
103== Logging API
104
105Persistit 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.
106
107

Subscribers

People subscribed via source and target branches