aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2018-08-05 01:58:13 +0200
committerJay Berkenbilt <ejb@ql.org>2018-08-05 01:58:13 +0200
commitfe769f2723237596af2730bccd7972dab208a10d (patch)
tree22b8a478933539601736bb4e974653a5f43bcb8d
parent4f4c627b77a169e1729982fa03dd75d5035f0297 (diff)
downloadqpdf-fe769f2723237596af2730bccd7972dab208a10d.tar.zst
Keep file open while adding its pages during merge (fixes #217)
-rw-r--r--ChangeLog3
-rw-r--r--qpdf/qpdf.cc32
2 files changed, 32 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index fa519fc4..7888293f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2018-08-04 Jay Berkenbilt <ejb@ql.org>
+ * Performance fix: optimize page merging operation to avoid
+ unnecessary open/close calls on files being merged. Fixes #217.
+
* Add ClosedFileInputSource::stayOpen method, enabling a
ClosedFileInputSource to stay open during manually indicated
periods of high activity, thus reducing the overhead of frequent
diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc
index 50352f6c..9655049f 100644
--- a/qpdf/qpdf.cc
+++ b/qpdf/qpdf.cc
@@ -2103,6 +2103,7 @@ static void handle_page_specs(QPDF& pdf, Options& o,
// Create a QPDF object for each file that we may take pages from.
std::map<std::string, QPDF*> page_spec_qpdfs;
+ std::map<std::string, ClosedFileInputSource*> page_spec_cfis;
page_spec_qpdfs[o.infilename] = &pdf;
std::vector<QPDFPageData> parsed_specs;
for (std::vector<PageSpec>::iterator iter = o.page_specs.begin();
@@ -2136,10 +2137,14 @@ static void handle_page_specs(QPDF& pdf, Options& o,
std::cout << whoami << ": processing "
<< page_spec.filename << std::endl;
}
- qpdf->processInputSource(
- new ClosedFileInputSource(
- page_spec.filename.c_str()), password);
+ ClosedFileInputSource* cis =
+ new ClosedFileInputSource(page_spec.filename.c_str());
+ PointerHolder<InputSource> is(cis);
+ cis->stayOpen(true);
+ qpdf->processInputSource(is, password);
+ cis->stayOpen(false);
page_spec_qpdfs[page_spec.filename] = qpdf;
+ page_spec_cfis[page_spec.filename] = cis;
}
// Read original pages from the PDF, and parse the page range
@@ -2156,9 +2161,20 @@ static void handle_page_specs(QPDF& pdf, Options& o,
page_spec_qpdfs.begin();
iter != page_spec_qpdfs.end(); ++iter)
{
+ std::string const& filename = (*iter).first;
+ ClosedFileInputSource* cis = 0;
+ if (page_spec_cfis.count(filename))
+ {
+ cis = page_spec_cfis[filename];
+ cis->stayOpen(true);
+ }
QPDFPageDocumentHelper dh(*((*iter).second));
dh.pushInheritedAttributesToPage();
dh.removeUnreferencedResources();
+ if (cis)
+ {
+ cis->stayOpen(false);
+ }
}
}
@@ -2204,7 +2220,17 @@ static void handle_page_specs(QPDF& pdf, Options& o,
// Pages are specified from 1 but numbered from 0 in the
// vector
int pageno = *pageno_iter - 1;
+ ClosedFileInputSource* cis = 0;
+ if (page_spec_cfis.count(page_data.filename))
+ {
+ cis = page_spec_cfis[page_data.filename];
+ cis->stayOpen(true);
+ }
dh.addPage(page_data.orig_pages.at(pageno), false);
+ if (cis)
+ {
+ cis->stayOpen(false);
+ }
if (page_data.qpdf == &pdf)
{
// This is a page from the original file. Keep track