[exo-jcr-commits] exo-jcr SVN: r4307 - in jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc: optimisation and 1 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Wed Apr 27 03:54:11 EDT 2011
Author: tolusha
Date: 2011-04-27 03:54:11 -0400 (Wed, 27 Apr 2011)
New Revision: 4307
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/SQLExceptionHandler.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java
Log:
EXOJCR-1111: Reduce the total amount of queries needed to update a property
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java 2011-04-26 13:20:25 UTC (rev 4306)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java 2011-04-27 07:54:11 UTC (rev 4307)
@@ -85,7 +85,7 @@
/**
* Helper.
*/
- class WriteValueHelper extends ValueFileIOHelper
+ protected class WriteValueHelper extends ValueFileIOHelper
{
/**
* {@inheritDoc}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/SQLExceptionHandler.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/SQLExceptionHandler.java 2011-04-26 13:20:25 UTC (rev 4306)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/SQLExceptionHandler.java 2011-04-27 07:54:11 UTC (rev 4307)
@@ -352,7 +352,7 @@
* @throws InvalidItemStateException
* if <code>InvalidItemStateException</code> should be thrown
*/
- protected String handleUpdateException(SQLException e, ItemData item) throws RepositoryException,
+ public String handleUpdateException(SQLException e, ItemData item) throws RepositoryException,
InvalidItemStateException
{
String message = "[" + containerName + "] EDIT " + (item.isNode() ? "NODE. " : "PROPERTY. ");
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java 2011-04-26 13:20:25 UTC (rev 4306)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java 2011-04-27 07:54:11 UTC (rev 4307)
@@ -18,8 +18,10 @@
*/
package org.exoplatform.services.jcr.impl.storage.jdbc.optimisation;
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
import org.exoplatform.services.jcr.access.AccessControlEntry;
import org.exoplatform.services.jcr.access.AccessControlList;
+import org.exoplatform.services.jcr.dataflow.ItemState;
import org.exoplatform.services.jcr.dataflow.persistent.PersistedNodeData;
import org.exoplatform.services.jcr.dataflow.persistent.PersistedPropertyData;
import org.exoplatform.services.jcr.datamodel.IllegalACLException;
@@ -31,15 +33,22 @@
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.dataflow.persistent.StreamPersistedValueData;
+import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCStorageConnection;
import org.exoplatform.services.jcr.impl.storage.jdbc.PrimaryTypeNotFoundException;
+import org.exoplatform.services.jcr.impl.storage.value.ValueStorageNotFoundException;
import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
+import org.exoplatform.services.jcr.impl.util.io.SwapFile;
+import org.exoplatform.services.jcr.storage.value.ValueIOChannel;
import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -47,6 +56,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -55,6 +65,7 @@
import java.util.TreeSet;
import javax.jcr.InvalidItemStateException;
+import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
/**
@@ -91,6 +102,21 @@
*/
protected String FIND_ITEM_QPATH_BY_ID_CQ;
+ /**
+ * FIND_PROPERTY_BY_ID.
+ */
+ protected String FIND_PROPERTY_BY_ID;
+
+ /**
+ * DELETE_VALUE_BY_ORDER_NUM.
+ */
+ protected String DELETE_VALUE_BY_ORDER_NUM;
+
+ /**
+ * UPDATE_VALUE.
+ */
+ protected String UPDATE_VALUE;
+
protected PreparedStatement findNodesByParentIdCQ;
protected PreparedStatement findPropertiesByParentIdCQ;
@@ -99,6 +125,12 @@
protected PreparedStatement findItemQPathByIdentifierCQ;
+ protected PreparedStatement findPropertyById;
+
+ protected PreparedStatement deleteValueDataByOrderNum;
+
+ protected PreparedStatement updateValue;
+
/**
* JDBCStorageConnection constructor.
*
@@ -190,11 +222,198 @@
}
}
}
+
/**
* {@inheritDoc}
*/
@Override
+ public void update(PropertyData data) throws RepositoryException, UnsupportedOperationException,
+ InvalidItemStateException, IllegalStateException
+ {
+ checkIfOpened();
+ ResultSet rs = null;
+ try
+ {
+ String cid = getInternalId(data.getIdentifier());
+ // update type
+ if (updatePropertyByIdentifier(data.getPersistedVersion(), data.getType(), cid) <= 0)
+ throw new JCRInvalidItemStateException("(update) Property not found " + data.getQPath().getAsString() + " "
+ + data.getIdentifier() + ". Probably was deleted by another session ", data.getIdentifier(),
+ ItemState.UPDATED);
+
+ rs = findPropertyById(cid);
+ Set<String> storageDescs = new HashSet<String>();
+ int totalOldValues = 0;
+ int prevType = -1;
+ while (rs.next())
+ {
+ if (prevType == -1)
+ {
+ prevType = rs.getInt(COLUMN_PTYPE);
+ }
+ totalOldValues++;
+ final String storageId = rs.getString(COLUMN_VSTORAGE_DESC);
+ if (!rs.wasNull())
+ {
+ storageDescs.add(storageId);
+ }
+ }
+ // update reference
+ try
+ {
+ if (prevType == PropertyType.REFERENCE)
+ {
+ deleteReference(cid);
+ }
+
+ if (data.getType() == PropertyType.REFERENCE)
+ {
+ addReference(data);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RepositoryException("Can't update REFERENCE property (" + data.getQPath() + " "
+ + data.getIdentifier() + ") value: " + e.getMessage(), e);
+ }
+
+ deleteValues(cid, data, storageDescs, totalOldValues);
+ addOrUpdateValues(cid, data, totalOldValues);
+ }
+ catch (IOException e)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.error("Property update. IO error: " + e, e);
+ throw new RepositoryException("Error of Property Value update " + e, e);
+ }
+ catch (SQLException e)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.error("Property update. Database error: " + e, e);
+ exceptionHandler.handleUpdateException(e, data);
+ }
+ finally
+ {
+ if (rs != null)
+ {
+ try
+ {
+ rs.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error("Can't close the ResultSet: " + e);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void addValues(String cid, PropertyData data) throws IOException, SQLException, RepositoryException
+ {
+ addOrUpdateValues(cid, data, 0);
+ }
+
+ protected void addOrUpdateValues(String cid, PropertyData data, int totalOldValues) throws IOException,
+ RepositoryException, SQLException
+ {
+ List<ValueData> vdata = data.getValues();
+
+ for (int i = 0; i < vdata.size(); i++)
+ {
+ ValueData vd = vdata.get(i);
+ ValueIOChannel channel = valueStorageProvider.getApplicableChannel(data, i);
+ InputStream stream;
+ int streamLength;
+ String storageId;
+ if (channel == null)
+ {
+ // prepare write of Value in database
+ if (vd.isByteArray())
+ {
+ byte[] dataBytes = vd.getAsByteArray();
+ stream = new ByteArrayInputStream(dataBytes);
+ streamLength = dataBytes.length;
+ }
+ else
+ {
+ StreamPersistedValueData streamData = (StreamPersistedValueData)vd;
+
+ SwapFile swapFile = SwapFile.get(swapDirectory, cid + i + "." + data.getPersistedVersion());
+ try
+ {
+ writeValueHelper.writeStreamedValue(swapFile, streamData);
+ }
+ finally
+ {
+ swapFile.spoolDone();
+ }
+
+ long vlen = PrivilegedFileHelper.length(swapFile);
+ if (vlen <= Integer.MAX_VALUE)
+ {
+ streamLength = (int)vlen;
+ }
+ else
+ {
+ throw new RepositoryException("Value data large of allowed by JDBC (Integer.MAX_VALUE) " + vlen
+ + ". Property " + data.getQPath().getAsString());
+ }
+
+ stream = streamData.getAsStream();
+ }
+ storageId = null;
+ }
+ else
+ {
+ // write Value in external VS
+ channel.write(data.getIdentifier(), vd);
+ valueChanges.add(channel);
+ storageId = channel.getStorageId();
+ stream = null;
+ streamLength = 0;
+ }
+ if (i < totalOldValues)
+ {
+ updateValueData(cid, i, stream, streamLength, storageId);
+ }
+ else
+ {
+ addValueData(cid, i, stream, streamLength, storageId);
+ }
+ }
+ }
+
+ private void deleteValues(String cid, PropertyData pdata, Set<String> storageDescs, int totalOldValues) throws ValueStorageNotFoundException, IOException, SQLException
+ {
+ for (String storageId : storageDescs)
+ {
+ final ValueIOChannel channel = valueStorageProvider.getChannel(storageId);
+ try
+ {
+ channel.delete(pdata.getIdentifier());
+ valueChanges.add(channel);
+ }
+ finally
+ {
+ channel.close();
+ }
+ }
+ if (pdata.getValues().size() < totalOldValues)
+ {
+ // Remove the extra values
+ deleteValueDataByOrderNum(cid, pdata.getValues().size());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException, IllegalStateException
{
checkIfOpened();
@@ -666,6 +885,21 @@
{
findItemQPathByIdentifierCQ.close();
}
+
+ if (findPropertyById != null)
+ {
+ findPropertyById.close();
+ }
+
+ if (deleteValueDataByOrderNum != null)
+ {
+ deleteValueDataByOrderNum.close();
+ }
+
+ if (updateValue != null)
+ {
+ updateValue.close();
+ }
}
catch (SQLException e)
{
@@ -680,4 +914,11 @@
protected abstract ResultSet findChildPropertiesByParentIdentifierCQ(String parentIdentifier) throws SQLException;
protected abstract ResultSet findNodeMainPropertiesByParentIdentifierCQ(String parentIdentifier) throws SQLException;
+
+ protected abstract ResultSet findPropertyById(String id) throws SQLException;
+
+ protected abstract int deleteValueDataByOrderNum(String id, int orderNum) throws SQLException;
+
+ protected abstract int updateValueData(String cid, int i, InputStream stream, int streamLength, String storageId)
+ throws SQLException;
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java 2011-04-26 13:20:25 UTC (rev 4306)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java 2011-04-27 07:54:11 UTC (rev 4307)
@@ -189,6 +189,11 @@
+ " join (select I.ID, I.PARENT_ID, I.NAME, I.VERSION, I.I_INDEX, I.N_ORDER_NUM from JCR_MITEM I"
+ " where I.I_CLASS=1 AND I.ID > ? order by I.ID LIMIT ? OFFSET ?) J on P.PARENT_ID = J.ID"
+ " where P.I_CLASS=2 and V.PROPERTY_ID=P.ID order by J.ID";
+
+ FIND_PROPERTY_BY_ID =
+ "select I.P_TYPE, V.STORAGE_DESC from JCR_MITEM I, JCR_MVALUE V where I.ID = ? and V.PROPERTY_ID = I.ID";
+ DELETE_VALUE_BY_ORDER_NUM = "delete from JCR_MVALUE where PROPERTY_ID=? and ORDER_NUM >= ?";
+ UPDATE_VALUE = "update JCR_MVALUE set DATA=?, STORAGE_DESC=? where PROPERTY_ID=? and ORDER_NUM=?";
}
/**
@@ -628,6 +633,55 @@
return findItemQPathByIdentifierCQ.executeQuery();
}
+ protected int deleteValueDataByOrderNum(String id, int orderNum) throws SQLException
+ {
+ if (deleteValueDataByOrderNum == null)
+ deleteValueDataByOrderNum = dbConnection.prepareStatement(DELETE_VALUE_BY_ORDER_NUM);
+ else
+ deleteValueDataByOrderNum.clearParameters();
+
+ deleteValueDataByOrderNum.setString(1, id);
+ deleteValueDataByOrderNum.setInt(2, orderNum);
+ return deleteValueDataByOrderNum.executeUpdate();
+ }
+
+ protected ResultSet findPropertyById(String id) throws SQLException
+ {
+ if (findPropertyById == null)
+ findPropertyById = dbConnection.prepareStatement(FIND_PROPERTY_BY_ID);
+ else
+ findPropertyById.clearParameters();
+
+ findPropertyById.setString(1, id);
+ return findPropertyById.executeQuery();
+ }
+
+ protected int updateValueData(String cid, int orderNumber, InputStream stream, int streamLength, String storageDesc)
+ throws SQLException
+ {
+
+ if (updateValue == null)
+ updateValue = dbConnection.prepareStatement(UPDATE_VALUE);
+ else
+ updateValue.clearParameters();
+
+ if (stream == null)
+ {
+ // [PN] store vd reference to external storage etc.
+ updateValue.setNull(1, Types.BINARY);
+ updateValue.setString(2, storageDesc);
+ }
+ else
+ {
+ updateValue.setBinaryStream(1, stream, streamLength);
+ updateValue.setNull(2, Types.VARCHAR);
+ }
+
+ updateValue.setString(3, cid);
+ updateValue.setInt(4, orderNumber);
+ return updateValue.executeUpdate();
+ }
+
/**
* {@inheritDoc}
*/
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java 2011-04-26 13:20:25 UTC (rev 4306)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java 2011-04-27 07:54:11 UTC (rev 4307)
@@ -196,6 +196,11 @@
+ " join (select I.ID, I.PARENT_ID, I.NAME, I.VERSION, I.I_INDEX, I.N_ORDER_NUM from JCR_SITEM I"
+ " where I.CONTAINER_NAME=? AND I.I_CLASS=1 AND I.ID > ? order by I.ID LIMIT ? OFFSET ?) J on P.PARENT_ID = J.ID"
+ " where P.I_CLASS=2 and P.CONTAINER_NAME=? and V.PROPERTY_ID=P.ID order by J.ID";
+
+ FIND_PROPERTY_BY_ID =
+ "select I.P_TYPE, V.STORAGE_DESC from JCR_SITEM I, JCR_SVALUE V where I.CONTAINER_NAME=? and I.ID = ? and V.PROPERTY_ID = I.ID";
+ DELETE_VALUE_BY_ORDER_NUM = "delete from JCR_SVALUE where PROPERTY_ID=? and ORDER_NUM >= ?";
+ UPDATE_VALUE = "update JCR_SVALUE set DATA=?, STORAGE_DESC=? where PROPERTY_ID=? and ORDER_NUM=?";
}
/**
@@ -673,4 +678,57 @@
return findNodesAndProperties.executeQuery();
}
+
+ @Override
+ protected int deleteValueDataByOrderNum(String id, int orderNum) throws SQLException
+ {
+ if (deleteValueDataByOrderNum == null)
+ deleteValueDataByOrderNum = dbConnection.prepareStatement(DELETE_VALUE_BY_ORDER_NUM);
+ else
+ deleteValueDataByOrderNum.clearParameters();
+
+ deleteValueDataByOrderNum.setString(1, id);
+ deleteValueDataByOrderNum.setInt(2, orderNum);
+ return deleteValueDataByOrderNum.executeUpdate();
+ }
+
+ @Override
+ protected ResultSet findPropertyById(String id) throws SQLException
+ {
+ if (findPropertyById == null)
+ findPropertyById = dbConnection.prepareStatement(FIND_PROPERTY_BY_ID);
+ else
+ findPropertyById.clearParameters();
+
+ findPropertyById.setString(1, containerName);
+ findPropertyById.setString(2, id);
+ return findPropertyById.executeQuery();
+ }
+
+ @Override
+ protected int updateValueData(String cid, int orderNumber, InputStream stream, int streamLength, String storageDesc)
+ throws SQLException
+ {
+
+ if (updateValue == null)
+ updateValue = dbConnection.prepareStatement(UPDATE_VALUE);
+ else
+ updateValue.clearParameters();
+
+ if (stream == null)
+ {
+ // [PN] store vd reference to external storage etc.
+ updateValue.setNull(1, Types.BINARY);
+ updateValue.setString(2, storageDesc);
+ }
+ else
+ {
+ updateValue.setBinaryStream(1, stream, streamLength);
+ updateValue.setNull(2, Types.VARCHAR);
+ }
+
+ updateValue.setString(3, cid);
+ updateValue.setInt(4, orderNumber);
+ return updateValue.executeUpdate();
+ }
}
More information about the exo-jcr-commits
mailing list