Re: Property index replacement / evolution

2016-08-08 Thread Vikas Saurabh
Hi Ian,

On Mon, Aug 8, 2016 at 3:41 PM, Ian Boston  wrote:
>
> If every successful commit writes the root node, due to every update
> updating a sync prop index, this leaves me wondering how the delayed sync
> reduces the writes to the root node ?
>
> I thought the justification of the 1s sync operation was to reduce the
> writes to the root node to n/s where n is the number of instances in the
> cluster, however based on what you are telling me the rate is (m+n)/s where
> m is the total commits per second of the whole cluster. I understand that
> the update to test for a conflicted commit may not be the same as the
> update of _lastRevs, but in MongoDB both update the MongoDB document.
>

I'm not sure of the exact numbers around how MongoDB would perform for
lots of edits to the same document. There's a bit of difference
between _lastRev write and commit-root conditional update -
commit-root update is a change on a sub-document... so, something like
'set "_revision.rX"="c" on _id=0:/ iff "_conflict.rX"' doesn't exist.
While last rev updates change the same key across commits from the
same cluster node - something like 'set "_lastRevs.r0-0-X"="rY-0-X" '.
I think the idea is to avoid any conflict on MongoDB's update
statements. I'm not sure if such edits (edits to same doc but at a
different sub-doc/key) degrade performance badly.

Thanks,
Vikas
PS: I wonder if we should open a different thread as it seems to be
digressing from the subject :)


Re: Property index replacement / evolution

2016-08-08 Thread Ian Boston
Hi Vikas,

On 8 August 2016 at 14:13, Vikas Saurabh  wrote:

> Hi Ian,
>
> On Sun, Aug 7, 2016 at 10:01 AM, Ian Boston  wrote:
> > Also, IIRC, the root document is not persisted on every commit, but
> > synchronized periodically (once every second) similar to fsync on a disk.
> > So the indexes (in fact all Oak Documents) are synchronous on the local
> Oak
> > instance and are synchronous on remote Oak instances but with a minimum
> > data latency of the root document sync rate (1s). IIUC the 1 second sync
> > period is a performance optimisation as the root document must be updated
> > by every commit and hence is a global singleton in an Oak cluster, and
> > already hot as you point out in 3.
> >
>
> Just to clarify a bit. There are potentially 2 updates that can modify
> root document.
> With every commit, oak (document mk) defines a document to be
> commit-root. That's root of the sub-tree which changes. A commit is
> successful if commit-root could be conditionally updated (condition to
> see if the commit conflicted with something else or not). With
> synchronous prop indices, commit root usually is at root - so each
> successful commit would write to root. That's what Michael was
> pointing to in point3.
> The other update is about asynchronous update of _lastRevs - _lastRevs
> control visibility horizon. For local nodes, a pending list of updates
> is kept in memory so local sessions/builders get to see committed
> changes. These are pushed to persistence mongo during background
> update which defaults at 1 s interval. So, other cluster nodes don't
> see changes immediately.
>

Thanks for the explanation. I learnt something more.

If every successful commit writes the root node, due to every update
updating a sync prop index, this leaves me wondering how the delayed sync
reduces the writes to the root node ?

I thought the justification of the 1s sync operation was to reduce the
writes to the root node to n/s where n is the number of instances in the
cluster, however based on what you are telling me the rate is (m+n)/s where
m is the total commits per second of the whole cluster. I understand that
the update to test for a conflicted commit may not be the same as the
update of _lastRevs, but in MongoDB both update the MongoDB document.

Best Regards
Ian


>
> Thanks,
> Vikas
>


Re: Property index replacement / evolution

2016-08-08 Thread Vikas Saurabh
Hi Ian,

On Sun, Aug 7, 2016 at 10:01 AM, Ian Boston  wrote:
> Also, IIRC, the root document is not persisted on every commit, but
> synchronized periodically (once every second) similar to fsync on a disk.
> So the indexes (in fact all Oak Documents) are synchronous on the local Oak
> instance and are synchronous on remote Oak instances but with a minimum
> data latency of the root document sync rate (1s). IIUC the 1 second sync
> period is a performance optimisation as the root document must be updated
> by every commit and hence is a global singleton in an Oak cluster, and
> already hot as you point out in 3.
>

Just to clarify a bit. There are potentially 2 updates that can modify
root document.
With every commit, oak (document mk) defines a document to be
commit-root. That's root of the sub-tree which changes. A commit is
successful if commit-root could be conditionally updated (condition to
see if the commit conflicted with something else or not). With
synchronous prop indices, commit root usually is at root - so each
successful commit would write to root. That's what Michael was
pointing to in point3.
The other update is about asynchronous update of _lastRevs - _lastRevs
control visibility horizon. For local nodes, a pending list of updates
is kept in memory so local sessions/builders get to see committed
changes. These are pushed to persistence mongo during background
update which defaults at 1 s interval. So, other cluster nodes don't
see changes immediately.

Thanks,
Vikas


Re: Are NodeStore.createBlob and NodeStore.getBlob not symmetric for the SegmentNodeStore?

2016-08-08 Thread Michael Dürig



On 8.8.16 12:46 , Robert Munteanu wrote:

On Mon, 2016-08-08 at 12:45 +0200, Michael Dürig wrote:

The segment node store inlines blobs up to a size of 16512 bytes.
This
is probably the reason you are not able to get them from the blob
store.


Good point. So it's expected that this happens and to test blob
handling I would need to use 'large' blobs?


If you want them to go into the blob store, yes.

Michael


Robert



Michael

On 8.8.16 12:38 , Robert Munteanu wrote:


Hi,

I'm trying to understand the behaviour of NodeStore.createBlob and
NodeStore.getBlob. For context, I'm experimenting with creating a
MultiplexingNodeStore [1] , and this multiplexing would neet to
include
the blob handling as well.

But before that, I'm trying to understand something basic :-)

I have created a SegmentNodeStore with a FileBlobStore

BlobStore blobStore = new FileBlobStore(blobStorePath);
FileStore store =
FileStore.builder(storePath).withBlobStore(blobStore).build();
SegmentNodeStore instance =
SegmentNodeStore.builder(store).build();

After that I have tried to retrieve a blob from the same store

Blob createdBlob = globalStore.createBlob(SMALL_BLOB);
Blob retrievedBlob =
globalStore.getBlob(createdBlob.getReference());

where

private static final InputStream SMALL_BLOB = new
ByteArrayInputStream("hello, world".getBytes());

To my surprise, retrievedBlob is null, since it has a null id.

I've traced the calls to understand what is going on, and in
SegmentBlob.getBlobId() the blobId is null, since the 'head'
variable
is the following code has the value 0.

byte head = segment.readByte(offset);
if ((head & 0xf0) == 0xe0) {
// 1110 : external value, small blob ID
return readShortBlobId(segment, offset, head);
} else if ((head & 0xf8) == 0xf0) {
//  0xxx: external value, long blob ID
return readLongBlobId(segment, offset);
} else {
return null;
}

Now, this works as expected for a DocumentNodeStore backed by H2,
so
something is not entirely right.

So my question is - why does this happen?

1) Is this sequence of calls (createBlob/getBlob) not supposed to
be
symmetric?
2) Am I configuring the SegmentNodeStore incorrectly?
3) Is it a bug to file against the SegmentNodeStore?

If you're curious, the full test code is at [2], although I haven't
committed the variant which checks the SegmentNodeStore for blob
handling consistency.

Thanks,

Robert

[1]: https://github.com/apache/jackrabbit-oak/compare/trunk...rombe
rt:f
eatures/nodestore-multiplex?expand=1
[2]: https://github.com/rombert/jackrabbit-oak/blob/99cd3d8b81213fa
03a2
ebee2ad754081dbd5977f/oak-
it/src/test/java/org/apache/jackrabbit/oak/plugins/memory/multiplex
/Mul
tiplexingMemoryNodeStoreTest.java





Re: Are NodeStore.createBlob and NodeStore.getBlob not symmetric for the SegmentNodeStore?

2016-08-08 Thread Robert Munteanu
On Mon, 2016-08-08 at 12:45 +0200, Michael Dürig wrote:
> The segment node store inlines blobs up to a size of 16512 bytes.
> This 
> is probably the reason you are not able to get them from the blob
> store.

Good point. So it's expected that this happens and to test blob
handling I would need to use 'large' blobs?

Robert

> 
> Michael
> 
> On 8.8.16 12:38 , Robert Munteanu wrote:
> > 
> > Hi,
> > 
> > I'm trying to understand the behaviour of NodeStore.createBlob and
> > NodeStore.getBlob. For context, I'm experimenting with creating a
> > MultiplexingNodeStore [1] , and this multiplexing would neet to
> > include
> > the blob handling as well.
> > 
> > But before that, I'm trying to understand something basic :-)
> > 
> > I have created a SegmentNodeStore with a FileBlobStore
> > 
> > BlobStore blobStore = new FileBlobStore(blobStorePath);
> > FileStore store =
> > FileStore.builder(storePath).withBlobStore(blobStore).build();
> > SegmentNodeStore instance =
> > SegmentNodeStore.builder(store).build();
> > 
> > After that I have tried to retrieve a blob from the same store
> > 
> > Blob createdBlob = globalStore.createBlob(SMALL_BLOB);
> > Blob retrievedBlob =
> > globalStore.getBlob(createdBlob.getReference());
> > 
> > where
> > 
> > private static final InputStream SMALL_BLOB = new
> > ByteArrayInputStream("hello, world".getBytes());
> > 
> > To my surprise, retrievedBlob is null, since it has a null id.
> > 
> > I've traced the calls to understand what is going on, and in
> > SegmentBlob.getBlobId() the blobId is null, since the 'head'
> > variable
> > is the following code has the value 0.
> > 
> > byte head = segment.readByte(offset);
> > if ((head & 0xf0) == 0xe0) {
> > // 1110 : external value, small blob ID
> > return readShortBlobId(segment, offset, head);
> > } else if ((head & 0xf8) == 0xf0) {
> > //  0xxx: external value, long blob ID
> > return readLongBlobId(segment, offset);
> > } else {
> > return null;
> > }
> > 
> > Now, this works as expected for a DocumentNodeStore backed by H2,
> > so
> > something is not entirely right.
> > 
> > So my question is - why does this happen?
> > 
> > 1) Is this sequence of calls (createBlob/getBlob) not supposed to
> > be
> > symmetric?
> > 2) Am I configuring the SegmentNodeStore incorrectly?
> > 3) Is it a bug to file against the SegmentNodeStore?
> > 
> > If you're curious, the full test code is at [2], although I haven't
> > committed the variant which checks the SegmentNodeStore for blob
> > handling consistency.
> > 
> > Thanks,
> > 
> > Robert
> > 
> > [1]: https://github.com/apache/jackrabbit-oak/compare/trunk...rombe
> > rt:f
> > eatures/nodestore-multiplex?expand=1
> > [2]: https://github.com/rombert/jackrabbit-oak/blob/99cd3d8b81213fa
> > 03a2
> > ebee2ad754081dbd5977f/oak-
> > it/src/test/java/org/apache/jackrabbit/oak/plugins/memory/multiplex
> > /Mul
> > tiplexingMemoryNodeStoreTest.java
> > 



Re: Are NodeStore.createBlob and NodeStore.getBlob not symmetric for the SegmentNodeStore?

2016-08-08 Thread Michael Dürig


The segment node store inlines blobs up to a size of 16512 bytes. This 
is probably the reason you are not able to get them from the blob store.


Michael

On 8.8.16 12:38 , Robert Munteanu wrote:

Hi,

I'm trying to understand the behaviour of NodeStore.createBlob and
NodeStore.getBlob. For context, I'm experimenting with creating a
MultiplexingNodeStore [1] , and this multiplexing would neet to include
the blob handling as well.

But before that, I'm trying to understand something basic :-)

I have created a SegmentNodeStore with a FileBlobStore

BlobStore blobStore = new FileBlobStore(blobStorePath);
FileStore store =
FileStore.builder(storePath).withBlobStore(blobStore).build();
SegmentNodeStore instance =
SegmentNodeStore.builder(store).build();

After that I have tried to retrieve a blob from the same store

Blob createdBlob = globalStore.createBlob(SMALL_BLOB);
Blob retrievedBlob =
globalStore.getBlob(createdBlob.getReference());

where

private static final InputStream SMALL_BLOB = new
ByteArrayInputStream("hello, world".getBytes());

To my surprise, retrievedBlob is null, since it has a null id.

I've traced the calls to understand what is going on, and in
SegmentBlob.getBlobId() the blobId is null, since the 'head' variable
is the following code has the value 0.

byte head = segment.readByte(offset);
if ((head & 0xf0) == 0xe0) {
// 1110 : external value, small blob ID
return readShortBlobId(segment, offset, head);
} else if ((head & 0xf8) == 0xf0) {
//  0xxx: external value, long blob ID
return readLongBlobId(segment, offset);
} else {
return null;
}

Now, this works as expected for a DocumentNodeStore backed by H2, so
something is not entirely right.

So my question is - why does this happen?

1) Is this sequence of calls (createBlob/getBlob) not supposed to be
symmetric?
2) Am I configuring the SegmentNodeStore incorrectly?
3) Is it a bug to file against the SegmentNodeStore?

If you're curious, the full test code is at [2], although I haven't
committed the variant which checks the SegmentNodeStore for blob
handling consistency.

Thanks,

Robert

[1]: https://github.com/apache/jackrabbit-oak/compare/trunk...rombert:f
eatures/nodestore-multiplex?expand=1
[2]: https://github.com/rombert/jackrabbit-oak/blob/99cd3d8b81213fa03a2
ebee2ad754081dbd5977f/oak-
it/src/test/java/org/apache/jackrabbit/oak/plugins/memory/multiplex/Mul
tiplexingMemoryNodeStoreTest.java