1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
26 // File: vogl_trace_file_reader.cpp
27 #include "vogl_trace_file_reader.h"
28 #include "vogl_console.h"
29 #include "vogl_file_utils.h"
31 vogl_trace_file_reader::trace_file_reader_status_t vogl_trace_file_reader::read_frame_packets(uint frame_index, uint num_frames, vogl_trace_packet_array &packets, uint &actual_frames_read)
35 actual_frames_read = 0;
39 vogl_error_printf("%s: Trace file is not open\n", VOGL_METHOD_NAME);
48 actual_frames_read = 0;
52 vogl_scoped_location_saver saved_loc(*this);
54 if (!seek_to_frame(frame_index))
56 vogl_error_printf("%s: Failed seeking to frame %u\n", VOGL_METHOD_NAME, frame_index);
60 uint total_frames_read = 0;
62 packets.reserve(packets.size() + num_frames * 1000);
64 trace_file_reader_status_t status = cOK;
67 status = read_next_packet();
68 if (status == cFailed)
70 vogl_error_printf("%s: Failed reading from trace file\n", VOGL_METHOD_NAME);
74 packets.push_back(get_packet_buf());
79 if (is_swap_buffers_packet())
81 if (++total_frames_read == num_frames)
86 actual_frames_read = total_frames_read;
91 void vogl_trace_file_reader::create_eof_packet()
95 vogl_trace_stream_packet_base eof_packet;
96 eof_packet.init(cTSPTEOF, sizeof(vogl_trace_stream_packet_base));
97 eof_packet.finalize();
98 m_packet_buf.resize(0);
99 m_packet_buf.append(reinterpret_cast<uint8 *>(&eof_packet), sizeof(eof_packet));
102 bool vogl_trace_file_reader::init_loose_file_blob_manager(const char *pTrace_filename, const char *pLoose_file_path)
106 dynamic_string loose_file_path(".");
108 if ((pLoose_file_path) && vogl_strlen(pLoose_file_path))
109 loose_file_path = pLoose_file_path;
110 else if ((pTrace_filename) && (vogl_strlen(pTrace_filename)))
112 dynamic_string fname;
113 if (!file_utils::split_path(pTrace_filename, loose_file_path, fname))
115 console::error("%s: Failed splitting trace filename \"%s\", assuming \".\" as the loose file path\n", VOGL_METHOD_NAME, pTrace_filename);
116 loose_file_path = ".";
120 if (!m_loose_file_blob_manager.init(cBMFReadable, loose_file_path.get_ptr()))
129 vogl_binary_trace_file_reader::vogl_binary_trace_file_reader()
130 : vogl_trace_file_reader(),
131 m_trace_file_size(0),
132 m_cur_frame_index(0),
133 m_max_frame_index(-1),
134 m_found_frame_file_offsets_packet(0)
138 m_frame_file_offsets.reserve(4096);
141 vogl_binary_trace_file_reader::~vogl_binary_trace_file_reader()
148 bool vogl_binary_trace_file_reader::read_frame_file_offsets()
152 m_frame_file_offsets.clear();
153 m_max_frame_index = -1;
154 m_found_frame_file_offsets_packet = false;
156 uint8_vec frame_offsets_data;
157 if (!m_archive_blob_manager.is_initialized() || !m_archive_blob_manager.get(VOGL_TRACE_ARCHIVE_FRAME_FILE_OFFSETS_FILENAME, frame_offsets_data))
159 vogl_debug_printf("%s: Couldn't find trace frame file offset file in trace archive, seeking will be slow in this trace file\n", VOGL_METHOD_NAME);
163 if (frame_offsets_data.size() & (sizeof(uint64_t) - 1))
165 vogl_error_printf("%s: Trace frame file offset file in trace archive is invalid, seeking will be slow in this trace file\n", VOGL_METHOD_NAME);
169 uint total_offsets = frame_offsets_data.size() / sizeof(uint64_t);
171 m_frame_file_offsets.resize(total_offsets);
172 memcpy(m_frame_file_offsets.get_ptr(), frame_offsets_data.get_ptr(), m_frame_file_offsets.size_in_bytes());
174 vogl_debug_printf("%s: Frame file offsets packet is OK, found %u total frame offsets\n", VOGL_METHOD_NAME, m_frame_file_offsets.size());
176 m_max_frame_index = m_frame_file_offsets.size() - 1;
178 m_found_frame_file_offsets_packet = true;
182 bool vogl_binary_trace_file_reader::open(const char *pFilename, const char *pLoose_file_path)
188 if (!init_loose_file_blob_manager(pFilename, pLoose_file_path))
191 if (!m_trace_stream.open(pFilename, cDataStreamReadable | cDataStreamSeekable, true))
197 m_trace_file_size = m_trace_stream.get_size();
199 if (m_trace_stream.read(&m_sof_packet, sizeof(m_sof_packet)) != sizeof(m_sof_packet))
205 if (!m_sof_packet.full_validation(sizeof(m_sof_packet)))
211 if (m_sof_packet.m_version < static_cast<uint16>(VOGL_TRACE_FILE_VERSION))
213 vogl_error_printf("%s: Trace file version is not supported, found version 0x%04X, expected version 0x%04X!\n", VOGL_METHOD_NAME, m_sof_packet.m_version, VOGL_TRACE_FILE_VERSION);
216 else if (m_sof_packet.m_version > static_cast<uint16>(VOGL_TRACE_FILE_VERSION))
218 // TODO: Make this an error? Backwards compat?
219 vogl_warning_printf("%s: Trace file version is 0x%04X, expected version 0x%04X, this may not work at all!\n", VOGL_METHOD_NAME, m_sof_packet.m_version, VOGL_TRACE_FILE_VERSION);
222 if (m_sof_packet.m_archive_size)
224 if (!m_archive_blob_manager.init_file(cBMFReadable | cBMFOpenExisting, pFilename, m_sof_packet.m_archive_offset, m_sof_packet.m_archive_size))
226 vogl_error_printf("%s: Failed reading in-trace archive!\n", VOGL_METHOD_NAME);
231 m_packet_buf.reserve(512 * 1024);
233 m_trace_stream.seek(m_sof_packet.m_first_packet_offset, false);
235 if (!read_frame_file_offsets())
237 // Keep this in sync with the offset pushed in vogl_init_tracefile()!
238 m_frame_file_offsets.push_back(get_cur_file_ofs());
244 bool vogl_binary_trace_file_reader::is_opened()
248 return m_trace_stream.is_opened();
251 const char *vogl_binary_trace_file_reader::get_filename()
255 return m_trace_stream.get_name().get_ptr();
258 void vogl_binary_trace_file_reader::close()
262 vogl_trace_file_reader::close();
264 m_trace_stream.close();
265 m_trace_file_size = 0;
267 m_cur_frame_index = 0;
268 m_max_frame_index = -1;
269 m_frame_file_offsets.resize(0);
271 m_saved_location_stack.clear();
273 m_found_frame_file_offsets_packet = false;
276 bool vogl_binary_trace_file_reader::is_at_eof()
280 return (m_trace_stream.get_remaining() < sizeof(vogl_trace_stream_packet_base));
283 bool vogl_binary_trace_file_reader::seek_to_frame(uint frame_index)
293 if (frame_index >= m_frame_file_offsets.size())
295 if ((m_max_frame_index >= 0) && (frame_index > m_max_frame_index))
297 vogl_warning_printf("%s: Can't seek to frame %u, max valid frame index is %u\n", VOGL_METHOD_NAME, frame_index, static_cast<uint>(m_max_frame_index));
301 vogl_warning_printf("%s: Seeking forward in binary trace from frame %u to frame %u, this could take a while to build the index\n", VOGL_METHOD_NAME, m_cur_frame_index, frame_index);
303 if (m_frame_file_offsets.size())
305 seek(m_frame_file_offsets.back());
306 m_cur_frame_index = m_frame_file_offsets.size() - 1;
311 trace_file_reader_status_t status = read_next_packet();
312 if (status == cFailed)
314 vogl_error_printf("%s: Failed reading next packet\n", VOGL_METHOD_NAME);
318 if ((status == cEOF) || (is_eof_packet()))
321 } while (frame_index >= m_frame_file_offsets.size());
323 if (frame_index >= m_frame_file_offsets.size())
325 if (g_command_line_params.get_value_as_bool("verbose"))
326 vogl_debug_printf("%s: Failed seeking forward in binary trace to frame %u, cur frame is now %u\n", VOGL_METHOD_NAME, frame_index, m_cur_frame_index);
331 seek(m_frame_file_offsets[frame_index]);
332 m_cur_frame_index = frame_index;
336 int64_t vogl_binary_trace_file_reader::get_max_frame_index()
340 if (m_max_frame_index < 0)
344 seek_to_frame(0xFFFFFFFF);
349 if (m_max_frame_index >= 0)
350 return m_max_frame_index;
355 vogl_trace_file_reader::trace_file_reader_status_t vogl_binary_trace_file_reader::read_next_packet()
359 m_packet_buf.resize(sizeof(vogl_trace_stream_packet_base));
362 vogl_trace_stream_packet_base &packet_base = *reinterpret_cast<vogl_trace_stream_packet_base *>(m_packet_buf.get_ptr());
363 uint bytes_actually_read = m_trace_stream.read(&packet_base, sizeof(packet_base));
364 if (bytes_actually_read != sizeof(packet_base))
366 // Jam in a fake EOF packet in case the caller doesn't get the message that something is wrong
369 // The could happen if the file was truncated, or the last packet didn't get entirely written.
370 if (bytes_actually_read)
373 if (m_max_frame_index < 0)
374 m_max_frame_index = m_cur_frame_index;
376 VOGL_ASSERT(m_max_frame_index == m_cur_frame_index);
381 if ((!packet_base.basic_validation()) || (packet_base.m_size >= 0x7FFFFFFFULL))
383 console::error("%s: Bad trace file - packet failed basic validation tests!\n", VOGL_METHOD_NAME);
390 m_packet_buf.resize(packet_base.m_size);
393 vogl_trace_stream_packet_base &packet_base = *reinterpret_cast<vogl_trace_stream_packet_base *>(m_packet_buf.get_ptr());
395 uint num_bytes_remaining = packet_base.m_size - sizeof(vogl_trace_stream_packet_base);
396 if (num_bytes_remaining)
398 uint actual_bytes_read = m_trace_stream.read(m_packet_buf.get_ptr() + sizeof(vogl_trace_stream_packet_base), num_bytes_remaining);
399 if (actual_bytes_read != num_bytes_remaining)
401 console::error("%s: Failed reading variable size trace packet data (wanted %u bytes, got %u bytes), trace file is probably corrupted/invalid\n", VOGL_METHOD_NAME, num_bytes_remaining, actual_bytes_read);
406 if (!packet_base.check_crc(packet_base.m_size))
408 console::error("%s: Bad trace file - packet CRC32 is bad!\n", VOGL_METHOD_NAME);
417 if (m_max_frame_index < 0)
418 m_max_frame_index = m_cur_frame_index;
420 VOGL_ASSERT(m_max_frame_index == m_cur_frame_index);
422 else if (is_swap_buffers_packet())
426 if (m_cur_frame_index >= m_frame_file_offsets.size())
428 m_frame_file_offsets.resize(math::maximum(m_frame_file_offsets.size(), m_cur_frame_index + 1));
429 m_frame_file_offsets[m_cur_frame_index] = get_cur_file_ofs();
433 VOGL_ASSERT(m_frame_file_offsets[m_cur_frame_index] == get_cur_file_ofs());
440 bool vogl_binary_trace_file_reader::push_location()
444 if (!m_trace_stream.is_opened())
447 saved_location *p = m_saved_location_stack.enlarge(1);
448 p->m_cur_frame_index = m_cur_frame_index;
449 p->m_cur_ofs = m_trace_stream.get_ofs();
454 bool vogl_binary_trace_file_reader::pop_location()
458 if ((!m_trace_stream.is_opened()) || (m_saved_location_stack.is_empty()))
461 saved_location &loc = m_saved_location_stack.back();
465 if (!m_trace_stream.seek(loc.m_cur_ofs, false))
468 m_cur_frame_index = loc.m_cur_frame_index;
470 m_saved_location_stack.pop_back();
475 //-----------------------------------------------------------------------------
476 // vogl_json_trace_file_reader::vogl_json_trace_file_reader
477 //-----------------------------------------------------------------------------
478 vogl_json_trace_file_reader::vogl_json_trace_file_reader()
479 : vogl_trace_file_reader(),
480 m_filename_exists(false),
481 m_filename_is_in_multiframe_form(false),
482 m_cur_frame_index(0), m_max_frame_index(0), m_cur_packet_node_index(0), m_packet_node_size(0), m_doc_eof_key_value(false),
484 m_trace_packet(&m_trace_ctypes)
489 vogl_json_trace_file_reader::~vogl_json_trace_file_reader()
496 bool vogl_json_trace_file_reader::open(const char *pFilename, const char *pLoose_file_path)
502 if (!init_loose_file_blob_manager(pFilename, pLoose_file_path))
505 m_filename = pFilename;
506 m_filename_is_in_multiframe_form = vogl_is_multiframe_json_trace_filename(pFilename);
508 if (!file_utils::split_path(pFilename, &m_drive, &m_dir, &m_fname, &m_ext))
510 console::error("%s: Failed splitting input filename: \"%s\"\n", VOGL_METHOD_NAME, pFilename);
515 m_filename_exists = file_utils::does_file_exist(pFilename);
516 if ((!m_filename_exists) && (m_filename_is_in_multiframe_form))
518 console::error("%s: Could not open JSON trace file: \"%s\"\n", VOGL_METHOD_NAME, pFilename);
523 if ((m_filename_exists) && (!m_filename_is_in_multiframe_form))
525 // Assume they just want to play one frame.
526 m_cur_frame_filename = m_filename;
527 m_base_filename = m_filename;
528 m_max_frame_index = 0;
533 for (i = 0; i < 99999999; i++)
535 dynamic_string trial_base_name(m_fname);
536 if (m_filename_is_in_multiframe_form)
537 trial_base_name.shorten(7);
540 file_utils::combine_path(m_base_filename, m_drive.get_ptr(), m_dir.get_ptr(), trial_base_name.get_ptr());
542 dynamic_string trial_name(cVarArg, "%s_%06u", trial_base_name.get_ptr(), i);
544 dynamic_string trial_filename;
545 file_utils::combine_path_and_extension(trial_filename, m_drive.get_ptr(), m_dir.get_ptr(), trial_name.get_ptr(), m_ext.get_ptr());
547 if (!file_utils::does_file_exist(trial_filename.get_ptr()))
551 m_cur_frame_filename = trial_filename;
556 console::error("%s: Could not open JSON trace file \"%s\"\n", VOGL_METHOD_NAME, pFilename);
561 m_max_frame_index = i - 1;
564 if (!open_first_document())
570 console::info("Opened JSON trace file \"%s\", frame range [%u - %u]\n", m_cur_frame_filename.get_ptr(), m_cur_frame_index, m_max_frame_index);
575 bool vogl_json_trace_file_reader::is_opened()
579 return m_pPackets_array != NULL;
582 const char *vogl_json_trace_file_reader::get_filename()
586 return m_filename.get_ptr();
589 bool vogl_json_trace_file_reader::open_first_document()
593 if (!read_document(m_cur_frame_filename))
596 const json_node *pRoot_node = m_cur_doc.get_root();
599 vogl_error_printf("%s: JSON file must be an object: \"%s\"\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr());
603 const json_node *pSOF_node = pRoot_node->find_child_object("sof");
606 vogl_error_printf("%s: Failed finding SOF (start of file) packet in JSON file \"%s\"\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr());
610 int meta_pointer_sizes = pSOF_node->value_as_int32("pointer_sizes", -1);
611 if ((meta_pointer_sizes != sizeof(uint32)) && (meta_pointer_sizes != sizeof(uint64_t)))
613 vogl_error_printf("%s: Invalid meta pointer sizes field in JSON file \"%s\"\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr());
617 dynamic_string archive_filename = pSOF_node->value_as_string("archive_filename");
618 if (!archive_filename.is_empty())
620 dynamic_string full_archive_filename(archive_filename);
622 // Determine if the archive path is absolute or not
623 if (!full_archive_filename.contains('/') && !full_archive_filename.contains('\\'))
625 file_utils::combine_path(full_archive_filename, m_drive.get_ptr(), m_dir.get_ptr(), archive_filename.get_ptr());
628 if (!m_archive_blob_manager.init_file(cBMFReadable | cBMFOpenExisting, full_archive_filename.get_ptr()))
630 vogl_error_printf("%s: JSON trace relies on archive \"%s\", which cannot be opened! Will try to read anyway, but later operations may fail if loose files cannot be found.\n", VOGL_METHOD_NAME, archive_filename.get_ptr());
631 // Don't immediately exit in case they have manually deleted the archive and want everything to read from loose files.
636 uint64_t trace_version = pSOF_node->value_as_uint64("version");
639 m_sof_packet.m_pointer_sizes = meta_pointer_sizes;
640 m_sof_packet.m_version = trace_version;
642 if (m_archive_blob_manager.is_initialized())
644 file_utils::get_file_size(m_archive_blob_manager.get_archive_filename().get_ptr(), m_sof_packet.m_archive_size);
647 const json_node *pUUID_array = pSOF_node->find_child_array("uuid");
650 for (uint i = 0; i < math::minimum<uint>(pUUID_array->size(), vogl_trace_stream_start_of_file_packet::cUUIDSize); i++)
651 m_sof_packet.m_uuid[i] = pUUID_array->value_as_uint32(i);
654 // Makes no sense to finalize it, it's not complete or valid.
655 //m_sof_packet.finalize();
657 m_trace_ctypes.change_pointer_sizes(meta_pointer_sizes);
662 bool vogl_json_trace_file_reader::read_document(const dynamic_string &filename)
666 m_cur_frame_filename = filename;
668 m_cur_packet_node_index = 0;
669 m_packet_node_size = 0;
670 m_doc_eof_key_value = 0;
671 m_pPackets_array = NULL;
674 bool deserialize_status = false;
676 // HACK HACK: to work around another app writing to the file as we try to read it in -endless mode
677 const uint cMaxRetries = 5;
678 for (uint tries = 0; tries < cMaxRetries; tries++)
680 if (!m_trace_stream.open(m_cur_frame_filename.get_ptr(), cDataStreamReadable, true))
682 console::error("%s: Could not open JSON trace file \"%s\"\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr());
686 deserialize_status = m_cur_doc.deserialize_file(m_cur_frame_filename.get_ptr());
688 m_trace_stream.close();
690 if (deserialize_status)
693 // Sleep a while in case another app is writing to the file
697 if (!deserialize_status)
699 if (m_cur_doc.get_error_msg().has_content())
700 vogl_error_printf("%s: Failed deserializing JSON file \"%s\"!\nError: %s Line: %u\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr(), m_cur_doc.get_error_msg().get_ptr(), m_cur_doc.get_error_line());
702 vogl_error_printf("%s: Failed deserializing JSON file \"%s\"!\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr());
708 vogl_message_printf("Processing JSON file \"%s\"\n", m_cur_frame_filename.get_ptr());
710 const json_node *pRoot_node = m_cur_doc.get_root();
713 vogl_error_printf("%s: Couldn't find root node in JSON file \"%s\"\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr());
718 const json_node *pMeta_node = pRoot_node->find_child("meta");
721 vogl_error_printf("%s: Couldn't find meta node in JSON file \"%s\"\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr());
726 int64_t meta_frame_index = pMeta_node->value_as_int64("cur_frame", -1);
727 if (meta_frame_index != m_cur_frame_index)
729 vogl_error_printf("%s: Invalid meta frame index in JSON file \"%s\" (expected %lli, got %lli)\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr(), static_cast<long long int>(m_cur_frame_index), static_cast<long long int>(meta_frame_index));
734 m_doc_eof_key_value = pMeta_node->value_as_int("eof", 0);
736 m_pPackets_array = pRoot_node->find_child_array("packets");
737 if (!m_pPackets_array)
739 vogl_error_printf("%s: Couldn't find packets node in JSON file \"%s\"\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr());
744 const json_node *pUUID_array = pMeta_node->find_child_array("uuid");
747 uint32 uuid[vogl_trace_stream_start_of_file_packet::cUUIDSize];
748 utils::zero_object(uuid);
750 for (uint i = 0; i < math::minimum<uint>(pUUID_array->size(), vogl_trace_stream_start_of_file_packet::cUUIDSize); i++)
751 uuid[i] = pUUID_array->value_as_uint32(i);
753 if (memcmp(uuid, m_sof_packet.m_uuid, sizeof(uuid)) != 0)
755 // Print the UUID's the way they would appear in the json for easier searching
756 vogl_warning_printf("%s: Document UUID (%u %u %u %u) in file %s differs from the UUID in the first frame's SOF packet (%u %u %u %u)\n", VOGL_METHOD_NAME,
757 uuid[0], uuid[1], uuid[2], uuid[3],
759 m_sof_packet.m_uuid[0], m_sof_packet.m_uuid[1], m_sof_packet.m_uuid[2], m_sof_packet.m_uuid[3]);
763 m_packet_node_size = m_pPackets_array->size();
768 void vogl_json_trace_file_reader::close()
772 vogl_trace_file_reader::close();
775 m_base_filename.clear();
776 m_filename_exists = false;
777 m_filename_is_in_multiframe_form = false;
784 m_cur_frame_filename.clear();
786 m_trace_stream.close();
788 m_cur_frame_index = 0;
789 m_max_frame_index = 0;
792 m_pPackets_array = NULL;
793 m_cur_packet_node_index = 0;
794 m_packet_node_size = 0;
795 m_doc_eof_key_value = 0;
799 m_saved_location_stack.clear();
802 bool vogl_json_trace_file_reader::is_at_eof()
806 if (!m_cur_doc.get_root())
810 (m_cur_frame_index > m_max_frame_index) ||
811 ((m_doc_eof_key_value > 0) && (m_cur_packet_node_index >= m_packet_node_size));
814 dynamic_string vogl_json_trace_file_reader::compose_frame_filename()
818 if ((m_filename_exists) && (!m_filename_is_in_multiframe_form))
821 dynamic_string trial_base_name(m_fname);
822 if (m_filename_is_in_multiframe_form)
823 trial_base_name.shorten(7);
825 dynamic_string trial_name(cVarArg, "%s_%06u", trial_base_name.get_ptr(), m_cur_frame_index);
827 dynamic_string trial_filename;
828 file_utils::combine_path_and_extension(trial_filename, m_drive.get_ptr(), m_dir.get_ptr(), trial_name.get_ptr(), m_ext.get_ptr());
830 return trial_filename;
833 bool vogl_json_trace_file_reader::seek_to_frame(uint frame_index)
837 // Special case: It's OK to seek to the very beginning of the frame just beyond the max valid JSON frame, to emulate how the binary read works.
838 if (frame_index == (m_max_frame_index + 1))
840 m_cur_frame_index = m_max_frame_index;
842 if (!read_document(compose_frame_filename()))
845 m_cur_packet_node_index = m_packet_node_size;
851 else if (frame_index > m_max_frame_index)
857 m_cur_frame_index = frame_index;
859 if (!read_document(compose_frame_filename()))
867 vogl_trace_file_reader::trace_file_reader_status_t vogl_json_trace_file_reader::read_next_packet()
871 if (!m_pPackets_array)
877 if ((m_at_eof) || (m_cur_frame_index > m_max_frame_index))
885 while (m_cur_packet_node_index >= m_packet_node_size)
887 if (m_doc_eof_key_value > 0)
894 if (m_cur_frame_index <= m_max_frame_index)
897 if (m_cur_frame_index > m_max_frame_index)
899 vogl_warning_printf("%s: Last JSON document %u did not have a non-zero eof meta key, forcing EOF\n", VOGL_METHOD_NAME, m_max_frame_index);
906 if (!read_document(compose_frame_filename()))
910 const json_node *pGL_node = m_pPackets_array->get_value_as_object(m_cur_packet_node_index);
913 vogl_warning_printf("%s: Ignoring invalid JSON key %s, file \"%s\"\n", VOGL_METHOD_NAME, m_pPackets_array->get_path_to_item(m_cur_packet_node_index).get_ptr(), m_cur_frame_filename.get_ptr());
914 m_cur_packet_node_index++;
918 bool success = m_trace_packet.json_deserialize(*pGL_node, m_cur_frame_filename.get_ptr(), &m_multi_blob_manager);
921 if (m_cur_doc.get_error_msg().has_content())
922 vogl_error_printf("%s: Failed deserializing JSON file \"%s\"!\nError: %s Line: %u\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr(), m_cur_doc.get_error_msg().get_ptr(), m_cur_doc.get_error_line());
924 vogl_error_printf("%s: Failed deserializing JSON file \"%s\"!\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr());
928 m_dyn_stream.reset();
931 if (!m_trace_packet.serialize(m_dyn_stream))
933 vogl_error_printf("%s: Failed serializing binary trace packet data while processing JSON file \"%s\"!\n", VOGL_METHOD_NAME, m_cur_frame_filename.get_ptr());
937 m_dyn_stream.get_buf().swap(m_packet_buf);
939 m_cur_packet_node_index++;
944 return m_at_eof ? cEOF : cOK;
947 bool vogl_is_multiframe_json_trace_filename(const char *pFilename)
951 dynamic_string drive, dir, fname, ext;
952 if (!file_utils::split_path(pFilename, &drive, &dir, &fname, &ext))
955 if ((fname.size() >= 7) && (fname.get_char_at_end(6) == '_'))
957 for (int i = 0; i < 6; i++)
958 if (!vogl_isdigit(fname.get_char_at_end(i)))
966 bool vogl_json_trace_file_reader::push_location()
970 if (!m_pPackets_array)
973 saved_location *p = m_saved_location_stack.enlarge(1);
974 p->m_cur_frame_filename = m_cur_frame_filename;
975 p->m_cur_frame_index = m_cur_frame_index;
976 p->m_cur_packet_node_index = m_cur_packet_node_index;
977 p->m_at_eof = m_at_eof;
982 bool vogl_json_trace_file_reader::pop_location()
986 if ((!m_pPackets_array) || (m_saved_location_stack.is_empty()))
989 saved_location &loc = m_saved_location_stack.back();
993 if ((loc.m_cur_frame_filename != m_cur_frame_filename) || (loc.m_cur_frame_index != m_cur_frame_index))
995 m_cur_frame_index = loc.m_cur_frame_index;
997 if (!read_document(loc.m_cur_frame_filename))
1003 m_cur_frame_index = loc.m_cur_frame_index;
1005 m_at_eof = loc.m_at_eof;
1007 if (loc.m_cur_packet_node_index > m_pPackets_array->size())
1010 m_cur_packet_node_index = loc.m_cur_packet_node_index;
1013 m_saved_location_stack.pop_back();
1018 vogl_trace_file_reader_type_t vogl_determine_trace_file_type(const dynamic_string &orig_filename, dynamic_string &filename_to_use)
1022 dynamic_string trace_extension(orig_filename);
1023 file_utils::get_extension(trace_extension);
1025 vogl_trace_file_reader_type_t trace_reader_type = cINVALID_TRACE_FILE_READER;
1027 if (trace_extension == "bin")
1029 trace_reader_type = cBINARY_TRACE_FILE_READER;
1030 filename_to_use = orig_filename;
1032 else if (trace_extension == "json")
1034 trace_reader_type = cJSON_TRACE_FILE_READER;
1035 filename_to_use = orig_filename;
1037 else if (file_utils::does_file_exist(orig_filename.get_ptr()))
1039 FILE *pFile = vogl_fopen(orig_filename.get_ptr(), "rb");
1042 int first_char = fgetc(pFile);
1043 if (first_char == '{')
1045 trace_reader_type = cJSON_TRACE_FILE_READER;
1046 filename_to_use = orig_filename;
1048 else if (first_char != EOF)
1050 vogl_trace_stream_packet_base first_packet;
1051 utils::zero_object(first_packet);
1053 *reinterpret_cast<char *>(&first_packet) = static_cast<char>(first_char);
1055 if (fread(reinterpret_cast<char *>(&first_packet) + 1, sizeof(first_packet) - 1, 1, pFile) == 1)
1057 if ((first_packet.m_prefix == vogl_trace_stream_packet_base::cTracePacketPrefix) && (first_packet.m_type == cTSPTSOF))
1059 trace_reader_type = cBINARY_TRACE_FILE_READER;
1060 filename_to_use = orig_filename;
1069 if (trace_reader_type == cINVALID_TRACE_FILE_READER)
1071 dynamic_string trial_filename(cVarArg, "%s.bin", orig_filename.get_ptr());
1072 if (file_utils::does_file_exist(trial_filename.get_ptr()))
1074 trace_reader_type = cBINARY_TRACE_FILE_READER;
1075 filename_to_use = trial_filename;
1079 trial_filename.format("%s.json", orig_filename.get_ptr());
1080 if (file_utils::does_file_exist(trial_filename.get_ptr()))
1082 trace_reader_type = cJSON_TRACE_FILE_READER;
1083 filename_to_use = trial_filename;
1087 trial_filename.format("%s_000000.json", orig_filename.get_ptr());
1088 if (file_utils::does_file_exist(trial_filename.get_ptr()))
1090 trace_reader_type = cJSON_TRACE_FILE_READER;
1091 filename_to_use = trial_filename;
1097 return trace_reader_type;
1100 vogl_trace_file_reader *vogl_create_trace_file_reader(vogl_trace_file_reader_type_t trace_type)
1106 case cBINARY_TRACE_FILE_READER:
1107 return vogl_new(vogl_binary_trace_file_reader);
1109 case cJSON_TRACE_FILE_READER:
1110 return vogl_new(vogl_json_trace_file_reader);
1122 vogl_trace_file_reader *vogl_open_trace_file(dynamic_string &orig_filename, dynamic_string &actual_filename, const char *pLoose_file_path)
1126 vogl_trace_file_reader_type_t trace_type = vogl_determine_trace_file_type(orig_filename, actual_filename);
1127 if (trace_type == cINVALID_TRACE_FILE_READER)
1129 vogl_error_printf("%s: Unable to determine file type of trace file \"%s\"\n", VOGL_FUNCTION_NAME, orig_filename.get_ptr());
1133 vogl_trace_file_reader *pTrace_reader = vogl_create_trace_file_reader(trace_type);
1136 vogl_error_printf("%s: Unable to determine file type of trace file \"%s\"\n", VOGL_FUNCTION_NAME, orig_filename.get_ptr());
1140 if (!pTrace_reader->open(actual_filename.get_ptr(), pLoose_file_path))
1142 vogl_error_printf("%s: Failed opening trace file \"%s\"\n", VOGL_FUNCTION_NAME, orig_filename.get_ptr());
1143 vogl_delete(pTrace_reader);
1147 return pTrace_reader;