Last active
December 30, 2015 21:49
-
-
Save weissi/7890467 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <dispatch/dispatch.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <sys/event.h> | |
#include <sys/event.h> | |
#include <sys/select.h> | |
#include <sys/stat.h> | |
#include <sys/time.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <sys/types.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
#define FILENAME "/tmp/.some-tmp-file" | |
#define MAX_FILE_SIZE 10*1000*1000 | |
int get_fd_size(int fd) | |
{ | |
off_t eof_pos = lseek(fd, 0, SEEK_END); | |
return eof_pos; | |
} | |
void go_on(int fd) | |
{ | |
int ret = -1; | |
int kq = kqueue(); | |
struct kevent changelist[1]; | |
if (kq < 0) { | |
/* errno set by kqueue */ | |
ret = -1; | |
goto out; | |
} | |
memset(changelist, 0, sizeof(changelist)); | |
EV_SET(&changelist[0], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_DELETE | NOTE_RENAME | NOTE_EXTEND, 0, 0); | |
if (kevent(kq, changelist, 1, NULL, 0, NULL) < 0) { | |
/* errno set by kevent */ | |
ret = -1; | |
goto out; | |
} | |
while (1) { | |
{ | |
/* Step 1: Check the size */ | |
off_t new_sz = get_fd_size(fd); | |
printf("new size: %lld\n", new_sz); | |
if (new_sz >= MAX_FILE_SIZE) { | |
printf("Ok, success\n"); | |
exit(0); | |
} | |
} | |
{ | |
/* Step 2: Wait for growth */ | |
struct timespec timeout = { .tv_sec = 1, .tv_nsec = 0 }; | |
int suc_kev = kevent(kq, NULL, 0, changelist, 1, &timeout); | |
if (0 == suc_kev) { | |
/* That's a timeout */ | |
off_t new_sz = get_fd_size(fd); | |
printf("Timeout (%lld)\n", new_sz); | |
errno = ETIMEDOUT; | |
ret = -1; | |
goto out; | |
} else if (suc_kev > 0) { | |
char *type = "?"; | |
if ( changelist[0].filter == EVFILT_VNODE && | |
changelist[0].fflags & NOTE_EXTEND) { | |
type = "EXTEND"; | |
} | |
if ( changelist[0].filter == EVFILT_VNODE && | |
changelist[0].fflags & NOTE_WRITE) { | |
type = "WRITE"; | |
} | |
printf("kevent %s #%p (%p | %p)\n", type, changelist[0].ident, changelist[0].data, changelist[0].udata); | |
if (changelist[0].filter == EVFILT_VNODE) { | |
if (changelist[0].fflags & NOTE_RENAME || changelist[0].fflags & NOTE_DELETE) { | |
/* file was deleted, renamed, ... */ | |
printf("Renamed\n"); | |
errno = ENOENT; | |
ret = -1; | |
goto out; | |
} | |
} | |
} else { | |
/* errno set by kevent */ | |
printf("Error: %d\n", errno); | |
ret = -1; | |
goto out; | |
} | |
} | |
} | |
out: { | |
int errno_save = errno; | |
if (kq >= 0) { | |
close(kq); | |
} | |
errno = errno_save; | |
return; | |
} | |
} | |
void do_writes(int xfd) | |
{ | |
int fd = open(FILENAME, O_WRONLY); | |
const int write_fd = dup(fd); | |
const off_t size_per_write = MAX_FILE_SIZE / 10; | |
const off_t desired_size = MAX_FILE_SIZE; | |
char *buf = malloc(size_per_write); | |
memset(buf, 'A', size_per_write); | |
for (int i=0; i<desired_size / size_per_write; i++) { | |
#ifndef USE_FTRUNCATE | |
{ | |
ssize_t suc_write = write(write_fd, buf, size_per_write); | |
assert(suc_write == size_per_write); | |
} | |
#else | |
ftruncate(write_fd, (1+i) * size_per_write); | |
#endif | |
printf("wrote\n"); | |
fsync(write_fd); | |
usleep(100000); | |
} | |
free(buf); | |
{ | |
struct stat stat_buf = {0}; | |
fstat(write_fd, &stat_buf); | |
printf("writing thread finished: desired: %lld, actual: %lld\n", desired_size, stat_buf.st_size); | |
} | |
/* | |
close(write_fd); | |
close(fd); | |
*/ | |
} | |
int main() | |
{ | |
int fd = open(FILENAME, O_CREAT | O_TRUNC | O_RDWR, 0777); | |
assert(fd >= 0); | |
dispatch_async_f(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), (void *)fd, do_writes); | |
go_on(fd); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment