TempFile: clean-up interface by using internal ref-counted class member. Uncomp: add interface to clear cache

This commit is contained in:
Jean-Francois Dockes 2018-05-17 10:24:01 +02:00
parent 40fd63662b
commit d69d2abbde
12 changed files with 147 additions and 96 deletions

View File

@ -47,6 +47,7 @@ using namespace std;
#include "copyfile.h" #include "copyfile.h"
#include "fetcher.h" #include "fetcher.h"
#include "extrameta.h" #include "extrameta.h"
#include "uncomp.h"
// The internal path element separator. This can't be the same as the rcldb // The internal path element separator. This can't be the same as the rcldb
// file to ipath separator : "|" // file to ipath separator : "|"
@ -188,7 +189,7 @@ void FileInterner::init(const string &f, const struct stat *stp, RclConfig *cnf,
int maxkbs = -1; int maxkbs = -1;
if (!m_cfg->getConfParam("compressedfilemaxkbs", &maxkbs) || if (!m_cfg->getConfParam("compressedfilemaxkbs", &maxkbs) ||
maxkbs < 0 || !stp || int(stp->st_size / 1024) < maxkbs) { maxkbs < 0 || !stp || int(stp->st_size / 1024) < maxkbs) {
if (!m_uncomp.uncompressfile(m_fn, ucmd, m_tfile)) { if (!m_uncomp->uncompressfile(m_fn, ucmd, m_tfile)) {
return; return;
} }
LOGDEB1("FileInterner:: after ucomp: tfile " << m_tfile <<"\n"); LOGDEB1("FileInterner:: after ucomp: tfile " << m_tfile <<"\n");
@ -293,8 +294,8 @@ void FileInterner::init(const string &data, RclConfig *cnf,
result = df->set_document_data(m_mimetype, data.c_str(), data.length()); result = df->set_document_data(m_mimetype, data.c_str(), data.length());
} else if (df->is_data_input_ok(Dijon::Filter::DOCUMENT_FILE_NAME)) { } else if (df->is_data_input_ok(Dijon::Filter::DOCUMENT_FILE_NAME)) {
TempFile temp = dataToTempFile(data, m_mimetype); TempFile temp = dataToTempFile(data, m_mimetype);
if (temp && if (temp.ok() &&
(result = df->set_document_file(m_mimetype, temp->filename()))) { (result = df->set_document_file(m_mimetype, temp.filename()))) {
m_tmpflgs[m_handlers.size()] = true; m_tmpflgs[m_handlers.size()] = true;
m_tempfiles.push_back(temp); m_tempfiles.push_back(temp);
} }
@ -312,7 +313,8 @@ void FileInterner::init(const string &data, RclConfig *cnf,
void FileInterner::initcommon(RclConfig *cnf, int flags) void FileInterner::initcommon(RclConfig *cnf, int flags)
{ {
m_cfg = cnf; m_cfg = cnf;
m_uncomp = m_forPreview = ((flags & FIF_forPreview) != 0); m_forPreview = ((flags & FIF_forPreview) != 0);
m_uncomp = new Uncomp(m_forPreview);
// Initialize handler stack. // Initialize handler stack.
m_handlers.reserve(MAXHANDLERS); m_handlers.reserve(MAXHANDLERS);
for (unsigned int i = 0; i < MAXHANDLERS; i++) for (unsigned int i = 0; i < MAXHANDLERS; i++)
@ -373,10 +375,10 @@ bool FileInterner::makesig(RclConfig *cnf, const Rcl::Doc& idoc, string& sig)
FileInterner::~FileInterner() FileInterner::~FileInterner()
{ {
for (vector<RecollFilter*>::iterator it = m_handlers.begin(); for (auto& entry: m_handlers) {
it != m_handlers.end(); it++) { returnMimeHandler(entry);
returnMimeHandler(*it);
} }
delete m_uncomp;
// m_tempfiles will take care of itself // m_tempfiles will take care of itself
} }
@ -386,14 +388,14 @@ FileInterner::~FileInterner()
TempFile FileInterner::dataToTempFile(const string& dt, const string& mt) TempFile FileInterner::dataToTempFile(const string& dt, const string& mt)
{ {
// Create temp file with appropriate suffix for mime type // Create temp file with appropriate suffix for mime type
TempFile temp(new TempFileInternal(m_cfg->getSuffixFromMimeType(mt))); TempFile temp(m_cfg->getSuffixFromMimeType(mt));
if (!temp->ok()) { if (!temp.ok()) {
LOGERR("FileInterner::dataToTempFile: cant create tempfile: " << LOGERR("FileInterner::dataToTempFile: cant create tempfile: " <<
temp->getreason() << "\n"); temp.getreason() << "\n");
return TempFile(); return TempFile();
} }
string reason; string reason;
if (!stringtofile(dt, temp->filename(), reason)) { if (!stringtofile(dt, temp.filename(), reason)) {
LOGERR("FileInterner::dataToTempFile: stringtofile: " <<reason << "\n"); LOGERR("FileInterner::dataToTempFile: stringtofile: " <<reason << "\n");
return TempFile(); return TempFile();
} }
@ -723,8 +725,8 @@ int FileInterner::addHandler()
setres = newflt->set_document_data(mimetype,txt->c_str(),txt->length()); setres = newflt->set_document_data(mimetype,txt->c_str(),txt->length());
} else if (newflt->is_data_input_ok(Dijon::Filter::DOCUMENT_FILE_NAME)) { } else if (newflt->is_data_input_ok(Dijon::Filter::DOCUMENT_FILE_NAME)) {
TempFile temp = dataToTempFile(*txt, mimetype); TempFile temp = dataToTempFile(*txt, mimetype);
if (temp && if (temp.ok() &&
(setres = newflt->set_document_file(mimetype, temp->filename()))) { (setres = newflt->set_document_file(mimetype, temp.filename()))) {
m_tmpflgs[m_handlers.size()] = true; m_tmpflgs[m_handlers.size()] = true;
m_tempfiles.push_back(temp); m_tempfiles.push_back(temp);
// Hack here, but really helps perfs: if we happen to // Hack here, but really helps perfs: if we happen to
@ -765,7 +767,7 @@ FileInterner::Status FileInterner::internfile(Rcl::Doc& doc,const string& ipath)
LOGDEB("FileInterner::internfile. ipath [" << ipath << "]\n"); LOGDEB("FileInterner::internfile. ipath [" << ipath << "]\n");
// Get rid of possible image tempfile from older call // Get rid of possible image tempfile from older call
m_imgtmp.reset(); m_imgtmp = TempFile();
if (m_handlers.size() < 1) { if (m_handlers.size() < 1) {
// Just means the constructor failed // Just means the constructor failed
@ -916,9 +918,8 @@ FileInterner::Status FileInterner::internfile(Rcl::Doc& doc,const string& ipath)
bool FileInterner::tempFileForMT(TempFile& otemp, RclConfig* cnf, bool FileInterner::tempFileForMT(TempFile& otemp, RclConfig* cnf,
const string& mimetype) const string& mimetype)
{ {
TempFile temp(new TempFileInternal( TempFile temp(cnf->getSuffixFromMimeType(mimetype));
cnf->getSuffixFromMimeType(mimetype))); if (!temp.ok()) {
if (!temp->ok()) {
LOGERR("FileInterner::tempFileForMT: can't create temp file\n"); LOGERR("FileInterner::tempFileForMT: can't create temp file\n");
return false; return false;
} }
@ -970,7 +971,7 @@ bool FileInterner::topdocToFile(
if (!tempFileForMT(temp, cnf, idoc.mimetype)) { if (!tempFileForMT(temp, cnf, idoc.mimetype)) {
return false; return false;
} }
filename = temp->filename(); filename = temp.filename();
} else { } else {
filename = tofile.c_str(); filename = tofile.c_str();
} }
@ -985,7 +986,7 @@ bool FileInterner::topdocToFile(
return false; return false;
} }
} }
fn = temp ? temp->filename() : rawdoc.data; fn = temp.ok() ? temp.filename() : rawdoc.data;
if (!copyfile(fn.c_str(), filename, reason)) { if (!copyfile(fn.c_str(), filename, reason)) {
LOGERR("FileInterner::idocToFile: copyfile: " << reason << "\n"); LOGERR("FileInterner::idocToFile: copyfile: " << reason << "\n");
return false; return false;
@ -1040,7 +1041,7 @@ bool FileInterner::interntofile(TempFile& otemp, const string& tofile,
if (!tempFileForMT(temp, m_cfg, mimetype)) { if (!tempFileForMT(temp, m_cfg, mimetype)) {
return false; return false;
} }
filename = temp->filename(); filename = temp.filename();
} else { } else {
filename = tofile.c_str(); filename = tofile.c_str();
} }
@ -1106,9 +1107,8 @@ bool FileInterner::maybeUncompressToTemp(TempFile& temp, const string& fn,
" kbs\n"); " kbs\n");
return false; return false;
} }
temp = temp = TempFile(cnf->getSuffixFromMimeType(doc.mimetype));
TempFile(new TempFileInternal(cnf->getSuffixFromMimeType(doc.mimetype))); if (!temp.ok()) {
if (!temp->ok()) {
LOGERR("FileInterner: cant create temporary file\n"); LOGERR("FileInterner: cant create temporary file\n");
return false; return false;
} }
@ -1123,9 +1123,9 @@ bool FileInterner::maybeUncompressToTemp(TempFile& temp, const string& fn,
// reason for this, but it's not nice here. Have to move, the // reason for this, but it's not nice here. Have to move, the
// uncompressed file, hopefully staying on the same dev. // uncompressed file, hopefully staying on the same dev.
string reason; string reason;
if (!renameormove(uncomped.c_str(), temp->filename(), reason)) { if (!renameormove(uncomped.c_str(), temp.filename(), reason)) {
LOGERR("FileInterner::maybeUncompress: move [" << uncomped << LOGERR("FileInterner::maybeUncompress: move [" << uncomped <<
"] -> [" << temp->filename() << "] failed: " << reason << "\n"); "] -> [" << temp.filename() << "] failed: " << reason << "\n");
return false; return false;
} }
return true; return true;

View File

@ -28,14 +28,15 @@ using std::map;
using std::set; using std::set;
#include "mimehandler.h" #include "mimehandler.h"
#include "uncomp.h"
#include "pathut.h" #include "pathut.h"
#include "rclutil.h"
class RclConfig; class RclConfig;
namespace Rcl { namespace Rcl {
class Doc; class Doc;
} }
class Uncomp;
struct stat; struct stat;
/** Storage for missing helper program info. We want to keep this out of the /** Storage for missing helper program info. We want to keep this out of the
@ -277,7 +278,7 @@ class FileInterner {
string m_reason; string m_reason;
FIMissingStore *m_missingdatap{nullptr}; FIMissingStore *m_missingdatap{nullptr};
Uncomp m_uncomp; Uncomp *m_uncomp{nullptr};
bool m_noxattrs; // disable xattrs usage bool m_noxattrs; // disable xattrs usage
bool m_direct; // External app did the extraction bool m_direct; // External app did the extraction

View File

@ -35,6 +35,12 @@ using std::vector;
Uncomp::UncompCache Uncomp::o_cache; Uncomp::UncompCache Uncomp::o_cache;
Uncomp::Uncomp(bool docache)
: m_docache(docache)
{
LOGDEB0("Uncomp::Uncomp: m_docache: " << m_docache << "\n");
}
bool Uncomp::uncompressfile(const string& ifn, bool Uncomp::uncompressfile(const string& ifn,
const vector<string>& cmdv, string& tfile) const vector<string>& cmdv, string& tfile)
{ {
@ -57,7 +63,8 @@ bool Uncomp::uncompressfile(const string& ifn,
} }
// Make sure tmp dir is empty. we guarantee this to filters // Make sure tmp dir is empty. we guarantee this to filters
if (!m_dir || !m_dir->ok() || !m_dir->wipe()) { if (!m_dir || !m_dir->ok() || !m_dir->wipe()) {
LOGERR("uncompressfile: can't clear temp dir " << (m_dir->dirname()) << "\n" ); LOGERR("uncompressfile: can't clear temp dir " << m_dir->dirname() <<
"\n");
return false; return false;
} }
@ -66,12 +73,14 @@ bool Uncomp::uncompressfile(const string& ifn,
int pc; int pc;
long long availmbs; long long availmbs;
if (!fsocc(m_dir->dirname(), &pc, &availmbs)) { if (!fsocc(m_dir->dirname(), &pc, &availmbs)) {
LOGERR("uncompressfile: can't retrieve avail space for " << (m_dir->dirname()) << "\n" ); LOGERR("uncompressfile: can't retrieve avail space for " <<
m_dir->dirname() << "\n");
// Hope for the best // Hope for the best
} else { } else {
long long fsize = path_filesize(ifn); long long fsize = path_filesize(ifn);
if (fsize < 0) { if (fsize < 0) {
LOGERR("uncompressfile: stat input file " << (ifn) << " errno " << (errno) << "\n" ); LOGERR("uncompressfile: stat input file " << ifn << " errno " <<
errno << "\n");
return false; return false;
} }
// We need at least twice the file size for the uncompressed // We need at least twice the file size for the uncompressed
@ -83,7 +92,9 @@ bool Uncomp::uncompressfile(const string& ifn,
long long filembs = fsize / (1024 * 1024); long long filembs = fsize / (1024 * 1024);
if (availmbs < 2 * filembs + 1) { if (availmbs < 2 * filembs + 1) {
LOGERR("uncompressfile. " << (lltodecstr(availmbs)) << " MBs available in " << (m_dir->dirname()) << " not enough to uncompress " << (ifn) << " of size " << (lltodecstr(filembs)) << " mbs\n" ); LOGERR("uncompressfile. " << availmbs << " MBs available in " <<
m_dir->dirname() << " not enough to uncompress " <<
ifn << " of size " << filembs << " MBs\n");
return false; return false;
} }
} }
@ -107,9 +118,10 @@ bool Uncomp::uncompressfile(const string& ifn,
ExecCmd ex; ExecCmd ex;
int status = ex.doexec(cmd, args, 0, &tfile); int status = ex.doexec(cmd, args, 0, &tfile);
if (status || tfile.empty()) { if (status || tfile.empty()) {
LOGERR("uncompressfile: doexec: failed for [" << (ifn) << "] status 0x" << (status) << "\n" ); LOGERR("uncompressfile: doexec: failed for [" << ifn << "] status 0x" <<
status << "\n");
if (!m_dir->wipe()) { if (!m_dir->wipe()) {
LOGERR("uncompressfile: wipedir failed\n" ); LOGERR("uncompressfile: wipedir failed\n");
} }
return false; return false;
} }
@ -122,6 +134,8 @@ bool Uncomp::uncompressfile(const string& ifn,
Uncomp::~Uncomp() Uncomp::~Uncomp()
{ {
LOGDEB0("Uncomp::~Uncomp: m_docache: " << m_docache << " m_dir " <<
(m_dir?m_dir->dirname():"(null)") << "\n");
if (m_docache) { if (m_docache) {
std::unique_lock<std::mutex> lock(o_cache.m_lock); std::unique_lock<std::mutex> lock(o_cache.m_lock);
delete o_cache.m_dir; delete o_cache.m_dir;
@ -133,4 +147,12 @@ Uncomp::~Uncomp()
} }
} }
void Uncomp::clearcache()
{
LOGDEB0("Uncomp::clearcache\n");
std::unique_lock<std::mutex> lock(o_cache.m_lock);
delete o_cache.m_dir;
o_cache.m_dir = 0;
o_cache.m_tfile.clear();
o_cache.m_srcpath.clear();
}

View File

@ -27,10 +27,7 @@
/// Uncompression script interface. /// Uncompression script interface.
class Uncomp { class Uncomp {
public: public:
Uncomp(bool docache = false) explicit Uncomp(bool docache = false);
: m_dir(0), m_docache(docache)
{
}
~Uncomp(); ~Uncomp();
/** Uncompress the input file into a temporary one, by executing the /** Uncompress the input file into a temporary one, by executing the
@ -41,25 +38,22 @@ public:
bool uncompressfile(const std::string& ifn, bool uncompressfile(const std::string& ifn,
const std::vector<std::string>& cmdv, const std::vector<std::string>& cmdv,
std::string& tfile); std::string& tfile);
static void clearcache();
private: private:
TempDir *m_dir; TempDir *m_dir{0};
std::string m_tfile; std::string m_tfile;
std::string m_srcpath; std::string m_srcpath;
bool m_docache; bool m_docache;
class UncompCache { class UncompCache {
public: public:
UncompCache() UncompCache() {}
: m_dir(0) ~UncompCache() {
{
}
~UncompCache()
{
delete m_dir; delete m_dir;
} }
std::mutex m_lock; std::mutex m_lock;
TempDir *m_dir; TempDir *m_dir{0};
std::string m_tfile; std::string m_tfile;
std::string m_srcpath; std::string m_srcpath;
}; };

View File

@ -42,6 +42,7 @@
#include "guiutils.h" #include "guiutils.h"
#include "smallut.h" #include "smallut.h"
#include "readfile.h" #include "readfile.h"
#include "uncomp.h"
#include "recollq.h" #include "recollq.h"
@ -52,10 +53,11 @@ static vector<TempFile> o_tempfiles;
/* Keep an array of temporary files for deletion at exit. It happens that we /* Keep an array of temporary files for deletion at exit. It happens that we
erase some of them before exiting (ie: when closing a preview tab), we don't erase some of them before exiting (ie: when closing a preview tab), we don't
reuse the array holes for now */ reuse the array holes for now */
void rememberTempFile(TempFile temp) TempFile *rememberTempFile(TempFile temp)
{ {
std::unique_lock<std::mutex> locker(thetempfileslock); std::unique_lock<std::mutex> locker(thetempfileslock);
o_tempfiles.push_back(temp); o_tempfiles.push_back(temp);
return &o_tempfiles.back();
} }
void forgetTempFile(string &fn) void forgetTempFile(string &fn)
@ -63,10 +65,9 @@ void forgetTempFile(string &fn)
if (fn.empty()) if (fn.empty())
return; return;
std::unique_lock<std::mutex> locker(thetempfileslock); std::unique_lock<std::mutex> locker(thetempfileslock);
for (vector<TempFile>::iterator it = o_tempfiles.begin(); for (auto& entry : o_tempfiles) {
it != o_tempfiles.end(); it++) { if (entry.ok() && !fn.compare(entry.filename())) {
if ((*it) && !fn.compare((*it)->filename())) { entry = TempFile();
it->reset();
} }
} }
fn.erase(); fn.erase();
@ -76,11 +77,10 @@ void deleteAllTempFiles()
{ {
std::unique_lock<std::mutex> locker(thetempfileslock); std::unique_lock<std::mutex> locker(thetempfileslock);
o_tempfiles.clear(); o_tempfiles.clear();
Uncomp::clearcache();
} }
Rcl::Db *rcldb; Rcl::Db *rcldb;
int recollNeedsExit; int recollNeedsExit;
RclMain *mainWindow; RclMain *mainWindow;
@ -151,7 +151,6 @@ static void recollCleanup()
deleteZ(theconfig); deleteZ(theconfig);
deleteAllTempFiles(); deleteAllTempFiles();
LOGDEB2("recollCleanup: done\n" ); LOGDEB2("recollCleanup: done\n" );
} }

View File

@ -832,15 +832,15 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
// an ipath, create it. // an ipath, create it.
if (fn.empty() || !idoc.ipath.empty()) { if (fn.empty() || !idoc.ipath.empty()) {
TempFile temp = lthr.tmpimg; TempFile temp = lthr.tmpimg;
if (temp) { if (temp.ok()) {
LOGDEB1("Preview: load: got temp file from internfile\n"); LOGDEB1("Preview: load: got temp file from internfile\n");
} else if (!FileInterner::idocToFile(temp, string(), } else if (!FileInterner::idocToFile(temp, string(),
theconfig, idoc)) { theconfig, idoc)) {
temp.reset(); // just in case. temp = TempFile(); // just in case.
} }
if (temp) { if (temp.ok()) {
rememberTempFile(temp); rememberTempFile(temp);
fn = temp->filename(); fn = temp.filename();
editor->m_tmpfilename = fn; editor->m_tmpfilename = fn;
} else { } else {
editor->m_tmpfilename.erase(); editor->m_tmpfilename.erase();

View File

@ -86,7 +86,7 @@ void RclMain::periodic100()
bool exited = m_idxproc->maybereap(&status); bool exited = m_idxproc->maybereap(&status);
if (exited) { if (exited) {
QString reasonmsg; QString reasonmsg;
if (m_idxreasontmp) { if (m_idxreasontmp && m_idxreasontmp->ok()) {
string reasons; string reasons;
file_to_string(m_idxreasontmp->filename(), reasons); file_to_string(m_idxreasontmp->filename(), reasons);
if (!reasons.empty()) { if (!reasons.empty()) {
@ -227,11 +227,11 @@ bool RclMain::checkIdxPaths()
// re-enabled by the indexing status check // re-enabled by the indexing status check
void RclMain::toggleIndexing() void RclMain::toggleIndexing()
{ {
if (!m_idxreasontmp) { if (!m_idxreasontmp || !m_idxreasontmp->ok()) {
// We just store the pointer and let the tempfile cleaner deal // We just store the pointer and let the tempfile cleaner deal
// with delete on exiting // with delete on exiting
m_idxreasontmp = new TempFileInternal(".txt"); TempFile temp(".txt");
rememberTempFile(TempFile(m_idxreasontmp)); m_idxreasontmp = rememberTempFile(temp);
} }
switch (m_indexerState) { switch (m_indexerState) {
@ -281,7 +281,7 @@ void RclMain::toggleIndexing()
return; return;
} }
vector<string> args{"-c", theconfig->getConfDir()}; vector<string> args{"-c", theconfig->getConfDir()};
if (m_idxreasontmp) { if (m_idxreasontmp && m_idxreasontmp->ok()) {
args.push_back("-R"); args.push_back("-R");
args.push_back(m_idxreasontmp->filename()); args.push_back(m_idxreasontmp->filename());
} }
@ -377,7 +377,7 @@ void RclMain::rebuildIndex()
} }
vector<string> args{"-c", theconfig->getConfDir(), "-z"}; vector<string> args{"-c", theconfig->getConfDir(), "-z"};
if (m_idxreasontmp) { if (m_idxreasontmp && m_idxreasontmp->ok()) {
args.push_back("-R"); args.push_back("-R");
args.push_back(m_idxreasontmp->filename()); args.push_back(m_idxreasontmp->filename());
} }
@ -458,7 +458,7 @@ void RclMain::specialIndex()
return; return;
vector<string> args{"-c", theconfig->getConfDir()}; vector<string> args{"-c", theconfig->getConfDir()};
if (m_idxreasontmp) { if (m_idxreasontmp && m_idxreasontmp->ok()) {
args.push_back("-R"); args.push_back("-R");
args.push_back(m_idxreasontmp->filename()); args.push_back(m_idxreasontmp->filename());
} }
@ -521,7 +521,7 @@ void RclMain::updateIdxForDocs(vector<Rcl::Doc>& docs)
vector<string> paths; vector<string> paths;
if (Rcl::docsToPaths(docs, paths)) { if (Rcl::docsToPaths(docs, paths)) {
vector<string> args{"-c", theconfig->getConfDir(), "-e", "-i"}; vector<string> args{"-c", theconfig->getConfDir(), "-e", "-i"};
if (m_idxreasontmp) { if (m_idxreasontmp && m_idxreasontmp->ok()) {
args.push_back("-R"); args.push_back("-R");
args.push_back(m_idxreasontmp->filename()); args.push_back(m_idxreasontmp->filename());
} }

View File

@ -313,7 +313,7 @@ void RclMain::startNativeViewer(Rcl::Doc doc, int pagenum, QString term)
bool enterHistory = false; bool enterHistory = false;
bool istempfile = false; bool istempfile = false;
LOGDEB("RclMain::startNV: groksipath " << groksipath << " wantsf " << LOGDEB("StartNativeViewer: groksipath " << groksipath << " wantsf " <<
wantsfile << " wantsparentf " << wantsparentfile << "\n"); wantsfile << " wantsparentf " << wantsparentfile << "\n");
// If the command wants a file but this is not a file url, or // If the command wants a file but this is not a file url, or
@ -332,7 +332,7 @@ void RclMain::startNativeViewer(Rcl::Doc doc, int pagenum, QString term)
enterHistory = true; enterHistory = true;
istempfile = true; istempfile = true;
rememberTempFile(temp); rememberTempFile(temp);
fn = temp->filename(); fn = temp.filename();
url = path_pathtofileurl(fn); url = path_pathtofileurl(fn);
} }
@ -354,10 +354,10 @@ void RclMain::startNativeViewer(Rcl::Doc doc, int pagenum, QString term)
return; return;
} }
} }
if (temp) { if (temp.ok()) {
istempfile = true; istempfile = true;
rememberTempFile(temp); rememberTempFile(temp);
fn = temp->filename(); fn = temp.filename();
url = path_pathtofileurl(fn); url = path_pathtofileurl(fn);
} }
} }

View File

@ -204,7 +204,7 @@ private:
vector<ExecCmd*> m_viewers; vector<ExecCmd*> m_viewers;
ExecCmd *m_idxproc{0}; // Indexing process ExecCmd *m_idxproc{0}; // Indexing process
bool m_idxkilled{false}; // Killed my process bool m_idxkilled{false}; // Killed my process
TempFileInternal *m_idxreasontmp{nullptr}; TempFile *m_idxreasontmp{nullptr};
map<QString, QAction*> m_stemLangToId; map<QString, QAction*> m_stemLangToId;
vector<string> m_catgbutvec; vector<string> m_catgbutvec;
int m_catgbutvecidx{0}; int m_catgbutvecidx{0};

View File

@ -36,7 +36,7 @@ bool getStemLangs(vector<string>& langs);
extern RclConfig *theconfig; extern RclConfig *theconfig;
extern void rememberTempFile(TempFile); extern TempFile *rememberTempFile(TempFile);
extern void forgetTempFile(string &fn); extern void forgetTempFile(string &fn);
extern void deleteAllTempFiles(); extern void deleteAllTempFiles();

View File

@ -43,6 +43,7 @@
#include "wipedir.h" #include "wipedir.h"
#include "transcode.h" #include "transcode.h"
#include "md5ut.h" #include "md5ut.h"
#include "log.h"
using namespace std; using namespace std;
@ -281,8 +282,51 @@ bool maketmpdir(string& tdir, string& reason)
return true; return true;
} }
TempFileInternal::TempFileInternal(const string& suffix)
: m_noremove(false) class TempFile::Internal {
public:
Internal(const std::string& suffix);
~Internal();
friend class TempFile;
private:
std::string m_filename;
std::string m_reason;
bool m_noremove{false};
};
TempFile::TempFile(const string& suffix)
: m(new Internal(suffix))
{
}
TempFile::TempFile()
{
m = std::shared_ptr<Internal>();
}
const char *TempFile::filename() const
{
return m ? m->m_filename.c_str() : "";
}
const std::string& TempFile::getreason() const
{
static string fatal{"fatal error"};
return m ? m->m_reason : fatal;
}
void TempFile::setnoremove(bool onoff)
{
if (m)
m->m_noremove = onoff;
}
bool TempFile::ok() const
{
return m ? !m->m_filename.empty() : false;
}
TempFile::Internal::Internal(const string& suffix)
{ {
// Because we need a specific suffix, can't use mkstemp // Because we need a specific suffix, can't use mkstemp
// well. There is a race condition between name computation and // well. There is a race condition between name computation and
@ -322,7 +366,7 @@ TempFileInternal::TempFileInternal(const string& suffix)
} }
} }
TempFileInternal::~TempFileInternal() TempFile::Internal::~Internal()
{ {
if (!m_filename.empty() && !m_noremove) { if (!m_filename.empty() && !m_noremove) {
unlink(m_filename.c_str()); unlink(m_filename.c_str());
@ -335,11 +379,13 @@ TempDir::TempDir()
m_dirname.erase(); m_dirname.erase();
return; return;
} }
LOGDEB("TempDir::TempDir: -> " << m_dirname << endl);
} }
TempDir::~TempDir() TempDir::~TempDir()
{ {
if (!m_dirname.empty()) { if (!m_dirname.empty()) {
LOGDEB("TempDir::~TempDir: erasing " << m_dirname << endl);
(void)wipedir(m_dirname, true, true); (void)wipedir(m_dirname, true, true);
m_dirname.erase(); m_dirname.erase();
} }

View File

@ -48,30 +48,19 @@ extern const std::string& tmplocation();
extern bool maketmpdir(std::string& tdir, std::string& reason); extern bool maketmpdir(std::string& tdir, std::string& reason);
/// Temporary file class /// Temporary file class
class TempFileInternal { class TempFile {
public: public:
TempFileInternal(const std::string& suffix); TempFile(const std::string& suffix);
~TempFileInternal(); TempFile();
const char *filename() { const char *filename() const;
return m_filename.c_str(); const std::string& getreason() const;
} void setnoremove(bool onoff);
const std::string& getreason() { bool ok() const;
return m_reason; class Internal;
}
void setnoremove(bool onoff) {
m_noremove = onoff;
}
bool ok() {
return !m_filename.empty();
}
private: private:
std::string m_filename; std::shared_ptr<Internal> m;
std::string m_reason;
bool m_noremove;
}; };
typedef std::shared_ptr<TempFileInternal> TempFile;
/// Temporary directory class. Recursively deleted by destructor. /// Temporary directory class. Recursively deleted by destructor.
class TempDir { class TempDir {
public: public: