jackrabbit-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefan Guggisberg <stefan.guggisb...@gmail.com>
Subject Re: [jr3] Tree model
Date Tue, 06 Mar 2012 11:11:37 GMT
On Tue, Mar 6, 2012 at 11:57 AM, Jukka Zitting <jukka.zitting@gmail.com> wrote:
> 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.

agreed.

>
> 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'd rather keep the length argument since it maps to the corresponding
microkernel method and it might make the implementation easier.

OTOH, i don't feel strong about it.

>
> 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.

+1 for this proposal,thanks!

cheers
stefan

>
> 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