|
Rex Dieter |
adf30af |
From 215b188d891d5236fe94131d176d7ddc3ae02d5d Mon Sep 17 00:00:00 2001
|
|
Rex Dieter |
adf30af |
From: =?UTF-8?q?Dan=20Vr=C3=A1til?= <dvratil@redhat.com>
|
|
Rex Dieter |
adf30af |
Date: Fri, 5 Dec 2014 17:12:28 +0100
|
|
Rex Dieter |
adf30af |
Subject: [PATCH 20/30] Avoid ridiculous amount of SQL queries by caching
|
|
Rex Dieter |
adf30af |
PartTypes
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
PartTypes are identified by their FQ name, which is in form NAMESPACE:NAME,
|
|
Rex Dieter |
adf30af |
where namespace and name are stored in individual columns. For this reason
|
|
Rex Dieter |
adf30af |
the standard ::retrieveByName() and name cache generated from entities.xslt
|
|
Rex Dieter |
adf30af |
does not work. This patch adds special handling for PartType table, so that
|
|
Rex Dieter |
adf30af |
a special PartType::retrieveByFQName() method as well as PartType name cache
|
|
Rex Dieter |
adf30af |
handling are generated during the XSL Transformation, allowing us to cache
|
|
Rex Dieter |
adf30af |
all the PartTypes.
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
This reduces the amount of SQL queries by at least two for each single AKAPPEND,
|
|
Rex Dieter |
adf30af |
MERGE, STORE and FETCH command, providing a nice performance boost during
|
|
Rex Dieter |
adf30af |
sync.
|
|
Rex Dieter |
adf30af |
---
|
|
Rex Dieter |
adf30af |
server/src/handler/append.cpp | 4 ++--
|
|
Rex Dieter |
adf30af |
server/src/storage/datastore.cpp | 4 +++-
|
|
Rex Dieter |
adf30af |
server/src/storage/entities-header.xsl | 7 ++++++-
|
|
Rex Dieter |
adf30af |
server/src/storage/entities-source.xsl | 31 ++++++++++++++++++++++++++++++-
|
|
Rex Dieter |
adf30af |
server/src/storage/entities.xsl | 7 ++++++-
|
|
Rex Dieter |
adf30af |
server/src/storage/parttypehelper.cpp | 29 +----------------------------
|
|
Rex Dieter |
adf30af |
server/src/storage/parttypehelper.h | 13 -------------
|
|
Rex Dieter |
adf30af |
7 files changed, 48 insertions(+), 47 deletions(-)
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
diff --git a/server/src/handler/append.cpp b/server/src/handler/append.cpp
|
|
Rex Dieter |
adf30af |
index c503216..b594e27 100644
|
|
Rex Dieter |
adf30af |
--- a/server/src/handler/append.cpp
|
|
Rex Dieter |
adf30af |
+++ b/server/src/handler/append.cpp
|
|
Rex Dieter |
adf30af |
@@ -134,7 +134,7 @@ bool Append::commit()
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
// wrap data into a part
|
|
Rex Dieter |
adf30af |
Part part;
|
|
Rex Dieter |
adf30af |
- part.setPartType( PartTypeHelper::fromName( "PLD", "RFC822" ) );
|
|
Rex Dieter |
adf30af |
+ part.setPartType( PartType::retrieveByFQName( QLatin1String("PLD"), QLatin1String("RFC822") ) );
|
|
Rex Dieter |
adf30af |
part.setData( m_data );
|
|
Rex Dieter |
adf30af |
part.setPimItemId( item.id() );
|
|
Rex Dieter |
adf30af |
part.setDatasize( dataSize );
|
|
Rex Dieter |
adf30af |
@@ -148,7 +148,7 @@ bool Append::commit()
|
|
Rex Dieter |
adf30af |
//akDebug() << "Append handler: doPreprocessing is" << doPreprocessing;
|
|
Rex Dieter |
adf30af |
if ( doPreprocessing ) {
|
|
Rex Dieter |
adf30af |
Part hiddenAttribute;
|
|
Rex Dieter |
adf30af |
- hiddenAttribute.setPartType( PartTypeHelper::fromName( "ATR", "HIDDEN" ) );
|
|
Rex Dieter |
adf30af |
+ hiddenAttribute.setPartType( PartType::retrieveByFQName( QLatin1String("ATR"), QLatin1String("HIDDEN") ) );
|
|
Rex Dieter |
adf30af |
hiddenAttribute.setData( QByteArray() );
|
|
Rex Dieter |
adf30af |
hiddenAttribute.setPimItemId( item.id() );
|
|
Rex Dieter |
adf30af |
hiddenAttribute.setDatasize( 0 );
|
|
Rex Dieter |
adf30af |
diff --git a/server/src/storage/datastore.cpp b/server/src/storage/datastore.cpp
|
|
Rex Dieter |
adf30af |
index ae78bab..304f0e8 100644
|
|
Rex Dieter |
adf30af |
--- a/server/src/storage/datastore.cpp
|
|
Rex Dieter |
adf30af |
+++ b/server/src/storage/datastore.cpp
|
|
Rex Dieter |
adf30af |
@@ -183,6 +183,7 @@ bool DataStore::init()
|
|
Rex Dieter |
adf30af |
Flag::enableCache( true );
|
|
Rex Dieter |
adf30af |
Resource::enableCache( true );
|
|
Rex Dieter |
adf30af |
Collection::enableCache( true );
|
|
Rex Dieter |
adf30af |
+ PartType::enableCache( true );
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
return true;
|
|
Rex Dieter |
adf30af |
}
|
|
Rex Dieter |
adf30af |
@@ -1025,7 +1026,8 @@ bool DataStore::unhideAllPimItems()
|
|
Rex Dieter |
adf30af |
akDebug() << "DataStore::unhideAllPimItems()";
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
try {
|
|
Rex Dieter |
adf30af |
- return PartHelper::remove( Part::partTypeIdFullColumnName(), PartTypeHelper::fromName( "ATR", "HIDDEN" ).id() );
|
|
Rex Dieter |
adf30af |
+ return PartHelper::remove( Part::partTypeIdFullColumnName(),
|
|
Rex Dieter |
adf30af |
+ PartType::retrieveByFQName( QLatin1String("ATR"), QLatin1String("HIDDEN") ).id() );
|
|
Rex Dieter |
adf30af |
} catch ( ... ) {} // we can live with this failing
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
return false;
|
|
Rex Dieter |
adf30af |
diff --git a/server/src/storage/entities-header.xsl b/server/src/storage/entities-header.xsl
|
|
Rex Dieter |
adf30af |
index 4966966..d515fd3 100644
|
|
Rex Dieter |
adf30af |
--- a/server/src/storage/entities-header.xsl
|
|
Rex Dieter |
adf30af |
+++ b/server/src/storage/entities-header.xsl
|
|
Rex Dieter |
adf30af |
@@ -133,11 +133,16 @@ class <xsl:value-of select="$className"/> : private Entity
|
|
Rex Dieter |
adf30af |
<xsl:text>static </xsl:text><xsl:value-of select="$className"/> retrieveById( qint64 id );
|
|
Rex Dieter |
adf30af |
</xsl:if>
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
- <xsl:if test="column[@name = 'name']">
|
|
Rex Dieter |
adf30af |
+ <xsl:if test="column[@name = 'name'] and $className != 'PartType'">
|
|
Rex Dieter |
adf30af |
/** Returns the record with name @p name. */
|
|
Rex Dieter |
adf30af |
<xsl:text>static </xsl:text><xsl:value-of select="$className"/> retrieveByName( const <xsl:value-of select="column[@name = 'name']/@type"/> &name );
|
|
Rex Dieter |
adf30af |
</xsl:if>
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
+ <xsl:if test="column[@name = 'name'] and $className = 'PartType'">
|
|
Rex Dieter |
adf30af |
+
|
|
Rex Dieter |
adf30af |
+ <xsl:text>static PartType retrieveByFQName( const QString &ns, const QString &name );</xsl:text>
|
|
Rex Dieter |
adf30af |
+ </xsl:if>
|
|
Rex Dieter |
adf30af |
+
|
|
Rex Dieter |
adf30af |
/** Retrieve all records from this table. */
|
|
Rex Dieter |
adf30af |
static <xsl:value-of select="$className"/>::List retrieveAll();
|
|
Rex Dieter |
adf30af |
/** Retrieve all records with value @p value in column @p key. */
|
|
Rex Dieter |
adf30af |
diff --git a/server/src/storage/entities-source.xsl b/server/src/storage/entities-source.xsl
|
|
Rex Dieter |
adf30af |
index e398da5..46ef3a6 100644
|
|
Rex Dieter |
adf30af |
--- a/server/src/storage/entities-source.xsl
|
|
Rex Dieter |
adf30af |
+++ b/server/src/storage/entities-source.xsl
|
|
Rex Dieter |
adf30af |
@@ -130,7 +130,15 @@ void <xsl:value-of select="$className"/>::Private::addToCache( const
|
|
Rex Dieter |
adf30af |
idCache.insert( entry.id(), entry );
|
|
Rex Dieter |
adf30af |
</xsl:if>
|
|
Rex Dieter |
adf30af |
<xsl:if test="column[@name = 'name']">
|
|
Rex Dieter |
adf30af |
+ <xsl:choose>
|
|
Rex Dieter |
adf30af |
+ <xsl:when test="$className = 'PartType'">
|
|
Rex Dieter |
adf30af |
+
|
|
Rex Dieter |
adf30af |
+ nameCache.insert( entry.ns() + QLatin1Char(':') + entry.name(), entry );
|
|
Rex Dieter |
adf30af |
+ </xsl:when>
|
|
Rex Dieter |
adf30af |
+ <xsl:otherwise>
|
|
Rex Dieter |
adf30af |
nameCache.insert( entry.name(), entry );
|
|
Rex Dieter |
adf30af |
+ </xsl:otherwise>
|
|
Rex Dieter |
adf30af |
+ </xsl:choose>
|
|
Rex Dieter |
adf30af |
</xsl:if>
|
|
Rex Dieter |
adf30af |
}
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
@@ -323,7 +331,7 @@ QVector< <xsl:value-of select="$className"/> >
|
|
Rex Dieter |
adf30af |
}
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
</xsl:if>
|
|
Rex Dieter |
adf30af |
-<xsl:if test="column[@name = 'name']">
|
|
Rex Dieter |
adf30af |
+<xsl:if test="column[@name = 'name'] and $className != 'PartType'">
|
|
Rex Dieter |
adf30af |
<xsl:value-of select="$className"/><xsl:text> </xsl:text><xsl:value-of select="$className"/>::retrieveByName( const <xsl:value-of select="column[@name = 'name']/@type"/> &name )
|
|
Rex Dieter |
adf30af |
{
|
|
Rex Dieter |
adf30af |
<xsl:call-template name="data-retrieval">
|
|
Rex Dieter |
adf30af |
@@ -333,6 +341,19 @@ QVector< <xsl:value-of select="$className"/> >
|
|
Rex Dieter |
adf30af |
}
|
|
Rex Dieter |
adf30af |
</xsl:if>
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
+<xsl:if test="column[@name = 'name'] and $className = 'PartType'">
|
|
Rex Dieter |
adf30af |
+<xsl:text>PartType PartType::retrieveByFQName( const QString & ns, const QString & name )</xsl:text>
|
|
Rex Dieter |
adf30af |
+{
|
|
Rex Dieter |
adf30af |
+ const QString fqname = ns + QLatin1Char(':') + name;
|
|
Rex Dieter |
adf30af |
+ <xsl:call-template name="data-retrieval">
|
|
Rex Dieter |
adf30af |
+ <xsl:with-param name="key">ns</xsl:with-param>
|
|
Rex Dieter |
adf30af |
+ <xsl:with-param name="key2">name</xsl:with-param>
|
|
Rex Dieter |
adf30af |
+ <xsl:with-param name="lookupKey">fqname</xsl:with-param>
|
|
Rex Dieter |
adf30af |
+ <xsl:with-param name="cache">nameCache</xsl:with-param>
|
|
Rex Dieter |
adf30af |
+ </xsl:call-template>
|
|
Rex Dieter |
adf30af |
+}
|
|
Rex Dieter |
adf30af |
+</xsl:if>
|
|
Rex Dieter |
adf30af |
+
|
|
Rex Dieter |
adf30af |
QVector<<xsl:value-of select="$className"/>> <xsl:value-of select="$className"/>::retrieveAll()
|
|
Rex Dieter |
adf30af |
{
|
|
Rex Dieter |
adf30af |
QSqlDatabase db = DataStore::self()->database();
|
|
Rex Dieter |
adf30af |
@@ -588,7 +609,15 @@ void <xsl:value-of select="$className"/>::invalidateCache() const
|
|
Rex Dieter |
adf30af |
Private::idCache.remove( id() );
|
|
Rex Dieter |
adf30af |
</xsl:if>
|
|
Rex Dieter |
adf30af |
<xsl:if test="column[@name = 'name']">
|
|
Rex Dieter |
adf30af |
+ <xsl:choose>
|
|
Rex Dieter |
adf30af |
+ <xsl:when test="$className = 'PartType'">
|
|
Rex Dieter |
adf30af |
+
|
|
Rex Dieter |
adf30af |
+ Private::nameCache.remove( ns() + QLatin1Char(':') + name() );
|
|
Rex Dieter |
adf30af |
+ </xsl:when>
|
|
Rex Dieter |
adf30af |
+ <xsl:otherwise>
|
|
Rex Dieter |
adf30af |
Private::nameCache.remove( name() );
|
|
Rex Dieter |
adf30af |
+ </xsl:otherwise>
|
|
Rex Dieter |
adf30af |
+ </xsl:choose>
|
|
Rex Dieter |
adf30af |
</xsl:if>
|
|
Rex Dieter |
adf30af |
}
|
|
Rex Dieter |
adf30af |
}
|
|
Rex Dieter |
adf30af |
diff --git a/server/src/storage/entities.xsl b/server/src/storage/entities.xsl
|
|
Rex Dieter |
adf30af |
index c8fb1fd..2cf96c4 100644
|
|
Rex Dieter |
adf30af |
--- a/server/src/storage/entities.xsl
|
|
Rex Dieter |
adf30af |
+++ b/server/src/storage/entities.xsl
|
|
Rex Dieter |
adf30af |
@@ -169,12 +169,14 @@ set<xsl:value-of select="$methodName"/>( <xsl:call-template name="argument"/> )
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
<xsl:template name="data-retrieval">
|
|
Rex Dieter |
adf30af |
<xsl:param name="key"/>
|
|
Rex Dieter |
adf30af |
+<xsl:param name="key2"/>
|
|
Rex Dieter |
adf30af |
+<xsl:param name="lookupKey" select="$key"/>
|
|
Rex Dieter |
adf30af |
<xsl:param name="cache"/>
|
|
Rex Dieter |
adf30af |
<xsl:variable name="className"><xsl:value-of select="@name"/></xsl:variable>
|
|
Rex Dieter |
adf30af |
<xsl:if test="$cache != ''">
|
|
Rex Dieter |
adf30af |
if ( Private::cacheEnabled ) {
|
|
Rex Dieter |
adf30af |
QMutexLocker lock(&Private::cacheMutex);
|
|
Rex Dieter |
adf30af |
- QHash<<xsl:value-of select="column[@name = $key]/@type"/>, <xsl:value-of select="$className"/>>::const_iterator it = Private::<xsl:value-of select="$cache"/>.constFind(<xsl:value-of select="$key"/>);
|
|
Rex Dieter |
adf30af |
+ QHash<<xsl:value-of select="column[@name = $key]/@type"/>, <xsl:value-of select="$className"/>>::const_iterator it = Private::<xsl:value-of select="$cache"/>.constFind(<xsl:value-of select="$lookupKey"/>);
|
|
Rex Dieter |
adf30af |
if ( it != Private::<xsl:value-of select="$cache"/>.constEnd() ) {
|
|
Rex Dieter |
adf30af |
return it.value();
|
|
Rex Dieter |
adf30af |
}
|
|
Rex Dieter |
adf30af |
@@ -188,6 +190,9 @@ set<xsl:value-of select="$methodName"/>( <xsl:call-template name="argument"/> )
|
|
Rex Dieter |
adf30af |
static const QStringList columns = removeEntry(columnNames(), <xsl:value-of select="$key"/>Column());
|
|
Rex Dieter |
adf30af |
qb.addColumns( columns );
|
|
Rex Dieter |
adf30af |
qb.addValueCondition( <xsl:value-of select="$key"/>Column(), Query::Equals, <xsl:value-of select="$key"/> );
|
|
Rex Dieter |
adf30af |
+ <xsl:if test="$key2 != ''">
|
|
Rex Dieter |
adf30af |
+ qb.addValueCondition( <xsl:value-of select="$key2"/>Column(), Query::Equals, <xsl:value-of select="$key2"/> );
|
|
Rex Dieter |
adf30af |
+ </xsl:if>
|
|
Rex Dieter |
adf30af |
if ( !qb.exec() ) {
|
|
Rex Dieter |
adf30af |
akDebug() << "Error during selection of record with <xsl:value-of select="$key"/>"
|
|
Rex Dieter |
adf30af |
<< <xsl:value-of select="$key"/> << "from table" << tableName()
|
|
Rex Dieter |
adf30af |
diff --git a/server/src/storage/parttypehelper.cpp b/server/src/storage/parttypehelper.cpp
|
|
Rex Dieter |
adf30af |
index b73dcd5..7654108 100644
|
|
Rex Dieter |
adf30af |
--- a/server/src/storage/parttypehelper.cpp
|
|
Rex Dieter |
adf30af |
+++ b/server/src/storage/parttypehelper.cpp
|
|
Rex Dieter |
adf30af |
@@ -37,7 +37,7 @@ QPair< QString, QString > PartTypeHelper::parseFqName(const QString& fqName)
|
|
Rex Dieter |
adf30af |
PartType PartTypeHelper::fromFqName(const QString& fqName)
|
|
Rex Dieter |
adf30af |
{
|
|
Rex Dieter |
adf30af |
const QPair<QString, QString> p = parseFqName( fqName );
|
|
Rex Dieter |
adf30af |
- return fromName( p.first, p.second );
|
|
Rex Dieter |
adf30af |
+ return PartType::retrieveByFQName(p.first, p.second);
|
|
Rex Dieter |
adf30af |
}
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
PartType PartTypeHelper::fromFqName(const QByteArray& fqName)
|
|
Rex Dieter |
adf30af |
@@ -45,33 +45,6 @@ PartType PartTypeHelper::fromFqName(const QByteArray& fqName)
|
|
Rex Dieter |
adf30af |
return fromFqName( QLatin1String(fqName) );
|
|
Rex Dieter |
adf30af |
}
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
-PartType PartTypeHelper::fromName(const QString& ns, const QString& typeName)
|
|
Rex Dieter |
adf30af |
-{
|
|
Rex Dieter |
adf30af |
- SelectQueryBuilder<PartType> qb;
|
|
Rex Dieter |
adf30af |
- qb.addValueCondition( PartType::nsColumn(), Query::Equals, ns );
|
|
Rex Dieter |
adf30af |
- qb.addValueCondition( PartType::nameColumn(), Query::Equals, typeName );
|
|
Rex Dieter |
adf30af |
- if ( !qb.exec() )
|
|
Rex Dieter |
adf30af |
- throw PartTypeException( "Unable to query part type table." );
|
|
Rex Dieter |
adf30af |
- const PartType::List result = qb.result();
|
|
Rex Dieter |
adf30af |
- if ( result.size() == 1 )
|
|
Rex Dieter |
adf30af |
- return result.first();
|
|
Rex Dieter |
adf30af |
- if ( result.size() > 1 )
|
|
Rex Dieter |
adf30af |
- throw PartTypeException( "Part type uniqueness constraint violation." );
|
|
Rex Dieter |
adf30af |
-
|
|
Rex Dieter |
adf30af |
- // doesn't exist yet, so let's create a new one
|
|
Rex Dieter |
adf30af |
- PartType type;
|
|
Rex Dieter |
adf30af |
- type.setName( typeName );
|
|
Rex Dieter |
adf30af |
- type.setNs( ns );
|
|
Rex Dieter |
adf30af |
- if ( !type.insert() )
|
|
Rex Dieter |
adf30af |
- throw PartTypeException( "Creating a new part type failed." );
|
|
Rex Dieter |
adf30af |
- return type;
|
|
Rex Dieter |
adf30af |
-}
|
|
Rex Dieter |
adf30af |
-
|
|
Rex Dieter |
adf30af |
-PartType PartTypeHelper::fromName(const char* ns, const char* typeName)
|
|
Rex Dieter |
adf30af |
-{
|
|
Rex Dieter |
adf30af |
- return fromName( QLatin1String(ns), QLatin1String(typeName) );
|
|
Rex Dieter |
adf30af |
-}
|
|
Rex Dieter |
adf30af |
-
|
|
Rex Dieter |
adf30af |
Query::Condition PartTypeHelper::conditionFromFqName(const QString& fqName)
|
|
Rex Dieter |
adf30af |
{
|
|
Rex Dieter |
adf30af |
const QPair<QString, QString> p = parseFqName( fqName );
|
|
Rex Dieter |
adf30af |
diff --git a/server/src/storage/parttypehelper.h b/server/src/storage/parttypehelper.h
|
|
Rex Dieter |
adf30af |
index 38cb858..4c4f42f 100644
|
|
Rex Dieter |
adf30af |
--- a/server/src/storage/parttypehelper.h
|
|
Rex Dieter |
adf30af |
+++ b/server/src/storage/parttypehelper.h
|
|
Rex Dieter |
adf30af |
@@ -48,19 +48,6 @@ namespace PartTypeHelper
|
|
Rex Dieter |
adf30af |
PartType fromFqName( const QByteArray &fqName );
|
|
Rex Dieter |
adf30af |
|
|
Rex Dieter |
adf30af |
/**
|
|
Rex Dieter |
adf30af |
- * Retrieve (or create) PartType for the given namespace and type name.
|
|
Rex Dieter |
adf30af |
- * @param ns Namespace
|
|
Rex Dieter |
adf30af |
- * @param typeName Part type name.
|
|
Rex Dieter |
adf30af |
- * @throws PartTypeException
|
|
Rex Dieter |
adf30af |
- */
|
|
Rex Dieter |
adf30af |
- PartType fromName( const QString &ns, const QString &typeName );
|
|
Rex Dieter |
adf30af |
-
|
|
Rex Dieter |
adf30af |
- /**
|
|
Rex Dieter |
adf30af |
- * Convenience overload of the above.
|
|
Rex Dieter |
adf30af |
- */
|
|
Rex Dieter |
adf30af |
- PartType fromName( const char *ns, const char *typeName );
|
|
Rex Dieter |
adf30af |
-
|
|
Rex Dieter |
adf30af |
- /**
|
|
Rex Dieter |
adf30af |
* Returns a query condition that matches the given part.
|
|
Rex Dieter |
adf30af |
* @param fqName fully-qualified part type name
|
|
Rex Dieter |
adf30af |
* @throws PartTypeException
|
|
Rex Dieter |
adf30af |
--
|
|
Rex Dieter |
adf30af |
2.1.0
|
|
Rex Dieter |
adf30af |
|