Merged 5.0.N (5.0.4) to 5.1.N (5.1.2)

124539 jvonka: Merged 50N-NDB (5.0.4) to 5.0.N (5.0.4)
      124514: MNT-15211: NDB-specific workaround fix for trashcan restore (since NDB does not support partial rollback on constraint violation)
      - this fix is dialect-specific (hence does not impact existing supported DB types)
      - note: MySQL Cluster NDB - experimental/unsupported


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.1.N/root@124582 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Raluca Munteanu
2016-03-30 08:01:49 +00:00
parent 363efe70ae
commit c9f13752c3
7 changed files with 193 additions and 32 deletions

View File

@@ -145,6 +145,9 @@
<bean id="nodeDAO.org.hibernate.dialect.MySQLInnoDBDialect" class="org.alfresco.repo.domain.node.ibatis.NodeDAOImpl$MySQL" parent="nodeDAO.org.hibernate.dialect.Dialect" /> <bean id="nodeDAO.org.hibernate.dialect.MySQLInnoDBDialect" class="org.alfresco.repo.domain.node.ibatis.NodeDAOImpl$MySQL" parent="nodeDAO.org.hibernate.dialect.Dialect" />
<bean id="nodeDAO.org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect" class="org.alfresco.repo.domain.node.ibatis.NodeDAOImpl$MSSQL" parent="nodeDAO.org.hibernate.dialect.Dialect" /> <bean id="nodeDAO.org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect" class="org.alfresco.repo.domain.node.ibatis.NodeDAOImpl$MSSQL" parent="nodeDAO.org.hibernate.dialect.Dialect" />
<!-- WARNING: Experimental/unsupported - see AlfrescoMySQLClusterNDBDialect ! -->
<bean id="nodeDAO.org.alfresco.repo.domain.hibernate.dialect.AlfrescoMySQLClusterNDBDialect" class="org.alfresco.repo.domain.node.ibatis.NodeDAOImpl$MySQLClusterNDB" parent="nodeDAO.org.hibernate.dialect.Dialect" />
<bean id="lockDAO" class="org.alfresco.repo.domain.locks.ibatis.LockDAOImpl"> <bean id="lockDAO" class="org.alfresco.repo.domain.locks.ibatis.LockDAOImpl">
<property name="sqlSessionTemplate" ref="locksSqlSessionTemplate"/> <property name="sqlSessionTemplate" ref="locksSqlSessionTemplate"/>
<property name="qnameDAO" ref="qnameDAO"/> <property name="qnameDAO" ref="qnameDAO"/>

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2005-2016 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.domain.hibernate.dialect;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.dialect.MySQLInnoDBDialect;
/**
* MySQL Cluster NDB specific DAO overrides
*
* WARNING:
* - Experimental only (unsupported) !
* - The NDB storage engine is *not* currently supported or certified !
* - Can be used for dev/test evaluation (please give us feedback)
* - Should not be used for live/prod env with real data !
* - Requires FK support (hence NDB 7.3.x or higher)
*
* @author janv
*
*/
//note: *not* a dialect of InnoDB but, for now, extends here so that we can override those scripts
public class AlfrescoMySQLClusterNDBDialect extends MySQLInnoDBDialect
{
protected Log logger = LogFactory.getLog(AlfrescoMySQLClusterNDBDialect.class);
public AlfrescoMySQLClusterNDBDialect()
{
super();
logger.error("Using NDB with Alfresco is experimental and unsupported (do not use for live/prod envs) !");
}
public String getTableTypeString() {
return " engine=NDB";
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2013 Alfresco Software Limited. * Copyright (C) 2005-2016 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -1390,6 +1390,37 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
if (!allowAuditableAspect) addAuditableAspect = false; if (!allowAuditableAspect) addAuditableAspect = false;
Long id = newNodeImplInsert(node);
node.setId(id);
Set<QName> nodeAspects = null;
if (addAuditableAspect)
{
Long auditableAspectQNameId = qnameDAO.getOrCreateQName(ContentModel.ASPECT_AUDITABLE).getFirst();
insertNodeAspect(id, auditableAspectQNameId);
nodeAspects = Collections.<QName>singleton(ContentModel.ASPECT_AUDITABLE);
}
else
{
nodeAspects = Collections.<QName>emptySet();
}
// Lock the node and cache
node.lock();
nodesCache.setValue(id, node);
// Pre-populate some of the other caches so that we don't immediately query
setNodeAspectsCached(id, nodeAspects);
setNodePropertiesCached(id, Collections.<QName, Serializable>emptyMap());
if (isDebugEnabled)
{
logger.debug("Created new node: \n" + " " + node);
}
return node;
}
protected Long newNodeImplInsert(NodeEntity node)
{
Long id = null; Long id = null;
Savepoint savepoint = controlDAO.createSavepoint("newNodeImpl"); Savepoint savepoint = controlDAO.createSavepoint("newNodeImpl");
try try
@@ -1425,32 +1456,8 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
throw new NodeExistsException(dbTargetNode.getNodePair(), e); throw new NodeExistsException(dbTargetNode.getNodePair(), e);
} }
} }
node.setId(id);
Set<QName> nodeAspects = null; return id;
if (addAuditableAspect)
{
Long auditableAspectQNameId = qnameDAO.getOrCreateQName(ContentModel.ASPECT_AUDITABLE).getFirst();
insertNodeAspect(id, auditableAspectQNameId);
nodeAspects = Collections.<QName>singleton(ContentModel.ASPECT_AUDITABLE);
}
else
{
nodeAspects = Collections.<QName>emptySet();
}
// Lock the node and cache
node.lock();
nodesCache.setValue(id, node);
// Pre-populate some of the other caches so that we don't immediately query
setNodeAspectsCached(id, nodeAspects);
setNodePropertiesCached(id, Collections.<QName, Serializable>emptyMap());
if (isDebugEnabled)
{
logger.debug("Created new node: \n" + " " + node);
}
return node;
} }
@Override @Override

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2011 Alfresco Software Limited. * Copyright (C) 2005-2016 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.ibatis.IdsEntity; import org.alfresco.ibatis.IdsEntity;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.domain.node.AbstractNodeDAOImpl; import org.alfresco.repo.domain.node.AbstractNodeDAOImpl;
@@ -37,6 +38,7 @@ import org.alfresco.repo.domain.node.Node;
import org.alfresco.repo.domain.node.NodeAspectsEntity; import org.alfresco.repo.domain.node.NodeAspectsEntity;
import org.alfresco.repo.domain.node.NodeAssocEntity; import org.alfresco.repo.domain.node.NodeAssocEntity;
import org.alfresco.repo.domain.node.NodeEntity; import org.alfresco.repo.domain.node.NodeEntity;
import org.alfresco.repo.domain.node.NodeExistsException;
import org.alfresco.repo.domain.node.NodeIdAndAclId; import org.alfresco.repo.domain.node.NodeIdAndAclId;
import org.alfresco.repo.domain.node.NodePropertyEntity; import org.alfresco.repo.domain.node.NodePropertyEntity;
import org.alfresco.repo.domain.node.NodePropertyKey; import org.alfresco.repo.domain.node.NodePropertyKey;
@@ -1719,7 +1721,7 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
} }
/** /**
* MySQL-specific DAO overrides * MySQL (InnoDB) specific DAO overrides
*/ */
public static class MySQL extends NodeDAOImpl public static class MySQL extends NodeDAOImpl
{ {
@@ -1743,6 +1745,58 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
return numDeleted; return numDeleted;
} }
} }
/**
* MySQL Cluster NDB specific DAO overrides
*
* WARNING: Experimental/unsupported - see AlfrescoMySQLClusterNDBDialect !
*
* @author janv
*/
public static class MySQLClusterNDB extends MySQL
{
@Override
protected Long newNodeImplInsert(NodeEntity node)
{
Long id = null;
try
{
// We need to handle existing deleted nodes.
NodeRef targetNodeRef = node.getNodeRef();
Node dbTargetNode = selectNodeByNodeRef(targetNodeRef);
if (dbTargetNode != null)
{
if (dbTargetNode.getDeleted(qnameDAO))
{
Long dbTargetNodeId = dbTargetNode.getId();
// This is OK. It happens when we create a node that existed in the past.
// Remove the row completely
deleteNodeProperties(dbTargetNodeId, (Set<Long>) null);
deleteNodeById(dbTargetNodeId);
}
else
{
// A live node exists.
throw new NodeExistsException(dbTargetNode.getNodePair(), null);
}
}
id = insertNode(node);
}
catch (Throwable e)
{
if (e instanceof NodeExistsException)
{
throw e;
}
// There does not appear to be any row that could prevent an insert
throw new AlfrescoRuntimeException("Failed to insert new node: " + node, e);
}
return id;
}
}
/** /**
* Get most recent transaction made in a given commit time range * Get most recent transaction made in a given commit time range

View File

@@ -1,6 +1,5 @@
/* /*
* Copyright (C) 2005-2015 Alfresco Software Limited. * Copyright (C) 2005-2016 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -70,6 +69,7 @@ import org.alfresco.repo.admin.patch.AppliedPatch;
import org.alfresco.repo.admin.patch.Patch; import org.alfresco.repo.admin.patch.Patch;
import org.alfresco.repo.admin.patch.impl.SchemaUpgradeScriptPatch; import org.alfresco.repo.admin.patch.impl.SchemaUpgradeScriptPatch;
import org.alfresco.repo.content.filestore.FileContentWriter; import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoMySQLClusterNDBDialect;
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoOracle9Dialect; import org.alfresco.repo.domain.hibernate.dialect.AlfrescoOracle9Dialect;
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect; import org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect;
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect; import org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect;
@@ -1478,6 +1478,23 @@ public class SchemaBootstrap extends AbstractLifecycleBean
sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=InnoDB"); sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=InnoDB");
} }
if (this.dialect != null && this.dialect instanceof AlfrescoMySQLClusterNDBDialect)
{
// note: enable bootstrap on MySQL Cluster NDB
/*
* WARNING: Experimental/unsupported - see AlfrescoMySQLClusterNDBDialect !
*/
sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=NDB"); // belts-and-braces
sql = sql.replaceAll("(?i)ENGINE=InnoDB", "ENGINE=NDB");
sql = sql.replaceAll("(?i) BIT ", " BOOLEAN ");
sql = sql.replaceAll("(?i) BIT,", " BOOLEAN,");
sql = sql.replaceAll("(?i) string_value text", " string_value VARCHAR(1024)");
sql = sql.replaceAll("(?i) VARCHAR(4000)", "TEXT(4000)");
}
Object fetchedVal = executeStatement(connection, sql, fetchColumnName, optional, line, scriptFile); Object fetchedVal = executeStatement(connection, sql, fetchColumnName, optional, line, scriptFile);
if (fetchVarName != null && fetchColumnName != null) if (fetchVarName != null && fetchColumnName != null)
{ {
@@ -1635,6 +1652,12 @@ public class SchemaBootstrap extends AbstractLifecycleBean
// serializable_value blob, // serializable_value blob,
maxStringLength = Integer.MAX_VALUE; maxStringLength = Integer.MAX_VALUE;
} }
else if (dialect instanceof AlfrescoMySQLClusterNDBDialect)
{
// string_value varchar(1024),
// serializable_value blob,
maxStringLength = SchemaBootstrap.DEFAULT_MAX_STRING_LENGTH;
}
else if (dialect instanceof AlfrescoOracle9Dialect) else if (dialect instanceof AlfrescoOracle9Dialect)
{ {
// string_value varchar2(1024 char), // string_value varchar2(1024 char),

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2014 Alfresco Software Limited. * Copyright (C) 2005-2016 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -35,6 +35,7 @@ import javax.sql.DataSource;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.filestore.FileContentWriter; import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoMySQLClusterNDBDialect;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.util.LogUtil; import org.alfresco.util.LogUtil;
import org.alfresco.util.TempFileProvider; import org.alfresco.util.TempFileProvider;
@@ -537,6 +538,23 @@ public class ScriptExecutorImpl implements ScriptExecutor
sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=InnoDB"); sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=InnoDB");
} }
if (this.dialect != null && this.dialect instanceof AlfrescoMySQLClusterNDBDialect)
{
// note: enable bootstrap on MySQL Cluster NDB
/*
* WARNING: Experimental/unsupported - see AlfrescoMySQLClusterNDBDialect !
*/
sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=NDB"); // belts-and-braces
sql = sql.replaceAll("(?i)ENGINE=InnoDB", "ENGINE=NDB");
sql = sql.replaceAll("(?i) BIT ", " BOOLEAN ");
sql = sql.replaceAll("(?i) BIT,", " BOOLEAN,");
sql = sql.replaceAll("(?i) string_value text", " string_value VARCHAR(1024)");
sql = sql.replaceAll("(?i) VARCHAR(4000)", "TEXT(4000)");
}
Object fetchedVal = executeStatement(connection, sql, fetchColumnName, optional, line, scriptFile); Object fetchedVal = executeStatement(connection, sql, fetchColumnName, optional, line, scriptFile);
if (fetchVarName != null && fetchColumnName != null) if (fetchVarName != null && fetchColumnName != null)
{ {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2014 Alfresco Software Limited. * Copyright (C) 2005-2016 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -916,6 +916,8 @@ public class ArchiveAndRestoreTest extends TestCase
RestoreNodeReport report = nodeArchiveService.restoreArchivedNode(r_); RestoreNodeReport report = nodeArchiveService.restoreArchivedNode(r_);
assertEquals("Restore failed", RestoreStatus.SUCCESS, report.getStatus()); assertEquals("Restore failed", RestoreStatus.SUCCESS, report.getStatus());
commitAndBeginNewTransaction();
//It is restored, still with no AUDITABLE ASPECT //It is restored, still with no AUDITABLE ASPECT
verifyNodeExistence(r, true); verifyNodeExistence(r, true);
verifyAspectExistence(r, ContentModel.ASPECT_AUDITABLE, false); verifyAspectExistence(r, ContentModel.ASPECT_AUDITABLE, false);