FETPAPI 0.3.0.0
This project provides C++ classes which facilitate the developement of ETP1.2 clients and servers.
Loading...
Searching...
No Matches
FesapiHdfProxy.h
1/*-----------------------------------------------------------------------
2Licensed to the Apache Software Foundation (ASF) under one
3or more contributor license agreements. See the NOTICE file
4distributed with this work for additional information
5regarding copyright ownership. The ASF licenses this file
6to you under the Apache License, Version 2.0 (the
7"License"; you may not use this file except in compliance
8with the License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing,
13software distributed under the License is distributed on an
14"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15KIND, either express or implied. See the License for the
16specific language governing permissions and limitations
17under the License.
18-----------------------------------------------------------------------*/
19#pragma once
20
21#include <fesapi/common/HdfProxyFactory.h>
22
23#include "../AbstractSession.h"
24#include "../ProtocolHandlers/GetFullDataArrayHandlers.h"
25
26#include <type_traits>
27
28namespace ETP_NS
29{
30 class FETPAPI_DLL_IMPORT_OR_EXPORT FesapiHdfProxy : public EML2_NS::AbstractHdfProxy
31 {
32 public:
33
37 FesapiHdfProxy(AbstractSession* session, COMMON_NS::DataObjectRepository * repo, const std::string & guid, const std::string & title, const std::string & packageDirAbsolutePath, const std::string & externalFilePath, COMMON_NS::DataObjectRepository::openingMode hdfPermissionAccess) :
38 EML2_NS::AbstractHdfProxy(packageDirAbsolutePath, externalFilePath, hdfPermissionAccess), session_(session), compressionLevel(0) {
39 xmlNs_ = repo->getDefaultEmlVersion() == COMMON_NS::DataObjectRepository::EnergisticsStandard::EML2_0 ? "eml20" : "eml23";
40 initGsoapProxy(repo, guid, title, 20);
41 }
42
46 FesapiHdfProxy(AbstractSession* session, gsoap_resqml2_0_1::_eml20__EpcExternalPartReference* fromGsoap) :
47 EML2_NS::AbstractHdfProxy(fromGsoap), session_(session), compressionLevel(0), xmlNs_("eml20") {}
48
52 FesapiHdfProxy(AbstractSession* session, const COMMON_NS::DataObjectReference& dor) :
53 EML2_NS::AbstractHdfProxy(dor), session_(session), compressionLevel(0) {
54 std::string ct = dor.getContentType();
55 if (ct.find("2.0") != std::string::npos) {
56 xmlNs_ = "eml20";
57 }
58 else if (ct.find("2.3") != std::string::npos) {
59 xmlNs_ = "eml23";
60 }
61 else {
62 throw std::invalid_argument("The HDF Proxy DataObjectReference does not look to be eml20 or eml23 neither : " + ct);
63 }
64 }
65
66
70 ~FesapiHdfProxy() = default;
71
72 AbstractSession* getSession() { return session_; }
73
77 void open() final {}
78
82 bool isOpened() const final { return session_ != nullptr && !session_->isWebSocketSessionClosed(); }
83
87 void close() final {}
88
89 /*
90 * Get the used (native) datatype in a dataset
91 */
92 COMMON_NS::AbstractObject::numericalDatatypeEnum getNumericalDatatype(const std::string & groupName) final;
93
98 int getHdfDatatypeClassInDataset(const std::string & datasetName) final;
99
112 void writeItemizedListOfList(const std::string & groupName,
113 const std::string & name,
114 COMMON_NS::AbstractObject::numericalDatatypeEnum cumulativeLengthDatatype,
115 const void * cumulativeLength,
116 uint64_t cumulativeLengthSize,
117 COMMON_NS::AbstractObject::numericalDatatypeEnum elementsDatatype,
118 const void * elements,
119 uint64_t elementsSize) final;
120
125 std::vector<uint32_t> getElementCountPerDimension(const std::string & datasetName) final;
126
131 void setCompressionLevel(unsigned int newCompressionLevel) final { if (newCompressionLevel > 9) compressionLevel = 9; else compressionLevel = newCompressionLevel; }
132
143 void writeArrayNd(const std::string & groupName,
144 const std::string & name,
145 COMMON_NS::AbstractObject::numericalDatatypeEnum datatype,
146 const void * values,
147 const uint64_t * numValuesInEachDimension,
148 unsigned int numDimensions) final;
149
160 const std::string& groupName,
161 const std::string& name,
162 COMMON_NS::AbstractObject::numericalDatatypeEnum datatype,
163 const uint64_t* numValuesInEachDimension,
164 unsigned int numDimensions) final;
165
177 const std::string& groupName,
178 const std::string& name,
179 COMMON_NS::AbstractObject::numericalDatatypeEnum datatype,
180 const void* values,
181 const uint64_t* numValuesInEachDimension,
182 const uint64_t* offsetValuesInEachDimension,
183 unsigned int numDimensions) final;
184
188 void writeGroupAttributes(const std::string&,
189 const std::vector<std::string>&,
190 const std::vector<std::string>&) final {
191 throw std::logic_error("Group attributes are not supported in ETP1.2");
192 }
193
197 void writeGroupAttribute(const std::string&,
198 const std::string&,
199 const std::vector<std::string>&) final {
200 throw std::logic_error("Group attributes are not supported in ETP1.2");
201 }
202
206 void writeGroupAttributes(const std::string&,
207 const std::vector<std::string>&,
208 const std::vector<double>&) {
209 throw std::logic_error("Group attributes are not supported in ETP1.2");
210 }
211
215 void writeGroupAttributes(const std::string&,
216 const std::vector<std::string>&,
217 const std::vector<int>&) final {
218 throw std::logic_error("Group attributes are not supported in ETP1.2");
219 }
220
224 void writeDatasetAttributes(const std::string&,
225 const std::vector<std::string>&,
226 const std::vector<std::string>&) final {
227 throw std::logic_error("Dataset attributes are not supported in ETP1.2");
228 }
229
233 void writeDatasetAttribute(const std::string&,
234 const std::string&,
235 const std::vector<std::string>&) final {
236 throw std::logic_error("Dataset attributes are not supported in ETP1.2");
237 }
238
242 void writeDatasetAttributes(const std::string&,
243 const std::vector<std::string>&,
244 const std::vector<double>&) final {
245 throw std::logic_error("Dataset attributes are not supported in ETP1.2");
246 }
247
251 void writeDatasetAttributes(const std::string&,
252 const std::vector<std::string>&,
253 const std::vector<int>&) final {
254 throw std::logic_error("Dataset attributes are not supported in ETP1.2");
255 }
256
257 std::string readStringAttribute(const std::string&,
258 const std::string&) const final {
259 throw std::logic_error("Attributes are not supported in ETP1.2");
260 }
261
262 std::vector<std::string> readStringArrayAttribute(const std::string&,
263 const std::string&) const final {
264 throw std::logic_error("Attributes are not supported in ETP1.2");
265 }
266
267 double readDoubleAttribute(const std::string&,
268 const std::string&) const final {
269 throw std::logic_error("Attributes are not supported in ETP1.2");
270 }
271
272 int64_t readInt64Attribute(const std::string&,
273 const std::string&) const final {
274 throw std::logic_error("Attributes are not supported in ETP1.2");
275 }
276
282 void readArrayNdOfDoubleValues(const std::string & datasetName, double* values) final { readArrayNdOfValues(datasetName, values); }
283
293 const std::string & datasetName,
294 double* values,
295 uint64_t const * numValuesInEachDimension,
296 uint64_t const * offsetInEachDimension,
297 unsigned int numDimensions) final;
298
310 const std::string & datasetName, double* values,
311 uint64_t const * blockCountPerDimension,
312 uint64_t const * offsetInEachDimension,
313 uint64_t const * strideInEachDimension,
314 uint64_t const * blockSizeInEachDimension,
315 unsigned int numDimensions) final;
316
317 void selectArrayNdOfValues(
318 const std::string & datasetName,
319 uint64_t const * blockCountPerDimension,
320 uint64_t const * offsetInEachDimension,
321 uint64_t const * strideInEachDimension,
322 uint64_t const * blockSizeInEachDimension,
323 unsigned int numDimensions,
324 bool newSelection,
325 hdf5_hid_t & dataset,
326 hdf5_hid_t & filespace) final;
327
336 hdf5_hid_t dataset,
337 hdf5_hid_t filespace,
338 void* values,
339 uint64_t slabSize) final;
340
346 void readArrayNdOfFloatValues(const std::string & datasetName, float* values) final { readArrayNdOfValues(datasetName, values); }
347
357 const std::string & datasetName,
358 float* values,
359 uint64_t const * numValuesInEachDimension,
360 uint64_t const * offsetInEachDimension,
361 unsigned int numDimensions) final;
362
368 void readArrayNdOfInt64Values(const std::string & datasetName, int64_t* values) final { readArrayNdOfValues(datasetName, values); }
369
379 const std::string & datasetName,
380 int64_t* values,
381 uint64_t const * numValuesInEachDimension,
382 uint64_t const * offsetInEachDimension,
383 unsigned int numDimensions) final;
384
390 void readArrayNdOfUInt64Values(const std::string & datasetName, uint64_t* values) final { readArrayNdOfValues(datasetName, values); }
391
397 void readArrayNdOfIntValues(const std::string & datasetName, int* values) final { readArrayNdOfValues(datasetName, values); }
398
408 const std::string & datasetName,
409 int* values,
410 uint64_t const * numValuesInEachDimension,
411 uint64_t const * offsetInEachDimension,
412 unsigned int numDimensions
413 ) final;
414
420 void readArrayNdOfUIntValues(const std::string & datasetName, unsigned int* values) final { readArrayNdOfValues(datasetName, values); }
421
428 void readArrayNdOfShortValues(const std::string & datasetName, short* values) final { readArrayNdOfValues(datasetName, values); }
429
435 void readArrayNdOfUShortValues(const std::string & datasetName, unsigned short* values) final { readArrayNdOfValues(datasetName, values); }
436
442 void readArrayNdOfInt8Values(const std::string & datasetName, int8_t* values) final { readArrayNdOfValues(datasetName, values); }
443
448 void readArrayNdOfUInt8Values(const std::string & datasetName, uint8_t* values) final { readArrayNdOfValues(datasetName, values); }
449
453 bool exist(const std::string & absolutePathInHdfFile) const final;
454
459 bool isCompressed(const std::string &) final { return false; }
460
466 std::vector<uint32_t> getElementCountPerChunkDimension(const std::string&) final { return {}; }
467
471 std::string getXmlNamespace() const { return xmlNs_; }
472
473 private:
474 AbstractSession* session_;
475 unsigned int compressionLevel;
476 std::string xmlNs_;
477 size_t maxArraySize_{ 12000000 }; // Bytes
478
479 Energistics::Etp::v12::Datatypes::DataArrayTypes::DataArrayIdentifier buildDataArrayIdentifier(const std::string & datasetName) const;
480 Energistics::Etp::v12::Protocol::DataArray::GetDataArrays buildGetDataArraysMessage(const std::string & datasetName) const;
481 Energistics::Etp::v12::Protocol::DataArray::GetDataArrayMetadata buildGetDataArrayMetadataMessage(const std::string & datasetName) const;
482
483 Energistics::Etp::v12::Datatypes::DataArrayTypes::DataArrayMetadata getDataArrayMetadata(const std::string & datasetName) const;
484
485 template<typename T> void readArrayNdOfValues(const std::string & datasetName, T* values)
486 {
487 // First get metadata about the data array
488 std::vector<uint64_t> dimensions;
489
490 const Energistics::Etp::v12::Datatypes::DataArrayTypes::DataArrayMetadata daMetadata = getDataArrayMetadata(datasetName);
491 size_t valueCount = 1;
492 for (int64_t dim : daMetadata.dimensions) {
493 valueCount *= dim;
494 }
495
496 size_t valueSize = 1;
497 switch (daMetadata.transportArrayType) {
498 case Energistics::Etp::v12::Datatypes::AnyArrayType::bytes:
499 case Energistics::Etp::v12::Datatypes::AnyArrayType::arrayOfBoolean: break;
500 case Energistics::Etp::v12::Datatypes::AnyArrayType::arrayOfInt: valueSize = 6; break; // 25% more because of zig zag encoding worst case scenario
501 case Energistics::Etp::v12::Datatypes::AnyArrayType::arrayOfFloat: valueSize = 4; break;
502 case Energistics::Etp::v12::Datatypes::AnyArrayType::arrayOfLong: valueSize = 10; break; // 25% more because of zig zag encoding worst case scenario
503 case Energistics::Etp::v12::Datatypes::AnyArrayType::arrayOfDouble: valueSize = 8; break;
504 default: throw std::logic_error("Array of strings are not implemented yet");
505 }
506 size_t wholeSize = valueCount * valueSize;
507
508 // maxAllowedDataArraySize is the maximum serialized size of the array (including avro extra longs for array blocks)
509 const size_t maxAllowedDataArraySize = session_->getMaxWebSocketMessagePayloadSize()
511 - (daMetadata.dimensions.size() * 2 + 1) * 8; // *2 because the array can contain a maximum of element count block, +1 for the length of the last block : https://avro.apache.org/docs/1.10.2/spec.html#binary_encode_complex
512
513 // Now get values of the data array
514 auto specializedHandler = std::make_shared<GetFullDataArrayHandlers<T>>(session_, values);
515 if (wholeSize + (valueCount + 1) * 8 <= maxAllowedDataArraySize) { // There can be valueCount array block and there is the length of the last array block
516 // Get all values at once
517 const int64_t msgId = session_->sendWithSpecificHandler(
518 buildGetDataArraysMessage(datasetName),
519 specializedHandler,
520 0, 0x02);
521
522 // Blocking loop
523 while (session_->isMessageStillProcessing(msgId)) {}
524 }
525 else {
526 // Get all values using several data subarrays allowing more granular streaming
527 std::vector<int64_t> counts(daMetadata.dimensions.size(), 1);
528
529 // Compute the dimensions of the subArrays to get
530 size_t subArrayValueCount = 1;
531 for (int64_t dimIndex = daMetadata.dimensions.size() - 1; dimIndex >= 0; --dimIndex) {
532 int64_t maxCountOnDim = daMetadata.preferredSubarrayDimensions.empty()
533 ? daMetadata.dimensions[dimIndex]
534 : daMetadata.preferredSubarrayDimensions[dimIndex];
535 subArrayValueCount *= maxCountOnDim;
536 int64_t allowedCountOnDim = maxCountOnDim;
537 while (subArrayValueCount * valueSize + (subArrayValueCount + 1) * 8 > maxAllowedDataArraySize) {
538 subArrayValueCount /= allowedCountOnDim;
539 allowedCountOnDim /= 2;
540 subArrayValueCount *= allowedCountOnDim;
541 }
542 counts[dimIndex] = allowedCountOnDim;
543 if (allowedCountOnDim != maxCountOnDim) {
544 break;
545 }
546 }
547
548 // Build the message
550 size_t subArrayIndex = 0;
551 std::vector<int64_t> starts(daMetadata.dimensions.size(), 0);
552 std::vector<int64_t> currentCounts = counts;
553 bool hasParsedAllArray = false;
554 while (!hasParsedAllArray) {
555 std::string subArrayIndexStr = std::to_string(subArrayIndex);
556 msg.dataSubarrays[subArrayIndexStr].uid = buildDataArrayIdentifier(datasetName);
557 msg.dataSubarrays[subArrayIndexStr].counts = currentCounts;
558 msg.dataSubarrays[subArrayIndexStr].starts = starts;
559
560 // next sub array to get
561 ++subArrayIndex;
562 hasParsedAllArray = true;
563 for (int64_t dimIndex = daMetadata.dimensions.size() - 1; dimIndex >= 0; --dimIndex) {
564 if (starts[dimIndex] + currentCounts[dimIndex] < daMetadata.dimensions[dimIndex]) {
565 starts[dimIndex] += currentCounts[dimIndex];
566 if (starts[dimIndex] + currentCounts[dimIndex] > daMetadata.dimensions[dimIndex]) {
567 currentCounts[dimIndex] = daMetadata.dimensions[dimIndex] - starts[dimIndex];
568 }
569
570 for (size_t dimIndex2 = dimIndex + 1; dimIndex2 < daMetadata.dimensions.size(); ++dimIndex2) {
571 starts[dimIndex2] = 0;
572 currentCounts[dimIndex2] = counts[dimIndex2];
573 }
574 hasParsedAllArray = false;
575 break;
576 }
577 }
578
579 specializedHandler->setDataSubarrays(subArrayIndexStr, msg.dataSubarrays[subArrayIndexStr]);
580 }
581
582 // Send message
583 const int64_t msgId = session_->sendWithSpecificHandler(
584 msg,
585 specializedHandler,
586 0, 0x02);
587
588 // Blocking loop
589 while (session_->isMessageStillProcessing(msgId)) {}
590 }
591 }
592 };
593
594 class FETPAPI_DLL_IMPORT_OR_EXPORT FesapiHdfProxyFactory : public COMMON_NS::HdfProxyFactory
595 {
596 public:
597 FesapiHdfProxyFactory(AbstractSession* session) : session_(session) {}
598
602 EML2_NS::AbstractHdfProxy* make(const COMMON_NS::DataObjectReference& dor) {
603 FesapiHdfProxy* result = new FesapiHdfProxy(session_, dor);
604 return result;
605 }
606
610 EML2_NS::AbstractHdfProxy* make(gsoap_resqml2_0_1::_eml20__EpcExternalPartReference* fromGsoap) {
611 FesapiHdfProxy* result = new FesapiHdfProxy(session_, fromGsoap);
612 return result;
613 }
614
615 EML2_NS::AbstractHdfProxy* make(COMMON_NS::DataObjectRepository * repo, const std::string & guid, const std::string & title,
616 const std::string & packageDirAbsolutePath, const std::string & externalFilePath,
617 COMMON_NS::DataObjectRepository::openingMode hdfPermissionAccess = COMMON_NS::DataObjectRepository::openingMode::READ_ONLY) {
618 FesapiHdfProxy* result = new FesapiHdfProxy(session_, repo, guid, title, packageDirAbsolutePath, externalFilePath, hdfPermissionAccess);
619 return result;
620 }
621
622 private:
623 AbstractSession* session_;
624 };
625}
Definition AbstractSession.h:51
Definition FesapiHdfProxy.h:595
EML2_NS::AbstractHdfProxy * make(const COMMON_NS::DataObjectReference &dor)
Definition FesapiHdfProxy.h:602
EML2_NS::AbstractHdfProxy * make(gsoap_resqml2_0_1::_eml20__EpcExternalPartReference *fromGsoap)
Definition FesapiHdfProxy.h:610
Definition FesapiHdfProxy.h:31
void writeGroupAttribute(const std::string &, const std::string &, const std::vector< std::string > &) final
Definition FesapiHdfProxy.h:197
void writeDatasetAttributes(const std::string &, const std::vector< std::string > &, const std::vector< int > &) final
Definition FesapiHdfProxy.h:251
void setCompressionLevel(unsigned int newCompressionLevel) final
Definition FesapiHdfProxy.h:131
void readArrayNdOfUInt64Values(const std::string &datasetName, uint64_t *values) final
Definition FesapiHdfProxy.h:390
void readArrayNdOfInt64Values(const std::string &datasetName, int64_t *values) final
Definition FesapiHdfProxy.h:368
void open() final
Definition FesapiHdfProxy.h:77
std::vector< uint32_t > getElementCountPerChunkDimension(const std::string &) final
Definition FesapiHdfProxy.h:466
void readArrayNdOfIntValues(const std::string &datasetName, int *values, uint64_t const *numValuesInEachDimension, uint64_t const *offsetInEachDimension, unsigned int numDimensions) final
void writeGroupAttributes(const std::string &, const std::vector< std::string > &, const std::vector< double > &)
Definition FesapiHdfProxy.h:206
int getHdfDatatypeClassInDataset(const std::string &datasetName) final
void readArrayNdOfUShortValues(const std::string &datasetName, unsigned short *values) final
Definition FesapiHdfProxy.h:435
void readArrayNdOfDoubleValues(hdf5_hid_t dataset, hdf5_hid_t filespace, void *values, uint64_t slabSize) final
void writeArrayNdSlab(const std::string &groupName, const std::string &name, COMMON_NS::AbstractObject::numericalDatatypeEnum datatype, const void *values, const uint64_t *numValuesInEachDimension, const uint64_t *offsetValuesInEachDimension, unsigned int numDimensions) final
void writeDatasetAttributes(const std::string &, const std::vector< std::string > &, const std::vector< std::string > &) final
Definition FesapiHdfProxy.h:224
void writeDatasetAttributes(const std::string &, const std::vector< std::string > &, const std::vector< double > &) final
Definition FesapiHdfProxy.h:242
std::vector< uint32_t > getElementCountPerDimension(const std::string &datasetName) final
bool isOpened() const final
Definition FesapiHdfProxy.h:82
void readArrayNdOfFloatValues(const std::string &datasetName, float *values) final
Definition FesapiHdfProxy.h:346
FesapiHdfProxy(AbstractSession *session, gsoap_resqml2_0_1::_eml20__EpcExternalPartReference *fromGsoap)
Definition FesapiHdfProxy.h:46
void readArrayNdOfShortValues(const std::string &datasetName, short *values) final
Definition FesapiHdfProxy.h:428
std::string getXmlNamespace() const
Definition FesapiHdfProxy.h:471
void readArrayNdOfDoubleValues(const std::string &datasetName, double *values, uint64_t const *numValuesInEachDimension, uint64_t const *offsetInEachDimension, unsigned int numDimensions) final
void readArrayNdOfDoubleValues(const std::string &datasetName, double *values) final
Definition FesapiHdfProxy.h:282
void close() final
Definition FesapiHdfProxy.h:87
void readArrayNdOfDoubleValues(const std::string &datasetName, double *values, uint64_t const *blockCountPerDimension, uint64_t const *offsetInEachDimension, uint64_t const *strideInEachDimension, uint64_t const *blockSizeInEachDimension, unsigned int numDimensions) final
void writeArrayNd(const std::string &groupName, const std::string &name, COMMON_NS::AbstractObject::numericalDatatypeEnum datatype, const void *values, const uint64_t *numValuesInEachDimension, unsigned int numDimensions) final
bool isCompressed(const std::string &) final
Definition FesapiHdfProxy.h:459
void writeDatasetAttribute(const std::string &, const std::string &, const std::vector< std::string > &) final
Definition FesapiHdfProxy.h:233
void readArrayNdOfInt8Values(const std::string &datasetName, int8_t *values) final
Definition FesapiHdfProxy.h:442
void readArrayNdOfFloatValues(const std::string &datasetName, float *values, uint64_t const *numValuesInEachDimension, uint64_t const *offsetInEachDimension, unsigned int numDimensions) final
void readArrayNdOfUIntValues(const std::string &datasetName, unsigned int *values) final
Definition FesapiHdfProxy.h:420
void createArrayNd(const std::string &groupName, const std::string &name, COMMON_NS::AbstractObject::numericalDatatypeEnum datatype, const uint64_t *numValuesInEachDimension, unsigned int numDimensions) final
void readArrayNdOfInt64Values(const std::string &datasetName, int64_t *values, uint64_t const *numValuesInEachDimension, uint64_t const *offsetInEachDimension, unsigned int numDimensions) final
bool exist(const std::string &absolutePathInHdfFile) const final
FesapiHdfProxy(AbstractSession *session, const COMMON_NS::DataObjectReference &dor)
Definition FesapiHdfProxy.h:52
void writeItemizedListOfList(const std::string &groupName, const std::string &name, COMMON_NS::AbstractObject::numericalDatatypeEnum cumulativeLengthDatatype, const void *cumulativeLength, uint64_t cumulativeLengthSize, COMMON_NS::AbstractObject::numericalDatatypeEnum elementsDatatype, const void *elements, uint64_t elementsSize) final
void readArrayNdOfIntValues(const std::string &datasetName, int *values) final
Definition FesapiHdfProxy.h:397
void writeGroupAttributes(const std::string &, const std::vector< std::string > &, const std::vector< int > &) final
Definition FesapiHdfProxy.h:215
void writeGroupAttributes(const std::string &, const std::vector< std::string > &, const std::vector< std::string > &) final
Definition FesapiHdfProxy.h:188
void readArrayNdOfUInt8Values(const std::string &datasetName, uint8_t *values) final
Definition FesapiHdfProxy.h:448
FesapiHdfProxy(AbstractSession *session, COMMON_NS::DataObjectRepository *repo, const std::string &guid, const std::string &title, const std::string &packageDirAbsolutePath, const std::string &externalFilePath, COMMON_NS::DataObjectRepository::openingMode hdfPermissionAccess)
Definition FesapiHdfProxy.h:37