void file::close() { if (!is_open()) return; #ifdef TORRENT_WINDOWS // if this file is open for writing, has the sparse // flag set, but there are no sparse regions, unset // the flag open_mode_t const rw_mode = m_open_mode & open_mode::rw_mask; if ((rw_mode != open_mode::read_only) && (m_open_mode & open_mode::sparse) && !is_sparse(native_handle())) { overlapped_t ol; // according to MSDN, clearing the sparse flag of a file only // works on windows vista and later #ifdef TORRENT_MINGW typedef struct _FILE_SET_SPARSE_BUFFER { BOOLEAN SetSparse; } FILE_SET_SPARSE_BUFFER; #endif DWORD temp; FILE_SET_SPARSE_BUFFER b; b.SetSparse = FALSE; BOOL ret = ::DeviceIoControl(native_handle(), FSCTL_SET_SPARSE, &b, sizeof(b) , 0, 0, &temp, &ol.ol); error_code ec; if (ret == FALSE && GetLastError() == ERROR_IO_PENDING) { ol.wait(native_handle(), ec); } } CloseHandle(native_handle()); #else if (m_file_handle != INVALID_HANDLE_VALUE) ::close(m_file_handle); #endif m_file_handle = INVALID_HANDLE_VALUE; m_open_mode = open_mode_t{}; }
static int write_direct_mapping(struct defrag_ctx *c, struct data_extent *e) { struct inode *inode = c->inodes[e->inode_nr]; __u32 cur_block = e->start_block; __u32 cur_logical = e->start_logical; __u32 new_block; int sync_inode = 0; /* Direct blocks */ for (cur_logical = e->start_logical; cur_logical < EXT2_IND_LBLOCK(&c->sb) && cur_block <= e->end_block; cur_logical++) { if (!is_sparse(inode, cur_logical)) new_block = cur_block++; else new_block = 0; if (inode->on_disk->i_block[cur_logical] != new_block) { inode->on_disk->i_block[cur_logical] = new_block; sync_inode = 1; } } if (cur_block > e->end_block) goto out; /* Singly indirect blocks */ if (cur_logical == EXT2_IND_LBLOCK(&c->sb)) { if (is_sparse(inode, cur_logical)) new_block = 0; else new_block = cur_block++; cur_logical++; } else { new_block = inode->on_disk->i_block[EXT2_IND_BLOCK]; } if (cur_logical > EXT2_IND_LBLOCK(&c->sb) && cur_logical < EXT2_DIND_LBLOCK(&c->sb)) { write_ind_metadata(c, e, new_block, &cur_logical, &cur_block); } if (inode->on_disk->i_block[EXT2_IND_BLOCK] != new_block) { inode->on_disk->i_block[EXT2_IND_BLOCK] = new_block; sync_inode = 1; } if (cur_block > e->end_block) goto out; /* Doubly indirect blocks */ if (cur_logical == EXT2_DIND_LBLOCK(&c->sb)) { if (is_sparse(inode, cur_logical) || cur_block > e->end_block) new_block = 0; else new_block = cur_block++; cur_logical++; } else { new_block = inode->on_disk->i_block[EXT2_DIND_BLOCK]; } if (cur_logical > EXT2_DIND_LBLOCK(&c->sb) && cur_logical < EXT2_TIND_LBLOCK(&c->sb)) { write_dind_metadata(c, e, new_block, &cur_logical, &cur_block); } if (inode->on_disk->i_block[EXT2_DIND_BLOCK] != new_block) { inode->on_disk->i_block[EXT2_DIND_BLOCK] = new_block; sync_inode = 1; } if (cur_block > e->end_block) goto out; /* Triply indirect blocks */ if (cur_logical == EXT2_TIND_LBLOCK(&c->sb)) { if (is_sparse(inode, cur_logical) || cur_block > e->end_block) new_block = 0; else new_block = cur_block++; cur_logical++; } else { new_block = inode->on_disk->i_block[EXT2_TIND_BLOCK]; } if (cur_logical > EXT2_TIND_LBLOCK(&c->sb)) { write_tind_metadata(c, e, new_block, &cur_logical, &cur_block); } if (inode->on_disk->i_block[EXT2_TIND_BLOCK] != new_block) { inode->on_disk->i_block[EXT2_TIND_BLOCK] = new_block; sync_inode = 1; } out: if (sync_inode) /* Assumes the inode is completely within one page */ return msync(PAGE_START(inode->on_disk),getpagesize(), MS_SYNC); return 0; }
static int write_tind_metadata(struct defrag_ctx *c, struct data_extent *e, __u32 tind_block, __u32 *cur_logical, __u32 *cur_block) { struct inode *inode = c->inodes[e->inode_nr]; __u32 offset = *cur_logical; __u32 ind_blocks = EXT2_ADDR_PER_BLOCK(&c->sb); __u32 blocks_per_ind = 1 + ind_blocks; __u32 blocks_per_dind = 1 + ind_blocks * blocks_per_ind; __u32 blocks_per_tind = 1 + ind_blocks * blocks_per_dind; __u32 buffer[EXT2_ADDR_PER_BLOCK(&c->sb)]; int ret; char to_sync = 0; if (tind_block == 0) { *cur_logical += blocks_per_tind; return 0; } ret = read_block(c, buffer, tind_block); if (ret) return -1; offset -= EXT2_TIND_LBLOCK(&c->sb) + 1; offset = offset % blocks_per_tind; if (offset % blocks_per_dind) { offset = offset / blocks_per_dind; ret = write_dind_metadata(c, e, buffer[offset], cur_logical, cur_block); if (ret) return ret; offset++; } else { offset = offset / blocks_per_dind; } while (offset < EXT2_ADDR_PER_BLOCK(&c->sb) && *cur_block <= e->end_block) { __u32 new_block; if (is_sparse(inode, *cur_logical)) new_block = 0; else new_block = (*cur_block)++; (*cur_logical)++; if (new_block) { ret = write_dind_metadata(c, e, new_block, cur_logical, cur_block); if (ret) return ret; } else { *cur_logical += blocks_per_dind - 1; } if (buffer[offset] != new_block) { to_sync = 1; buffer[offset] = new_block; } offset++; } if (to_sync) { ret = write_block(c, buffer, tind_block); return ret; } return 0; }
/*------------------------------------------------------------------------- * Function: main * * Purpose: Tests indexed storage stuff. * * Return: Success: exit(0) * * Failure: exit(non-zero) * * Programmer: Robb Matzke * Wednesday, October 15, 1997 * * Modifications: * *------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { hid_t fapl=-1, file=-1, fcpl=-1; herr_t status; int nerrors = 0; unsigned size_of_test; unsigned u; /* Local index variable */ char filename[1024]; int skip_test = 0; int has_sparse_support = 0; /* Parse arguments or assume these tests (`small', `medium' ) */ if (1 == argc) { size_of_test = TEST_SMALL | TEST_MEDIUM | TEST_LARGE; } else { int i; for (i = 1, size_of_test = 0; i < argc; i++) { if (!strcmp(argv[i], "small")) { size_of_test |= TEST_SMALL; } else if (!strcmp(argv[i], "medium")) { size_of_test |= TEST_MEDIUM; } else if (!strcmp(argv[i], "large")) { size_of_test |= TEST_LARGE; } else { printf("unrecognized argument: %s\n", argv[i]); #if 0 exit(1); #endif } } } printf("Test sizes: "); if (size_of_test & TEST_SMALL) printf(" SMALL"); if (size_of_test & TEST_MEDIUM) printf(" MEDIUM"); if (size_of_test & TEST_LARGE) printf(" LARGE"); printf("\n"); /* Set the random # seed */ HDsrandom((unsigned)HDtime(NULL)); /* Check to see if the file system supports POSIX-style sparse files. * Windows NTFS does not, so we want to avoid tests which create * very large files. */ has_sparse_support = is_sparse(); /* Reset library */ h5_reset(); fapl = h5_fileaccess(); /* Use larger file addresses... */ fcpl = H5Pcreate(H5P_FILE_CREATE); H5Pset_sizes(fcpl, (size_t)8, (size_t)0); /* Create the test file */ h5_fixname(FILENAME[0], fapl, filename, sizeof filename); if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) { printf("Cannot create file %s; test aborted\n", filename); exit(1); } /* Initialize chunk dimensions */ for(u = 0; u < H5O_LAYOUT_NDIMS; u++) chunk_dims[u] = TEST_CHUNK_SIZE; /* * Creation test: Creates empty objects with various raw data sizes * and alignments. */ status = test_create(file, "create"); nerrors += status < 0 ? 1 : 0; if (size_of_test & TEST_SMALL) { status = test_extend(file, "extend", (size_t)10, (size_t)0, (size_t)0); nerrors += status < 0 ? 1 : 0; status = test_extend(file, "extend", (size_t)10, (size_t)10, (size_t)0); nerrors += status < 0 ? 1 : 0; status = test_extend(file, "extend", (size_t)10, (size_t)10, (size_t)10); nerrors += status < 0 ? 1 : 0; } if (size_of_test & TEST_MEDIUM) { status = test_extend(file, "extend", (size_t)10000, (size_t)0, (size_t)0); nerrors += status < 0 ? 1 : 0; status = test_extend(file, "extend", (size_t)2500, (size_t)10, (size_t)0); nerrors += status < 0 ? 1 : 0; status = test_extend(file, "extend", (size_t)10, (size_t)400, (size_t)10); nerrors += status < 0 ? 1 : 0; } skip_test = 0; if (size_of_test & TEST_SMALL) { status = test_sparse(file, "sparse", (size_t)100, (size_t)5, (size_t)0, (size_t)0, skip_test); nerrors += status < 0 ? 1 : 0; status = test_sparse(file, "sparse", (size_t)100, (size_t)3, (size_t)4, (size_t)0, skip_test); nerrors += status < 0 ? 1 : 0; status = test_sparse(file, "sparse", (size_t)100, (size_t)2, (size_t)3, (size_t)4, skip_test); nerrors += status < 0 ? 1 : 0; } if (size_of_test & TEST_MEDIUM) { status = test_sparse(file, "sparse", (size_t)1000, (size_t)30, (size_t)0, (size_t)0, skip_test); nerrors += status < 0 ? 1 : 0; status = test_sparse(file, "sparse", (size_t)2000, (size_t)7, (size_t)3, (size_t)0, skip_test); nerrors += status < 0 ? 1 : 0; status = test_sparse(file, "sparse", (size_t)2000, (size_t)4, (size_t)2, (size_t)3, skip_test); nerrors += status < 0 ? 1 : 0; } skip_test = !has_sparse_support; if (size_of_test & TEST_LARGE) { /* This test is skipped if there is no POSIX-style sparse file support * e.g.: Windows NTFS filesystems */ status = test_sparse(file, "sparse", (size_t)800, (size_t)50, (size_t)50, (size_t)50, skip_test); if(skip_test) printf(" The current VFD does not support sparse files on this platform.\n"); nerrors += status < 0 ? 1 : 0; } /* Close the test file and exit */ H5Pclose(fcpl); H5Fclose(file); /* Verify symbol table messages are cached */ nerrors += (h5_verify_cached_stabs(FILENAME, fapl) < 0 ? 1 : 0); if (nerrors) { printf("***** %d I-STORE TEST%s FAILED! *****\n", nerrors, 1 == nerrors ? "" : "S"); exit(1); } printf("All i-store tests passed.\n"); h5_cleanup(FILENAME, fapl); return 0; }
/*------------------------------------------------------------------------- * Function: main * * Purpose: * * Return: Success: * * Failure: * * Programmer: Robb Matzke * Friday, April 10, 1998 * * Modifications: * Albert Cheng, 2002/03/28 * Added command option -fsize. * Albert Cheng, 2002/04/19 * Added command option -c. * * Raymond Lu, 2007/05/25 * Added similar tests for SEC2 and STDIO drivers. * *------------------------------------------------------------------------- */ int main (int ac, char **av) { unsigned long seed = 0; /* Random # seed */ hid_t fapl = -1; hid_t driver = -1; /* parameters setup */ while (--ac > 0){ av++; if (HDstrcmp("-fsize", *av)==0){ /* specify a different family file size */ ac--; av++; if (ac > 0) { family_size_def = (hsize_t)HDstrtoull(*av, NULL, 0); } else{ printf("***Missing fsize value***\n"); usage(); return 1; } } else if (HDstrcmp("-c", *av)==0){ /* turn off file system check before test */ cflag=0; } else if (HDstrcmp("-h", *av)==0){ usage(); return 0; }else{ usage(); return 1; } } /* check VFD to see if this is one we test */ if((fapl = h5_fileaccess()) < 0) goto error; if((driver = H5Pget_driver(fapl)) < 0) goto error; /* check sparse file support unless cflag is not set. */ if(cflag) sparse_support = is_sparse(); /* Choose random # seed */ seed = (unsigned long)HDtime(NULL); #ifdef QAK /* seed = (unsigned long)1155438845; */ HDfprintf(stderr, "Random # seed was: %lu\n", seed); #endif /* QAK */ HDsrandom(seed); /* run VFD-specific test */ if(H5FD_SEC2 == driver) { if(test_sec2(fapl) != 0) goto error; } else if(H5FD_STDIO == driver) { if(test_stdio(fapl) != 0) goto error; } else if(H5FD_FAMILY == driver) { if(test_family(fapl) != 0) goto error; } else HDputs("This VFD is not supported"); /* End with normal exit code */ /* fapls are cleaned up in the vfd test code */ return 0; error: HDputs("*** TEST FAILED ***"); if(fapl > 0) H5Pclose(fapl); return 1; }
/*------------------------------------------------------------------------- * Function: main * * Purpose: * * Return: Success: * * Failure: * * Programmer: Robb Matzke * Friday, April 10, 1998 * * Modifications: * Albert Cheng, 2002/03/28 * Added command option -fsize. * Albert Cheng, 2002/04/19 * Added command option -c. * *------------------------------------------------------------------------- */ int main (int ac, char **av) { hid_t fapl=-1; hsize_t family_size; hsize_t family_size_def; /* default family file size */ double family_size_def_dbl; /* default family file size */ int cflag=1; /* check file system before test */ char filename[1024]; /* parameters setup */ family_size_def = FAMILY_SIZE; while (--ac > 0){ av++; if (strcmp("-fsize", *av)==0){ /* specify a different family file size */ ac--; av++; if (ac > 0){ family_size_def_dbl = atof(*av); H5_ASSIGN_OVERFLOW(family_size_def,family_size_def_dbl,double,hsize_t); if (family_size_def <= 0) family_size_def = (hsize_t)FAMILY_SIZE; } else{ printf("***Missing fsize value***\n"); usage(); return 1; } } else if (strcmp("-c", *av)==0){ /* turn off file system check before test */ cflag=0; } else if (strcmp("-h", *av)==0){ usage(); return 0; }else{ usage(); return 1; } } /* Reset library */ h5_reset(); fapl = h5_fileaccess(); /* Test big file with the family driver */ puts("Testing big file with the Family Driver "); if (H5FD_FAMILY!=H5Pget_driver(fapl)) { HDfprintf(stdout, "Changing file drivers to the family driver, %Hu bytes each\n", family_size_def); if (H5Pset_fapl_family(fapl, family_size_def, H5P_DEFAULT)<0) goto error; } else if (H5Pget_fapl_family(fapl, &family_size, NULL)<0) { goto error; } else if (family_size!=family_size_def) { HDfprintf(stdout, "Changing family member size from %Hu to %Hu\n", family_size, family_size_def); if (H5Pset_fapl_family(fapl, family_size_def, H5P_DEFAULT)<0) goto error; } if (cflag){ /* * We shouldn't run this test if the file system doesn't support holes * because we would generate multi-gigabyte files. */ puts("Checking if file system is adequate for this test..."); if (sizeof(long_long)<8 || 0==GB8LL) { puts("Test skipped because sizeof(long_long) is too small. This"); puts("hardware apparently doesn't support 64-bit integer types."); usage(); goto quit; } if (!is_sparse()) { puts("Test skipped because file system does not support holes."); usage(); goto quit; } if (!enough_room(fapl)) { puts("Test skipped because of quota (file size or num open files)."); usage(); goto quit; } if (sizeof(hsize_t)<=4) { puts("Test skipped because the hdf5 library was configured with the"); puts("--disable-hsizet flag in order to work around a compiler bug."); usage(); goto quit; } } /* Do the test with the Family Driver */ h5_fixname(FILENAME[0], fapl, filename, sizeof filename); if (writer(filename, fapl, WRT_N)) goto error; if (reader(filename, fapl)) goto error; puts("Test passed with the Family Driver."); /* * We shouldn't run this test if the file system doesn't support big files * because we would generate multi-gigabyte files. */ puts("\nChecking if file system supports big files..."); if (!supports_big()) { puts("Tests for sec2 and stdio are skipped because file system does not support big files."); usage(); goto quit; } /* Clean up the test file */ if (h5_cleanup(FILENAME, fapl)) remove(DNAME); /* Test big file with the SEC2 driver */ puts("Testing big file with the SEC2 Driver "); fapl = h5_fileaccess(); if(H5Pset_fapl_sec2(fapl)<0) HDmemset(filename, 0, sizeof(filename)); h5_fixname(FILENAME[2], fapl, filename, sizeof filename); if (writer(filename, fapl, WRT_N)) goto error; if (reader(filename, fapl)) goto error; puts("Test passed with the SEC2 Driver."); #ifdef H5_HAVE_FSEEKO /* Clean up the test file */ if (h5_cleanup(FILENAME, fapl)) remove(DNAME); /* Test big file with the STDIO driver only if fseeko is supported, * because the OFFSET parameter of fseek has the type LONG, not big * enough to support big files. */ puts("\nTesting big file with the STDIO Driver "); fapl = h5_fileaccess(); if(H5Pset_fapl_stdio(fapl)<0) HDmemset(filename, 0, sizeof(filename)); h5_fixname(FILENAME[1], fapl, filename, sizeof filename); if (writer(filename, fapl, WRT_N)) goto error; if (reader(filename, fapl)) goto error; puts("Test passed with the STDIO Driver."); #endif quit: /* End with normal exit code */ if (h5_cleanup(FILENAME, fapl)) remove(DNAME); return 0; error: if (fapl>=0) H5Pclose(fapl); puts("*** TEST FAILED ***"); return 1; }