Return-Path: X-Original-To: apmail-jackrabbit-dev-archive@www.apache.org Delivered-To: apmail-jackrabbit-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id AF3C695B2 for ; Wed, 29 Feb 2012 07:56:04 +0000 (UTC) Received: (qmail 29338 invoked by uid 500); 29 Feb 2012 07:56:04 -0000 Delivered-To: apmail-jackrabbit-dev-archive@jackrabbit.apache.org Received: (qmail 29285 invoked by uid 500); 29 Feb 2012 07:56:04 -0000 Mailing-List: contact dev-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list dev@jackrabbit.apache.org Received: (qmail 29267 invoked by uid 99); 29 Feb 2012 07:56:03 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 29 Feb 2012 07:56:03 +0000 X-ASF-Spam-Status: No, hits=-2.3 required=5.0 tests=RCVD_IN_DNSWL_MED,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of mueller@adobe.com designates 64.18.1.21 as permitted sender) Received: from [64.18.1.21] (HELO exprod6og108.obsmtp.com) (64.18.1.21) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 29 Feb 2012 07:55:55 +0000 Received: from outbound-smtp-2.corp.adobe.com ([193.104.215.16]) by exprod6ob108.postini.com ([64.18.5.12]) with SMTP ID DSNKT03Z76DGpQTU1jpISnoidmdnEucxyOb8@postini.com; Tue, 28 Feb 2012 23:55:27 PST Received: from inner-relay-1.corp.adobe.com (inner-relay-1.adobe.com [153.32.1.51]) by outbound-smtp-2.corp.adobe.com (8.12.10/8.12.10) with ESMTP id q1T7tPN3024691 for ; Tue, 28 Feb 2012 23:55:26 -0800 (PST) Received: from nacas01.corp.adobe.com (nacas01.corp.adobe.com [10.8.189.99]) by inner-relay-1.corp.adobe.com (8.12.10/8.12.10) with ESMTP id q1T7tOMM028299 for ; Tue, 28 Feb 2012 23:55:24 -0800 (PST) Received: from eurcas01.eur.adobe.com (10.128.4.27) by nacas01.corp.adobe.com (10.8.189.99) with Microsoft SMTP Server (TLS) id 8.3.192.1; Tue, 28 Feb 2012 23:55:25 -0800 Received: from eurmbx01.eur.adobe.com ([10.128.4.32]) by eurcas01.eur.adobe.com ([10.128.4.27]) with mapi; Wed, 29 Feb 2012 07:55:23 +0000 From: Thomas Mueller To: "dev@jackrabbit.apache.org" Date: Wed, 29 Feb 2012 07:55:19 +0000 Subject: Re: [jr3] Tree model Thread-Topic: [jr3] Tree model Thread-Index: Acz2t32A8YULW7ZESj+/7qdsr8YV3Q== Message-ID: In-Reply-To: <4F4D79B2.1050009@apache.org> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: user-agent: Microsoft-MacOutlook/14.14.0.111121 acceptlanguage: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Virus-Checked: Checked by ClamAV on apache.org Hi, I think we all have more or less the same basic idea. Well, I would call it "Node" and not "Tree" because the term node more closely matches what we do. But first about what we seem to agree: * A persistent and immutable data structure has many benefits (for example concurrency). * Mutable data strucutures also have benefits: it avoids creating lots of garbage and a new root node for each and every modification. I think we should use a structure that is immutable when reading, but mutable when writing. Write methods should return a new object (for example cloneAndAddChildNode), but only when necessary, that is, if the revision doesn't match. When the revision matches, the internal state is changed instead, and the cloneAndAddChildNode method returns 'this'. A first implementation is org.apache.jackrabbit.mk.simple.NodeImpl. > everyone has their own > MicroKernel implementation. The reasons why we have two implementations is, Stefan and I could not agree on a few implementation details. My view is: * Stefan assumes it's important to use the content hash as the node id, while I think this hurts performance too much (as the randomly distributed node ids hurt storage performance in Jackrabbit 2). With the copy-on-write model it is even a bigger performance problem because each time a node is changed it gets a new node id (I didn't think about this first). That means even small repositories are problematic if there are many changes. * Stefan implemented a different way to represent large child node lists. He used a h-tree (the hash code of the child node name), which means child nodes are pseudo-randomly distributed. I think this hurts performance too much (same reason as above: a stored index on randomly distributed keys is required). =20 * Stefan believes concurrent write operations are very important while I believe this will not increase write throughput as much as it complicates the implementation (Stefan implementations merges changes while my implementation does not). =20 * Stefans implementation re-constructs the journal by diffing the node tree. I believe this is troublesome because it is not always possible to re-construct the journal with regards to re-order and move operations. Also I believe this adds more complexity that the possible benefit (because the journal doesn't need to be stored). In my implementation the journal is stored.=20 There is quite a lot of common code, for example the data store, parsing and constructing JSON / JSOP. My implementation consists of the classes in org.apache.jackrabbit.mk.simple. The classes NodeImpl, NodeList, NodeListSmall are used again in multiple different modules (the index and the wrapper implementations for example). So what is really unique in my "storage" implementation is the 3 NodeMap implementations, NodeListTrie to support large child node lists, the Revision class, and SimpleKernelImpl. Regards, Thomas