Skip to content
Snippets Groups Projects
Commit 9e97047a authored by Axel Naumann's avatar Axel Naumann
Browse files

Don't open the history file for enery entered line, to determine its number of lines.

Do it when we reach 50% of the difference between fPruneLength and fMaxDepth: this means the history file can contain more lines than fMaxDepth (if multiple processes write to it sort of synchronously), but not many (getting them to work synchronously over hundreds of lines is rare).


git-svn-id: http://root.cern.ch/svn/root/trunk@39533 27541ba8-7e3a-0410-8455-c3a389f83636
parent c41a6602
No related branches found
No related tags found
No related merge requests found
......@@ -25,7 +25,7 @@
namespace textinput {
History::History(const char* filename):
fHistFileName(filename ? filename : ""), fMaxDepth((size_t) -1),
fPruneLength(0) {
fPruneLength(0), fNumHistFileLines(0) {
// Create a history object, initialize from filename if the file
// exists. Append new lines to filename taking into account the
// maximal number of lines allowed by SetMaxDepth().
......@@ -37,6 +37,7 @@ namespace textinput {
void
History::AddLine(const std::string& line) {
// Add a line to entries and file.
if (line.empty()) return;
fEntries.push_back(line);
AppendToFile();
}
......@@ -55,8 +56,11 @@ namespace textinput {
if (c != '\n' && c != '\r') break;
line.erase(len - 1);
}
fEntries.push_back(line);
if (!line.empty()) {
fEntries.push_back(line);
}
}
fNumHistFileLines = fEntries.size();
}
void
......@@ -65,23 +69,32 @@ namespace textinput {
// Prune if needed.
if (fHistFileName.empty() || !fMaxDepth) return;
// Count lines:
size_t numLines = 0;
std::string line;
std::ifstream in(fHistFileName.c_str());
while (std::getline(in, line))
++numLines;
if (numLines >= fMaxDepth) {
// Prune!
size_t nPrune = fPruneLength;
if (nPrune == (size_t)kPruneLengthDefault) {
nPrune = (size_t)(fMaxDepth * 0.8);
}
// Calculate prune length to use
size_t nPrune = fPruneLength;
if (nPrune == (size_t)kPruneLengthDefault) {
nPrune = (size_t)(fMaxDepth * 0.8);
} else if (nPrune > fMaxDepth) {
nPrune = fMaxDepth - 1; // fMaxDepth is guaranteed to be > 0.
}
// Don't check for the actual line count of the history file after every
// single line. Once every 50% on the way between nPrune and fMaxDepth is
// enough.
if (fNumHistFileLines < fMaxDepth
&& (fNumHistFileLines % (fMaxDepth - nPrune)) == 0) {
fNumHistFileLines = 0;
std::string line;
std::ifstream in(fHistFileName.c_str());
while (std::getline(in, line))
++fNumHistFileLines;
}
// Don't write our lines - other processes might have
size_t numLines = fNumHistFileLines;
if (numLines >= fMaxDepth) {
// Prune! But don't simply write our lines - other processes might have
// added their own.
in.clear();
in.seekg(0);
std::string line;
std::ifstream in(fHistFileName.c_str());
std::string pruneFileName = fHistFileName + "_prune";
std::ofstream out(pruneFileName.c_str());
if (out) {
......@@ -103,10 +116,12 @@ namespace textinput {
::unlink(fHistFileName.c_str());
#endif
::rename(pruneFileName.c_str(), fHistFileName.c_str());
fNumHistFileLines = nPrune;
}
} else {
std::ofstream out(fHistFileName.c_str(), std::ios_base::app);
out << fEntries.back() << '\n';
++fNumHistFileLines;
}
}
}
......@@ -58,6 +58,7 @@ namespace textinput {
std::string fHistFileName; // History file name
size_t fMaxDepth; // Max number of entries before pruning
size_t fPruneLength; // Remaining entries after pruning
size_t fNumHistFileLines; // Hist file's number of lines at previous access
std::vector<std::string> fEntries; // Previous input lines
};
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment