- Use a global cache fox index file sizes to avoid potentially very expensive
authorPanu Matilainen <pmatilai@turre.koti.laiskiainen.org>
Tue, 24 Apr 2007 08:03:59 +0000 (11:03 +0300)
committerPanu Matilainen <pmatilai@turre.koti.laiskiainen.org>
Tue, 24 Apr 2007 08:03:59 +0000 (11:03 +0300)
  successive calls to CreateHandler() just for progress reporting where it
  doesn't even matter if the information is 100% accurate. This also allows
  getting rid of xml/sqlite specific optimizations inside rpmindexfile.cc
  and fixes old "must optimize this somehow" cases in rpm-dir type indexes.

apt-pkg/rpm/rpmhandler.cc
apt-pkg/rpm/rpmindexfile.cc
apt-pkg/rpm/rpmindexfile.h

index 95e225f..14c70e0 100644 (file)
@@ -55,6 +55,8 @@
 // not happen.
 bool HideZeroEpoch;
 
+extern map<string,int> rpmIndexSizes;
+
 string RPMHandler::EVR()
 {
    string e = Epoch();
@@ -465,6 +467,7 @@ RPMFileHandler::RPMFileHandler(string File)
       return;
    }
    iSize = fdSize(FD);
+   rpmIndexSizes[ID] = iSize;
 }
 
 RPMFileHandler::RPMFileHandler(FileFd *File)
@@ -479,6 +482,7 @@ RPMFileHandler::RPMFileHandler(FileFd *File)
       return;
    }
    iSize = fdSize(FD);
+   rpmIndexSizes[ID] = iSize;
 }
 
 RPMFileHandler::~RPMFileHandler()
@@ -624,6 +628,7 @@ RPMDirHandler::RPMDirHandler(string DirName)
    TS = rpmtsCreate();
    rpmtsSetVSFlags(TS, (rpmVSFlags_e)-1);
 #endif
+   rpmIndexSizes[ID] = iSize;
 }
 
 const char *RPMDirHandler::nextFileName()
@@ -802,6 +807,7 @@ RPMDBHandler::RPMDBHandler(bool WriteLock)
    iSize = St.st_size;
 
 #endif
+   rpmIndexSizes[ID] = iSize;
 
 
    // Restore just after opening the database, and just after closing.
@@ -979,6 +985,7 @@ RPMRepomdHandler::RPMRepomdHandler(string File): RPMHandler(),
       _error->Warning(_("Inconsistent metadata, package count doesn't match in %s"), File.c_str());
       iSize = pkgcount;
    }
+   rpmIndexSizes[ID] = iSize;
 
    return;
 
@@ -1323,6 +1330,7 @@ RPMRepomdReaderHandler::RPMRepomdReaderHandler(string File) : RPMHandler(),
         ret = xmlTextReaderRead(XmlFile);
       }
    }
+   rpmIndexSizes[ID] = iSize;
    return;
 
 error:
@@ -1468,6 +1476,7 @@ RPMSqliteHandler::RPMSqliteHandler(string File) :
 
    Packages->Exec("select * from packages");
    iSize = Packages->Size();
+   rpmIndexSizes[ID] = iSize;
 }
 
 RPMSqliteHandler::~RPMSqliteHandler()
index b2bb577..9e888a8 100644 (file)
                                                                        /*}}}*/
 vector<pkgRepository *> RepList;
 
+extern map<string,int> IndexSizes;
+
+// Hack to avoid potentially very expensive CreateHandler() calls from
+// indexfile progress reporting. It's only used for progress so it doesn't
+// really matter if it's even accurate. 
+map<string,int> rpmIndexSizes;
+
+off_t rpmIndexFile::Size() const
+{
+   off_t Res;
+   string IP = IndexPath();
+
+   if (rpmIndexSizes.find(IP) == rpmIndexSizes.end()) {
+      RPMHandler *Handler = CreateHandler();
+      Res = Handler->Size();
+      delete Handler;
+   } else {
+      Res = rpmIndexSizes[IP];
+   }
+   return Res;
+}
+
 // rpmListIndex::Release* - Return the URI to the release file         /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -172,17 +194,6 @@ bool rpmListIndex::Exists() const
    return FileExists(IndexPath());
 }
                                                                        /*}}}*/
-// rpmListIndex::Size - Return the size of the index                   /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-off_t rpmListIndex::Size() const
-{
-   struct stat S;
-   if (stat(IndexPath().c_str(),&S) != 0)
-      return 0;
-   return S.st_size;
-}
-                                                                       /*}}}*/
 // rpmListIndex::Describe - Give a descriptive path to the index       /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -479,19 +490,6 @@ string rpmPkgDirIndex::ReleasePath() const
    return ::URI(IndexURI("release")).Path;
 }
                                                                        /*}}}*/
-// PkgDirIndex::Size - Return the size of the index                    /*{{{*/
-// ---------------------------------------------------------------------
-/* This is really only used for progress reporting. */
-off_t rpmPkgDirIndex::Size() const
-{
-   // XXX: Must optimize this somehow.
-   RPMHandler *Handler = CreateHandler();
-   off_t Res = Handler->Size();
-   delete Handler;
-   return Res;
-}
-                                                                       /*}}}*/
-
 // SrcDirIndex::Index* - Return the URI to the index files             /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -500,17 +498,6 @@ string rpmSrcDirIndex::IndexPath() const
    return ::URI(ArchiveURI("")).Path;
 }
                                                                        /*}}}*/
-// SrcDirIndex::Size - Return the size of the index                    /*{{{*/
-// ---------------------------------------------------------------------
-/* This is really only used for progress reporting. */
-off_t rpmSrcDirIndex::Size() const
-{
-   // XXX: Must optimize this somehow.
-   RPMHandler *Handler = CreateHandler();
-   off_t Res = Handler->Size();
-   delete Handler;
-   return Res;
-}
 
 // SinglePkgIndex::ArchiveURI - URI for the archive                    /*{{{*/
 // ---------------------------------------------------------------------
@@ -699,29 +686,6 @@ string rpmRepomdIndex::ReleasePath() const
    return _config->FindDir("Dir::State::lists")+URItoFileName(ReleaseURI("repomd.xml"));
 }
 
-// This gets called several times per each index during cache generation,
-// only for progress percentage reporting. A rough estimate would do just
-// fine but using xmlReader appears to be cheap enough. OTOH creating a new 
-// handler like is done for rpmPkgDirIndex is hideously expensive.
-off_t rpmRepomdIndex::Size() const
-{
-   xmlTextReaderPtr Index;
-   off_t Res;
-   Index = xmlReaderForFile(IndexPath().c_str(), NULL,
-                         XML_PARSE_NONET|XML_PARSE_NOBLANKS);
-   if (Index == NULL) return 0;
-
-   if (xmlTextReaderRead(Index) == 1) {
-      xmlChar *pkgs = xmlTextReaderGetAttribute(Index, (xmlChar*)"packages");
-      Res = atoi((char*)pkgs);
-      xmlFree(pkgs);
-   } else {
-      Res = 0;
-   }
-   xmlFreeTextReader(Index);
-   return Res;
-}
-
 bool rpmRepomdIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
 {
    string PackageFile = IndexPath();
@@ -850,22 +814,6 @@ bool rpmRepomdDBIndex::GetIndexes(pkgAcquire *Owner) const
    return true;
 }
 
-off_t rpmRepomdDBIndex::Size() const
-{
-   off_t Res;
-   SqliteDB DB(IndexPath());
-   SqliteQuery *Q = DB.Query();
-   Q->Exec("select pkgKey from packages");
-   Res = Q->Size();
-   delete Q;
-   return Res;
-#if 0
-   RPMHandler *Handler = CreateHandler();
-   off_t Res = Handler->Size();
-   delete Handler;
-   return Res;
-#endif
-}
 bool rpmRepomdDBIndex::MergeFileProvides(pkgCacheGenerator &Gen,
                                        OpProgress &Prog) const
 {
@@ -893,6 +841,12 @@ rpmDatabaseIndex::rpmDatabaseIndex()
 {
 }
                                                                        /*}}}*/
+
+string rpmDatabaseIndex::IndexPath() const
+{
+   return rpmSys.GetDBHandler()->DataPath(false);
+}
+
 // DatabaseIndex::Size - Return the size of the index                  /*{{{*/
 // ---------------------------------------------------------------------
 /* */
index 4c35445..57fbbb3 100644 (file)
@@ -31,16 +31,22 @@ class pkgRepository;
 
 class rpmIndexFile : public pkgIndexFile
 {
+   protected:
+   virtual string IndexPath() const = 0;
    
    public:
 
    virtual RPMHandler *CreateHandler() const = 0;
    virtual bool HasPackages() const {return false;};
+   virtual off_t Size() const;
 
 };
 
 class rpmDatabaseIndex : public rpmIndexFile
 {
+   protected:
+   virtual string IndexPath() const;
+
    public:
 
    virtual const Type *GetType() const;
@@ -52,8 +58,8 @@ class rpmDatabaseIndex : public rpmIndexFile
    virtual string Describe(bool Short) const {return "RPM Database";};
    
    // Interface for the Cache Generator
-   virtual bool Exists() const {return true;};
    virtual off_t Size() const;
+   virtual bool Exists() const {return true;};
    virtual bool HasPackages() const {return true;};
    virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
    virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,
@@ -91,7 +97,6 @@ class rpmListIndex : public rpmIndexFile
 
    // Interface for the Cache Generator
    virtual bool Exists() const;
-   virtual off_t Size() const;
 
    // Interface for acquire
    virtual string Describe(bool Short) const;   
@@ -189,9 +194,6 @@ class rpmPkgDirIndex : public rpmPkgListIndex
           { return new RPMDirHandler(IndexPath()); };
 
    virtual const Type *GetType() const;
-   
-   // Interface for the Cache Generator
-   virtual off_t Size() const;
 
    rpmPkgDirIndex(string URI,string Dist,string Section,
                   pkgRepository *Repository) :
@@ -217,9 +219,6 @@ class rpmSrcDirIndex : public rpmSrcListIndex
 
    virtual const Type *GetType() const;
    
-   // Interface for the Cache Generator
-   virtual off_t Size() const;
-
    rpmSrcDirIndex(string URI,string Dist,string Section,
                   pkgRepository *Repository) :
           rpmSrcListIndex(URI,Dist,Section,Repository)
@@ -310,7 +309,6 @@ class rpmRepomdIndex : public rpmIndexFile
 
    // Interface for the Cache Generator
    virtual bool Exists() const;
-   virtual off_t Size() const;
 
    // Interface for acquire
    virtual string Describe(bool Short) const;
@@ -384,7 +382,6 @@ class rpmRepomdDBIndex : public rpmRepomdIndex
    virtual RPMHandler *CreateHandler() const
           { return new RPMSqliteHandler(IndexFile("primary_db")); };
    virtual bool GetIndexes(pkgAcquire *Owner) const;
-   virtual off_t Size() const;
    virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,
                                  OpProgress &/*Prog*/) const;