advancing file pointer in read completion routine
This commit is contained in:
Manoj Ampalam 2016-03-07 14:25:38 -08:00
parent 991be1f492
commit 2305a16980
4 changed files with 35 additions and 23 deletions

View File

@ -270,12 +270,13 @@ VOID CALLBACK ReadCompletionRoutine(
pio->read_details.remaining = dwNumberOfBytesTransfered;
pio->read_details.completed = 0;
pio->read_details.pending = FALSE;
*((__int64*)&lpOverlapped->Offset) += dwNumberOfBytesTransfered;
}
/* initiate an async read */
int
fileio_ReadFileEx(struct w32_io* pio) {
HANDLE h = pio->handle;
debug2("io:%p", pio);
if (pio->read_details.buf == NULL){
pio->read_details.buf = malloc(READ_BUFFER_SIZE);
@ -287,7 +288,11 @@ fileio_ReadFileEx(struct w32_io* pio) {
pio->read_details.buf_size = READ_BUFFER_SIZE;
}
if (ReadFileEx(pio->handle, pio->read_details.buf, pio->read_details.buf_size,
/* get underlying handle for standard io */
if (pio->type == STD_IO_FD)
h = GetStdHandle(pio->std_handle);
if (ReadFileEx(h, pio->read_details.buf, pio->read_details.buf_size,
&pio->read_overlapped, &ReadCompletionRoutine))
pio->read_details.pending = TRUE;
else {
@ -325,16 +330,6 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
}
if (fileio_is_io_available(pio, TRUE) == FALSE) {
/* Workaround for - ReadFileEx is restting file pointer to beginning upon encoutering a EOF*/
/* If there was a previous read and if the file pointer is at 0, then its been reset*/
if ((pio->type == FILE_FD) && (pio->read_details.completed > 0)){
LARGE_INTEGER to_move, new_fp;
to_move.QuadPart = 0;
if (SetFilePointerEx(pio->handle, to_move, &new_fp, FILE_CURRENT) && (new_fp.QuadPart == 0)) {
errno = 0;
return 0;
}
}
if (-1 == fileio_ReadFileEx(pio)) {
if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) {
/* write end of the pipe closed */
@ -406,6 +401,7 @@ VOID CALLBACK WriteCompletionRoutine(
int
fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
int bytes_copied;
HANDLE h = pio->handle;
debug2("io:%p", pio);
if ((pio->type == PIPE_FD) && (pio->internal.state == PIPE_READ_END)) {
@ -450,7 +446,11 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
bytes_copied = min(max, pio->write_details.buf_size);
memcpy(pio->write_details.buf, buf, bytes_copied);
if (WriteFileEx(pio->handle, pio->write_details.buf, bytes_copied,
/* get underlying handle for standard io */
if (pio->type == STD_IO_FD)
h = GetStdHandle(pio->std_handle);
if (WriteFileEx(h, pio->write_details.buf, bytes_copied,
&pio->write_overlapped, &WriteCompletionRoutine)) {
pio->write_details.pending = TRUE;
/* execute APC if write has completed */

View File

@ -24,21 +24,20 @@ static struct w32_io w32_io_stdin, w32_io_stdout, w32_io_stderr;
void fd_table_set(struct w32_io* pio, int index);
#pragma warning(disable:4312)
/* initializes mapping table*/
static int
fd_table_initialize() {
memset(&fd_table, 0, sizeof(fd_table));
memset(&w32_io_stdin, 0, sizeof(w32_io_stdin));
w32_io_stdin.handle = (HANDLE)STD_INPUT_HANDLE;
w32_io_stdin.std_handle = STD_INPUT_HANDLE;
w32_io_stdin.type = STD_IO_FD;
fd_table_set(&w32_io_stdin, STDIN_FILENO);
memset(&w32_io_stdout, 0, sizeof(w32_io_stdout));
w32_io_stdout.handle = (HANDLE)STD_OUTPUT_HANDLE;
w32_io_stdout.std_handle = STD_OUTPUT_HANDLE;
w32_io_stdout.type = STD_IO_FD;
fd_table_set(&w32_io_stdout, STDOUT_FILENO);
memset(&w32_io_stderr, 0, sizeof(w32_io_stderr));
w32_io_stderr.handle = (HANDLE)STD_ERROR_HANDLE;
w32_io_stderr.std_handle = STD_ERROR_HANDLE;
w32_io_stderr.type = STD_IO_FD;
fd_table_set(&w32_io_stderr, STDERR_FILENO);
return 0;
@ -425,7 +424,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
HANDLE events[SELECT_EVENT_LIMIT];
int num_events = 0;
int in_set_fds = 0, out_ready_fds = 0, i;
unsigned int time_ms_rem = 0;
unsigned int timeout_ms = 0, time_rem = 0;
errno = 0;
/* TODO - the size of these can be reduced based on fds */
@ -433,7 +432,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
memset(&write_ready_fds, 0, sizeof(w32_fd_set));
if (timeout)
time_ms_rem = timeout->tv_sec * 100 + timeout->tv_usec / 1000;
timeout_ms = timeout->tv_sec * 100 + timeout->tv_usec / 1000;
if (fds > MAX_FDS) {
errno = EINVAL;
@ -538,17 +537,18 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
/* wait for io if none is already ready */
while (out_ready_fds == 0) {
ticks_spent = GetTickCount64() - ticks_start;
time_rem = 0;
if (timeout != NULL) {
if (time_ms_rem < ticks_spent) {
if (timeout_ms < ticks_spent) {
errno = ETIMEDOUT;
debug("select timing out");
return -1;
}
time_ms_rem -= ticks_spent & 0xffffffff;
time_rem = timeout_ms - (ticks_spent & 0xffffffff);
}
if (0 != wait_for_any_event(events, num_events, time_ms_rem))
if (0 != wait_for_any_event(events, num_events, time_rem))
return -1;
/* check on fd status */

View File

@ -71,6 +71,7 @@ struct w32_io {
union {
SOCKET sock;
HANDLE handle;
DWORD std_handle; /* ex. STD_INPUT_HANDLE */
};
/*handle specific internal state context, used by sockets and pipes*/

View File

@ -224,12 +224,23 @@ file_select_tests() {
}
void console_io_test()
{
char tmp[10];
TEST_START("console io test");
ret = read(STDIN_FILENO, tmp, 10);
ret = write(STDOUT_FILENO, "sample output", 13);
ASSERT_INT_EQ(errno, 0);
ASSERT_INT_EQ(ret, 13);
TEST_DONE();
}
void
file_tests()
{
w32posix_initialize();
file_simple_fileio();
//console_io_test();
//file_simple_fileio();
file_blocking_io_tests();
file_nonblocking_io_tests();
file_select_tests();