void AsyncFile::openReq(Request* request) { m_auto_sync_freq = 0; m_write_wo_sync = 0; m_open_flags = request->par.open.flags; // for open.flags, see signal FSOPENREQ #ifdef NDB_WIN32 DWORD dwCreationDisposition; DWORD dwDesiredAccess = 0; DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_NO_BUFFERING; Uint32 flags = request->par.open.flags; // Convert file open flags from Solaris to Windows if ((flags & FsOpenReq::OM_CREATE) && (flags & FsOpenReq::OM_TRUNCATE)){ dwCreationDisposition = CREATE_ALWAYS; } else if (flags & FsOpenReq::OM_TRUNCATE){ dwCreationDisposition = TRUNCATE_EXISTING; } else if (flags & FsOpenReq::OM_CREATE){ dwCreationDisposition = CREATE_NEW; } else { dwCreationDisposition = OPEN_EXISTING; } switch(flags & 3){ case FsOpenReq::OM_READONLY: dwDesiredAccess = GENERIC_READ; break; case FsOpenReq::OM_WRITEONLY: dwDesiredAccess = GENERIC_WRITE; break; case FsOpenReq::OM_READWRITE: dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; break; default: request->error = 1000; break; return; } hFile = CreateFile(theFileName.c_str(), dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0); if(INVALID_HANDLE_VALUE == hFile) { request->error = GetLastError(); if(((ERROR_PATH_NOT_FOUND == request->error) || (ERROR_INVALID_NAME == request->error)) && (flags & FsOpenReq::OM_CREATE)) { createDirectories(); hFile = CreateFile(theFileName.c_str(), dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0); if(INVALID_HANDLE_VALUE == hFile) request->error = GetLastError(); else request->error = 0; return; } } else { request->error = 0; return; } #else Uint32 flags = request->par.open.flags; int new_flags = 0; // Convert file open flags from Solaris to Liux if (flags & FsOpenReq::OM_CREATE) { new_flags |= O_CREAT; } if (flags & FsOpenReq::OM_TRUNCATE){ #if 0 if(Global_unlinkO_CREAT){ unlink(theFileName.c_str()); } else #endif new_flags |= O_TRUNC; } if (flags & FsOpenReq::OM_AUTOSYNC) { m_auto_sync_freq = request->par.open.auto_sync_size; } if (flags & FsOpenReq::OM_APPEND){ new_flags |= O_APPEND; } if (flags & FsOpenReq::OM_DIRECT) #ifdef O_DIRECT { new_flags |= O_DIRECT; } #endif if ((flags & FsOpenReq::OM_SYNC) && ! (flags & FsOpenReq::OM_INIT)) { #ifdef O_SYNC new_flags |= O_SYNC; #endif } const char * rw = ""; switch(flags & 0x3){ case FsOpenReq::OM_READONLY: rw = "r"; new_flags |= O_RDONLY; break; case FsOpenReq::OM_WRITEONLY: rw = "w"; new_flags |= O_WRONLY; break; case FsOpenReq::OM_READWRITE: rw = "rw"; new_flags |= O_RDWR; break; default: request->error = 1000; break; return; } // allow for user to choose any permissionsa with umask const int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; if (flags & FsOpenReq::OM_CREATE_IF_NONE) { Uint32 tmp_flags = new_flags; #ifdef O_DIRECT tmp_flags &= ~O_DIRECT; #endif if ((theFd = ::open(theFileName.c_str(), tmp_flags, mode)) != -1) { close(theFd); request->error = FsRef::fsErrFileExists; return; } new_flags |= O_CREAT; } no_odirect: if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) { PRINT_ERRORANDFLAGS(new_flags); if ((errno == ENOENT) && (new_flags & O_CREAT)) { createDirectories(); if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) { #ifdef O_DIRECT if (new_flags & O_DIRECT) { new_flags &= ~O_DIRECT; goto no_odirect; } #endif PRINT_ERRORANDFLAGS(new_flags); request->error = errno; return; } } #ifdef O_DIRECT else if (new_flags & O_DIRECT) { new_flags &= ~O_DIRECT; goto no_odirect; } #endif else { request->error = errno; return; } } if (flags & FsOpenReq::OM_CHECK_SIZE) { struct stat buf; if ((fstat(theFd, &buf) == -1)) { request->error = errno; } else if((Uint64)buf.st_size != request->par.open.file_size) { request->error = FsRef::fsErrInvalidFileSize; } if (request->error) return; } if (flags & FsOpenReq::OM_INIT) { off_t off = 0; const off_t sz = request->par.open.file_size; Uint32 tmp[sizeof(SignalHeader)+25]; Signal * signal = (Signal*)(&tmp[0]); FsReadWriteReq* req = (FsReadWriteReq*)signal->getDataPtrSend(); Uint32 index = 0; Uint32 block = refToBlock(request->theUserReference); #ifdef HAVE_XFS_XFS_H if(platform_test_xfs_fd(theFd)) { ndbout_c("Using xfsctl(XFS_IOC_RESVSP64) to allocate disk space"); xfs_flock64_t fl; fl.l_whence= 0; fl.l_start= 0; fl.l_len= (off64_t)sz; if(xfsctl(NULL, theFd, XFS_IOC_RESVSP64, &fl) < 0) ndbout_c("failed to optimally allocate disk space"); } #endif #ifdef HAVE_POSIX_FALLOCATE posix_fallocate(theFd, 0, sz); #endif while(off < sz) { req->filePointer = 0; // DATA 0 req->userPointer = request->theUserPointer; // DATA 2 req->numberOfPages = 1; // DATA 5 req->varIndex = index++; req->data.pageData[0] = m_page_ptr.i; m_fs.EXECUTE_DIRECT(block, GSN_FSWRITEREQ, signal, FsReadWriteReq::FixedLength + 1); retry: Uint32 size = request->par.open.page_size; char* buf = (char*)m_page_ptr.p; while(size > 0){ const int n = write(theFd, buf, size); if(n == -1 && errno == EINTR) { continue; } if(n == -1 || n == 0) { break; } size -= n; buf += n; } if(size != 0) { int err = errno; #ifdef O_DIRECT if ((new_flags & O_DIRECT) && off == 0) { ndbout_c("error on first write(%d), disable O_DIRECT", err); new_flags &= ~O_DIRECT; close(theFd); theFd = ::open(theFileName.c_str(), new_flags, mode); if (theFd != -1) goto retry; } #endif close(theFd); unlink(theFileName.c_str()); request->error = err; return; } off += request->par.open.page_size; } if(lseek(theFd, 0, SEEK_SET) != 0) request->error = errno; } else if (flags & FsOpenReq::OM_DIRECT) { #ifdef O_DIRECT if (flags & (FsOpenReq::OM_TRUNCATE | FsOpenReq::OM_CREATE)) { request->error = check_odirect_write(flags, new_flags, mode); } else { request->error = check_odirect_read(flags, new_flags, mode); } if (request->error) return; #endif } #ifdef VM_TRACE if (flags & FsOpenReq::OM_DIRECT) { #ifdef O_DIRECT ndbout_c("%s %s O_DIRECT: %d", theFileName.c_str(), rw, !!(new_flags & O_DIRECT)); #else ndbout_c("%s %s O_DIRECT: 0", theFileName.c_str(), rw); #endif } #endif if ((flags & FsOpenReq::OM_SYNC) && (flags & FsOpenReq::OM_INIT)) { #ifdef O_SYNC /** * reopen file with O_SYNC */ close(theFd); new_flags &= ~(O_CREAT | O_TRUNC); new_flags |= O_SYNC; theFd = ::open(theFileName.c_str(), new_flags, mode); if (theFd == -1) { request->error = errno; } #endif } #endif }
void AsyncFile::openReq(Request* request) { m_openedWithSync = false; m_syncFrequency = 0; m_syncCount= 0; // for open.flags, see signal FSOPENREQ #ifdef NDB_WIN32 DWORD dwCreationDisposition; DWORD dwDesiredAccess = 0; DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_NO_BUFFERING; const Uint32 flags = request->par.open.flags; // Convert file open flags from Solaris to Windows if ((flags & FsOpenReq::OM_CREATE) && (flags & FsOpenReq::OM_TRUNCATE)){ dwCreationDisposition = CREATE_ALWAYS; } else if (flags & FsOpenReq::OM_TRUNCATE){ dwCreationDisposition = TRUNCATE_EXISTING; } else if (flags & FsOpenReq::OM_CREATE){ dwCreationDisposition = CREATE_NEW; } else { dwCreationDisposition = OPEN_EXISTING; } switch(flags & 3){ case FsOpenReq::OM_READONLY: dwDesiredAccess = GENERIC_READ; break; case FsOpenReq::OM_WRITEONLY: dwDesiredAccess = GENERIC_WRITE; break; case FsOpenReq::OM_READWRITE: dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; break; default: request->error = 1000; break; return; } hFile = CreateFile(theFileName.c_str(), dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0); if(INVALID_HANDLE_VALUE == hFile) { request->error = GetLastError(); if(((ERROR_PATH_NOT_FOUND == request->error) || (ERROR_INVALID_NAME == request->error)) && (flags & FsOpenReq::OM_CREATE)) { createDirectories(); hFile = CreateFile(theFileName.c_str(), dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0); if(INVALID_HANDLE_VALUE == hFile) request->error = GetLastError(); else request->error = 0; return; } } else { request->error = 0; return; } #else const Uint32 flags = request->par.open.flags; Uint32 new_flags = 0; // Convert file open flags from Solaris to Liux if(flags & FsOpenReq::OM_CREATE){ new_flags |= O_CREAT; } if(flags & FsOpenReq::OM_TRUNCATE){ #if 0 if(Global_unlinkO_CREAT){ unlink(theFileName.c_str()); } else #endif new_flags |= O_TRUNC; } if(flags & FsOpenReq::OM_APPEND){ new_flags |= O_APPEND; } if(flags & FsOpenReq::OM_SYNC){ #if 0 if(Global_useO_SYNC){ new_flags |= O_SYNC; m_openedWithSync = true; m_syncFrequency = 0; } else { #endif m_openedWithSync = false; m_syncFrequency = Global_syncFreq; #if 0 } #endif } else { m_openedWithSync = false; m_syncFrequency = 0; } #if 0 //#if NDB_LINUX if(Global_useO_DIRECT){ new_flags |= O_DIRECT; } #endif switch(flags & 0x3){ case FsOpenReq::OM_READONLY: new_flags |= O_RDONLY; break; case FsOpenReq::OM_WRITEONLY: new_flags |= O_WRONLY; break; case FsOpenReq::OM_READWRITE: new_flags |= O_RDWR; break; default: request->error = 1000; break; return; } const int mode = S_IRUSR | S_IWUSR | S_IRGRP; if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) { PRINT_ERRORANDFLAGS(new_flags); if( (errno == ENOENT ) && (new_flags & O_CREAT ) ) { createDirectories(); if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) { PRINT_ERRORANDFLAGS(new_flags); request->error = errno; } } else { request->error = errno; } } #endif }