7#ifndef __qdp_map_obj_disk_h__
8#define __qdp_map_obj_disk_h__
12#include <unordered_map>
24 std::string
getMetaData(
const std::string& filename);
27 bool checkForNewFile(
const std::string& filename, std::ios_base::openmode mode);
35 template<
typename K,
typename V>
52 void open(
const std::string& file, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
69 int insert(
const K& key,
const V& val);
77 int get(
const K& key, V& val)
const;
91 bool exist(
const K& key)
const;
96 unsigned int size()
const {
return static_cast<unsigned long>(src_map.size());}
103 void keys(std::vector<K>& keys_)
const;
133 typedef std::array<uint64_t, 2> priv_pos_type_t;
136 typedef std::unordered_map<std::string, priv_pos_type_t> MapType_t;
139 enum State {INIT, UNCHANGED, MODIFIED};
151 mutable MapType_t src_map;
154 std::string filename;
157 std::string user_data;
163 priv_pos_type_t convertToPrivate(
const pos_type& input)
const;
166 pos_type convertFromPrivate(
const priv_pos_type_t& input)
const;
169 void openWrite(
const std::string& file, std::ios_base::openmode mode);
172 void openRead(
const std::string& file, std::ios_base::openmode mode);
175 void writeSkipHeader(
void);
178 priv_pos_type_t readCheckHeader(
void);
181 void writeMapBinary(
void);
184 void readMapBinary(
const priv_pos_type_t& md_start);
187 void closeWrite(
void);
190 void errorState(
const std::string err)
const {
200 template<
typename K,
typename V>
209 template<
typename K,
typename V>
210 typename MapObjectDisk<K,V>::priv_pos_type_t
211 MapObjectDisk<K,V>::convertToPrivate(
const pos_type& input)
const
213 const pos_type max_uint64 = pos_type(std::numeric_limits<uint64_t>::max()) + pos_type(1u);
214 uint64_t less = uint64_t(input % max_uint64);
215 uint64_t more = input / max_uint64;
217 return (
QDPUtil::big_endian() ? priv_pos_type_t{more, less} : priv_pos_type_t{less, more});
221 template<
typename K,
typename V>
223 MapObjectDisk<K,V>::convertFromPrivate(
const priv_pos_type_t& input)
const
225 const pos_type max_uint64 = pos_type(std::numeric_limits<uint64_t>::max()) + pos_type(1u);
228 return pos_type(input[0]) + pos_type(input[1]) * max_uint64;
230 return pos_type(input[1]) + pos_type(input[0]) * max_uint64;
235 template<
typename K,
typename V>
241 openWrite(file, mode);
245 openRead(file, mode);
251 template<
typename K,
typename V>
253 MapObjectDisk<K,V>::openWrite(
const std::string& file, std::ios_base::openmode mode)
260 QDPIO::cout <<
"MapObjectDisk: opening file " << filename
261 <<
" for writing" << std::endl;
263 streamer.open(filename, mode);
266 QDPIO::cout <<
"sizeof(unsigned char) = " <<
sizeof(
unsigned char) << std::endl;
267 QDPIO::cout <<
"sizeof(int) = " <<
sizeof(int) << std::endl;
268 QDPIO::cout <<
"sizeof(pos_type) = " <<
sizeof(pos_type) << std::endl;
269 QDPIO::cout <<
"sizeof(priv_pos_type_t) = " <<
sizeof(priv_pos_type_t) << std::endl;
281 QDPIO::cout <<
"Wrote magic. Current Position: " << streamer.currentPosition() << std::endl;
287 QDPIO::cout <<
"Wrote Version. Current Position is: " << streamer.currentPosition() << std::endl;
291 QDPIO::cout <<
"Writing User Data string=" << user_data << std::endl;
296 QDPIO::cout <<
"Wrote User Data string. Current Position is: " << streamer.currentPosition() << std::endl;
299 priv_pos_type_t dummypos = convertToPrivate(streamer.currentPosition());
302 int user_len = user_data.length();
306 pos_type cur_pos = streamer.currentPosition();
309 +user_len+
sizeof(
int)
312 QDPIO::cout <<
"cur pos=" << (size_t)(cur_pos) <<
" expected " << (size_t)(exp_pos) << std::endl;
314 if ( cur_pos != exp_pos ) {
315 QDPIO::cout <<
"ERROR: Sanity Check 1 failed." << std::endl;
316 QDPIO::cout <<
"cur pos=" << (size_t)(cur_pos) <<
" expected " << (size_t)(exp_pos) << std::endl;
322 streamer.writeArray((
char *)&dummypos,
sizeof(priv_pos_type_t), 1);
325 QDPIO::cout <<
"Wrote dummy link: Current Position " << streamer.currentPosition() << std::endl;
326 int user_len = user_data.length();
330 pos_type cur_pos = streamer.currentPosition();
333 +user_len+
sizeof(
int)
335 +
sizeof(priv_pos_type_t);
337 if ( cur_pos != exp_pos ) {
338 QDPIO::cout <<
"Cur pos = " << (size_t)(cur_pos) << std::endl;
339 QDPIO::cout <<
"Expected: " << (size_t)(exp_pos) << std::endl;
340 QDPIO::cout <<
"ERROR: Sanity Check 2 failed." << std::endl;
343 QDPIO::cout <<
"Finished sanity Check 2" << std::endl;
352 errorState(
"MapOjectDisk: openWrite called from invalid state");
362 template<
typename K,
typename V>
364 MapObjectDisk<K,V>::openRead(
const std::string& file, std::ios_base::openmode mode)
371 QDPIO::cout <<
"MapObjectDisk: opening file " << filename
372 <<
" for reading" << std::endl;
375 streamer.open(filename, mode);
377 QDPIO::cout <<
"MapObjectDisk: reading and checking header" << std::endl;
379 priv_pos_type_t md_start = readCheckHeader();
382 QDPIO::cout <<
"MapObjectDisk: reading key/fileposition data" << std::endl;
385 readMapBinary(md_start);
392 errorState(
"MapObjectDisk: openRead() called from invalid state");
402 template<
typename K,
typename V>
408 if( streamer.is_open() ) {
414 if( streamer.is_open() ) {
421 errorState(
"close: destructor called from invalid state");
430 template<
typename K,
typename V>
438 template<
typename K,
typename V>
458 template<
typename K,
typename V>
462 if( streamer.is_open() )
464 typename MapType_t::const_iterator iter;
465 for(iter = src_map.begin();
466 iter != src_map.end();
472 keys_.push_back(key);
481 template<
typename K,
typename V>
488 user_data = _user_data;
497 errorState(
"MapObjectDisk::insertUserdata() called from invalid state");
511 template<
typename K,
typename V>
526 _user_data = user_data;
530 errorState(
"MapObjectDisk::getUserdata called from unknown state");
541 template<
typename K,
typename V>
553 typename MapType_t::const_iterator key_ptr = src_map.find(bin.
str());
555 if (key_ptr != src_map.end()) {
557 pos_type wpos = convertFromPrivate(key_ptr->second);
559 QDPIO::cout <<
"Found key to update. Position is " << wpos << std::endl;
565 QDPIO::cout <<
"Sought write position. Current Position: " << streamer.currentPosition() << std::endl;
567 streamer.resetChecksum();
568 write(streamer, val);
571 QDPIO::cout <<
"Wrote value to disk. Current Position: " << streamer.currentPosition() << std::endl;
573 write(streamer, streamer.getChecksum());
577 QDPIO::cout <<
"Wrote checksum " << streamer.getChecksum() <<
" to disk. Current Position: " << streamer.currentPosition() << std::endl;
587 pos_type pos = streamer.currentPosition();
590 src_map.insert(std::make_pair(bin.
str(), convertToPrivate(pos)));
592 streamer.resetChecksum();
599 write(streamer, val);
604 pos_type end_pos = streamer.currentPosition();
605 double MiBWritten = (double)(end_pos - pos)/(double)(1024*1024);
608 QDPIO::cout <<
" wrote: " << MiBWritten <<
" MiB. Time: " << time <<
" sec. Write Bandwidth: " << MiBWritten/time<<std::endl;
612 QDPIO::cout <<
"Wrote value to disk. Current Position: " << streamer.currentPosition() << std::endl;
615 write(streamer, streamer.getChecksum());
619 QDPIO::cout <<
"Wrote checksum " << streamer.getChecksum() <<
" to disk. Current Position: " << streamer.currentPosition() << std::endl;
640 template<
typename K,
typename V>
651 typename MapType_t::const_iterator key_ptr = src_map.find(bin.
str());
653 if (key_ptr != src_map.end())
656 pos_type pos = convertFromPrivate(key_ptr->second);
668 streamer.resetChecksum();
680 pos_type end_pos = streamer.currentPosition();
684 double MiBRead = (double)(end_pos - start_pos)/(double)(1024*1024);
686 <<
" sec. read time: " << read_time
687 <<
" " << MiBRead <<
" MiB, " << MiBRead/read_time <<
" MiB/sec" << std::endl;
692 QDPIO::cout <<
"Read record. Current position: " << streamer.currentPosition() << std::endl;
697 read(streamer, read_checksum);
700 QDPIO::cout <<
" Record checksum: " << read_checksum <<
" Current Position: " << streamer.currentPosition() << std::endl;
703 if( read_checksum != calc_checksum ) {
704 QDPIO::cout <<
"Mismatched Checksums: Expected: " << calc_checksum <<
" but read " << read_checksum << std::endl;
731 template<
typename K,
typename V>
737 return (src_map.find(bin.
str()) == src_map.end()) ? false :
true;
746 template<
typename K,
typename V>
748 MapObjectDisk<K,V>::writeSkipHeader(
void)
752 if ( streamer.is_open() )
754 int user_len = user_data.length();
758 + user_len +
sizeof(
int)
762 QDPIO::cerr <<
"Attempting writeSkipHeader, not in write mode" <<std::endl;
768 errorState(
"MapObjectDisk: writeSkipHeader() called not in MODIFIED state");
774 template<
typename K,
typename V>
775 typename MapObjectDisk<K,V>::priv_pos_type_t
776 MapObjectDisk<K,V>::readCheckHeader(
void)
778 priv_pos_type_t md_position{0, 0};
780 if( streamer.is_open() )
788 std::string read_magic;
789 streamer.readDesc(read_magic);
794 <<
" but read: " << read_magic << std::endl;
799 QDPIO::cout <<
"Read File Magic. Current Position: " << streamer.currentPosition() << std::endl;
803 read(streamer, read_version);
806 QDPIO::cout <<
"Read File Verion. Current Position: " << streamer.currentPosition() << std::endl;
810 QDPIO::cout <<
"MapObjectDisk: file has version: " << read_version << std::endl;
814 QDPIO::cout <<
"User data. String=" << user_data <<
". Current Position: " << streamer.currentPosition() << std::endl;
818 streamer.readArray((
char *)&md_position,
sizeof(priv_pos_type_t), 1);
821 QDPIO::cout <<
"Read MD Location. Current position: " << streamer.currentPosition() << std::endl;
825 QDPIO::cout <<
"Metadata starts at position: " << convertFromPrivate(md_position) << std::endl;
830 QDPIO::cerr <<
"readCheckHeader needs reader mode to be opened. It is not" << std::endl;
839 template<
typename K,
typename V>
841 MapObjectDisk<K,V>::writeMapBinary(
void)
843 unsigned int map_size = src_map.size();
845 streamer.resetChecksum();
846 write(streamer, map_size);
848 QDPIO::cout <<
"Wrote map size: " << map_size <<
" entries. Current position : " << streamer.currentPosition() << std::endl;
851 typename MapType_t::const_iterator iter;
852 for(iter = src_map.begin();
853 iter != src_map.end();
856 priv_pos_type_t pos=iter->second;
859 streamer.writeArray((
char *)&pos,
sizeof(priv_pos_type_t),1);
862 QDPIO::cout <<
"Wrote Key/Position pair: Current Position: " << streamer.currentPosition() << std::endl;
865 write(streamer, streamer.getChecksum());
866 QDPIO::cout <<
"Wrote Checksum On Map: " << streamer.getChecksum() << std::endl;
873 template<
typename K,
typename V>
875 MapObjectDisk<K,V>::readMapBinary(
const priv_pos_type_t& md_start)
877 streamer.seek(convertFromPrivate(md_start));
878 streamer.resetChecksum();
881 QDPIO::cout <<
"Sought start of metadata. Current position: " << streamer.currentPosition() << std::endl;
884 unsigned int num_records;
885 read(streamer, num_records);
888 QDPIO::cout <<
"Read num of entries: " << num_records <<
" records. Current Position: " << streamer.currentPosition() << std::endl;
891 for(
unsigned int i=0; i < num_records; i++)
893 priv_pos_type_t rpos;
897 streamer.readArray((
char *)&rpos,
sizeof(priv_pos_type_t),1);
900 QDPIO::cout <<
"Read Key/Position pair. Current position: " << streamer.currentPosition() << std::endl;
903 src_map.insert(std::make_pair(key_str,rpos));
907 read(streamer, read_checksum);
910 QDPIO::cout <<
"Read Map checksum: " << read_checksum <<
" Current Position: " << streamer.currentPosition();
912 if( read_checksum != calc_checksum ) {
913 QDPIO::cout <<
"Mismatched Checksums: Expected: " << calc_checksum <<
" but read " << read_checksum << std::endl;
929 template<
typename K,
typename V>
931 MapObjectDisk<K,V>::closeWrite(
void)
937 QDPIO::cout <<
"Beginning closeWrite: current position: " << streamer.currentPosition() << std::endl;
944 priv_pos_type_t metadata_start = convertToPrivate(streamer.currentPosition());
947 QDPIO::cout <<
"CloseWrite: Metadata starts at position: " << convertFromPrivate(metadata_start) << std::endl;
956 QDPIO::cout <<
"Rewound file. Current Position: " << streamer.currentPosition() << std::endl;
960 QDPIO::cout <<
"Skipped Header. Current Position: " << streamer.currentPosition() << std::endl;
963 streamer.writeArray((
const char *)&metadata_start,
sizeof(priv_pos_type_t),1);
966 QDPIO::cout <<
"Wrote link to metadata. Current Position: " << streamer.currentPosition() << std::endl;
973 QDPIO::cout <<
"MapObjectDisk: Closed file " << filename<<
" for write access" << std::endl;
977 errorState(
"MapObjectDisk: closeWrite() called in an invalid state");
Binary buffer input class.
Binary buffer output class.
std::string str() const
Return entire buffer as a string.
Binary file input/output class.
~MapObjectDisk()
Finalizes object.
std::iostream::pos_type pos_type
MapObjectDisk()
Empty constructor.
unsigned int size() const
int insert(const K &key, const V &val)
std::iostream::off_type off_type
void setDebug(int level)
Set debugging level.
int insertUserdata(const std::string &user_data)
void close()
Close the file.
int get(const K &key, V &val) const
bool exist(const K &key) const
void open(const std::string &file, std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)
Open a file.
int getDebug() const
Get debugging level.
bool fileExists(const std::string &file) const
Check if a DB file exists before opening.
void keys(std::vector< K > &keys_) const
Dump keys.
int getUserdata(std::string &user_data) const
void write(BinaryWriter &bin, const std::string &output)
void readDesc(BinaryReader &bin, std::string &input)
void writeDesc(BinaryWriter &bin, const std::string &output)
void read(BinaryReader &bin, std::string &input, size_t maxBytes)
void close(QDPFileReader &qsw)
Close a QDPFileReader.
double getTimeInSeconds()
Get time in seconds.
void reset()
Reset the timer.
void start()
Start the timer.
void stop()
Stop the timer.
bool big_endian()
Is the native byte order big endian?
bool checkForNewFile(const std::string &file, std::ios_base::openmode mode)
Check if this will be a new file.
std::string getFileMagic()
Get the file magic.
unsigned int file_version_t
std::string getMetaData(const std::string &filename)
Get the meta-data from a file.
StandardOutputStream cout
StandardOutputStream cerr
void broadcast(T &dest)
Broadcast from primary node to all other nodes.
Yet another random number generator.
void QDP_abort(int status)
Panic button.