Report percentage complete based on file size

This patch makes the (reasonable) assumption that the total size of all checked
files fits in a 'long' type.
This commit is contained in:
Greg Hewgill 2011-04-19 23:52:32 +12:00
parent 46645ab327
commit 6d858b63a1
17 changed files with 113 additions and 37 deletions

View File

@ -85,13 +85,14 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
std::vector<std::string> pathnames = parser.GetPathNames();
std::vector<std::string> filenames;
std::map<std::string, long> filesizes;
if (!pathnames.empty())
{
// Execute recursiveAddFiles() to each given file parameter
std::vector<std::string>::const_iterator iter;
for (iter = pathnames.begin(); iter != pathnames.end(); ++iter)
FileLister::recursiveAddFiles(filenames, Path::toNativeSeparators(*iter));
FileLister::recursiveAddFiles(filenames, filesizes, Path::toNativeSeparators(*iter));
}
if (!filenames.empty())
@ -114,7 +115,10 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
{
std::vector<std::string>::iterator iter;
for (iter = filenames.begin(); iter != filenames.end(); ++iter)
{
_filenames.push_back(*iter);
_filesizes[*iter] = filesizes[*iter];
}
return true;
}
@ -146,10 +150,22 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
if (_settings._jobs == 1)
{
// Single process
long totalfilesize = 0;
for (std::map<std::string, long>::const_iterator i = _filesizes.begin(); i != _filesizes.end(); ++i)
{
totalfilesize += i->second;
}
long processedsize = 0;
for (unsigned int c = 0; c < _filenames.size(); c++)
{
returnValue += cppCheck.check(_filenames[c]);
reportStatus(c + 1, _filenames.size());
if (_filesizes.find(_filenames[c]) != _filesizes.end())
{
processedsize += _filesizes[_filenames[c]];
}
reportStatus(c + 1, _filenames.size(), processedsize, totalfilesize);
}
}
else if (!ThreadExecutor::isEnabled())
@ -160,7 +176,7 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
{
// Multiple processes
Settings &settings = cppCheck.settings();
ThreadExecutor executor(_filenames, settings, *this);
ThreadExecutor executor(_filenames, _filesizes, settings, *this);
returnValue = executor.check();
}
@ -216,14 +232,14 @@ void CppCheckExecutor::reportProgress(const std::string &filename, const char st
}
}
void CppCheckExecutor::reportStatus(unsigned int index, unsigned int max)
void CppCheckExecutor::reportStatus(unsigned int fileindex, unsigned int filecount, long sizedone, long sizetotal)
{
if (max > 1 && !_settings._errorsOnly)
if (filecount > 1 && !_settings._errorsOnly)
{
std::ostringstream oss;
oss << index << "/" << max
oss << fileindex << "/" << filecount
<< " files checked " <<
static_cast<int>(static_cast<double>(index) / max*100)
(sizetotal > 0 ? static_cast<long>(static_cast<double>(sizedone) / sizetotal*100) : 0)
<< "% done";
std::cout << oss.str() << std::endl;
}

View File

@ -72,7 +72,7 @@ public:
void reportProgress(const std::string &filename, const char stage[], const unsigned int value);
virtual void reportStatus(unsigned int index, unsigned int max);
virtual void reportStatus(unsigned int fileindex, unsigned int filecount, long sizedone, long sizetotal);
protected:
@ -113,6 +113,11 @@ private:
* List of files to check.
*/
std::vector<std::string> _filenames;
/**
* Sizes of files in _filenames.
*/
std::map<std::string, long> _filesizes;
};
#endif // CPPCHECKEXECUTOR_H

View File

@ -129,7 +129,7 @@ static HANDLE MyFindFirstFile(std::string path, LPWIN32_FIND_DATA findData)
#endif // defined(UNICODE)
void FileLister::recursiveAddFiles(std::vector<std::string> &filenames, const std::string &path)
void FileLister::recursiveAddFiles(std::vector<std::string> &filenames, std::map<std::string, long> &filesizes, const std::string &path)
{
// oss is the search string passed into FindFirst and FindNext.
// bdir is the base directory which is used to form pathnames.
@ -201,12 +201,14 @@ void FileLister::recursiveAddFiles(std::vector<std::string> &filenames, const st
{
const std::string nativename = Path::fromNativeSeparators(fname.str());
filenames.push_back(nativename);
// Limitation: file sizes are assumed to fit in a 'long'
filesizes[nativename] = ffd.nFileSizeLow;
}
}
else
{
// Directory
FileLister::recursiveAddFiles(filenames, fname.str());
FileLister::recursiveAddFiles(filenames, filesizes, fname.str());
}
#if defined(UNICODE)
delete [] ansiFfd;
@ -239,9 +241,11 @@ bool FileLister::isDirectory(const std::string &path)
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/stat.h>
void FileLister::recursiveAddFiles2(std::vector<std::string> &relative,
std::vector<std::string> &absolute,
std::map<std::string, long> &filesizes,
const std::string &path)
{
std::ostringstream oss;
@ -284,6 +288,14 @@ void FileLister::recursiveAddFiles2(std::vector<std::string> &relative,
{
relative.push_back(filename);
absolute.push_back(fname);
struct stat sb;
off_t size = 0;
if (stat(fname, &sb) == 0)
{
size = sb.st_size;
}
// Limitation: file sizes are assumed to fit in a 'long'
filesizes[filename] = static_cast<long>(size);
}
#ifndef PATH_MAX
@ -293,17 +305,17 @@ void FileLister::recursiveAddFiles2(std::vector<std::string> &relative,
else
{
// Directory
recursiveAddFiles2(relative, absolute, filename);
recursiveAddFiles2(relative, absolute, filesizes, filename);
}
}
globfree(&glob_results);
}
void FileLister::recursiveAddFiles(std::vector<std::string> &filenames, const std::string &path)
void FileLister::recursiveAddFiles(std::vector<std::string> &filenames, std::map<std::string, long> &filesizes, const std::string &path)
{
std::vector<std::string> abs;
recursiveAddFiles2(filenames, abs, path);
recursiveAddFiles2(filenames, abs, filesizes, path);
}
bool FileLister::isDirectory(const std::string &path)

View File

@ -21,6 +21,7 @@
#include <vector>
#include <string>
#include <map>
/// @addtogroup CLI
/// @{
@ -35,9 +36,11 @@ public:
* given vector. Only files with accepted extensions
* (*.c;*.cpp;*.cxx;*.c++;*.cc;*.txx) are added.
* @param filenames output vector that filenames are written to
* @param filesizes output map that contains the size of each file
* @param path root path
*/
static void recursiveAddFiles(std::vector<std::string> &filenames,
std::map<std::string, long> &filesizes,
const std::string &path);
/**
@ -57,6 +60,7 @@ public:
#ifndef _WIN32
static void recursiveAddFiles2(std::vector<std::string> &relative,
std::vector<std::string> &absolute,
std::map<std::string, long> &filesizes,
const std::string &path);
#endif
};

View File

@ -31,8 +31,8 @@
#include <time.h>
#endif
ThreadExecutor::ThreadExecutor(const std::vector<std::string> &filenames, Settings &settings, ErrorLogger &errorLogger)
: _filenames(filenames), _settings(settings), _errorLogger(errorLogger), _fileCount(0)
ThreadExecutor::ThreadExecutor(const std::vector<std::string> &filenames, const std::map<std::string, long> &filesizes, Settings &settings, ErrorLogger &errorLogger)
: _filenames(filenames), _filesizes(filesizes), _settings(settings), _errorLogger(errorLogger), _fileCount(0)
{
#ifdef THREADING_MODEL_FORK
_wpipe = 0;
@ -116,12 +116,10 @@ int ThreadExecutor::handleRead(int rpipe, unsigned int &result)
}
else if (type == '3')
{
_fileCount++;
std::istringstream iss(buf);
unsigned int fileResult = 0;
iss >> fileResult;
result += fileResult;
_errorLogger.reportStatus(_fileCount, _filenames.size());
delete [] buf;
return -1;
}
@ -135,8 +133,16 @@ unsigned int ThreadExecutor::check()
_fileCount = 0;
unsigned int result = 0;
long totalfilesize = 0;
for (std::map<std::string, long>::const_iterator i = _filesizes.begin(); i != _filesizes.end(); ++i)
{
totalfilesize += i->second;
}
std::list<int> rpipes;
std::map<pid_t, std::string> childFile;
std::map<int, std::string> pipeFile;
long processedsize = 0;
unsigned int i = 0;
while (true)
{
@ -199,6 +205,7 @@ unsigned int ThreadExecutor::check()
close(pipes[1]);
rpipes.push_back(pipes[0]);
childFile[pid] = _filenames[i];
pipeFile[pipes[0]] = _filenames[i];
++i;
}
@ -221,6 +228,23 @@ unsigned int ThreadExecutor::check()
int readRes = handleRead(*rp, result);
if (readRes == -1)
{
long size = 0;
std::map<int, std::string>::iterator p = pipeFile.find(*rp);
if (p != pipeFile.end())
{
std::string name = p->second;
pipeFile.erase(p);
std::map<std::string, long>::const_iterator fs = _filesizes.find(name);
if (fs != _filesizes.end())
{
size = fs->second;
}
}
_fileCount++;
processedsize += size;
_errorLogger.reportStatus(_fileCount, _filenames.size(), processedsize, totalfilesize);
close(*rp);
rp = rpipes.erase(rp);
}
@ -299,7 +323,7 @@ void ThreadExecutor::reportErr(const ErrorLogger::ErrorMessage &msg)
writeToPipe('2', msg.serialize());
}
void ThreadExecutor::reportStatus(unsigned int /*index*/, unsigned int /*max*/)
void ThreadExecutor::reportStatus(unsigned int /*fileindex*/, unsigned int /*filecount*/, long /*sizedone*/, long /*sizetotal*/)
{
// Not used
}
@ -319,7 +343,7 @@ void ThreadExecutor::reportErr(const ErrorLogger::ErrorMessage &/*msg*/)
}
void ThreadExecutor::reportStatus(unsigned int /*index*/, unsigned int /*max*/)
void ThreadExecutor::reportStatus(unsigned int /*fileindex*/, unsigned int /*filecount*/, long /*sizedone*/, long /*sizetotal*/)
{
}

View File

@ -39,12 +39,12 @@
class ThreadExecutor : public ErrorLogger
{
public:
ThreadExecutor(const std::vector<std::string> &filenames, Settings &settings, ErrorLogger &_errorLogger);
ThreadExecutor(const std::vector<std::string> &filenames, const std::map<std::string, long> &filesizes, Settings &settings, ErrorLogger &_errorLogger);
virtual ~ThreadExecutor();
unsigned int check();
virtual void reportOut(const std::string &outmsg);
virtual void reportErr(const ErrorLogger::ErrorMessage &msg);
virtual void reportStatus(unsigned int index, unsigned int max);
virtual void reportStatus(unsigned int fileindex, unsigned int filecount, long sizedone, long sizetotal);
/**
* @brief Add content to a file, to be used in unit testing.
*
@ -56,6 +56,7 @@ public:
private:
const std::vector<std::string> &_filenames;
const std::map<std::string, long> &_filesizes;
Settings &_settings;
ErrorLogger &_errorLogger;
unsigned int _fileCount;

View File

@ -92,10 +92,12 @@ QString ThreadResult::GetNextFile()
}
void ThreadResult::reportStatus(unsigned int index, unsigned int max)
void ThreadResult::reportStatus(unsigned int fileindex, unsigned int filecount, FileLister::filesize_t sizedone, FileLister::filesize_t sizetotal)
{
Q_UNUSED(index);
Q_UNUSED(max);
Q_UNUSED(fileindex);
Q_UNUSED(filecount);
Q_UNUSED(sizedone);
Q_UNUSED(sizetotal);
}
void ThreadResult::SetFiles(const QStringList &files)

View File

@ -71,7 +71,7 @@ public:
*/
void reportOut(const std::string &outmsg);
void reportErr(const ErrorLogger::ErrorMessage &msg);
void reportStatus(unsigned int index, unsigned int max);
void reportStatus(unsigned int fileindex, unsigned int filecount, FileLister::filesize_t sizedone, FileLister::filesize_t sizetotal);
public slots:
/**

View File

@ -433,7 +433,7 @@ void CppCheck::reportProgress(const std::string &filename, const char stage[], c
_errorLogger.reportProgress(filename, stage, value);
}
void CppCheck::reportStatus(unsigned int /*index*/, unsigned int /*max*/)
void CppCheck::reportStatus(unsigned int /*fileindex*/, unsigned int /*filecount*/, long /*sizedone*/, long /*sizetotal*/)
{
}

View File

@ -99,7 +99,7 @@ public:
*/
static const char * version();
virtual void reportStatus(unsigned int index, unsigned int max);
virtual void reportStatus(unsigned int fileindex, unsigned int filecount, long sizedone, long sizetotal);
/**
* @brief Terminate checking. The checking will be terminated as soon as possible.

View File

@ -275,10 +275,12 @@ public:
/**
* Information about how many files have been checked
*
* @param index This many files have been checked.
* @param max This many files there are in total.
* @param fileindex This many files have been checked.
* @param filecount This many files there are in total.
* @param sizedone The sum of sizes of the files checked.
* @param sizetotal The total sizes of the files.
*/
virtual void reportStatus(unsigned int index, unsigned int max) = 0;
virtual void reportStatus(unsigned int fileindex, unsigned int filecount, long sizedone, long sizetotal) = 0;
/**
* Report progress to client

View File

@ -59,7 +59,7 @@ private:
id.push_back(msg._id);
}
void reportStatus(unsigned int /*index*/, unsigned int /*max*/)
void reportStatus(unsigned int /*fileindex*/, unsigned int /*filecount*/, long /*sizedone*/, long /*sizetotal*/)
{
}
};

View File

@ -52,7 +52,15 @@ private:
{
// Recursively add add files..
std::vector<std::string> filenames;
FileLister::recursiveAddFiles(filenames, ".");
std::map<std::string, long> filesizes;
FileLister::recursiveAddFiles(filenames, filesizes, ".");
// Ensure a nonzero size is present for each listed file
for (std::vector<std::string>::const_iterator i = filenames.begin(); i != filenames.end(); ++i)
{
ASSERT(filesizes.find(*i) != filesizes.end());
ASSERT(filesizes[*i] > 0);
}
// In case there are leading "./"..
for (unsigned int i = 0; i < filenames.size(); ++i)

View File

@ -179,9 +179,9 @@ private:
if (!msg._callStack.empty() && !_settings.nomsg.isSuppressed(msg._id, msg._callStack.begin()->getfile(), msg._callStack.begin()->line))
_next->reportErr(msg);
}
virtual void reportStatus(unsigned int index, unsigned int max)
virtual void reportStatus(unsigned int fileindex, unsigned int filecount, long sizedone, long sizetotal)
{
_next->reportStatus(index, max);
_next->reportStatus(fileindex, filecount, sizedone, sizetotal);
}
private:
Settings &_settings;

View File

@ -61,7 +61,7 @@ protected:
public:
virtual void reportOut(const std::string &outmsg);
virtual void reportErr(const ErrorLogger::ErrorMessage &msg);
virtual void reportStatus(unsigned int /*index*/, unsigned int /*max*/) {}
virtual void reportStatus(unsigned int /*fileindex*/, unsigned int /*filecount*/, long /*sizedone*/, long /*sizetotal*/) {}
void run(const std::string &str);
TestFixture(const std::string &_name);

View File

@ -71,6 +71,7 @@ private:
}
std::vector<std::string> filenames;
std::map<std::string, long> filesizes;
filenames.push_back("test.cpp");
Settings settings;
@ -81,7 +82,7 @@ private:
std::string r = settings.nomsg.addSuppressionLine(suppression);
ASSERT_EQUALS("", r);
}
ThreadExecutor executor(filenames, settings, *this);
ThreadExecutor executor(filenames, filesizes, settings, *this);
for (unsigned int i = 0; i < filenames.size(); ++i)
executor.addFileContent(filenames[i], code);

View File

@ -56,6 +56,7 @@ private:
}
std::vector<std::string> filenames;
std::map<std::string, long> filesizes;
for (int i = 1; i <= files; ++i)
{
std::ostringstream oss;
@ -65,7 +66,7 @@ private:
Settings settings;
settings._jobs = jobs;
ThreadExecutor executor(filenames, settings, *this);
ThreadExecutor executor(filenames, filesizes, settings, *this);
for (unsigned int i = 0; i < filenames.size(); ++i)
executor.addFileContent(filenames[i], data);