libdballe 9.6
structbuf.h
1/*
2 * core/structbuf - memory or file-backed storage of structures
3 *
4 * Copyright (C) 2014 ARPA-SIM <urpsim@smr.arpa.emr.it>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * Author: Enrico Zini <enrico@enricozini.com>
20 */
21
22#ifndef DBALLE_CORE_STRUCTBUF_H
23#define DBALLE_CORE_STRUCTBUF_H
24
25#include <wreport/error.h>
26#include <cstdlib>
27#include <unistd.h>
28#include <sys/mman.h>
29
30namespace dballe {
31
32namespace structbuf {
33int make_anonymous_tmpfile();
34void write_buffer(int fd, void* buf, size_t size);
35}
36
44template<typename T, int bufsize=1024>
46{
47protected:
52 T* membuf = nullptr;
53
55 unsigned membuf_last = 0;
56
61 const T* readbuf = (const T*)MAP_FAILED;
62
64 size_t m_count = 0;
65
68 int tmpfile_fd = -1;
69
70public:
71 Structbuf()
72 : membuf(new T[bufsize])
73 {
74 }
76 {
77 delete[] membuf;
78 if (tmpfile_fd != -1)
79 {
80 if (readbuf != MAP_FAILED)
81 munmap((void*)readbuf, m_count * sizeof(T));
82 ::close(tmpfile_fd);
83 }
84 }
85
87 size_t size() const { return m_count; }
88
90 bool is_file_backed() const { return tmpfile_fd != -1; }
91
93 void append(const T& val)
94 {
95 if (readbuf != MAP_FAILED)
96 throw wreport::error_consistency("writing to a Structbuf that is already being read");
97 if (membuf_last == bufsize)
98 write_to_file();
99 membuf[membuf_last++] = val;
100 ++m_count;
101 }
102
105 {
106 if (tmpfile_fd == -1)
107 readbuf = membuf;
108 else
109 {
110 // Flush the remaining memory data to file
111 if (membuf_last) write_to_file();
112
113 // mmap the file for reading
114 readbuf = (const T*)mmap(nullptr, m_count * sizeof(T), PROT_READ, MAP_SHARED, tmpfile_fd, 0);
115 if (readbuf == MAP_FAILED)
116 throw wreport::error_system("cannot map temporary file contents to memory");
117 }
118 }
119
121 const T& operator[](size_t idx) const
122 {
123 return readbuf[idx];
124 }
125
126protected:
127 void write_to_file()
128 {
129 if (tmpfile_fd == -1)
130 tmpfile_fd = structbuf::make_anonymous_tmpfile();
131 structbuf::write_buffer(tmpfile_fd, membuf, sizeof(T) * membuf_last);
132 membuf_last = 0;
133 }
134};
135
136}
137
138#endif
Buffer of simple structures that becomes file backed if it grows beyond a certain size.
Definition: structbuf.h:46
T * membuf
In-memory buffer using during appending.
Definition: structbuf.h:52
void ready_to_read()
Stop appending and get ready to read back the data.
Definition: structbuf.h:104
unsigned membuf_last
Number of items in membuf.
Definition: structbuf.h:55
const T * readbuf
Memory area used for reading.
Definition: structbuf.h:61
size_t m_count
Number of items appended so far.
Definition: structbuf.h:64
size_t size() const
Get the number of structures that have been added to the buffer so far.
Definition: structbuf.h:87
bool is_file_backed() const
Return true if the buffer has become file-backed.
Definition: structbuf.h:90
void append(const T &val)
Append an item to the buffer.
Definition: structbuf.h:93
int tmpfile_fd
Unix file descriptor to the temporary file, or -1 if we are memory backed.
Definition: structbuf.h:68
const T & operator[](size_t idx) const
Read back an item.
Definition: structbuf.h:121