+/* DEBUG 2 prints information obtained via mincore(2) */
+// #define DEBUG 2
+/* do not calculate exact madvise hints but assume 1 page for headers and
+ * set DONTNEED for the rest, which is assumed to be data */
+//#define ONE_PAGE 1
+/* Avoid calling madvise on areas that were already hinted. May be benefical if
+ * your syscalls are very slow */
+#define CHECK_MADVISE_OVERLAPS 1
+
+#ifdef HAVE_MMAP
+/* the cast to void* is there to avoid this warning seen on ia64 with certain
+ versions of gcc: 'cast increases required alignment of target type'
+*/
+#define __rrd_read(dst, dst_t, cnt) \
+ (dst) = (dst_t*)(void*) (data + offset); \
+ offset += sizeof(dst_t) * (cnt)
+#else
+#define __rrd_read(dst, dst_t, cnt) \
+ if ((dst = malloc(sizeof(dst_t)*(cnt))) == NULL) { \
+ rrd_set_error(#dst " malloc"); \
+ goto out_nullify_head; \
+ } \
+ offset += read (rrd_file->fd, dst, sizeof(dst_t)*(cnt))
+#endif
+
+/* 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.
+ */