Skip to content

Commit 6ffd88d

Browse files
authored
Print location in error messages (#10948)
1 parent 7b36d5b commit 6ffd88d

File tree

5 files changed

+210
-50
lines changed

5 files changed

+210
-50
lines changed

ydb/public/lib/ydb_cli/dump/restore_compat.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,23 @@ class TDataAccumulator: public NPrivate::IDataAccumulator, protected TQueryBuild
4646
Begin();
4747
}
4848

49-
bool Fits(const TString& line) const override {
49+
EStatus Check(const NPrivate::TLine& line) const override {
5050
if (RowsPerRequest > 0 && (Rows + 1) > RowsPerRequest) {
51-
return Rows == 0;
51+
return Rows == 0 ? OK : FULL;
5252
}
5353

5454
if (BytesPerRequest > 0 && (Bytes + RecordSize(line)) > BytesPerRequest) {
55-
return Bytes == 0;
55+
return Bytes == 0 ? OK : FULL;
5656
}
5757

5858
if (RequestUnitsPerRequest > 0 && CalcRequestUnits(RequestUnitsX2 + RecordRequestUnitsX2(line)) > RequestUnitsPerRequest) {
59-
return RequestUnitsX2 == 0;
59+
return RequestUnitsX2 == 0 ? OK : FULL;
6060
}
6161

62-
return true;
62+
return OK;
6363
}
6464

65-
void Feed(TString&& line) override {
65+
void Feed(NPrivate::TLine&& line) override {
6666
AddLine(line);
6767

6868
++Rows;
@@ -90,7 +90,7 @@ class TDataAccumulator: public NPrivate::IDataAccumulator, protected TQueryBuild
9090
return false;
9191
}
9292

93-
TString GetData(bool) override {
93+
NPrivate::TBatch GetData(bool) override {
9494
Rows = 0;
9595
Bytes = 0;
9696
RequestUnitsX2 = 0;
@@ -133,7 +133,7 @@ class TDataWriter: public NPrivate::IDataWriter {
133133
Uploader = MakeHolder<TUploader>(opts, TableClient, Accumulator->GetQueryString());
134134
}
135135

136-
bool Push(TString&&) override {
136+
bool Push(NPrivate::TBatch&&) override {
137137
bool ok;
138138

139139
if (UseBulkUpsert) {

ydb/public/lib/ydb_cli/dump/restore_impl.cpp

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include <util/generic/maybe.h>
1616
#include <util/generic/vector.h>
1717
#include <util/stream/file.h>
18-
#include <util/string/builder.h>
1918
#include <util/string/join.h>
2019

2120
namespace NYdb {
@@ -83,6 +82,61 @@ bool IsOperationStarted(TStatus operationStatus) {
8382

8483
} // anonymous
8584

85+
namespace NPrivate {
86+
87+
TLocation::TLocation(TStringBuf file, ui64 lineNo)
88+
: File(file)
89+
, LineNo(lineNo)
90+
{
91+
}
92+
93+
void TLocation::Out(IOutputStream& out) const {
94+
out << File << ":" << LineNo;
95+
}
96+
97+
TLine::TLine(TString&& data, TStringBuf file, ui64 lineNo)
98+
: Data(std::move(data))
99+
, Location(file, lineNo)
100+
{
101+
}
102+
103+
TLine::TLine(TString&& data, const TLocation& location)
104+
: Data(std::move(data))
105+
, Location(location)
106+
{
107+
}
108+
109+
void TBatch::Add(const TLine& line) {
110+
Data << line.GetData() << "\n";
111+
Locations.push_back(line.GetLocation());
112+
}
113+
114+
TString TBatch::GetLocation() const {
115+
THashMap<TStringBuf, std::pair<ui64, ui64>> locations;
116+
for (const auto& location : Locations) {
117+
auto it = locations.find(location.File);
118+
if (it == locations.end()) {
119+
it = locations.emplace(location.File, std::make_pair(Max<ui64>(), Min<ui64>())).first;
120+
}
121+
it->second.first = Min(location.LineNo, it->second.first);
122+
it->second.second = Max(location.LineNo, it->second.second);
123+
}
124+
125+
TStringBuilder result;
126+
bool comma = false;
127+
for (const auto& [file, range] : locations) {
128+
if (comma) {
129+
result << ", ";
130+
}
131+
result << file << ":" << range.first << "-" << range.second;
132+
comma = true;
133+
}
134+
135+
return result;
136+
}
137+
138+
} // NPrivate
139+
86140
TRestoreClient::TRestoreClient(const TDriver& driver, const std::shared_ptr<TLog>& log)
87141
: ImportClient(driver)
88142
, OperationClient(driver)
@@ -371,25 +425,35 @@ TRestoreResult TRestoreClient::RestoreData(const TFsPath& fsPath, const TString&
371425
return Result<TRestoreResult>(dbPath, std::move(descResult));
372426
}
373427

374-
accumulator.Reset(CreateImportDataAccumulator(desc, *actualDesc, settings));
428+
accumulator.Reset(CreateImportDataAccumulator(desc, *actualDesc, settings, Log));
375429
writer.Reset(CreateImportDataWriter(dbPath, desc, ImportClient, TableClient, accumulator.Get(), settings, Log));
376430

377431
break;
378432
}
379433
}
380434

381435
TWriterWaiter waiter(*writer);
436+
382437
ui32 dataFileId = 0;
383438
TFsPath dataFile = fsPath.Child(DataFileName(dataFileId));
439+
TVector<TString> dataFileNames;
384440

385441
while (dataFile.Exists()) {
386442
LOG_D("Read data from " << dataFile.GetPath().Quote());
387443

444+
dataFileNames.push_back(dataFile);
388445
TFileInput input(dataFile, settings.FileBufferSize_);
389446
TString line;
447+
ui64 lineNo = 0;
390448

391449
while (input.ReadLine(line)) {
392-
while (!accumulator->Fits(line)) {
450+
auto l = NPrivate::TLine(std::move(line), dataFileNames.back(), ++lineNo);
451+
for (auto status = accumulator->Check(l); status != NPrivate::IDataAccumulator::OK; status = accumulator->Check(l)) {
452+
if (status == NPrivate::IDataAccumulator::ERROR) {
453+
return Result<TRestoreResult>(dbPath, EStatus::GENERIC_ERROR,
454+
TStringBuilder() << "Invalid data: " << l.GetLocation());
455+
}
456+
393457
if (!accumulator->Ready(true)) {
394458
LOG_E("Error reading data from " << dataFile.GetPath().Quote());
395459
return Result<TRestoreResult>(dbPath, EStatus::INTERNAL_ERROR, "Data is not ready");
@@ -401,7 +465,7 @@ TRestoreResult TRestoreClient::RestoreData(const TFsPath& fsPath, const TString&
401465
}
402466
}
403467

404-
accumulator->Feed(std::move(line));
468+
accumulator->Feed(std::move(l));
405469
if (accumulator->Ready()) {
406470
if (!writer->Push(accumulator->GetData())) {
407471
LOG_E("Error writing data to " << dbPath.Quote() << ", file: " << dataFile.GetPath().Quote());
@@ -518,3 +582,7 @@ TRestoreResult TRestoreClient::RestoreEmptyDir(const TFsPath& fsPath, const TStr
518582

519583
} // NDump
520584
} // NYdb
585+
586+
Y_DECLARE_OUT_SPEC(, NYdb::NDump::NPrivate::TLocation, o, x) {
587+
return x.Out(o);
588+
}

ydb/public/lib/ydb_cli/dump/restore_impl.h

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include <util/folder/path.h>
1111
#include <util/generic/hash_set.h>
12+
#include <util/stream/fwd.h>
13+
#include <util/string/builder.h>
1214

1315
namespace NYdb {
1416
namespace NDump {
@@ -18,19 +20,91 @@ extern const char DOC_API_REQUEST_TYPE[22];
1820

1921
namespace NPrivate {
2022

23+
class TBatch;
24+
25+
class TLocation {
26+
friend class TBatch;
27+
TStringBuf File;
28+
ui64 LineNo;
29+
30+
public:
31+
explicit TLocation(TStringBuf file, ui64 lineNo);
32+
void Out(IOutputStream& out) const;
33+
};
34+
35+
class TLine {
36+
TString Data;
37+
TLocation Location;
38+
39+
public:
40+
explicit TLine(TString&& data, TStringBuf file, ui64 lineNo);
41+
explicit TLine(TString&& data, const TLocation& location);
42+
43+
inline const TString& GetData() const {
44+
return Data;
45+
}
46+
47+
inline const TLocation& GetLocation() const {
48+
return Location;
49+
}
50+
51+
inline operator TString() const {
52+
return Data;
53+
}
54+
55+
inline operator TStringBuf() const {
56+
return Data;
57+
}
58+
59+
inline auto size() const {
60+
return Data.size();
61+
}
62+
};
63+
64+
class TBatch {
65+
TStringBuilder Data;
66+
TVector<TLocation> Locations;
67+
68+
public:
69+
void Add(const TLine& line);
70+
TString GetLocation() const;
71+
72+
inline const TString& GetData() const {
73+
return Data;
74+
}
75+
76+
inline const TLocation& GetLocation(ui32 index) const {
77+
return Locations.at(index);
78+
}
79+
80+
inline operator TString() const {
81+
return Data;
82+
}
83+
84+
inline auto size() const {
85+
return Data.size();
86+
}
87+
};
88+
2189
class IDataAccumulator {
2290
public:
91+
enum EStatus {
92+
OK,
93+
FULL,
94+
ERROR,
95+
};
96+
2397
virtual ~IDataAccumulator() = default;
24-
virtual bool Fits(const TString& line) const = 0;
25-
virtual void Feed(TString&& line) = 0;
98+
virtual EStatus Check(const TLine& line) const = 0;
99+
virtual void Feed(TLine&& line) = 0;
26100
virtual bool Ready(bool force = false) const = 0;
27-
virtual TString GetData(bool force = false) = 0;
101+
virtual TBatch GetData(bool force = false) = 0;
28102
};
29103

30104
class IDataWriter {
31105
public:
32106
virtual ~IDataWriter() = default;
33-
virtual bool Push(TString&& data) = 0;
107+
virtual bool Push(TBatch&& data) = 0;
34108
virtual void Wait() = 0;
35109
};
36110

0 commit comments

Comments
 (0)