1
0
mirror of https://github.com/wfjm/w11.git synced 2026-02-23 16:02:18 +00:00
Files
wfjm.w11/tools/src/librw11/Rw11VirtDiskOver.cpp

193 lines
6.0 KiB
C++

// $Id: Rw11VirtDiskOver.cpp 1049 2018-09-22 13:56:52Z mueller $
//
// Copyright 2017-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2017-06-05 907 1.0.5 more detailed stats
// 2017-06-03 903 1.0.4 Read(): BUGFIX: fix index error in blockwise read
// 2017-05-07 896 1.0.3 List(): BUGFIX: correct write count accumulation
// 2017-04-15 875 1.0.2 Open(): use overload with scheme handling
// 2017-04-07 868 1.0.1 Dump(): add detail arg
// 2017-03-10 859 1.0 Initial version
// ---------------------------------------------------------------------------
/*!
\file
\brief Implemenation of Rw11VirtDiskOver.
*/
#include "librtools/RosFill.hpp"
#include "librtools/RosPrintf.hpp"
#include "Rw11VirtDiskOver.hpp"
using namespace std;
/*!
\class Retro::Rw11VirtDiskOver
\brief FIXME_docs
*/
// all method definitions in namespace Retro
namespace Retro {
//------------------------------------------+-----------------------------------
//! Default constructor
Rw11VirtDiskOver::Rw11VirtDiskOver(Rw11Unit* punit)
: Rw11VirtDiskFile(punit),
fBlkMap()
{
fStats.Define(kStatNVDORead, "NVDORead", "over: Read() calls");
fStats.Define(kStatNVDOReadBlkFF, "NVDOReadBlkFF",
"over: blocks read file full");
fStats.Define(kStatNVDOReadBlkFP, "NVDOReadBlkFP",
"over: blocks read file part");
fStats.Define(kStatNVDOReadBlkO, "NVDOReadBlkO",
"over: blocks read from over");
fStats.Define(kStatNVDOWrite, "NVDOWrite", "over: Write() calls");
fStats.Define(kStatNVDOWriteBlk, "NVDOWriteBlk", "over: blocks written");
fStats.Define(kStatNVDOFlush, "NVDOFlush", "over: Flush() calls");
}
//------------------------------------------+-----------------------------------
//! Destructor
Rw11VirtDiskOver::~Rw11VirtDiskOver()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool Rw11VirtDiskOver::WProt() const
{
return false; // from unit always writable !!
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool Rw11VirtDiskOver::Open(const std::string& url, RerrMsg& emsg)
{
// FIXME_code: do we need to handle wpro ?
return Rw11VirtDiskFile::Open(url, "over", emsg);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool Rw11VirtDiskOver::Read(size_t lba, size_t nblk, uint8_t* data,
RerrMsg& emsg)
{
fStats.Inc(kStatNVDORead);
auto it = fBlkMap.lower_bound(lba);
if (it == fBlkMap.end() || it->first >= lba+nblk) { // no match
fStats.Inc(kStatNVDOReadBlkFF, double(nblk));
return Rw11VirtDiskFile::Read(lba, nblk, data, emsg); // one swoop from disk
} else { // match
for (size_t i=0; i<nblk; i++) { // get it blockwise
auto it = fBlkMap.find(lba+i);
if (it == fBlkMap.end()) {
fStats.Inc(kStatNVDOReadBlkFP);
bool rc = Rw11VirtDiskFile::Read(lba+i, 1, data+i*fBlkSize, emsg);
if (!rc) return rc;
} else {
fStats.Inc(kStatNVDOReadBlkO);
(it->second).Read(data+i*fBlkSize);
}
}
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool Rw11VirtDiskOver::Write(size_t lba, size_t nblk, const uint8_t* data,
RerrMsg& /*emsg*/)
{
fStats.Inc(kStatNVDOWrite);
fStats.Inc(kStatNVDOWriteBlk, double(nblk));
for (size_t i=0; i<nblk; i++) {
auto it = fBlkMap.find(lba+i);
if (it == fBlkMap.end()) {
auto rc = fBlkMap.emplace(lba+i, Rw11VirtDiskBuffer(fBlkSize));
it = rc.first;
}
(it->second).Write(data+i*fBlkSize);
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool Rw11VirtDiskOver::Flush(RerrMsg& emsg)
{
if (fWProt) {
emsg.Init("Rw11VirtDiskOver::Flush()", "file write protected");
return false;
}
fStats.Inc(kStatNVDOFlush);
for (auto& kv: fBlkMap) {
bool rc = Rw11VirtDiskFile::Write(kv.first, 1, kv.second.Data(), emsg);
if (!rc) return rc;
}
fBlkMap.clear();
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void Rw11VirtDiskOver::List(std::ostream& os) const
{
if (fBlkMap.empty()) return;
uint32_t lbabeg = fBlkMap.begin()->first; // first lba
uint32_t nwrite = 0;
for (auto it=fBlkMap.begin(); it!=fBlkMap.end(); ) {
nwrite += (it->second).NWrite();
auto itnext = next(it);
if (itnext == fBlkMap.end() || itnext->first != (it->first)+1) {
os << RosPrintf(lbabeg,"d",8)
<< " .. " << RosPrintf(it->first,"d",8)
<< " : nb=" << RosPrintf(it->first-lbabeg+1,"d",8)
<< " nw=" << RosPrintf(nwrite,"d",8) << endl;
if (itnext != fBlkMap.end()) lbabeg = itnext->first;
nwrite = 0;
}
it = itnext;
}
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void Rw11VirtDiskOver::Dump(std::ostream& os, int ind, const char* text,
int detail) const
{
RosFill bl(ind);
os << bl << (text?text:"--") << "Rw11VirtDiskOver @ " << this << endl;
os << bl << " fBlkMap.size: " << fBlkMap.size() << endl;
Rw11VirtDiskFile::Dump(os, ind, " ^", detail);
return;
}
} // end namespace Retro