Files
Jungfraujoch/common/JFJochException.h
T
leonarski_fandClaude Opus 4.8 02514bb6b7 Compressor: throw on overflow instead of returning a negative size
Compress() and FrameTransformation::CompressImage() returned int64_t with a
negative value meaning "did not fit". That is a footgun: the negative result
silently converts to a huge size_t if a caller forgets to check it. Return
size_t and instead throw a named CompressionBufferTooSmallException (deriving
from JFJochException, Compression category) when the output would not fit the
destination buffer.

The receiver catches it explicitly and drops just that frame, as before; the
offline/GetCompressedImage path uses a worst-case buffer so it never throws.
Add a test that a too-small destination throws and a worst-case buffer does not.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 08:17:21 +02:00

173 lines
6.1 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <cstring>
#include <string>
#include <exception>
enum class JFJochExceptionCategory {
JSON,
InputParameterAboveMax,
InputParameterBelowMin,
InputParameterInvalid,
WrongNumber,
WrongUnit,
ArrayOutOfBounds,
HDF5,
IBVerbs,
RESTCommandUnknown,
WrongDAQState,
WrongReceiverState,
Detector,
MemAllocFailed,
AcquisitionDeviceError,
GPUCUDAError,
GainFileOpenError,
MockFileOpenError,
Compression,
SharedMemory,
ZeroMQ,
ServiceUndefined,
TriggerError,
FileWriteError,
ZSTDCompressionError,
LogstashConnectionFailure,
TIFFGeneratorError,
gRPCError,
PreviewError,
HardwareParityError,
SpotFinderError,
PCIeError,
CBORError,
UDPError,
CommunicationError,
SimplonError,
CalibrationError
};
class JFJochException : public std::exception {
protected:
std::string msg;
JFJochExceptionCategory category;
static std::string DecodeCategory(JFJochExceptionCategory category) {
switch (category) {
case JFJochExceptionCategory::JSON:
return "JSON parsing or analysis error";
case JFJochExceptionCategory::InputParameterAboveMax:
return "Input parameter above max";
case JFJochExceptionCategory::InputParameterBelowMin:
return "Input parameter below min";
case JFJochExceptionCategory::InputParameterInvalid:
return "Input parameter invalid";
case JFJochExceptionCategory::WrongNumber:
return "Wrong number";
case JFJochExceptionCategory::WrongUnit:
return "Wrong unit";
case JFJochExceptionCategory::ArrayOutOfBounds:
return "Array out of bounds";
case JFJochExceptionCategory::HDF5:
return "HDF5 error";
case JFJochExceptionCategory::IBVerbs:
return "Infiniband error";
case JFJochExceptionCategory::RESTCommandUnknown:
return "REST command unknown";
case JFJochExceptionCategory::WrongDAQState:
return "DAQ state error";
case JFJochExceptionCategory::Detector:
return "Detector error";
case JFJochExceptionCategory::MemAllocFailed:
return "Memory error";
case JFJochExceptionCategory::AcquisitionDeviceError:
return "Acquisition device error";
case JFJochExceptionCategory::GPUCUDAError:
return "CUDA (GPU) error";
case JFJochExceptionCategory::GainFileOpenError:
return "Gain file open error";
case JFJochExceptionCategory::MockFileOpenError:
return "Mock file open error";
case JFJochExceptionCategory::Compression:
return "Compression error";
case JFJochExceptionCategory::SharedMemory:
return "Shared memory error";
case JFJochExceptionCategory::ZeroMQ:
return "ZeroMQ error";
case JFJochExceptionCategory::ServiceUndefined:
return "Service undefined error";
case JFJochExceptionCategory::TriggerError:
return "Trigger error";
case JFJochExceptionCategory::FileWriteError:
return "File writer error";
case JFJochExceptionCategory::ZSTDCompressionError:
return "Zstd compressor error";
case JFJochExceptionCategory::LogstashConnectionFailure:
return "Logstash connection error";
case JFJochExceptionCategory::TIFFGeneratorError:
return "TIFF writer error";
case JFJochExceptionCategory::gRPCError:
return "Remote node (gRPC) error";
case JFJochExceptionCategory::PreviewError:
return "Preview error";
case JFJochExceptionCategory::HardwareParityError:
return "Parity error (HW)";
case JFJochExceptionCategory::SpotFinderError:
return "Spot finder";
case JFJochExceptionCategory::PCIeError:
return "PCIe driver error";
case JFJochExceptionCategory::CBORError:
return "CBOR serialization error";
case JFJochExceptionCategory::UDPError:
return "UDP simulator error";
case JFJochExceptionCategory::CommunicationError:
return "Communication error";
case JFJochExceptionCategory::SimplonError:
return "Simplon API error";
case JFJochExceptionCategory::CalibrationError:
return "Detector calibration error";
default:
return "";
}
}
public:
JFJochException(JFJochExceptionCategory in_val, const std::string &description) noexcept :
category(in_val) {
try {
msg = DecodeCategory(category) + " (" + description + ")";
} catch (...) {}
}
JFJochException(const JFJochException &e) noexcept {
try {
category = e.category;
msg = e.msg;
} catch (...) {}
}
[[nodiscard]] const char *what() const noexcept override {
return msg.c_str();
}
};
class WrongDAQStateException : public JFJochException {
public:
explicit WrongDAQStateException(const std::string &description)
: JFJochException(JFJochExceptionCategory::WrongDAQState, description) {}
};
class PCIeDeviceException : public JFJochException {
public:
explicit PCIeDeviceException(const std::string &description)
: JFJochException(JFJochExceptionCategory::PCIeError, description) {
msg += " (" + std::string(strerror(errno)) + ")";
}
};
// Thrown by JFJochBitShuffleCompressor::Compress when the compressed output does not fit in the
// caller-provided destination buffer. Lets callers (e.g. the receiver) drop just that frame.
class CompressionBufferTooSmallException : public JFJochException {
public:
explicit CompressionBufferTooSmallException(const std::string &description)
: JFJochException(JFJochExceptionCategory::Compression, description) {}
};