Skip to content

Commit 81e038d

Browse files
authored
dumpling: fix dumpling ignore file writer close error (#45374) (#45404)
close #45353
1 parent 89ba2e7 commit 81e038d

File tree

6 files changed

+79
-14
lines changed

6 files changed

+79
-14
lines changed

dumpling/export/ir_impl.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ func newMultiQueriesChunk(queries []string, colLength int) *multiQueriesChunk {
362362
func (td *multiQueriesChunk) Start(tctx *tcontext.Context, conn *sql.Conn) error {
363363
td.tctx = tctx
364364
td.conn = conn
365+
td.SQLRowIter = nil
365366
return nil
366367
}
367368

dumpling/export/metadata.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,12 @@ func (m *globalMetadata) writeGlobalMetaData() error {
219219
if err != nil {
220220
return err
221221
}
222-
defer tearDown(m.tctx)
223-
224-
return write(m.tctx, fileWriter, m.String())
222+
err = write(m.tctx, fileWriter, m.String())
223+
tearDownErr := tearDown(m.tctx)
224+
if err == nil {
225+
return tearDownErr
226+
}
227+
return err
225228
}
226229

227230
func getValidStr(str []string, idx int) string {

dumpling/export/writer.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,13 @@ func (w *Writer) tryToWriteTableData(tctx *tcontext.Context, meta TableMeta, ir
241241
for {
242242
fileWriter, tearDown := buildInterceptFileWriter(tctx, w.extStorage, fileName, conf.CompressType)
243243
n, err := format.WriteInsert(tctx, conf, meta, ir, fileWriter, w.metrics)
244-
tearDown(tctx)
244+
tearDownErr := tearDown(tctx)
245245
if err != nil {
246246
return err
247247
}
248+
if tearDownErr != nil {
249+
return tearDownErr
250+
}
248251

249252
if w, ok := fileWriter.(*InterceptFileWriter); ok && !w.SomethingIsWritten {
250253
break
@@ -279,13 +282,16 @@ func (w *Writer) writeMetaToFile(tctx *tcontext.Context, target, metaSQL string,
279282
if err != nil {
280283
return errors.Trace(err)
281284
}
282-
defer tearDown(tctx)
283-
284-
return WriteMeta(tctx, &metaData{
285+
err = WriteMeta(tctx, &metaData{
285286
target: target,
286287
metaSQL: metaSQL,
287288
specCmts: getSpecialComments(w.conf.ServerInfo.ServerType),
288289
}, fileWriter)
290+
tearDownErr := tearDown(tctx)
291+
if err == nil {
292+
return tearDownErr
293+
}
294+
return err
289295
}
290296

291297
type outputFileNamer struct {

dumpling/export/writer_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"testing"
1212

1313
"github.com/DATA-DOG/go-sqlmock"
14+
"github.com/pingcap/failpoint"
1415
"github.com/pingcap/tidb/br/pkg/version"
1516
tcontext "github.com/pingcap/tidb/dumpling/context"
1617
"github.com/pingcap/tidb/util/promutil"
@@ -71,6 +72,12 @@ func TestWriteTableMeta(t *testing.T) {
7172
bytes, err := os.ReadFile(p)
7273
require.NoError(t, err)
7374
require.Equal(t, "/*!40014 SET FOREIGN_KEY_CHECKS=0*/;\n/*!40101 SET NAMES binary*/;\nCREATE TABLE t (a INT);\n", string(bytes))
75+
76+
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/dumpling/export/FailToCloseMetaFile", "return(true)"))
77+
defer failpoint.Disable("github.com/pingcap/tidb/dumpling/export/FailToCloseMetaFile")
78+
79+
err = writer.WriteTableMeta("test", "t", "CREATE TABLE t (a INT)")
80+
require.ErrorContains(t, err, "injected error: fail to close meta file")
7481
}
7582

7683
func TestWriteViewMeta(t *testing.T) {
@@ -137,6 +144,13 @@ func TestWriteTableData(t *testing.T) {
137144
"(3,'male','john@mail.com','020-1256','healthy'),\n" +
138145
"(4,'female','sarah@mail.com','020-1235','healthy');\n"
139146
require.Equal(t, expected, string(bytes))
147+
148+
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/dumpling/export/FailToCloseDataFile", "return(true)"))
149+
defer failpoint.Disable("github.com/pingcap/tidb/dumpling/export/FailToCloseDataFile")
150+
151+
tableIR = newMockTableIR("test", "employee", data, specCmts, colTypes)
152+
err = writer.WriteTableData(tableIR, tableIR, 0)
153+
require.ErrorContains(t, err, "injected error: fail to close data file")
140154
}
141155

142156
func TestWriteTableDataWithFileSize(t *testing.T) {

dumpling/export/writer_util.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ func writeBytes(tctx *tcontext.Context, writer storage.ExternalFileWriter, p []b
451451
return errors.Trace(err)
452452
}
453453

454-
func buildFileWriter(tctx *tcontext.Context, s storage.ExternalStorage, fileName string, compressType storage.CompressType) (storage.ExternalFileWriter, func(ctx context.Context), error) {
454+
func buildFileWriter(tctx *tcontext.Context, s storage.ExternalStorage, fileName string, compressType storage.CompressType) (storage.ExternalFileWriter, func(ctx context.Context) error, error) {
455455
fileName += compressFileSuffix(compressType)
456456
fullPath := s.URI() + "/" + fileName
457457
writer, err := storage.WithCompression(s, compressType).Create(tctx, fileName)
@@ -462,20 +462,24 @@ func buildFileWriter(tctx *tcontext.Context, s storage.ExternalStorage, fileName
462462
return nil, nil, errors.Trace(err)
463463
}
464464
tctx.L().Debug("opened file", zap.String("path", fullPath))
465-
tearDownRoutine := func(ctx context.Context) {
465+
tearDownRoutine := func(ctx context.Context) error {
466466
err := writer.Close(ctx)
467+
failpoint.Inject("FailToCloseMetaFile", func(_ failpoint.Value) {
468+
err = errors.New("injected error: fail to close meta file")
469+
})
467470
if err == nil {
468-
return
471+
return nil
469472
}
470473
err = errors.Trace(err)
471474
tctx.L().Warn("fail to close file",
472475
zap.String("path", fullPath),
473476
zap.Error(err))
477+
return err
474478
}
475479
return writer, tearDownRoutine, nil
476480
}
477481

478-
func buildInterceptFileWriter(pCtx *tcontext.Context, s storage.ExternalStorage, fileName string, compressType storage.CompressType) (storage.ExternalFileWriter, func(context.Context)) {
482+
func buildInterceptFileWriter(pCtx *tcontext.Context, s storage.ExternalStorage, fileName string, compressType storage.CompressType) (storage.ExternalFileWriter, func(context.Context) error) {
479483
fileName += compressFileSuffix(compressType)
480484
var writer storage.ExternalFileWriter
481485
fullPath := s.URI() + "/" + fileName
@@ -497,17 +501,21 @@ func buildInterceptFileWriter(pCtx *tcontext.Context, s storage.ExternalStorage,
497501
}
498502
fileWriter.initRoutine = initRoutine
499503

500-
tearDownRoutine := func(ctx context.Context) {
504+
tearDownRoutine := func(ctx context.Context) error {
501505
if writer == nil {
502-
return
506+
return nil
503507
}
504508
pCtx.L().Debug("tear down lazy file writer...", zap.String("path", fullPath))
505509
err := writer.Close(ctx)
510+
failpoint.Inject("FailToCloseDataFile", func(_ failpoint.Value) {
511+
err = errors.New("injected error: fail to close data file")
512+
})
506513
if err != nil {
507514
pCtx.L().Warn("fail to close file",
508515
zap.String("path", fullPath),
509516
zap.Error(err))
510517
}
518+
return err
511519
}
512520
return fileWriter, tearDownRoutine
513521
}

dumpling/tests/basic/run.sh

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,43 @@ run_dumpling -B "test_db" -L ${DUMPLING_OUTPUT_DIR}/dumpling.log
155155
cnt=$(grep "IOTotalBytes=" ${DUMPLING_OUTPUT_DIR}/dumpling.log | grep -v "IOTotalBytes=0" | wc -l)
156156
[ "$cnt" -ge 1 ]
157157

158-
export GO_FAILPOINTS=""
158+
echo "Test for failing to close meta/data file"
159+
export GO_FAILPOINTS="github.com/pingcap/tidb/dumpling/export/FailToCloseMetaFile=1*return"
160+
rm ${DUMPLING_OUTPUT_DIR}/dumpling.log
161+
set +e
162+
run_dumpling -B "test_db" -L ${DUMPLING_OUTPUT_DIR}/dumpling.log
163+
set -e
164+
cnt=$(grep -w "dump failed error stack info" ${DUMPLING_OUTPUT_DIR}/dumpling.log|wc -l)
165+
[ "$cnt" -ge 1 ]
166+
167+
# dumpling retry will make it succeed
168+
export GO_FAILPOINTS="github.com/pingcap/tidb/dumpling/export/FailToCloseDataFile=1*return"
159169
export DUMPLING_TEST_PORT=4000
170+
run_sql "drop database if exists test_db;"
171+
run_sql "create database test_db;"
172+
run_sql "create table test_db.test_table (a int primary key);"
173+
run_sql "insert into test_db.test_table values (1),(2),(3),(4),(5),(6),(7),(8);"
174+
rm ${DUMPLING_OUTPUT_DIR}/dumpling.log
175+
set +e
176+
run_dumpling -B "test_db" -L ${DUMPLING_OUTPUT_DIR}/dumpling.log
177+
set -e
178+
cnt=$(grep -w "dump data successfully" ${DUMPLING_OUTPUT_DIR}/dumpling.log|wc -l)
179+
[ "$cnt" -ge 1 ]
180+
cnt=$(grep -w "(.*)" ${DUMPLING_OUTPUT_DIR}/test_db.test_table.000000000.sql|wc -l)
181+
echo "records count is ${cnt}"
182+
[ "$cnt" -eq 8 ]
183+
184+
export GO_FAILPOINTS="github.com/pingcap/tidb/dumpling/export/FailToCloseDataFile=5*return"
185+
rm ${DUMPLING_OUTPUT_DIR}/dumpling.log
186+
set +e
187+
run_dumpling -B "test_db" -L ${DUMPLING_OUTPUT_DIR}/dumpling.log
188+
set -e
189+
cnt=$(grep -w "dump failed error stack info" ${DUMPLING_OUTPUT_DIR}/dumpling.log|wc -l)
190+
[ "$cnt" -ge 1 ]
191+
160192
echo "Test for empty query result, should success."
161193
run_sql "drop database if exists test_db;"
162194
run_sql "create database test_db;"
163195
run_sql "create table test_db.test_table (a int primary key);"
196+
export GO_FAILPOINTS=""
164197
run_dumpling --sql "select * from test_db.test_table" --filetype csv > ${DUMPLING_OUTPUT_DIR}/dumpling.log

0 commit comments

Comments
 (0)