Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00024
00025 #include "HardwareCanSourceCanfile.h"
00026
00027 #include <icl_core_config/Config.h>
00028 #include <icl_sourcesink/SimpleURI.h>
00029 #include <icl_sourcesink/Position.h>
00030
00031 #include "icl_hardware_can/Logging.h"
00032
00033 namespace icl_hardware {
00034 namespace can {
00035
00036 HardwareCanSourceCanfile::HardwareCanSourceCanfile(const std::string& uri,
00037 const std::string& name)
00038 : HardwareCanSource(uri, name,
00039 icl_sourcesink::PositionResolverBase::Ptr(
00040 new icl_sourcesink::KeyframePositionResolver(
00041 icl_sourcesink::FileResolutionHelper::Ptr(
00042 new CanFileResolutionHelper(icl_sourcesink::SimpleURI(uri).path())),
00043 1000))),
00044 m_buffer(),
00045 m_resolver_x(
00046 boost::dynamic_pointer_cast<icl_sourcesink::KeyframePositionResolver>(
00047 m_resolver)),
00048 m_resolution_helper(
00049 dynamic_cast<CanFileResolutionHelper *>(
00050 m_resolver_x->resolutionHelper()->clone())),
00051 m_sequence_number(0)
00052 {
00053 prepareFile();
00054 }
00055
00056 void HardwareCanSourceCanfile::prepareFile()
00057 {
00058 if (!m_resolution_helper)
00059 {
00060 LOGGING_ERROR_C(CAN, HardwareCanSourceCanfile,
00061 "Failed to open URI '" << uri() << "'." << endl);
00062 m_is_good = false;
00063 return;
00064 }
00065
00066
00067 LOGGING_DEBUG_C(CAN, HardwareCanSourceCanfile,
00068 "Checking for resolver index cache." << endl);
00069 std::string resolver_index_filename =
00070 icl_sourcesink::SimpleURI(uri()).path()
00071 + icl_sourcesink::PositionResolverBase::INDEX_FILE_SUFFIX;
00072 LOGGING_DEBUG_C(CAN, HardwareCanSourceCanfile,
00073 "Checking for resolver index cache at '" << resolver_index_filename << "'..." << endl);
00074 if (m_resolver->load(resolver_index_filename))
00075 {
00076 LOGGING_INFO_C(CAN, HardwareCanSourceCanfile,
00077 "Successfully loaded resolver index cache from '" << resolver_index_filename << "'." << endl);
00078 }
00079 else
00080 {
00081
00082 LOGGING_DEBUG_C(CAN, HardwareCanSourceCanfile,
00083 "No resolver index cache found, building index." << endl);
00084 uint64_t filesize = m_resolution_helper->size();
00085 std::size_t count = 0;
00086 for (; m_resolution_helper->good(); m_resolution_helper->advance())
00087 {
00088 icl_sourcesink::Position pos = m_resolution_helper->current();
00089 uint64_t filepos = m_resolution_helper->tellg();
00090 m_resolver_x->addEntry(pos.timestamp, pos.dsin, filepos);
00091 if (++count % 1000 == 0)
00092 {
00093 std::cerr << "Building resolver index: "
00094 << int(double(filepos)*100.0/double(filesize)) << "% \r"
00095 << std::flush;
00096 }
00097 }
00098 std::cerr << "Resolver index completed. " << std::endl;
00099
00100
00101 LOGGING_DEBUG_C(CAN, HardwareCanSourceCanfile,
00102 "Storing resolver index cache at '" << resolver_index_filename << "'." << endl);
00103 if (!m_resolver->save(resolver_index_filename))
00104 {
00105 LOGGING_WARNING_C(CAN, HardwareCanSourceCanfile,
00106 "Failed to store resolver index cache at '" << resolver_index_filename << "'." << endl);
00107 }
00108 }
00109
00110
00111 m_resolver->makeFragmentable();
00112 m_is_good = seek(icl_sourcesink::Index(0));
00113
00114
00115 LOGGING_DEBUG_C(CAN, HardwareCanSourceCanfile,
00116 "Resolver index complete, total number of elements: " << m_resolver->registerSize() << endl);
00117 }
00118
00119 bool HardwareCanSourceCanfile::seekImpl(const icl_sourcesink::InternalIndex internal_index)
00120 {
00121
00122 icl_sourcesink::Position pos(m_resolver_x->mapIndex<icl_sourcesink::Index>(internal_index));
00123 boost::optional<uint64_t> seek_pos = m_resolver_x->resolveExtra(pos, icl_sourcesink::RT_EXACT);
00124 if (seek_pos)
00125 {
00126 if (!m_resolution_helper->seekg(*seek_pos))
00127 {
00128 LOGGING_ERROR_C(CAN, HardwareCanSourceCanfile,
00129 "Failed to seek to position " << seek_pos
00130 << " even though the resolver had a valid entry for that position!" << endl);
00131 m_buffer.reset();
00132 m_is_good = false;
00133 return false;
00134 }
00135 m_buffer = m_resolution_helper->currentMessage();
00136 m_buffer->header().sequence_number = m_sequence_number++;
00137 return true;
00138 }
00139 else
00140 {
00141 LOGGING_WARNING_C(CAN, HardwareCanSourceCanfile,
00142 "Failed to resolve internal index " << internal_index.value
00143 << ", probably end of file" << endl);
00144 m_buffer.reset();
00145 return false;
00146 }
00147 }
00148
00149 bool HardwareCanSourceCanfile::advance()
00150 {
00151 if (m_resolver->advance())
00152 {
00153 if (!m_resolution_helper->advance())
00154 {
00155 LOGGING_ERROR_C(CAN, HardwareCanSourceCanfile,
00156 "Resolution helper failed to advance. This should not happen!" << endl);
00157 return false;
00158 }
00159 else
00160 {
00161 m_buffer = m_resolution_helper->currentMessage();
00162 m_buffer->header().sequence_number = m_sequence_number++;
00163 return true;
00164 }
00165 }
00166 else
00167 {
00168 LOGGING_WARNING_C(CAN, HardwareCanSourceCanfile,
00169 "Failed to advance, probably end of file" << endl);
00170 m_buffer.reset();
00171 m_is_good = false;
00172 return false;
00173 }
00174 }
00175
00176 }
00177 }