+/* next page-aligned (i.e. page-align up) */
+#ifndef PAGE_ALIGN
+#define PAGE_ALIGN(addr) (((addr)+_page_size-1)&(~(_page_size-1)))
+#endif
+/* previous page-aligned (i.e. page-align down) */
+#ifndef PAGE_ALIGN_DOWN
+#define PAGE_ALIGN_DOWN(addr) (((addr)+_page_size-1)&(~(_page_size-1)))
+#endif
+
+#ifdef HAVE_MMAP
+/* vector of last madvise hint */
+typedef struct _madvise_vec_t {
+ void *start;
+ ssize_t length;
+} _madvise_vec_t;
+_madvise_vec_t _madv_vec = { NULL, 0 };
+#endif
+
+#if defined CHECK_MADVISE_OVERLAPS
+#define _madvise(_start, _off, _hint) \
+ if ((_start) != _madv_vec.start && (ssize_t)(_off) != _madv_vec.length) { \
+ _madv_vec.start = (_start) ; _madv_vec.length = (_off); \
+ madvise((_start), (_off), (_hint)); \
+ }
+#else
+#define _madvise(_start, _off, _hint) \
+ madvise((_start), (_off), (_hint))
+#endif
+
+/* Open a database file, return its header and an open filehandle,
+ * positioned to the first cdp in the first rra.
+ * In the error path of rrd_open, only rrd_free(&rrd) has to be called
+ * before returning an error. Do not call rrd_close upon failure of rrd_open.
+ */