libdballe 9.13
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 <cstdlib>
26#include <sys/mman.h>
27#include <unistd.h>
28#include <wreport/error.h>
29
30namespace dballe {
31
32namespace structbuf {
33int make_anonymous_tmpfile();
34void write_buffer(int fd, void* buf, size_t size);
35} // namespace structbuf
36
44template <typename T, int bufsize = 1024> class Structbuf
45{
46protected:
51 T* membuf = nullptr;
52
54 unsigned membuf_last = 0;
55
60 const T* readbuf = (const T*)MAP_FAILED;
61
63 size_t m_count = 0;
64
67 int tmpfile_fd = -1;
68
69public:
70 Structbuf() : membuf(new T[bufsize]) {}
72 {
73 delete[] membuf;
74 if (tmpfile_fd != -1)
75 {
76 if (readbuf != MAP_FAILED)
77 munmap(const_cast<T*>(readbuf), m_count * sizeof(T));
78 ::close(tmpfile_fd);
79 }
80 }
81
83 size_t size() const { return m_count; }
84
86 bool is_file_backed() const { return tmpfile_fd != -1; }
87
89 void append(const T& val)
90 {
91 if (readbuf != MAP_FAILED)
93 "writing to a Structbuf that is already being read");
94 if (membuf_last == bufsize)
95 write_to_file();
96 membuf[membuf_last++] = val;
97 ++m_count;
98 }
99
102 {
103 if (tmpfile_fd == -1)
104 readbuf = membuf;
105 else
106 {
107 // Flush the remaining memory data to file
108 if (membuf_last)
109 write_to_file();
110
111 // mmap the file for reading
112 readbuf = (const T*)mmap(nullptr, m_count * sizeof(T), PROT_READ,
113 MAP_SHARED, tmpfile_fd, 0);
114 if (readbuf == MAP_FAILED)
116 "cannot map temporary file contents to memory");
117 }
118 }
119
121 const T& operator[](size_t idx) const { return readbuf[idx]; }
122
123protected:
124 void write_to_file()
125 {
126 if (tmpfile_fd == -1)
127 tmpfile_fd = structbuf::make_anonymous_tmpfile();
128 structbuf::write_buffer(tmpfile_fd, membuf, sizeof(T) * membuf_last);
129 membuf_last = 0;
130 }
131};
132
133} // namespace dballe
134
135#endif
Buffer of simple structures that becomes file backed if it grows beyond a certain size.
Definition structbuf.h:45
T * membuf
In-memory buffer using during appending.
Definition structbuf.h:51
void ready_to_read()
Stop appending and get ready to read back the data.
Definition structbuf.h:101
unsigned membuf_last
Number of items in membuf.
Definition structbuf.h:54
const T * readbuf
Memory area used for reading.
Definition structbuf.h:60
size_t m_count
Number of items appended so far.
Definition structbuf.h:63
size_t size() const
Get the number of structures that have been added to the buffer so far.
Definition structbuf.h:83
bool is_file_backed() const
Return true if the buffer has become file-backed.
Definition structbuf.h:86
void append(const T &val)
Append an item to the buffer.
Definition structbuf.h:89
int tmpfile_fd
Unix file descriptor to the temporary file, or -1 if we are memory backed.
Definition structbuf.h:67
const T & operator[](size_t idx) const
Read back an item.
Definition structbuf.h:121