20 #include <sys/types.h>
26 #if defined(__ANDROID__) && !defined(PHAVE_LOCKF)
38 VertexDataSaveFile(
const Filename &directory,
const std::string &prefix,
43 if (directory.empty()) {
56 std::ostringstream strm;
57 strm << prefix <<
"_" << index <<
".dat";
59 std::string basename = strm.str();
61 std::string os_specific = _filename.to_os_specific();
63 if (gobj_cat.is_debug()) {
65 <<
"Creating vertex data save file " << os_specific <<
"\n";
70 DWORD flags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_RANDOM_ACCESS;
71 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
73 flags |= FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING;
75 _handle = CreateFile(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE,
76 0,
nullptr, CREATE_ALWAYS, flags,
nullptr);
77 if (_handle != INVALID_HANDLE_VALUE) {
84 DWORD err = GetLastError();
86 if (err != ERROR_SHARING_VIOLATION) {
93 <<
"Couldn't open vertex data save file.\n";
103 int flags = O_RDWR | O_CREAT;
104 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
109 _fd = ::open(os_specific.c_str(), flags, 0666);
110 while (_fd == -1 && errno == EAGAIN) {
112 _fd = ::open(os_specific.c_str(), flags, 0666);
117 if (!_filename.exists()) {
124 <<
"Couldn't open vertex data save file.\n";
137 int result = lockf(_fd, F_TLOCK, 0);
139 int result = flock(_fd, LOCK_EX | LOCK_NB);
144 if (ftruncate(_fd, 0) < 0) {
146 <<
"Couldn't truncate vertex data save file.\n";
154 unlink(os_specific.c_str());
171 ~VertexDataSaveFile() {
173 if (_handle !=
nullptr) {
174 CloseHandle(_handle);
198 write_data(
const unsigned char *data,
size_t size,
bool compressed) {
206 if (block !=
nullptr) {
207 _total_file_size = std::max(_total_file_size, block->get_start() + size);
208 block->set_compressed(compressed);
211 OVERLAPPED overlapped;
212 memset(&overlapped, 0,
sizeof(overlapped));
213 overlapped.Offset = block->get_start();
215 DWORD bytes_written = 0;
218 BOOL success = WriteFile(_handle, data, size, &bytes_written, &overlapped);
220 DWORD error = GetLastError();
221 if (error == ERROR_IO_INCOMPLETE || error == ERROR_IO_PENDING) {
227 <<
"Error writing " << size
228 <<
" bytes to save file, windows error code 0x" << hex
229 << error << dec <<
". Disk full?\n";
232 success = GetOverlappedResult(_handle, &overlapped, &bytes_written,
false);
234 nassertr(bytes_written == size,
nullptr);
236 if (gobj_cat.is_debug()) {
238 <<
"Wrote " << size <<
" bytes in " << *
Thread::get_current_thread() <<
" over " << floor((finish_time - start_time) * 1000.0) <<
" ms and " << num_passes <<
" passes.\n";
242 if (lseek(_fd, block->get_start(), SEEK_SET) == -1) {
244 <<
"Error seeking to position " << block->get_start() <<
" in save file.\n";
249 ssize_t result = ::write(_fd, data, size);
251 if (errno == EAGAIN) {
255 <<
"Error writing " << size <<
" bytes to save file. Disk full?\n";
283 nassertr(size == block->
get_size(),
false);
293 OVERLAPPED overlapped;
294 memset(&overlapped, 0,
sizeof(overlapped));
297 DWORD bytes_read = 0;
300 BOOL success = ReadFile(_handle, data, size, &bytes_read, &overlapped);
302 DWORD error = GetLastError();
303 if (error == ERROR_IO_INCOMPLETE || error == ERROR_IO_PENDING) {
309 <<
"Error reading " << size
310 <<
" bytes from save file, windows error code 0x" << hex
311 << error << dec <<
".\n";
314 success = GetOverlappedResult(_handle, &overlapped, &bytes_read,
false);
316 nassertr(bytes_read == size,
nullptr);
318 if (gobj_cat.is_debug()) {
320 <<
"Read " << size <<
" bytes in " << *
Thread::get_current_thread() <<
" over " << floor((finish_time - start_time) * 1000.0) <<
" ms and " << num_passes <<
" passes.\n";
325 if (lseek(_fd, block->
get_start(), SEEK_SET) == -1) {
327 <<
"Error seeking to position " << block->
get_start() <<
" in save file.\n";
331 ssize_t result = read(_fd, data, size);
333 if (errno == EAGAIN) {
337 <<
"Error reading " << size <<
" bytes from save file.\n";
356 make_block(
size_t start,
size_t size) {