jackrabbit-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jukka Zitting <jukka.zitt...@gmail.com>
Subject Re: [jr3] Tree model
Date Tue, 06 Mar 2012 10:57:03 GMT
Hi,

On Mon, Mar 5, 2012 at 3:06 PM, Stefan Guggisberg
<stefan.guggisberg@gmail.com> wrote:
> Properties and child nodes are all addressed using an unordered
> name->item mapping on the parent node.
>
> what made me change my mind is that the JSON model
> doesn't (naturally) support ordered child entries. i've forgot
> about that and i guess that mandating order in a JSON-like
> model spells trouble sooner or later.

Right. That's also my intuition.

> for getChildNodeEntries() we can therefore drop the distinction
> between user-defined and native order and just
> state that the iteration order is stable.

Sounds good. The nice thing about this is that it's fairly easy to put
orderability back in at a later point as adding an extra API
constraint can't break existing code whereas removing one (like in
dropping the orderability requirement) can get a bit painful in case
we've already started relying on it in higher-level code.

See below for an updated NodeState interface draft that drops the
orderability requirement (but still requires some stable ordering). I
also changed the size and offset types from int to long to resolve the
mini-debate on a potential built-in size limit, regardless of how
likely reaching a 2G limit would have been. Finally, for simplicity I
dropped the length argument from getChildNodeEntries(), as the added
value it gives is pretty small.

I'm still keeping the numeric offset parameter since it's needed for
efficiently implementing the MicroKernel interface and there's no easy
alternative that would still keep the MicroKernel directly applicable
as a remote access interface.

BR,

Jukka Zitting


/**
 * A content tree consists of nodes and properties, each of which
 * evolves through different states during its lifecycle. This interface
 * represents a specific, immutable state of a node in a content tree.
 * Depending on context, a NodeState instance can be interpreted as
 * representing the state of just that node, of the subtree starting at
 * that node, or of an entire tree in case it's a root node.
 * <p>
 * The crucial difference between this interface and the similarly named
 * class in Jackrabbit 2.x is that this interface represents a specific,
 * immutable state of a node, whereas the Jackrabbit 2.x class represented
 * the "current" state of a node.
 *
 * <h2>Properties and child nodes</h2>
 * <p>
 * A node consists of an unordered set of name -&gt; item mappings. Each
 * property and child node is uniquely named and a single name can only
 * refer to a property or a child node, not both at the same time.
 *
 * <h2>Immutability and thread-safety</h2>
 * <p>
 * As mentioned above, all node and property states are always immutable.
 * Thus repeating a method call is always guaranteed to produce the same
 * result as before unless some internal error occurs (see below). Note
 * however that this immutability only applies to a specific state instance.
 * Different states of a node can obviously be different, and in some cases
 * even different instances of the same state may behave slightly differently.
 * For example due to performance optimization or other similar changes the
 * iteration order of properties or child nodes may be different for two
 * instances of the same state.
 * <p>
 * In addition to being immutable, a specific state instance guaranteed to
 * be fully thread-safe. Possible caching or other internal changes need to
 * be properly synchronized so that any number of concurrent clients can
 * safely access a state instance.
 *
 * <h2>Persistence and error-handling</h2>
 * <p>
 * A node state can be (and often is) backed by local files or network
 * resources. All IO operations or related concerns like caching should be
 * handled transparently below this interface. Potential IO problems and
 * recovery attempts like retrying a timed-out network access need to be
 * handled below this interface, and only hard errors should be thrown up
 * as {@link RuntimeException unchecked exceptions} that higher level code
 * is not expected to be able to recover from.
 * <p>
 * Since this interface exposes no higher level constructs like access
 * controls, locking, node types or even path parsing, there's no way
 * for content access to fail because of such concerns. Such functionality
 * and related checked exceptions or other control flow constructs should
 * be implemented on a higher level above this interface.
 *
 * <h2>Decoration and virtual content</h2>
 * <p>
 * Not all content exposed by this interface needs to be backed by actual
 * persisted data. An implementation may want to provide provide derived
 * data like for example the aggregate size of the entire subtree as an
 * extra virtual property. A virtualization, sharding or caching layer
 * could provide a composite view over multiple underlying content trees.
 * Or a basic access control layer could decide to hide certain content
 * based on specific rules. All such features need to be implemented
 * according to the API contract of this interface. A separate higher level
 * interface needs to be used if an implementation can't for example
 * guarantee immutability of exposed content as discussed above.
 */
public interface NodeState {

    /**
     * Returns the named property. The name is an opaque string and
     * is not parsed or otherwise interpreted by this method.
     * <p>
     * The namespace of properties and child nodes is shared, so if
     * this method returns a non-<code>null</code> value for a given
     * name, then {@link #getChildNode(String)} is guaranteed to return
     * <code>null</code> for the same name.
     *
     * @param name name of the property to return
     * @return named property, or <code>null</code> if not found
     */
    PropertyState getProperty(String name);

    /**
     * Returns the number of properties of this node.
     *
     * @return number of properties
     */
    long getPropertyCount();

    /**
     * Returns an iterable of the properties of this node. Multiple
     * iterations are guaranteed to return the properties in the same
     * order, but the specific order used is implementation-dependent
     * and may change across different states of the same node.
     *
     * @return properties in some stable order
     */
    Iterable<PropertyState> getProperties();

    /**
     * Returns the named child node. The name is an opaque string and
     * is not parsed or otherwise interpreted by this method.
     * <p>
     * The namespace of properties and child nodes is shared, so if
     * this method returns a non-<code>null</code> value for a given
     * name, then {@link #getProperty(String)} is guaranteed to return
     * <code>null</code> for the same name.
     *
     * @param name name of the child node to return
     * @return named child node, or <code>null</code> if not found
     */
    NodeState getChildNode(String name);

    /**
     * Returns the number of child nodes of this node.
     *
     * @return number of child nodes
     */
    long getChildNodeCount();

    /**
     * Returns an iterable of the child node entries starting from the
     * given offset. Multiple iterations are guaranteed to return the
     * child nodes in the same order, but the specific order used is
     * implementation-dependent and may change across different states
     * of the same node. An empty iterable is returned if the given
     * offset is greater than the offset of the last child node entry.
     *
     * @param offset zero-based offset of the first entry to return
     * @return requested child node entries in some stable order
     */
    Iterable<ChildNodeEntry> getChildNodeEntries(long offset);

}

Mime
View raw message