diff --git a/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/ORidBag.java b/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/ORidBag.java index e84ab7d0729..20f4561154e 100755 --- a/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/ORidBag.java +++ b/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/ORidBag.java @@ -270,41 +270,48 @@ public void checkAndConvert() { if (isEmbedded() && ODatabaseRecordThreadLocal.instance().get().getSbTreeCollectionManager() != null && delegate.size() >= topThreshold) { ORidBagDelegate oldDelegate = delegate; + boolean isTransactionModified = oldDelegate.isTransactionModified(); delegate = new OSBTreeRidBag(); boolean oldAutoConvert = oldDelegate.isAutoConvertToRecord(); oldDelegate.setAutoConvertToRecord(false); + final ORecordElement owner = oldDelegate.getOwner(); + delegate.disableTracking(owner); for (OIdentifiable identifiable : oldDelegate) { delegate.add(identifiable); } - final ORecordElement owner = oldDelegate.getOwner(); delegate.setOwner(owner); delegate.setTracker(oldDelegate.getTracker()); oldDelegate.disableTracking(owner); - delegate.setDirty(); + delegate.setTransactionModified(isTransactionModified); + delegate.enableTracking(owner); oldDelegate.setAutoConvertToRecord(oldAutoConvert); oldDelegate.requestDelete(); } else if (bottomThreshold >= 0 && !isEmbedded() && delegate.size() <= bottomThreshold) { ORidBagDelegate oldDelegate = delegate; + boolean isTransactionModified = oldDelegate.isTransactionModified(); boolean oldAutoConvert = oldDelegate.isAutoConvertToRecord(); oldDelegate.setAutoConvertToRecord(false); delegate = new OEmbeddedRidBag(); + final ORecordElement owner = oldDelegate.getOwner(); + delegate.disableTracking(owner); for (OIdentifiable identifiable : oldDelegate) { delegate.add(identifiable); } - final ORecordElement owner = oldDelegate.getOwner(); delegate.setOwner(owner); delegate.setTracker(oldDelegate.getTracker()); oldDelegate.disableTracking(owner); delegate.setDirty(); + delegate.setTransactionModified(isTransactionModified); + delegate.enableTracking(owner); oldDelegate.setAutoConvertToRecord(oldAutoConvert); oldDelegate.requestDelete(); diff --git a/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/ORidBagDelegate.java b/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/ORidBagDelegate.java index 29fb5a61479..2de80567c97 100755 --- a/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/ORidBagDelegate.java +++ b/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/ORidBagDelegate.java @@ -82,4 +82,6 @@ public interface ORidBagDelegate OSimpleMultiValueTracker getTracker(); void setTracker(OSimpleMultiValueTracker tracker); + + void setTransactionModified(boolean transactionModified); } diff --git a/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/embedded/OEmbeddedRidBag.java b/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/embedded/OEmbeddedRidBag.java index abe3a43ae1d..ceaa183ef17 100755 --- a/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/embedded/OEmbeddedRidBag.java +++ b/core/src/main/java/com/orientechnologies/orient/core/db/record/ridbag/embedded/OEmbeddedRidBag.java @@ -276,7 +276,6 @@ public void remove(OIdentifiable identifiable) { * * @param index * @param newValue - * * @return */ public boolean swap(int index, OIdentifiable newValue) { @@ -616,6 +615,10 @@ public RET setDirty() { return (RET) this; } + public void setTransactionModified(boolean transactionDirty) { + this.transactionDirty = transactionDirty; + } + @Override public void setDirtyNoChanged() { if (owner != null) diff --git a/core/src/main/java/com/orientechnologies/orient/core/record/impl/OSimpleMultiValueTracker.java b/core/src/main/java/com/orientechnologies/orient/core/record/impl/OSimpleMultiValueTracker.java index 1d805f2bae8..3e908a07ee5 100644 --- a/core/src/main/java/com/orientechnologies/orient/core/record/impl/OSimpleMultiValueTracker.java +++ b/core/src/main/java/com/orientechnologies/orient/core/record/impl/OSimpleMultiValueTracker.java @@ -112,8 +112,9 @@ public boolean isEnabled() { return enabled; } - public void sourceFrom(OSimpleMultiValueTracker tracker) { + public void sourceFrom(OSimpleMultiValueTracker tracker) { this.timeLine = tracker.timeLine; + this.transactionTimeLine = tracker.transactionTimeLine; } public OMultiValueChangeTimeLine getTimeLine() { diff --git a/core/src/main/java/com/orientechnologies/orient/core/serialization/serializer/record/binary/ODocumentSerializerDelta.java b/core/src/main/java/com/orientechnologies/orient/core/serialization/serializer/record/binary/ODocumentSerializerDelta.java index cad695974c1..a82d8d28c84 100644 --- a/core/src/main/java/com/orientechnologies/orient/core/serialization/serializer/record/binary/ODocumentSerializerDelta.java +++ b/core/src/main/java/com/orientechnologies/orient/core/serialization/serializer/record/binary/ODocumentSerializerDelta.java @@ -603,7 +603,7 @@ private void serializeDeltaLinkBag(BytesContainer bytes, ORidBag value) { OUUIDSerializer.INSTANCE.serialize(uuid, bytes.bytes, uuidPos); OMultiValueChangeTimeLine timeline = value.getTransactionTimeLine(); - assert timeline != null : "Collection timeline required for link* types serialization"; + assert timeline != null : "Collection timeline required for link types serialization"; OVarIntSerializer.write(bytes, timeline.getMultiValueChangeEvents().size()); for (OMultiValueChangeEvent event : timeline.getMultiValueChangeEvents()) { switch (event.getChangeType()) { diff --git a/core/src/main/java/com/orientechnologies/orient/core/storage/ridbag/sbtree/OSBTreeRidBag.java b/core/src/main/java/com/orientechnologies/orient/core/storage/ridbag/sbtree/OSBTreeRidBag.java index 298a0b187bc..cfcae8f1ba9 100755 --- a/core/src/main/java/com/orientechnologies/orient/core/storage/ridbag/sbtree/OSBTreeRidBag.java +++ b/core/src/main/java/com/orientechnologies/orient/core/storage/ridbag/sbtree/OSBTreeRidBag.java @@ -1067,6 +1067,10 @@ public RET setDirty() { return (RET) this; } + public void setTransactionModified(boolean transactionDirty) { + this.transactionDirty = transactionDirty; + } + @Override public void setDirtyNoChanged() { if (owner != null) @@ -1089,4 +1093,5 @@ public void setTracker(OSimpleMultiValueTracker tr public OMultiValueChangeTimeLine getTransactionTimeLine() { return this.tracker.getTransactionTimeLine(); } + } diff --git a/distributed/src/main/java/com/orientechnologies/orient/server/distributed/impl/OTransactionOptimisticDistributed.java b/distributed/src/main/java/com/orientechnologies/orient/server/distributed/impl/OTransactionOptimisticDistributed.java index c0d480654c8..1f2f60cff32 100644 --- a/distributed/src/main/java/com/orientechnologies/orient/server/distributed/impl/OTransactionOptimisticDistributed.java +++ b/distributed/src/main/java/com/orientechnologies/orient/server/distributed/impl/OTransactionOptimisticDistributed.java @@ -71,29 +71,23 @@ private void resolveTracking(ORecordOperation change, boolean onlyExecutorCase) break; case ORecordOperation.UPDATED: { OIdentifiable updateRecord = change.getRecord(); - - ODocument original = database.load(updateRecord.getIdentity()); - if (original == null) { - throw new ORecordNotFoundException(updateRecord.getIdentity()); - } - - original.merge((ODocument) updateRecord, false, false); - - ODocument updateDoc = original; - OLiveQueryHook.addOp(updateDoc, ORecordOperation.UPDATED, database); - OLiveQueryHookV2.addOp(updateDoc, ORecordOperation.UPDATED, database); - OImmutableClass clazz = ODocumentInternal.getImmutableSchemaClass(updateDoc); - if (clazz != null) { - if (onlyExecutorCase) { - OClassIndexManager.processIndexOnUpdate(database, updateDoc, changes); - } - if (clazz.isFunction()) { - database.getSharedContext().getFunctionLibrary().updatedFunction(updateDoc); - Orient.instance().getScriptManager().close(database.getName()); - } - if (clazz.isSequence()) { - ((OSequenceLibraryProxy) database.getMetadata().getSequenceLibrary()).getDelegate() - .onSequenceUpdated(database, updateDoc); + if (updateRecord instanceof ODocument) { + ODocument updateDoc = (ODocument) updateRecord; + OLiveQueryHook.addOp(updateDoc, ORecordOperation.UPDATED, database); + OLiveQueryHookV2.addOp(updateDoc, ORecordOperation.UPDATED, database); + OImmutableClass clazz = ODocumentInternal.getImmutableSchemaClass(updateDoc); + if (clazz != null) { + if (onlyExecutorCase) { + OClassIndexManager.processIndexOnUpdate(database, updateDoc, changes); + } + if (clazz.isFunction()) { + database.getSharedContext().getFunctionLibrary().updatedFunction(updateDoc); + Orient.instance().getScriptManager().close(database.getName()); + } + if (clazz.isSequence()) { + ((OSequenceLibraryProxy) database.getMetadata().getSequenceLibrary()).getDelegate() + .onSequenceUpdated(database, updateDoc); + } } } updatedRecords.put(change.getRID(), change.getRecord()); diff --git a/distributed/src/main/java/com/orientechnologies/orient/server/distributed/impl/task/OTransactionPhase1Task.java b/distributed/src/main/java/com/orientechnologies/orient/server/distributed/impl/task/OTransactionPhase1Task.java index 054e654eb51..53b9c463b2f 100644 --- a/distributed/src/main/java/com/orientechnologies/orient/server/distributed/impl/task/OTransactionPhase1Task.java +++ b/distributed/src/main/java/com/orientechnologies/orient/server/distributed/impl/task/OTransactionPhase1Task.java @@ -11,6 +11,8 @@ import com.orientechnologies.orient.core.id.ORecordId; import com.orientechnologies.orient.core.record.ORecord; import com.orientechnologies.orient.core.record.ORecordInternal; +import com.orientechnologies.orient.core.record.impl.ODocument; +import com.orientechnologies.orient.core.serialization.serializer.record.binary.ODocumentSerializerDelta; import com.orientechnologies.orient.core.serialization.serializer.record.binary.ORecordSerializerNetworkDistributed; import com.orientechnologies.orient.core.storage.ORecordDuplicatedException; import com.orientechnologies.orient.core.storage.impl.local.paginated.wal.OLogSequenceNumber; @@ -69,10 +71,17 @@ public void genOps(List ops) { request.setRecordType(ORecordInternal.getRecordType(txEntry.getRecord())); switch (txEntry.type) { case ORecordOperation.CREATED: - case ORecordOperation.UPDATED: request.setRecord(ORecordSerializerNetworkDistributed.INSTANCE.toStream(txEntry.getRecord())); request.setContentChanged(ORecordInternal.isContentChanged(txEntry.getRecord())); break; + case ORecordOperation.UPDATED: + if (request.getRecordType() == ODocument.RECORD_TYPE) { + request.setRecord(ODocumentSerializerDelta.instance().serializeDelta((ODocument) txEntry.getRecord())); + } else { + request.setRecord(ORecordSerializerNetworkDistributed.INSTANCE.toStream(txEntry.getRecord())); + } + request.setContentChanged(ORecordInternal.isContentChanged(txEntry.getRecord())); + break; case ORecordOperation.DELETED: break; } @@ -162,20 +171,30 @@ private void convert(ODatabaseDocumentInternal database) { ORecord record = null; switch (type) { - case ORecordOperation.CREATED: - case ORecordOperation.UPDATED: { + case ORecordOperation.CREATED: { record = ORecordSerializerNetworkDistributed.INSTANCE.fromStream(req.getRecord(), null); ORecordInternal.setRecordSerializer(record, database.getSerializer()); + break; } + case ORecordOperation.UPDATED: { + if (req.getRecordType() == ODocument.RECORD_TYPE) { + record = database.load(req.getId()); + ODocumentSerializerDelta.instance().deserializeDelta(req.getRecord(), (ODocument) record); + } else { + record = ORecordSerializerNetworkDistributed.INSTANCE.fromStream(req.getRecord(), null); + ORecordInternal.setRecordSerializer(record, database.getSerializer()); + } break; - case ORecordOperation.DELETED: - record = database.getRecord(req.getId()); + } + case ORecordOperation.DELETED: { + record = database.load(req.getId()); if (record == null) { record = Orient.instance().getRecordFactoryManager() .newInstance(req.getRecordType(), req.getId().getClusterId(), database); } break; } + } ORecordInternal.setIdentity(record, (ORecordId) req.getId()); ORecordInternal.setVersion(record, req.getVersion()); ORecordOperation op = new ORecordOperation(record, type);