Commit c337b827 authored by Paal Kvamme's avatar Paal Kvamme
Browse files

Use a single logger for each reader and writer. Except cloud related messages...

Use a single logger for each reader and writer. Except cloud related messages which still use a global logger.
parent f870db4b
......@@ -29,6 +29,9 @@
#include "impl/genlod.h"
#include "impl/compression.h"
#include "impl/guid.h"
#include "impl/logger.h"
#include <tuple>
#ifdef _MSC_VER
#pragma warning(push)
......@@ -68,6 +71,41 @@ namespace {
}
}
namespace {
/**
* Attach a logger. Used by the ZgyReader and ZgyWriter constructors.
*
* If the iocontext belongs to seismic store and if it has a logger
* set then use that logger also for the higher level ZgyInteralMeta
* and ZgyInternalBulk instances. And the other was around: If a
* logger is created here, and a seismic store iocontext exists
* without a logger, then use the iocontext to push the logger down
* to the low level code.
*
* TODO-Medium: Bad code smell. The iocontext is supposed to be
* populated by the application code only, and used by the file
* layer only.
*/
std::tuple<std::function<bool(int, const std::string&)>, std::shared_ptr<OpenZGY::IOContext>> setupLogging(const OpenZGY::IOContext *iocontext)
{
std::function<bool(int, const std::string&)> logger;
std::shared_ptr<OpenZGY::IOContext> ctxt = iocontext ? iocontext->clone() : nullptr;
auto iocontext_sd = dynamic_cast<OpenZGY::SeismicStoreIOContext*>(ctxt.get());
if (iocontext_sd && iocontext_sd->getLogger()) {
logger = iocontext_sd->getLogger();
}
else {
logger = InternalZGY::LoggerBase::standardCallback
(InternalZGY::LoggerBase::getVerboseFromEnv("OPENZGY_VERBOSE"),
"openzgy-api: ", "");
// logger = std::ref(logger);
if (iocontext_sd)
iocontext_sd->logger(logger);
}
return std::make_tuple(logger, ctxt);
}
}
namespace OpenZGY {
class IOContext;
}
......@@ -537,24 +575,29 @@ public:
*/
ZgyReader(const std::string& filename, const IOContext* iocontext)
{
std::function<bool(int, const std::string&)> logger;
std::shared_ptr<IOContext> ctxt;
std::tie(logger, ctxt) = setupLogging(iocontext);
logger(1, "open for read: \"" + filename + "\"");
// Note: Currently the Python version of this constructor has an
// additional "update" parameter which, if set, causes the underlying
// file to be opened in read/write mode. This is a kludge to facilitate
// a stand alone lowres generator. Which was only ever used for testing.
_fd = InternalZGY::FileFactory::instance().create(
filename, InternalZGY::OpenMode::ReadOnly, iocontext);
filename, InternalZGY::OpenMode::ReadOnly, ctxt.get());
// Set the protected metadata information in the ZgyMeta base class.
// ZgyInternalMeta does not retain the file descriptor. The file is
// only used inside the constructor to populate the headers.
_meta.reset(new InternalZGY::ZgyInternalMeta(this->_fd));
_meta.reset(new InternalZGY::ZgyInternalMeta(this->_fd, logger));
// At the implementation level the bulk- and meta access are separate,
// and the bulk accessor needs some of the meta information to work.
// The accessor will have its own metadata pointer which it holds on to.
// It also holds on to the file descriptor. Unlike the metadata reader
// it is obviously not possible to read everything up front.
_accessor.reset(new InternalZGY::ZgyInternalBulk(_fd, _meta, nullptr, false));
_accessor.reset(new InternalZGY::ZgyInternalBulk(_fd, _meta, nullptr, false, logger));
}
~ZgyReader()
......@@ -788,6 +831,11 @@ public:
, _compressor(args._compressor)
, _lodcompressor(args._lodcompressor ? args._lodcompressor : args._compressor)
{
std::function<bool(int, const std::string&)> logger;
std::shared_ptr<IOContext> ctxt;
std::tie(logger, ctxt) = setupLogging(args._iocontext.get());
logger(1, "open for write: \"" + args._filename + "\"");
for (int ii=0; ii<3; ++ii) {
if (args._size[ii] < 1)
throw Errors::ZgyUserError("Survey size cannot be empty or negative.");
......@@ -805,16 +853,16 @@ public:
// we need to hold on to _fd ourselves and provide it when it is time
// to flush metadata to disk.
InternalZGY::ZgyInternalWriterArgs iargs = EnumMapper::mapWriterArgs(args);
_meta_rw.reset(new InternalZGY::ZgyInternalMeta(iargs, compress));
_meta_rw.reset(new InternalZGY::ZgyInternalMeta(iargs, compress, logger));
_meta = _meta_rw; // in base class
// The file creation was deferred until after the consistency checks.
_fd = InternalZGY::FileFactory::instance().create(
args._filename, InternalZGY::OpenMode::Truncate, args._iocontext.get());
args._filename, InternalZGY::OpenMode::Truncate, ctxt.get());
_meta_rw->flushMeta(_fd);
// Compress or not at this level only controls alignment etc.
// The actual compression functor is passed to each write.
_accessor_rw.reset(new InternalZGY::ZgyInternalBulk(_fd, _meta_rw, _meta_rw, compress));
_accessor_rw.reset(new InternalZGY::ZgyInternalBulk(_fd, _meta_rw, _meta_rw, compress, logger));
// A file that is recently created is dirty because even if nothing
// was written to it the low resolution bricks should be generated.
......@@ -841,17 +889,22 @@ public:
, _compressor(args._compressor)
, _lodcompressor(args._lodcompressor ? args._lodcompressor : args._compressor)
{
std::function<bool(int, const std::string&)> logger;
std::shared_ptr<IOContext> ctxt;
std::tie(logger, ctxt) = setupLogging(args._iocontext.get());
logger(1, "open for update: \"" + args._filename + "\"");
const bool compress = _compressor || _lodcompressor;
_fd = InternalZGY::FileFactory::instance().create(
args._filename, InternalZGY::OpenMode::ReadWrite, args._iocontext.get());
args._filename, InternalZGY::OpenMode::ReadWrite, ctxt.get());
// Set the protected metadata information in the ZgyMeta base class.
// The metadata ctor is very different on update. bulkdata is not.
// ZgyInternalMeta does not retain the file descriptor. The file is
// only used inside the constructor to populate the headers.
InternalZGY::ZgyInternalWriterArgs iargs = EnumMapper::mapWriterArgs(args);
_meta_rw.reset(new InternalZGY::ZgyInternalMeta(_fd, iargs, compress));
_meta_rw.reset(new InternalZGY::ZgyInternalMeta(_fd, iargs, compress, logger));
_meta = _meta_rw;
if (compress && _meta->ih().datatype() != InternalZGY::RawDataType::Float32)
......@@ -862,7 +915,7 @@ public:
// The accessor will have its own metadata pointer which it holds on to.
// It also holds on to the file descriptor. Unlike the metadata reader
// it is obviously not possible to read everything up front.
_accessor_rw.reset(new InternalZGY::ZgyInternalBulk(_fd, _meta_rw, _meta_rw, compress));
_accessor_rw.reset(new InternalZGY::ZgyInternalBulk(_fd, _meta_rw, _meta_rw, compress, logger));
// If low resolution data, statistics, or histogram are not
// available, mark as dirty because even if there has been no
......@@ -1660,8 +1713,13 @@ public:
*/
ZgyUtils(const std::string& prefix, const IOContext* iocontext)
{
std::function<bool(int, const std::string&)> logger;
std::shared_ptr<IOContext> ctxt;
std::tie(logger, ctxt) = setupLogging(iocontext);
logger(1, "open utility class");
_fd = InternalZGY::FileFactory::instance().create
(prefix, InternalZGY::OpenMode::Closed, iocontext);
(prefix, InternalZGY::OpenMode::Closed, ctxt.get());
// TODO-Low: Use some kind of factory here.
#ifdef HAVE_SD
_fd_sd = std::dynamic_pointer_cast<InternalZGY::FileUtilsSeismicStore>(_fd);
......
......@@ -93,6 +93,7 @@ class OPENZGY_API SeismicStoreIOContext : public IOContext
public:
typedef std::function<std::string()> tokencb_t;
typedef std::function<void(const std::string&, std::int64_t, std::int64_t, std::int64_t, const std::vector<std::int64_t>&)> debugtrace_t;
typedef std::function<bool(int, const std::string&)> logger_t;
virtual std::string toString() const override;
virtual std::shared_ptr<IOContext> clone() const override;
SeismicStoreIOContext();
......@@ -115,6 +116,7 @@ private:
std::string _sdtoken_cbtype;
tokencb_t _sdtokencb;
debugtrace_t _debug_trace;
logger_t _logger;
private: // really private. Keep off.
std::int64_t _real_segsize;
......@@ -451,6 +453,35 @@ public:
this->_debug_trace = value;
return *this;
}
/**
* For debugging. This callback will be invoked whenever
* something needs to be written to the console or to a file.
* See LoggerBase::standardCallback() for an example.
*
* The default is to use standardCallback() configured
* according to OPENZGY_VERBOSE, OPENZGY_VERBOSE_LOGFILE,
* and OPENZGY_VERBOSE_DETAILS.
*
* Note that it might be a good idea to use a std::ref here,
* that could avoid some surprises.
*/
SeismicStoreIOContext& logger(const logger_t& logger)
{
this->_logger = logger;
return *this;
}
/**
* Internal access to read out the current logger.
* The logger is applied to higher level parts
* of the system and needs this slight breakage
* of encapsulation.
*/
logger_t getLogger() const
{
return this->_logger;
}
};
/** \endcond */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment