Add CreateFileMapping file_segment implementation for win32

This commit is contained in:
Nick Mathewson 2010-10-25 12:29:39 -04:00
parent c2d9884a6a
commit 3f405d2d4b
2 changed files with 65 additions and 4 deletions

View File

@ -192,9 +192,14 @@ evbuffer_chain_free(struct evbuffer_chain *chain)
EVBUFFER_CHAIN_EXTRA( EVBUFFER_CHAIN_EXTRA(
struct evbuffer_chain_file_segment, struct evbuffer_chain_file_segment,
chain); 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); evbuffer_file_segment_free(info->segment);
} }
}
mm_free(chain); mm_free(chain);
} }
@ -2615,7 +2620,6 @@ evbuffer_file_segment_new(
} }
#endif #endif
#if defined(_EVENT_HAVE_MMAP) #if defined(_EVENT_HAVE_MMAP)
/* TODO: Implement an mmap-alike for windows. */
if (!(flags & EVBUF_FS_DISABLE_MMAP)) { if (!(flags & EVBUF_FS_DISABLE_MMAP)) {
off_t offset_rounded = 0, offset_leftover = 0; off_t offset_rounded = 0, offset_leftover = 0;
void *mapped; void *mapped;
@ -2656,6 +2660,24 @@ evbuffer_file_segment_new(
} }
} }
#endif #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; ev_off_t start_pos = lseek(fd, 0, SEEK_CUR), pos;
@ -2719,8 +2741,12 @@ evbuffer_file_segment_free(struct evbuffer_file_segment *seg)
if (seg->type == EVBUF_FS_SENDFILE) { if (seg->type == EVBUF_FS_SENDFILE) {
; ;
} else if (seg->type == EVBUF_FS_MMAP) { } 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) if (munmap(seg->mapping, seg->length) == -1)
event_warn("%s: munmap failed", __func__); event_warn("%s: munmap failed", __func__);
#endif
} else { } else {
EVUTIL_ASSERT(seg->type == EVBUF_FS_IO); EVUTIL_ASSERT(seg->type == EVBUF_FS_IO);
mm_free(seg->contents); mm_free(seg->contents);
@ -2772,9 +2798,36 @@ evbuffer_add_file_segment(struct evbuffer *buf,
chain->off = length; chain->off = length;
chain->buffer_len = chain->misalign + length; chain->buffer_len = chain->misalign + length;
} else if (seg->type == EVBUF_FS_MMAP) { } 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 = (unsigned char*)(seg->contents + offset);
chain->buffer_len = length; chain->buffer_len = length;
chain->off = length; chain->off = length;
#endif
} else { } else {
EVUTIL_ASSERT(seg->type == EVBUF_FS_IO); EVUTIL_ASSERT(seg->type == EVBUF_FS_IO);
chain->buffer = (unsigned char*)(seg->contents + offset); chain->buffer = (unsigned char*)(seg->contents + offset);

View File

@ -204,6 +204,10 @@ struct evbuffer_chain_reference {
* evbuffer_chain with the EVBUFFER_FILESEGMENT flag set. */ * evbuffer_chain with the EVBUFFER_FILESEGMENT flag set. */
struct evbuffer_chain_file_segment { struct evbuffer_chain_file_segment {
struct evbuffer_file_segment *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. */ /* Declared in event2/buffer.h; defined here. */
@ -219,6 +223,10 @@ struct evbuffer_file_segment {
int fd; int fd;
/** If we're using mmap, this is the raw mapped memory. */ /** If we're using mmap, this is the raw mapped memory. */
void *mapping; 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 /** If we're using mmap or IO, this is the content of the file
* segment. */ * segment. */
char *contents; char *contents;
@ -226,9 +234,9 @@ struct evbuffer_file_segment {
* this data segment begins. If we're using sendfile, this is the * 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, * offset within the file where this data begins. If we're using IO,
* this is 0. */ * this is 0. */
off_t offset; ev_off_t offset;
/** The length of this segment. */ /** The length of this segment. */
off_t length; ev_off_t length;
}; };
#define EVBUFFER_CHAIN_SIZE sizeof(struct evbuffer_chain) #define EVBUFFER_CHAIN_SIZE sizeof(struct evbuffer_chain)