bulk.h 6.55 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Copyright 2017-2020, Schlumberger
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include "../declspec.h"
#include "enum.h"

#include <memory>
#include <functional>
#include <array>
#include <vector>
#include <tuple>
#include <sstream>
Paal Kvamme's avatar
Paal Kvamme committed
26
#include <atomic>
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

/**
 * \file bulk.h
 * \brief Bulk data read/write.
 */

namespace Test { class TestBulk; }
namespace InternalZGY {
#if 0
}
#endif

class FileADT;
class ZgyInternalMeta;
class DataBuffer;
struct IJK;
struct LutInfoEx;

/**
 * Read or write bulk data. The meta data needs to have been read
 * already. The user-callable API will forward its read requests here.
48
49
50
51
52
53
54
55
 *
 * Thread safety:
 * \li most data members are only used for write.
 *     Those don't need to be thread safe.
 * \li this->_file points to a FileADT which is already thread safe
 *     where needed.
 * \li this->_metadata is problematic because it is too easy to
 *     accidentally invoke a method that changes data even if the
56
57
 *     file is open for read only. Mitigated by separate const
 *     and mutable pointers to metadata. See ZgyInternalBulk::ZgyInternalBulk.
58
59
60
61
62
63
64
65
66
67
 */
class OPENZGY_TEST_API ZgyInternalBulk
{
  friend class Test::TestBulk;
public:
  typedef std::function<bool(int, const std::string&)> LoggerFn;

private:
  class ErrorsWillCorruptFile;
  std::shared_ptr<FileADT>         _file;
68
69
70
  std::shared_ptr<const ZgyInternalMeta> _metadata;
  std::shared_ptr<ZgyInternalMeta> _metadata_rw;
  std::shared_ptr<ZgyInternalMeta> _get_metadata_rw();
71
72
  UpdateMode _update_mode;
  bool       _compressed_write; // If true: do not align bricks.
Paal Kvamme's avatar
Paal Kvamme committed
73
  std::atomic<bool> _is_bad;    // If true: instance not usable.
74
75
76
77
78
79
80
  double     _written_sample_min;
  double     _written_sample_max;
  LoggerFn   _loggerfn;

public:
  ZgyInternalBulk(
      const std::shared_ptr<FileADT>& file,
81
82
      const std::shared_ptr<const ZgyInternalMeta>& metadata,
      const std::shared_ptr<ZgyInternalMeta>& metadata_rw,
83
84
85
86
87
88
      bool compressed_write,
      const LoggerFn& logger = LoggerFn());

  std::pair<bool,double> readConstantValue(
      const std::array<std::int64_t,3>& start,
      const std::array<std::int64_t,3>& size,
89
      int32_t lod, bool as_float) const;
90
91
92
93

  void readToExistingBuffer(
      const std::shared_ptr<DataBuffer>& data,
      const std::array<std::int64_t,3>& start,
94
      int32_t lod, bool as_float) const;
95
96
97
98

  std::shared_ptr<DataBuffer> readToNewBuffer(
      const std::array<std::int64_t,3>& start,
      const std::array<std::int64_t,3>& size,
99
      int32_t lod, bool as_float, bool check_constant) const;
100
101
102
103
104
105
106
107
108

  void writeRegion(
      const std::shared_ptr<DataBuffer>& data,
      const std::array<std::int64_t,3>& start,
      int32_t lod, bool is_storage,
      const compressor_t& compressor);

public: // actually internal

Paal Kvamme's avatar
Paal Kvamme committed
109
110
  bool errorflag() const        { return _is_bad.load(); }
  void set_errorflag(bool flag) { _is_bad.store(flag); }
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  LoggerFn set_logger(const LoggerFn& logger) {
    LoggerFn old = _loggerfn;
    _loggerfn = logger;
    return old;
  }
  std::array<double,2> valueRangeWritten() const {
    return std::array<double,2>{_written_sample_min, _written_sample_max};
  }

private:

  bool _logger(int priority, const std::string& ss = std::string()) const;

  bool _logger(int priority, const std::ios& ss) const;

  void _validateUserPosition(
      const std::array<std::int64_t,3>& start,
      const std::array<std::int64_t,3>& size,
129
      int32_t lod) const;
130
131

  std::shared_ptr<DataBuffer> _scaleDataToFloat(
132
      const std::shared_ptr<DataBuffer>& data) const;
133
134

  std::shared_ptr<DataBuffer> _scaleDataToStorage(
135
      const std::shared_ptr<DataBuffer>& data) const;
136
137
138
139
140
141
142
143

  static double _decodeConstant(std::uint32_t in, RawDataType dtype);

  static std::int32_t _encodeConstant(double in, RawDataType dtype);

  std::vector<LutInfoEx> _partsNeeded(
      const std::array<std::int64_t,3>& start,
      const std::array<std::int64_t,3>& size,
144
      int32_t lod) const;
145
146
147
148
149
150

  void _deliverOneBrick(
      const std::shared_ptr<DataBuffer>& result,
      const std::array<std::int64_t,3>& start,
      const std::array<std::int64_t,3>& startpos,
      const void *raw, std::int64_t rawsize,
151
      BrickStatus brickstatus, bool as_float) const;
152
153
154
155
156
157

  // --- WRITE SUPPORT ---

  std::array<std::int64_t,3> _usedPartOfBrick(
      const std::array<std::int64_t,3>& size,
      const std::array<std::int64_t,3>& brickpos,
158
      std::int32_t lod) const;
159
160
161
162

  bool _isUsedPartOfBrickAllConstant(
      const std::shared_ptr<DataBuffer>& data,
      const std::array<std::int64_t,3>& brickpos,
163
      int32_t lod) const;
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201

  static void _setPaddingToEdge(
      const std::shared_ptr<DataBuffer>& data,
      const std::array<std::int64_t,3>& used,
      int modulo, int dim);

  static void _setPaddingToConst(
      const std::shared_ptr<DataBuffer>& data,
      const std::array<std::int64_t,3>& used,
      double missingvalue, int dim);

  static void _setPaddingSamples(
      const std::shared_ptr<DataBuffer>& data,
      const std::array<std::int64_t,3>& used,
      double missingvalue, const compressor_t& compressor);

  void _writeWithRetry(
      rawdata_t rawdata,
      BrickStatus brickstatus,
      std::int64_t fileoffset,
      const std::array<std::int64_t,3>& brickpos,
      std::int32_t lod);

  void _writeOneNormalBrick(
      const std::shared_ptr<DataBuffer>& data,
      std::int64_t fileoffset,
      const std::array<std::int64_t,3>& brickpos,
      std::int32_t lod,
      const compressor_t& compressor);

  void _writeOneConstantBrick(
      const std::shared_ptr<DataBuffer>& data,
      const std::array<std::int64_t,3>& brickpos,
      std::int32_t lod);

  bool _mustLeakOldBrick(
      const std::shared_ptr<DataBuffer>& data,
      const compressor_t& compressor,
202
      BrickStatus brickstatus) const;
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217

  void _writeOneBrick(
      const std::shared_ptr<DataBuffer>& data,
      const std::array<std::int64_t,3>& brickpos,
      std::int32_t lod,
      const compressor_t& compressor);

  void _writeAlignedRegion(
      const std::shared_ptr<DataBuffer>& data,
      const std::array<std::int64_t,3>& start,
      std::int32_t lod,
      const compressor_t& compressor);
};

} // namespace