EVBUFFER_CHAIN_EXTRA(
struct evbuffer_chain_file_segment,
chain);
- if (info->segment)
+ if (info->segment) {
+#ifdef WIN32
+ if (info->segment->type == EVBUF_FS_MMAP)
+ UnmapViewOfFile(chain->buffer);
+#endif
evbuffer_file_segment_free(info->segment);
+ }
}
mm_free(chain);
}
#endif
#if defined(_EVENT_HAVE_MMAP)
- /* TODO: Implement an mmap-alike for windows. */
if (!(flags & EVBUF_FS_DISABLE_MMAP)) {
off_t offset_rounded = 0, offset_leftover = 0;
void *mapped;
}
}
#endif
+#ifdef WIN32
+ if (!(flags & EVBUF_FS_DISABLE_MMAP)) {
+ long h = (long)_get_osfhandle(fd);
+ HANDLE m;
+ ev_uint64_t total_size = length+offset;
+ if (h == (long)INVALID_HANDLE_VALUE)
+ return NULL;
+ m = CreateFileMapping((HANDLE)h, NULL, PAGE_READONLY,
+ (total_size >> 32), total_size & 0xfffffffful,
+ NULL);
+ if (m != INVALID_HANDLE_VALUE) { /* Does h leak? */
+ seg->mapping_handle = m;
+ seg->offset = offset;
+ seg->type = EVBUF_FS_MMAP;
+ goto done;
+ }
+ }
+#endif
{
ev_off_t start_pos = lseek(fd, 0, SEEK_CUR), pos;
if (seg->type == EVBUF_FS_SENDFILE) {
;
} else if (seg->type == EVBUF_FS_MMAP) {
+#ifdef WIN32
+ CloseHandle(seg->mapping_handle);
+#elif defined (_EVENT_HAVE_MMAP)
if (munmap(seg->mapping, seg->length) == -1)
event_warn("%s: munmap failed", __func__);
+#endif
} else {
EVUTIL_ASSERT(seg->type == EVBUF_FS_IO);
mm_free(seg->contents);
chain->off = length;
chain->buffer_len = chain->misalign + length;
} else if (seg->type == EVBUF_FS_MMAP) {
+#ifdef WIN32
+ ev_uint64_t total_offset = seg->offset+offset;
+ ev_uint64_t offset_rounded=0, offset_remaining=0;
+ LPVOID data;
+ if (total_offset) {
+ SYSTEM_INFO si;
+ memset(&si, 0, sizeof(si)); /* cargo cult */
+ GetSystemInfo(&si);
+ offset_remaining = total_offset % si.dwAllocationGranularity;
+ offset_rounded = total_offset - offset_remaining;
+ }
+ data = MapViewOfFile(
+ seg->mapping_handle,
+ FILE_MAP_READ,
+ offset_rounded >> 32,
+ offset_rounded & 0xfffffffful,
+ length);
+ if (data == NULL) {
+ mm_free(chain);
+ goto err;
+ }
+ chain->buffer = (unsigned char*) data;
+ chain->buffer_len = length+offset_remaining;
+ chain->misalign = offset_remaining;
+ chain->off = length;
+#else
chain->buffer = (unsigned char*)(seg->contents + offset);
chain->buffer_len = length;
chain->off = length;
+#endif
} else {
EVUTIL_ASSERT(seg->type == EVBUF_FS_IO);
chain->buffer = (unsigned char*)(seg->contents + offset);
* evbuffer_chain with the EVBUFFER_FILESEGMENT flag set. */
struct evbuffer_chain_file_segment {
struct evbuffer_file_segment *segment;
+#ifdef WIN32
+ /** If we're using CreateFileMapping, this is the handle to the view. */
+ HANDLE view_handle;
+#endif
};
/* Declared in event2/buffer.h; defined here. */
int fd;
/** If we're using mmap, this is the raw mapped memory. */
void *mapping;
+#ifdef WIN32
+ /** If we're using CreateFileMapping, this is the mapping */
+ HANDLE mapping_handle;
+#endif
/** If we're using mmap or IO, this is the content of the file
* segment. */
char *contents;
* this data segment begins. If we're using sendfile, this is the
* offset within the file where this data begins. If we're using IO,
* this is 0. */
- off_t offset;
+ ev_off_t offset;
/** The length of this segment. */
- off_t length;
+ ev_off_t length;
};
#define EVBUFFER_CHAIN_SIZE sizeof(struct evbuffer_chain)