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) {
A block of bytes on the save file.
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
An implementation of a very simple block allocator.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
static void force_yield()
Suspends the current thread for the rest of the current epoch.
A single block as returned from SimpleAllocator::alloc().
The name of a file, such as a texture file or an Egg file.
get_real_time
Returns the actual number of seconds elapsed since the ClockObject was created, or since it was last ...
static const Filename & get_temp_directory()
Returns a path to a system-defined temporary directory.
PT(VertexDataSaveBlock) VertexDataSaveFile
Writes a block of data to the file, and returns a handle to the block handle.
size_t get_start() const
Returns the starting point of this block.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool read_data(unsigned char *data, size_t size, VertexDataSaveBlock *block)
Reads a block of data from the file, and returns true on success, false on failure.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
size_t get_size() const
Returns the size of this block.