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