LTP GCOV extension - code coverage report
Current view: directory - ept/popcon/maint - popconindexer.cc
Test: lcov.info
Date: 2008-08-14 Instrumented lines: 116
Code covered: 79.3 % Executed lines: 92

       1                 : #include <ept/popcon/popcon.h>
       2                 : #include <ept/popcon/maint/popconindexer.h>
       3                 : #include <ept/popcon/maint/path.h>
       4                 : 
       5                 : #include <wibble/exception.h>
       6                 : #include <wibble/sys/fs.h>
       7                 : 
       8                 : #include <tagcoll/diskindex/mmap.h>
       9                 : 
      10                 : #include <set>
      11                 : #include <string>
      12                 : #include <cstdio>
      13                 : #include <cstring>
      14                 : 
      15                 : using namespace std;
      16                 : 
      17                 : namespace ept {
      18                 : namespace popcon {
      19                 : 
      20                 : template<typename STRUCT>
      21                 : struct StructIndexer : public tagcoll::diskindex::MMapIndexer
      22               1 : {
      23                 :         const STRUCT& data;
      24               1 :         StructIndexer(const STRUCT& data) : data(data) {}
      25                 : 
      26               1 :         int encodedSize() const { return sizeof(STRUCT); }
      27               1 :         void encode(char* buf) const { *(STRUCT*)buf = data; }
      28                 : };
      29                 : 
      30                 : /// MMapIndexer that indexes the package names
      31                 : struct PopconGenerator : public tagcoll::diskindex::MMapIndexer
      32               4 : {
      33                 :         // Sorted set of all available package names and data
      34                 :         std::map<std::string, Score> data;
      35                 : 
      36               1 :         int encodedSize() const
      37                 :         {
      38               1 :                 int size = data.size() * sizeof(Score);
      39           69911 :                 for (std::map<std::string, Score>::const_iterator i = data.begin();
      40                 :                                 i != data.end(); ++i)
      41           69910 :                         size += i->first.size() + 1;
      42               1 :                 return tagcoll::diskindex::MMap::align(size);
      43                 :         }
      44                 : 
      45               1 :         void encode(char* buf) const
      46                 :         {
      47               1 :                 int pos = data.size() * sizeof(Score);
      48               1 :                 int idx = 0;
      49           69911 :                 for (std::map<std::string, Score>::const_iterator i = data.begin();
      50                 :                                 i != data.end(); ++i)
      51                 :                 {
      52           69910 :                         ((Score*)buf)[idx] = i->second;
      53           69910 :                         ((Score*)buf)[idx].offset = pos;
      54           69910 :                         memcpy(buf + pos, i->first.c_str(), i->first.size() + 1);
      55           69910 :                         pos += i->first.size() + 1;
      56           69910 :                         ++idx;
      57                 :                 }
      58               1 :         }
      59                 : };
      60                 : 
      61                 : 
      62               7 : PopconIndexer::PopconIndexer()
      63                 :         : mainSource(Path::popconSourceDir()),
      64               7 :           userSource(Path::popconUserSourceDir())
      65                 : {
      66               7 :         rescan();
      67               7 : }
      68                 : 
      69               7 : void PopconIndexer::rescan()
      70                 : {
      71               7 :         ts_main_src = mainSource.timestamp();
      72               7 :         ts_user_src = userSource.timestamp();
      73               7 :         ts_main_sco = Path::timestamp(Path::scores());
      74              14 :         ts_user_sco = Path::timestamp(Path::userScores());
      75              14 :         ts_main_idx = Path::timestamp(Path::scoresIndex());
      76              14 :         ts_user_idx = Path::timestamp(Path::userScoresIndex());
      77               7 : }
      78                 : 
      79               7 : bool PopconIndexer::needsRebuild() const
      80                 : {
      81                 :         // If there are no indexes of any kind, then we need rebuilding
      82               7 :         if (ts_user_sco == 0 || ts_main_sco == 0 || ts_user_idx == 0 && ts_main_idx == 0)
      83               2 :                 return true;
      84                 : 
      85                 :         // If the user index is ok, then we are fine
      86               5 :         if (ts_user_sco >= sourceTimestamp() && ts_user_idx >= sourceTimestamp())
      87               5 :                 return false;
      88                 : 
      89                 :         // If there are user sources, then we cannot use the system index
      90               0 :         if (ts_user_src > 0)
      91               0 :                 return true;
      92                 : 
      93                 :         // If there are no user sources, then we can fallback on the system
      94                 :         // indexes in case the user indexes are not up to date
      95               0 :         if (ts_main_sco >= sourceTimestamp() && ts_main_idx >= sourceTimestamp())
      96               0 :                 return false;
      97                 : 
      98               0 :         return true;
      99                 : }
     100                 : 
     101               7 : bool PopconIndexer::userIndexIsRedundant() const
     102                 : {
     103                 :         // If there is no user index, then it is not redundant
     104               7 :         if (ts_user_idx == 0)
     105               1 :                 return false;
     106                 : 
     107                 :         // If the system index is not up to date, then the user index is not
     108                 :         // redundant
     109               6 :         if (ts_main_idx < sourceTimestamp())
     110               0 :                 return false;
     111                 : 
     112               6 :         return true;
     113                 : }
     114                 : 
     115               2 : bool PopconIndexer::rebuild(const std::string& scofname, const std::string& idxfname)
     116                 : {
     117               2 :         PopconGenerator gen;
     118                 :         InfoStruct is;
     119               2 :         is.submissions = 0;
     120               2 :         if (!mainSource.readScores(gen.data, is.submissions))
     121               1 :                 userSource.readScores(gen.data, is.submissions);
     122               2 :         if (gen.data.empty())
     123               1 :                 return false;
     124                 : 
     125               1 :         StructIndexer<InfoStruct> infoStruct(is);
     126                 : 
     127                 :         // Create the index
     128               1 :         tagcoll::diskindex::MasterMMapIndexer master(idxfname);
     129               1 :         master.append(gen);
     130               1 :         master.append(infoStruct);
     131               1 :         master.commit();
     132                 : 
     133                 : //      for (map<string, Score>::const_iterator i = gen.data.begin(); i != gen.data.end(); ++i)
     134                 : //      {
     135                 : //              fprintf(stderr, "%s   %d   %f\n", i->first.c_str(), i->second.offset, i->second.score);
     136                 : //      }
     137                 : 
     138                 :         // Create the score file
     139               1 :         FILE* out = fopen(scofname.c_str(), "wt");
     140               1 :         if (out == NULL)
     141               0 :                 throw wibble::exception::File(scofname, "opening and truncating file for writing");
     142           69911 :         for (map<string, Score>::const_iterator i = gen.data.begin();
     143                 :                         i != gen.data.end(); ++i)
     144                 :         {
     145           69910 :                 fprintf(out, "%s %f\n", i->first.c_str(), i->second.score);
     146                 :         }
     147               1 :         fclose(out);
     148               1 :         return true;
     149                 : }
     150                 : 
     151               7 : bool PopconIndexer::rebuildIfNeeded()
     152                 : {
     153               7 :         if (needsRebuild())
     154                 :         {
     155                 :                 // Decide if we rebuild the user index or the system index
     156               2 :                 if (Path::access(Path::popconIndexDir(), W_OK) == 0)
     157                 :                 {
     158                 :                         // Since we can write on the system index directory, we rebuild
     159                 :                         // the system index
     160               2 :                         if (!rebuild(Path::scores(), Path::scoresIndex()))
     161               1 :                                 return false;
     162               1 :                         ts_main_sco = Path::timestamp(Path::scores());
     163               2 :                         ts_main_idx = Path::timestamp(Path::scoresIndex());
     164               2 :                         if (Path::scores() == Path::userScores())
     165               1 :                                 ts_user_sco = ts_main_sco;
     166               1 :                         if (Path::scoresIndex() == Path::userScoresIndex())
     167               1 :                                 ts_user_idx = ts_main_idx;
     168                 :                 } else {
     169               0 :                         wibble::sys::fs::mkFilePath(Path::userScores());
     170               0 :                         wibble::sys::fs::mkFilePath(Path::userScoresIndex());
     171               0 :                         if (!rebuild(Path::userScores(), Path::userScoresIndex()))
     172               0 :                                 return false;
     173               0 :                         ts_user_sco = Path::timestamp(Path::userScores());
     174               0 :                         ts_user_idx = Path::timestamp(Path::userScoresIndex());
     175                 :                 }
     176               1 :                 return true;
     177                 :         }
     178               5 :         return false;
     179                 : }
     180                 : 
     181               7 : bool PopconIndexer::deleteRedundantUserIndex()
     182                 : {
     183               7 :         if (userIndexIsRedundant())
     184                 :         {
     185                 :                 // Delete the user indexes if they exist
     186               6 :                 if (Path::scores() != Path::userScores())
     187                 :                 {
     188               0 :                         unlink(Path::userScores().c_str());
     189               0 :                         ts_user_sco = 0;
     190                 :                 }
     191               6 :                 if (Path::scoresIndex() != Path::userScoresIndex())
     192                 :                 {
     193               0 :                         unlink(Path::userScoresIndex().c_str());
     194               0 :                         ts_user_idx = 0;
     195                 :                 }
     196               6 :                 return true;
     197                 :         }
     198               1 :         return false;
     199                 : }
     200                 : 
     201               7 : bool PopconIndexer::getUpToDatePopcon(std::string& scofname, std::string& idxfname)
     202                 : {
     203                 :         // If there are no indexes of any kind, then we have nothing to return
     204               7 :         if (ts_user_sco == 0 && ts_main_sco == 0 && ts_user_idx == 0 && ts_main_idx == 0)
     205               1 :                 return false;
     206                 : 
     207                 :         // If the user index is up to date, use it
     208               6 :         if (ts_user_sco >= sourceTimestamp() &&
     209                 :             ts_user_idx >= sourceTimestamp())
     210                 :         {
     211               6 :                 scofname = Path::userScores();
     212              12 :                 idxfname = Path::userScoresIndex();
     213               6 :                 return true;
     214                 :         }
     215                 : 
     216                 :         // If the user index is not up to date and we have user sources, we cannot
     217                 :         // fall back to the system index
     218               0 :         if (ts_user_src != 0)
     219               0 :                 return false;
     220                 : 
     221                 :         // Fallback to the system index
     222               0 :         if (ts_main_sco >= sourceTimestamp() &&
     223                 :             ts_main_idx >= sourceTimestamp())
     224                 :         {
     225               0 :                 scofname = Path::scores();
     226               0 :                 idxfname = Path::scoresIndex();
     227               0 :                 return true;
     228                 :         }
     229                 : 
     230               0 :         return false;
     231                 : }
     232                 : 
     233                 : 
     234               7 : bool PopconIndexer::obtainWorkingPopcon(std::string& scofname, std::string& idxfname)
     235                 : {
     236               7 :         PopconIndexer indexer;
     237                 : 
     238               7 :         indexer.rebuildIfNeeded();
     239               7 :         indexer.deleteRedundantUserIndex();
     240               7 :         return indexer.getUpToDatePopcon(scofname, idxfname);
     241                 : }
     242                 : 
     243                 : 
     244                 : }
     245               6 : }
     246                 : 
     247                 : // vim:set ts=4 sw=4:

Generated by: LTP GCOV extension version 1.6