int free_systimer(systimer_t * timer) { int err ; err = free_iochannel(timer) ; if (err) goto ONERR; return 0 ; ONERR: TRACEEXITFREE_ERRLOG(err); return err ; }
int free_logbuffer(logbuffer_t * logbuf) { int err; logbuf->addr = 0; logbuf->size = 0; logbuf->logsize = 0; if ( logbuf->io == iochannel_STDOUT || logbuf->io == iochannel_STDERR) { logbuf->io = iochannel_FREE; } else { err = free_iochannel(&logbuf->io); if (err) goto ONERR; } return 0; ONERR: TRACEEXITFREE_ERRLOG(err); return err; }
static int test_rwpartial(directory_t* tmpdir) { iothread_t iothr = iothread_FREE; file_t file = file_FREE; memblock_t writebuf = memblock_FREE; memblock_t readbuf = memblock_FREE; iotask_t iotask_buffer; iotask_t* iotask = &iotask_buffer; eventcount_t counter = eventcount_INIT; // prepare0 TEST(0 == init_iothread(&iothr)); // alloc buffer TEST(0 == ALLOC_PAGECACHE(pagesize_1MB, &readbuf)); TEST(0 == ALLOC_PAGECACHE(pagesize_1MB, &writebuf)); for (size_t val = 0; val < writebuf.size/sizeof(uint32_t); ++val) { ((uint32_t*)writebuf.addr)[val] = (uint32_t) val; } memset(readbuf.addr, 0, readbuf.size); for (int ispos = 0; ispos <= 1; ++ispos) { // TEST insertiotask_iothread: (writep,write) && syscall writes less than writebuf.size TEST(0 == initcreate_file(&file, "testpartial", tmpdir)) if (ispos) { initwritep_iotask(iotask, io_file(file), writebuf.size, writebuf.addr, 0, &counter); } else { initwrite_iotask(iotask, io_file(file), writebuf.size, writebuf.addr, &counter); } // test s_iothread_errtimer_count = 0; init_testerrortimer(&s_iothread_errtimer, 2/*trigger partial io*/, 1); insertiotask_iothread(&iothr, 1, &iotask); // wait for writer ready wait_eventcount(&counter,0); // check iotask TEST(iotask->iolist_next == 0); TEST(iotask->bytesrw == writebuf.size); TEST(iotask->state == iostate_OK); TEST(iotask->op == ioop_WRITE); TEST(iotask->ioc == io_file(file)); TEST(iotask->offset == (ispos ? 0 : -1)); TEST(iotask->bufaddr == writebuf.addr); TEST(iotask->bufsize == writebuf.size); TEST(iotask->readycount == &counter); // check 32 partial writes (1+32) TEST(32 == s_iothread_errtimer_count); // reset TEST(0 == free_file(&file)); free_testerrortimer(&s_iothread_errtimer); // TEST insertiotask_iothread: (readp, read) && syscall reads less than writebuf.size TEST(0 == init_file(&file, "testpartial", accessmode_READ, tmpdir)); if (ispos) { initreadp_iotask(iotask, io_file(file), readbuf.size, readbuf.addr, 0, &counter); } else { initread_iotask(iotask, io_file(file), readbuf.size, readbuf.addr, &counter); } // test s_iothread_errtimer_count = 0; init_testerrortimer(&s_iothread_errtimer, 2/*trigger partial io*/, 1); insertiotask_iothread(&iothr, 1, &iotask); // wait for reader ready wait_eventcount(&counter,0); // check iotask.ioop[0] TEST(iotask->iolist_next == 0); TEST(iotask->bytesrw == writebuf.size); TEST(iotask->state == iostate_OK); TEST(iotask->op == ioop_READ); TEST(iotask->ioc == io_file(file)); TEST(iotask->offset == (ispos ? 0 : -1)); TEST(iotask->bufaddr == readbuf.addr); TEST(iotask->bufsize == readbuf.size); TEST(iotask->readycount == &counter); // check content of readbuf for (size_t val = 0; val < readbuf.size/sizeof(uint32_t); ++val) { TEST(val == ((uint32_t*)readbuf.addr)[val]); } // check 32 partial writes (1+32) TEST(32 == s_iothread_errtimer_count); // reset memset(readbuf.addr, 0, readbuf.size); TEST(0 == free_file(&file)); TEST(0 == removefile_directory(tmpdir, "testpartial")); free_testerrortimer(&s_iothread_errtimer); } // reset TEST(0 == free_iothread(&iothr)); TEST(0 == free_eventcount(&counter)); TEST(0 == free_iochannel(&file)); TEST(0 == RELEASE_PAGECACHE(&writebuf)); TEST(0 == RELEASE_PAGECACHE(&readbuf)); return 0; ONERR: free_iothread(&iothr); free_eventcount(&counter); free_iochannel(&file); RELEASE_PAGECACHE(&writebuf); RELEASE_PAGECACHE(&readbuf); removefile_directory(tmpdir, "testpartial"); return EINVAL; }
static int test_write(directory_t* tmpdir) { iothread_t iothr = iothread_FREE; file_t file = file_FREE; memblock_t mblock[10] = { memblock_FREE }; memblock_t readbuf = memblock_FREE; iotask_t iotask_buffer[lengthof(mblock)]; iotask_t* iotask[lengthof(mblock)]; eventcount_t counter = eventcount_INIT; // prepare0 TEST(0 == init_iothread(&iothr)); memset(iotask_buffer, 0, sizeof(iotask_buffer)); for (unsigned i = 0; i < lengthof(iotask); ++i) { iotask[i] = &iotask_buffer[i]; } // fill write buffer for (size_t i = 0, val = 0; i < lengthof(mblock); ++i) { TEST(0 == ALLOC_PAGECACHE(pagesize_1MB, &mblock[i])); for (size_t off = 0; off < mblock[i].size/sizeof(uint32_t); ++off, ++val) { ((uint32_t*)mblock[i].addr)[off] = (uint32_t) val; } } // alloc read buffer TEST(0 == ALLOC_PAGECACHE(pagesize_1MB, &readbuf)); memset(readbuf.addr, 0, readbuf.size); // TEST insertiotask_iothread: writep (forward) static_assert((lengthof(iotask)-1) % 3 == 0, "full range 1..lengthof(iotask)"); for (unsigned nrio = 1; nrio <= lengthof(iotask); nrio += 3) { // prepare TEST(0 == initcreate_file(&file, "testwrite", tmpdir)); for (size_t i = 0; i < nrio; ++i) { initwritep_iotask(iotask[i], io_file(file), mblock[i].size, mblock[i].addr, (off_t) (i*mblock[0].size), &counter); } // test insertiotask_iothread(&iothr, (uint8_t) nrio, &iotask[0]); // check for (unsigned i = 0; i < nrio; ++i) { // wait for ready counter while (iostate_QUEUED == read_atomicint(&iotask[i]->state)) { wait_eventcount(&counter,0); } // check iotask TEST(0 == compare_iotask(iotask[i], 0, mblock[i].size, iostate_OK, ioop_WRITE, io_file(file), (off_t) (i*mblock[0].size), mblock[i].addr, mblock[i].size, &counter)); // check written bytes TEST((int)readbuf.size == pread(io_file(file), readbuf.addr, readbuf.size, iotask[i]->offset)); for (size_t vi = 0, val = (size_t)iotask[i]->offset/sizeof(uint32_t); vi < readbuf.size/sizeof(uint32_t); ++vi, ++val) { TEST(val == ((uint32_t*)readbuf.addr)[vi]); } // reset iotask[i]->bytesrw = 0; } // check file position (offset) not changed TEST(0 == lseek(io_file(file), 0, SEEK_CUR)); // reset TEST(0 == free_iochannel(&file)); TEST(0 == removefile_directory(tmpdir, "testwrite")); counter.nrevents = 0; } // TEST insertiotask_iothread: writep (backward) static_assert((lengthof(iotask)-1) % 3 == 0, "full range 1..lengthof(iotask)"); for (unsigned nrio = 1; nrio <= lengthof(iotask); nrio += 3) { // prepare TEST(0 == initcreate_file(&file, "testwrite", tmpdir)); for (unsigned i = 0; i < nrio; ++i) { initwritep_iotask(iotask[i], io_file(file), mblock[i].size, mblock[i].addr, (off_t)((nrio-1-i)*mblock[0].size), &counter); } // test insertiotask_iothread(&iothr, (uint8_t) nrio, &iotask[0]); // check for (unsigned i = 0; i < nrio; ++i) { // wait for ready counter while (iostate_QUEUED == read_atomicint(&iotask[i]->state)) { wait_eventcount(&counter,0); } // check iotask TEST(0 == compare_iotask(iotask[i], 0, mblock[i].size, iostate_OK, ioop_WRITE, io_file(file), (off_t) ((nrio-1-i)*mblock[0].size), mblock[i].addr, mblock[i].size, &counter)); // check written bytes TEST((int)readbuf.size == pread(io_file(file), readbuf.addr, readbuf.size, iotask[i]->offset)); for (size_t vi = 0, val = i*mblock[0].size/sizeof(uint32_t); vi < readbuf.size/sizeof(uint32_t); ++vi, ++val) { TEST(val == ((uint32_t*)readbuf.addr)[vi]); } // reset iotask[i]->bytesrw = 0; } // check file position (offset) not changed TEST(0 == lseek(io_file(file), 0, SEEK_CUR)); // reset TEST(0 == free_iochannel(&file)); TEST(0 == removefile_directory(tmpdir, "testwrite")); counter.nrevents = 0; } // TEST insertiotask_iothread: write // prepare TEST(0 == initcreate_file(&file, "testwrite", tmpdir)); for (unsigned i = 0; i < lengthof(iotask); ++i) { initwrite_iotask(iotask[i], io_file(file), mblock[i].size, mblock[i].addr, 0); } // test insertiotask_iothread(&iothr, lengthof(iotask), &iotask[0]); // check for (unsigned i = 0; i < lengthof(iotask); ++i) { // wait for ready counter for (int w = 0; w < 500000; ++w) { if (iostate_QUEUED != read_atomicint(&iotask[i]->state)) break; yield_thread(); } // check iotask TEST(0 == compare_iotask(iotask[i], 0, mblock[i].size, iostate_OK, ioop_WRITE, io_file(file), -1, mblock[i].addr, mblock[i].size, 0)); // check written bytes TEST((int)readbuf.size == pread(io_file(file), readbuf.addr, readbuf.size, (off_t)(i*mblock[0].size))); for (size_t vi = 0, val = (i*mblock[0].size)/sizeof(uint32_t); vi < readbuf.size/sizeof(uint32_t); ++vi, ++val) { TEST(val == ((uint32_t*)readbuf.addr)[vi]); } // reset iotask[i]->bytesrw = 0; } // check file position (offset) changed TEST((off_t)(lengthof(mblock)*mblock[0].size) == lseek(io_file(file), 0, SEEK_CUR)); // reset TEST(0 == free_iochannel(&file)); TEST(0 == removefile_directory(tmpdir, "testwrite")); // reset0 TEST(0 == free_iothread(&iothr)); TEST(0 == free_eventcount(&counter)); for (unsigned i = 0; i < lengthof(mblock); ++i) { TEST(0 == RELEASE_PAGECACHE(&mblock[i])); } TEST(0 == RELEASE_PAGECACHE(&readbuf)); return 0; ONERR: free_iothread(&iothr); free_eventcount(&counter); free_iochannel(&file); for (unsigned i = 0; i < lengthof(mblock); ++i) { RELEASE_PAGECACHE(&mblock[i]); } RELEASE_PAGECACHE(&readbuf); removefile_directory(tmpdir, "testwrite"); return EINVAL; }