Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XWIKI-22782: Only save modified xobjects #3798

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,8 @@ private static Transformation getMacroTransformation()
*/
private boolean isMetaDataDirty = true;

private boolean changeTracked;

private int elements = HAS_OBJECTS | HAS_ATTACHMENTS;

// Meta Data
Expand Down Expand Up @@ -2429,6 +2431,34 @@ public void setMetaDataDirty(boolean metaDataDirty)
this.isMetaDataDirty = metaDataDirty;
}

/**
* Indicate if flags indicating which part of the document has been modified can be trusted.
*
* @return the true if change made to this {@link XWikiDocument} instance are tracked
* @since 17.1.0RC1
* @since 16.10.4
* @since 16.4.7
*/
@Unstable
public boolean isChangeTracked()
tmortagne marked this conversation as resolved.
Show resolved Hide resolved
{
return this.changeTracked;
}

/**
* Indicate if flags indicating which part of the document has been modified can be trusted.
*
* @param changeTracked true if change made to this {@link XWikiDocument} instance are tracked
* @since 17.1.0RC1
* @since 16.10.4
* @since 16.4.7
*/
@Unstable
public void setChangeTracked(boolean changeTracked)
{
this.changeTracked = changeTracked;
}

public String getAttachmentURL(String filename, XWikiContext context)
{
return getAttachmentURL(filename, "download", context);
Expand Down Expand Up @@ -4595,6 +4625,10 @@ private XWikiDocument cloneInternal(DocumentReference newDocumentReference, bool
Constructor<? extends XWikiDocument> constructor = getClass().getConstructor(DocumentReference.class);
doc = constructor.newInstance(newDocumentReference);

if (keepsIdentity && getDocumentReference().equals(doc.getDocumentReference())) {
doc.setChangeTracked(isChangeTracked());
}

// Make sure the coordinate of the document is fully accurate before any other manipulation
doc.setLocale(getLocale());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.inject.Inject;
import javax.inject.Named;
Expand All @@ -29,6 +31,9 @@
import org.apache.commons.lang3.StringUtils;
import org.xwiki.component.annotation.Component;
import org.xwiki.configuration.ConfigurationSource;
import org.xwiki.model.EntityType;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.model.reference.EntityReferenceResolver;

import com.xpn.xwiki.internal.XWikiCfgConfigurationSource;

Expand All @@ -46,6 +51,10 @@ public class HibernateConfiguration
@Named(XWikiCfgConfigurationSource.ROLEHINT)
private ConfigurationSource xwikiConfiguration;

@Inject
@Named("relative")
private EntityReferenceResolver<String> resolver;

private String path;

/**
Expand Down Expand Up @@ -164,4 +173,21 @@ public List<String> getIgnoredMigrations()
{
return getList("xwiki.store.migration.ignored");
}

/**
* @return the local references of the classes for which we should apply a save optimization (save only the modified
* ones)
* @since 17.1.0RC1
* @since 16.10.4
* @since 16.4.7
*/
public Set<EntityReference> getOptimizedXObjectClasses()
tmortagne marked this conversation as resolved.
Show resolved Hide resolved
{
List<String> references =
this.xwikiConfiguration.getProperty("xwiki.store.hibernate.optimizedObjectSave.classes", List.class);

return references != null
? references.stream().map(r -> this.resolver.resolve(r, EntityType.DOCUMENT)).collect(Collectors.toSet())
: null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -224,8 +225,12 @@ public void setXClassReference(EntityReference xClassReference)
}
}

this.xClassReference = ref;
this.xClassReferenceCache = null;
if (!Objects.equals(this.xClassReference, ref)) {
this.xClassReference = ref;
this.xClassReferenceCache = null;

setDirty(true);
}
}

/**
Expand Down Expand Up @@ -265,7 +270,6 @@ public void safeput(String name, PropertyInterface property)
{
addField(name, property);
if (property instanceof BaseProperty) {
((BaseProperty) property).setObject(this);
((BaseProperty) property).setName(name);
}
}
Expand Down Expand Up @@ -537,9 +541,15 @@ public void addField(String name, PropertyInterface element)
{
this.fields.put(name, element);

if (element instanceof BaseElement) {
((BaseElement) element).setOwnerDocument(getOwnerDocument());
if (element instanceof BaseElement baseElement) {
baseElement.setOwnerDocument(getOwnerDocument());

if (element instanceof BaseProperty baseProperty) {
baseProperty.setObject(this);
}
}

setDirty(true);
}

public void removeField(String name)
Expand All @@ -548,6 +558,8 @@ public void removeField(String name)
if (field != null) {
this.fields.remove(name);
this.fieldsToRemove.add(field);

setDirty(true);
}
}

Expand Down Expand Up @@ -647,6 +659,8 @@ public BaseCollection clone()
}
collection.setFields(cfields);

collection.setDirty(isDirty());

return collection;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.io.IOException;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.Objects;

import javax.inject.Provider;

Expand All @@ -37,6 +38,7 @@
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.model.reference.EntityReferenceSerializer;
import org.xwiki.stability.Unstable;
import org.xwiki.store.merge.MergeManager;
import org.xwiki.store.merge.MergeManagerResult;

Expand Down Expand Up @@ -101,7 +103,37 @@ public abstract class BaseElement<R extends EntityReference> implements ElementI
private EntityReferenceSerializer<String> localUidStringEntityReferenceSerializer;

private ContextualLocalizationManager localization;


private transient boolean dirty = true;

/**
* @return true of the element was modified (or created)
* @since 17.1.0RC1
* @since 16.10.4
* @since 16.4.7
*/
tmortagne marked this conversation as resolved.
Show resolved Hide resolved
@Unstable
public boolean isDirty()
{
return this.dirty;
}

/**
* @param dirty true of the element was modified (or created)
* @since 17.1.0RC1
* @since 16.10.4
* @since 16.4.7
*/
tmortagne marked this conversation as resolved.
Show resolved Hide resolved
@Unstable
public void setDirty(boolean dirty)
{
this.dirty = dirty;

if (dirty && this.ownerDocument != null) {
this.ownerDocument.setMetaDataDirty(true);
tmortagne marked this conversation as resolved.
Show resolved Hide resolved
}
}

/**
* @return a merge manager instance.
* @since 11.8RC1
Expand Down Expand Up @@ -161,12 +193,16 @@ public String getName()
}

@Override
public void setDocumentReference(DocumentReference reference)
public void setDocumentReference(DocumentReference documentReference)
{
// If the name is already set then reset it since we're now using a reference
this.documentReference = reference;
this.name = null;
this.referenceCache = null;
if (!Objects.equals(documentReference, this.documentReference)) {
// If the name is already set then reset it since we're now using a reference
this.documentReference = documentReference;
this.name = null;
this.referenceCache = null;

setDirty(true);
}
}

/**
Expand All @@ -185,8 +221,12 @@ public void setName(String name)
throw new IllegalStateException("BaseElement#setName could not be called when a reference has been set.");
}

this.name = name;
this.referenceCache = null;
if (!StringUtils.equals(name, this.name)) {
this.name = name;
this.referenceCache = null;

setDirty(true);
}
}

public String getPrettyName()
Expand Down Expand Up @@ -349,6 +389,8 @@ public BaseElement clone()
}

element.setPrettyName(getPrettyName());

element.dirty = this.dirty;
} catch (Exception e) {
// This should not happen
element = null;
Expand Down Expand Up @@ -417,7 +459,13 @@ public boolean apply(ElementInterface newElement, boolean clean)
*/
public void setOwnerDocument(XWikiDocument ownerDocument)
{
this.ownerDocument = ownerDocument;
if (this.ownerDocument != ownerDocument) {
this.ownerDocument = ownerDocument;

if (this.ownerDocument != null && isDirty()) {
this.ownerDocument.setMetaDataDirty(true);
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
*/
package com.xpn.xwiki.objects;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -44,7 +43,7 @@
import com.xpn.xwiki.objects.classes.PropertyClass;
import com.xpn.xwiki.web.Utils;

public class BaseObject extends BaseCollection<BaseObjectReference> implements ObjectInterface, Serializable, Cloneable
public class BaseObject extends BaseCollection<BaseObjectReference> implements ObjectInterface, Cloneable
{
private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -201,6 +200,8 @@ public BaseObject clone()
// is expensive)
object.setGuid(this.guid);

object.setDirty(isDirty());

return object;
}

Expand Down
Loading