libdballe  9.14
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 
30 namespace dballe {
31 
32 namespace structbuf {
33 int make_anonymous_tmpfile();
34 void write_buffer(int fd, void* buf, size_t size);
35 } // namespace structbuf
36 
44 template <typename T, int bufsize = 1024> class Structbuf
45 {
46 protected:
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 
69 public:
70  Structbuf() : membuf(new T[bufsize]) {}
71  ~Structbuf()
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)
115  throw wreport::error_system(
116  "cannot map temporary file contents to memory");
117  }
118  }
119 
121  const T& operator[](size_t idx) const { return readbuf[idx]; }
122 
123 protected:
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
const T * readbuf
Memory area used for reading.
Definition: structbuf.h:60
unsigned membuf_last
Number of items in membuf.
Definition: structbuf.h:54
T * membuf
In-memory buffer using during appending.
Definition: structbuf.h:51
Buffer of simple structures that becomes file backed if it grows beyond a certain size...
Definition: structbuf.h:44
size_t m_count
Number of items appended so far.
Definition: structbuf.h:63
Definition: cmdline.h:18
size_t size() const
Get the number of structures that have been added to the buffer so far.
Definition: structbuf.h:83
void ready_to_read()
Stop appending and get ready to read back the data.
Definition: structbuf.h:101
int tmpfile_fd
Unix file descriptor to the temporary file, or -1 if we are memory backed.
Definition: structbuf.h:67
void append(const T &val)
Append an item to the buffer.
Definition: structbuf.h:89
bool is_file_backed() const
Return true if the buffer has become file-backed.
Definition: structbuf.h:86
const T & operator[](size_t idx) const
Read back an item.
Definition: structbuf.h:121