This is a variation of an interesting problem I am currently dealing with. We have a large input file which is being continuously written (size: 10-20G). We need to write a log filter which reads content from the file with the following conditions
- It looks for specific keywords in each line and if they present, it writes that line to another output file
- We only read first X characters of the line (e.g. x <= 5000) and everything else until the next newline starts, we can ignore. Be mindful that we should not load the whole line into memory. We have tight memory constraints
- We read from a file which is continuously being written, so if we reach to the end of the file, we wait until new data is available
Here's the sample code I came up with
bool Contains(const std::string& input) {
for (const auto& keyword : KEY_WORDS) {
for (int i = 0; i < std::min(input.length(), input.length() - keyword.length() + 1); i++) {
std::string_view view{ input.c_str() + i, keyword.length() };
if (view == keyword) {
return true;
}
}
}
return false;
}
void ClearFlags(std::ifstream& input_file) {
input_file.clear();
input_file.seekg(0, std::ios::end);
}
void ProcessFile(std::ifstream& input_file) {
// seek to the beginning but we will change this later
input_file.seekg(0, std::ios::beg);
while (true) {
std::string buffer;
char ch;
// Read until either the new line is found or the first 5000 characters
while (buffer.length() < BUFFER_SIZE) {
if (input_file.good()) {
ch = input_file.get();
if (ch == '\n')
break;
if (ch != EOF)
buffer += ch;
} else {
ClearFlags(input_file);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
// Process the line
if (buffer.length() && Contains(buffer)) {
sink.write(buffer);
}
if (ch == '\n')
continue;
// We have more characters. so, we read one by one until we reach newline
while (ch != '\n') {
if (input_file.good()) {
input_file.get(ch);
} else {
ClearFlags(input_file);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
}
}
Would like to get some comments and also possible improvements and edge cases I might be missing here? Currently, I sleep for 1 millisecond, clear the flags and repeat the EOF check. I think it's not optimal and any suggestions over there would be highly appreciated
input file which is being continuously written
unusual for an input file. \$\endgroup\$