diff --git a/core/src/main/java/com/orientechnologies/orient/core/record/impl/ODocument.java b/core/src/main/java/com/orientechnologies/orient/core/record/impl/ODocument.java index 1ad5fbca952..ebfac428c1b 100755 --- a/core/src/main/java/com/orientechnologies/orient/core/record/impl/ODocument.java +++ b/core/src/main/java/com/orientechnologies/orient/core/record/impl/ODocument.java @@ -3246,10 +3246,83 @@ protected void unTrack(OIdentifiable id) { super.unTrack(id); } - private Object getUpdateDeltaValue(Object currentValue, boolean changed){ + private class TypeValue{ + Object value; + UpdateDeltaValueType type; + } + + private TypeValue getUpdateDeltaValue(Object currentValue, Object previousValue, boolean changed){ //TODO review this clause once again if (changed || !(currentValue instanceof ODocument)){ - return currentValue; + OType currentType = OType.getTypeByClass(currentValue.getClass()); + TypeValue retVal = new TypeValue(); + //separate processing for embedded lists + //if previous value is null we want to send whole list to reduce overhead + if (currentType == OType.EMBEDDEDLIST && previousValue != null){ + OType previousType = OType.getTypeByClass(previousValue.getClass()); + //if previous value differs in type we want to send whole list to reduce overhead + if (currentType == previousType){ + retVal.type = UpdateDeltaValueType.LIST_UPDATE; + List deltaList = new ArrayList(); + retVal.value = deltaList; + //now find a diff + List currentList = (List)currentValue; + List previousList = (List)previousValue; + int i = 0; + for (i = 0; i < currentList.size(); i++){ + Object currentElement = currentList.get(i); + if (i > previousList.size() - 1){ + //these elements doesn't have pair in original list + ODocument deltaElement = new ODocument(); + deltaElement.field("t", UpdateDeltaValueType.getOrd(UpdateDeltaValueType.LIST_ELEMENT_ADD)); + deltaElement.field("v", currentElement); + deltaElement.field("i", i); + deltaList.add(deltaElement); + continue; + } + //these elements have pairs in original list, so we need to calculate deltas + Object originalElement = previousList.get(i); + //check if can we go just we value change + if (!currentElement.getClass().equals(originalElement.getClass()) || + !(currentElement instanceof ODocument) || + !(currentElement instanceof List)){ + ODocument deltaElement = new ODocument(); + deltaElement.field("t", UpdateDeltaValueType.getOrd(UpdateDeltaValueType.LIST_ELEMENT_CHANGE)); + deltaElement.field("v", currentElement); + deltaElement.field("i", i); + deltaList.add(deltaElement); + } + else{ + if (!currentElement.equals(originalElement)){ + //now we want to go in depth to get delta value + ODocument deltaElement = new ODocument(); + deltaElement.field("t", UpdateDeltaValueType.getOrd(UpdateDeltaValueType.LIST_ELEMENT_UPDATE)); + + TypeValue delta = getUpdateDeltaValue(currentElement, originalElement, true); + ODocument doc = new ODocument(); + doc.field("t", UpdateDeltaValueType.getOrd(delta.type)); + doc.field("v", delta.value); + deltaElement.field("v", doc); + deltaElement.field("i", i); + deltaList.add(deltaElement); + } + //this means that elements are equal so nothig to do + } + } + //these element are contained only in original list , so they should be removed + for (int j = i; j < previousList.size(); j++){ + ODocument deltaEelement = new ODocument(); + deltaEelement.field("t", UpdateDeltaValueType.getOrd(UpdateDeltaValueType.LIST_ELEMENT_REMOVE)); + deltaEelement.field("i", j); + deltaList.add(deltaEelement); + } + return retVal; + } + } + + retVal.value = currentValue; + retVal.type = UpdateDeltaValueType.UPDATE; + return new TypeValue(); } else{ ODocument docVal; @@ -3259,7 +3332,10 @@ private Object getUpdateDeltaValue(Object currentValue, boolean changed){ else{ docVal = (ODocument)currentValue; } - return docVal.getDeltaFromOriginalForUpdate(); + TypeValue retVal = new TypeValue(); + retVal.value = docVal.getDeltaFromOriginalForUpdate(); + retVal.type = UpdateDeltaValueType.UPDATE; + return retVal; } } @@ -3296,7 +3372,10 @@ private ODocument getDeltaFromOriginalForUpdate(){ ODocumentEntry val = fieldVal.getValue(); if (val.isChangedTree()){ String fieldName = fieldVal.getKey(); - Object deltaValue = getUpdateDeltaValue(val.value, val.isChanged()); + TypeValue deltaValue = getUpdateDeltaValue(val.value, val.original, val.isChanged()); + ODocument doc = new ODocument(); + doc.field("v", deltaValue.value); + doc.field("t", UpdateDeltaValueType.getOrd(deltaValue.type)); updated.field(fieldName, deltaValue); } } diff --git a/core/src/main/java/com/orientechnologies/orient/core/record/impl/UpdateDeltaValueType.java b/core/src/main/java/com/orientechnologies/orient/core/record/impl/UpdateDeltaValueType.java new file mode 100644 index 00000000000..ca4348c43f4 --- /dev/null +++ b/core/src/main/java/com/orientechnologies/orient/core/record/impl/UpdateDeltaValueType.java @@ -0,0 +1,69 @@ +/* + * Copyright 2018 OrientDB. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.orientechnologies.orient.core.record.impl; + +/** + * + * @author mdjurovi + */ +public enum UpdateDeltaValueType { + UPDATE, + LIST_UPDATE, + LIST_ELEMENT_ADD, + LIST_ELEMENT_REMOVE, + LIST_ELEMENT_UPDATE, + LIST_ELEMENT_CHANGE, + UNKNOWN; + + public static byte getOrd(UpdateDeltaValueType type){ + switch (type){ + case UPDATE: + return 1; + case LIST_UPDATE: + return 2; + case LIST_ELEMENT_ADD: + return 4; + case LIST_ELEMENT_REMOVE: + return 8; + case LIST_ELEMENT_UPDATE: + return 16; + case LIST_ELEMENT_CHANGE: + return 32; + default: + return 0; + } + } + + public static UpdateDeltaValueType fromOrd(byte ordValue){ + switch (ordValue){ + case 1: + return UPDATE; + case 2: + return LIST_UPDATE; + case 4: + return LIST_ELEMENT_ADD; + case 8: + return LIST_ELEMENT_REMOVE; + case 16: + return LIST_ELEMENT_UPDATE; + case 32: + return LIST_ELEMENT_CHANGE; + case 0: + default: + return UNKNOWN; + } + } +}