aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authorAlexander Smirnov <alex@ydb.tech>2025-03-28 00:51:44 +0000
committerAlexander Smirnov <alex@ydb.tech>2025-03-28 00:51:44 +0000
commit149dc5893b4b90db5ad40d019d2d1ffa6e1f0abd (patch)
tree6e3243c1b457c31839ddc9fa75b5f46bcc1fecb4 /library/cpp
parent4c8dfa633cab20dabf3d11464d986335519bfcfa (diff)
parent71e9df83f284bf42c2f8ea872752bf02e1055555 (diff)
downloadydb-149dc5893b4b90db5ad40d019d2d1ffa6e1f0abd.tar.gz
Merge branch 'rightlib' into merge-libs-250328-0050
Diffstat (limited to 'library/cpp')
-rw-r--r--library/cpp/neh/tcp2.cpp30
-rw-r--r--library/cpp/type_info/type_io.cpp33
-rw-r--r--library/cpp/type_info/ut/type_deserialize.cpp34
3 files changed, 71 insertions, 26 deletions
diff --git a/library/cpp/neh/tcp2.cpp b/library/cpp/neh/tcp2.cpp
index 641408973d..fa24635e46 100644
--- a/library/cpp/neh/tcp2.cpp
+++ b/library/cpp/neh/tcp2.cpp
@@ -621,8 +621,8 @@ namespace {
, State_(Init)
, BuffSize_(TTcp2Options::InputBufferSize)
, Buff_(new char[BuffSize_])
- , NeedCheckReqsQueue_(0)
- , NeedCheckCancelsQueue_(0)
+ , NeedCheckReqsQueue_(false)
+ , NeedCheckCancelsQueue_(false)
, GenReqId_(0)
, LastSendedReqId_(0)
{
@@ -651,7 +651,7 @@ namespace {
throw;
}
- AtomicSet(NeedCheckReqsQueue_, 1);
+ NeedCheckReqsQueue_.store(true);
req->SetConnection(this);
TAtomicBase state = AtomicGet(State_);
if (Y_LIKELY(state == Connected)) {
@@ -682,7 +682,7 @@ namespace {
//called from client thread
void Cancel(TRequestId id) {
Cancels_.Enqueue(id);
- AtomicSet(NeedCheckCancelsQueue_, 1);
+ NeedCheckCancelsQueue_.store(true);
if (Y_LIKELY(AtomicGet(State_) == Connected)) {
ProcessOutputCancelsQueue();
}
@@ -758,7 +758,7 @@ namespace {
do {
if (asioThread) {
- AtomicSet(NeedCheckCancelsQueue_, 0);
+ NeedCheckCancelsQueue_.store(false);
TRequestId reqId;
ProcessReqsInFlyQueue();
@@ -776,14 +776,14 @@ namespace {
}
}
}
- } else if (AtomicGet(NeedCheckCancelsQueue_)) {
+ } else if (NeedCheckCancelsQueue_.load()) {
AS_.GetIOService().Post(std::bind(&TConnection::SendMessages, TConnectionRef(this), true));
return;
}
TRequestId lastReqId = 0;
{
- AtomicSet(NeedCheckReqsQueue_, 0);
+ NeedCheckReqsQueue_.store(false);
TRequest* reqPtr;
while (Reqs_.Dequeue(&reqPtr)) {
@@ -824,7 +824,7 @@ namespace {
OutputLock_.Release();
- if (!AtomicGet(NeedCheckReqsQueue_) && !AtomicGet(NeedCheckCancelsQueue_)) {
+ if (!NeedCheckReqsQueue_.load() && !NeedCheckCancelsQueue_.load()) {
DBGOUT("TClient::SendMessages(exit2)");
return;
}
@@ -1031,9 +1031,9 @@ namespace {
//output
TSpinLock OutputLock_; //protect socket/buffers from simultaneous access from few threads
- TAtomic NeedCheckReqsQueue_;
+ std::atomic<bool> NeedCheckReqsQueue_;
TLockFreeQueue<TRequest*> Reqs_;
- TAtomic NeedCheckCancelsQueue_;
+ std::atomic<bool> NeedCheckCancelsQueue_;
TLockFreeQueue<TRequestId> Cancels_;
TAdaptiveLock GenReqIdLock_;
std::atomic<TRequestId> GenReqId_;
@@ -1182,7 +1182,7 @@ namespace {
, RemoteHost_(NNeh::PrintHostByRfc(*AS_->RemoteEndpoint().Addr()))
, BuffSize_(TTcp2Options::InputBufferSize)
, Buff_(new char[BuffSize_])
- , NeedCheckOutputQueue_(0)
+ , NeedCheckOutputQueue_(false)
{
DBGOUT("TServer::TConnection()");
}
@@ -1383,7 +1383,7 @@ namespace {
}
void ProcessOutputQueue() {
- AtomicSet(NeedCheckOutputQueue_, 1);
+ NeedCheckOutputQueue_.store(true);
if (OutputLock_.TryAcquire()) {
SendMessages(false);
return;
@@ -1396,7 +1396,7 @@ namespace {
DBGOUT("TServer::SendMessages(enter)");
try {
do {
- AtomicUnlock(&NeedCheckOutputQueue_);
+ NeedCheckOutputQueue_.store(false);
TAutoPtr<TOutputData> d;
while (OutputData_.Dequeue(&d)) {
d->MoveTo(OutputBuffers_);
@@ -1415,7 +1415,7 @@ namespace {
OutputLock_.Release();
- if (!AtomicGet(NeedCheckOutputQueue_)) {
+ if (!NeedCheckOutputQueue_.load()) {
DBGOUT("Server::SendMessages(exit2): " << (int)!OutputLock_.IsLocked());
return;
}
@@ -1491,7 +1491,7 @@ namespace {
//output
TSpinLock OutputLock_; //protect socket/buffers from simultaneous access from few threads
- TAtomic NeedCheckOutputQueue_;
+ std::atomic<bool> NeedCheckOutputQueue_;
NNeh::TAutoLockFreeQueue<TOutputData> OutputData_;
TOutputBuffers OutputBuffers_;
};
diff --git a/library/cpp/type_info/type_io.cpp b/library/cpp/type_info/type_io.cpp
index 12f0058fed..f397466abc 100644
--- a/library/cpp/type_info/type_io.cpp
+++ b/library/cpp/type_info/type_io.cpp
@@ -13,6 +13,8 @@
#include <util/generic/vector.h>
#include <util/generic/scope.h>
+#include <optional>
+
namespace NTi::NIo {
namespace {
class TYsonDeserializer: private TNonCopyable {
@@ -61,7 +63,8 @@ namespace NTi::NIo {
const TType *Key, *Value;
};
struct TDecimalData {
- ui8 Precision, Scale;
+ std::optional<ui8> Precision;
+ std::optional<ui8> Scale;
};
using TTypeData = std::variant<
std::monostate,
@@ -162,11 +165,19 @@ namespace NTi::NIo {
}
} else if (mapKey == "precision") {
if (std::holds_alternative<std::monostate>(data)) {
- data = TDecimalData{ReadSmallInt(R"("precision")"), 0};
+ const auto precision = ReadSmallInt(R"("precision")");
+ if (0 == precision) {
+ ythrow TDeserializationException() << R"(invalid zero "precision")";
+ }
+ data = TDecimalData{precision, std::nullopt};
} else if (std::holds_alternative<TDecimalData>(data)) {
auto& decimalData = std::get<TDecimalData>(data);
- if (decimalData.Precision == 0) {
- decimalData.Precision = ReadSmallInt(R"("precision")");
+ if (!decimalData.Precision.has_value()) {
+ const auto precision = ReadSmallInt(R"("precision")");
+ if (0 == precision) {
+ ythrow TDeserializationException() << R"(invalid zero "precision")";
+ }
+ decimalData.Precision = precision;
} else {
ythrow TDeserializationException() << R"(duplicate key "precision")";
}
@@ -175,10 +186,10 @@ namespace NTi::NIo {
}
} else if (mapKey == "scale") {
if (std::holds_alternative<std::monostate>(data)) {
- data = TDecimalData{0, ReadSmallInt(R"("scale")")};
+ data = TDecimalData{std::nullopt, ReadSmallInt(R"("scale")")};
} else if (std::holds_alternative<TDecimalData>(data)) {
auto& decimalData = std::get<TDecimalData>(data);
- if (decimalData.Scale == 0) {
+ if (!decimalData.Scale.has_value()) {
decimalData.Scale = ReadSmallInt(R"("scale")");
} else {
ythrow TDeserializationException() << R"(duplicate key "scale")";
@@ -272,15 +283,15 @@ namespace NTi::NIo {
auto& decimalData = std::get<TDecimalData>(data);
- if (decimalData.Precision == 0) {
+ if (!decimalData.Precision.has_value()) {
ythrow TDeserializationException() << R"(missing required key "precision" for type Decimal)";
}
- if (decimalData.Scale == 0) {
+ if (!decimalData.Scale.has_value()) {
ythrow TDeserializationException() << R"(missing required key "scale" for type Decimal)";
}
- return Factory_->DecimalRaw(decimalData.Precision, decimalData.Scale);
+ return Factory_->DecimalRaw(decimalData.Precision.value(), decimalData.Scale.value());
}
case ETypeName::Json:
type = TJsonType::InstanceRaw();
@@ -420,8 +431,8 @@ namespace NTi::NIo {
auto result = event.AsScalar().AsInt64();
- if (result <= 0) {
- ythrow TDeserializationException() << what << " must be greater than zero";
+ if (result < 0) {
+ ythrow TDeserializationException() << what << " must be greater or equal to zero";
}
if (result > Max<ui8>()) {
diff --git a/library/cpp/type_info/ut/type_deserialize.cpp b/library/cpp/type_info/ut/type_deserialize.cpp
index 9e93a26bee..7d5f60bad0 100644
--- a/library/cpp/type_info/ut/type_deserialize.cpp
+++ b/library/cpp/type_info/ut/type_deserialize.cpp
@@ -120,6 +120,40 @@ TEST(TypeDeserialize, Decimal) {
ASSERT_DESERIALIZED_EQ(NTi::Decimal(20, 10), R"({type_name=decimal; precision=20; scale=10})");
ASSERT_DESERIALIZED_EQ(NTi::Decimal(20, 10), R"({scale=10; type_name=decimal; precision=20})");
ASSERT_DESERIALIZED_EQ(NTi::Decimal(10, 10), R"({type_name=decimal; precision=10; scale=10})");
+ ASSERT_DESERIALIZED_EQ(NTi::Decimal(10, 0), R"({type_name=decimal; precision=10; scale=0})");
+}
+
+TEST(TypeDeserialize, DecimalBadTypeParameters) {
+ UNIT_ASSERT_EXCEPTION_CONTAINS(
+ []() {
+ NTi::NIo::DeserializeYson(*NTi::HeapFactory(), R"({type_name=decimal; precision=0; scale=10})");
+ }(),
+ NTi::TDeserializationException, R"(invalid zero "precision")");
+ UNIT_ASSERT_EXCEPTION_CONTAINS(
+ []() {
+ NTi::NIo::DeserializeYson(*NTi::HeapFactory(), R"({type_name=decimal; precision=-2; scale=10})");
+ }(),
+ NTi::TDeserializationException, R"("precision" must be greater or equal to zero)");
+ UNIT_ASSERT_EXCEPTION_CONTAINS(
+ []() {
+ NTi::NIo::DeserializeYson(*NTi::HeapFactory(), R"({type_name=decimal; precision=2; scale=-2})");
+ }(),
+ NTi::TDeserializationException, R"("scale" must be greater or equal to zero)");
+ UNIT_ASSERT_EXCEPTION_CONTAINS(
+ []() {
+ NTi::NIo::DeserializeYson(*NTi::HeapFactory(), R"({type_name=decimal; precision=2; scale=-2})");
+ }(),
+ NTi::TDeserializationException, R"("scale" must be greater or equal to zero)");
+ UNIT_ASSERT_EXCEPTION_CONTAINS(
+ []() {
+ NTi::NIo::DeserializeYson(*NTi::HeapFactory(), R"({type_name=decimal; precision=1000; scale=2})");
+ }(),
+ NTi::TDeserializationException, R"("precision" is too big)");
+ UNIT_ASSERT_EXCEPTION_CONTAINS(
+ []() {
+ NTi::NIo::DeserializeYson(*NTi::HeapFactory(), R"({type_name=decimal; precision=2; scale=1000})");
+ }(),
+ NTi::TDeserializationException, R"("scale" is too big)");
}
TEST(TypeDeserialize, DecimalMissingTypeParameters) {