Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Commit 56886a2

Browse files
authored
Merge pull request #354 from kuba--/enh-343/cancel_by_drop
Drop indexes in progress.
2 parents ad0eefd + 459b8b8 commit 56886a2

File tree

11 files changed

+150
-34
lines changed

11 files changed

+150
-34
lines changed

sql/analyzer/index_catalog.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"gopkg.in/src-d/go-mysql-server.v0/sql/plan"
66
)
77

8-
// indexCatalog sets the catalog in the CreateIndexm, DropIndex and ShowIndexes nodes.
8+
// indexCatalog sets the catalog in the CreateIndex, DropIndex and ShowIndexes nodes.
99
func indexCatalog(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error) {
1010
if !n.Resolved() {
1111
return n, nil

sql/index.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -279,12 +279,7 @@ func (r *IndexRegistry) Index(db, id string) Index {
279279
defer r.mut.RUnlock()
280280

281281
r.retainIndex(db, id)
282-
idx := r.indexes[indexKey{db, strings.ToLower(id)}]
283-
if idx != nil && !r.canUseIndex(idx) {
284-
return nil
285-
}
286-
287-
return idx
282+
return r.indexes[indexKey{db, strings.ToLower(id)}]
288283
}
289284

290285
// IndexesByTable returns a slice of all the indexes existing on the given table.
@@ -295,9 +290,7 @@ func (r *IndexRegistry) IndexesByTable(db, table string) []Index {
295290
indexes := []Index{}
296291
for _, key := range r.indexOrder {
297292
idx := r.indexes[key]
298-
if idx.Database() == db &&
299-
idx.Table() == table && r.statuses[key] == IndexReady {
300-
293+
if idx.Database() == db && idx.Table() == table {
301294
indexes = append(indexes, idx)
302295
r.retainIndex(db, idx.ID())
303296
}
@@ -533,7 +526,7 @@ func (r *IndexRegistry) DeleteIndex(db, id string, force bool) (<-chan struct{},
533526

534527
r.rcmut.Lock()
535528
// If no query is using this index just delete it right away
536-
if r.refCounts[key] <= 0 {
529+
if force || r.refCounts[key] <= 0 {
537530
r.mut.Lock()
538531
defer r.mut.Unlock()
539532
defer r.rcmut.Unlock()

sql/index/pilosa/driver.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package pilosa
22

33
import (
4+
"context"
45
"crypto/sha1"
56
"fmt"
67
"io"
@@ -232,20 +233,21 @@ func (d *Driver) savePartition(
232233
for colID = offset; err == nil; colID++ {
233234
// commit each batch of objects (pilosa and boltdb)
234235
if colID%sql.IndexBatchSize == 0 && colID != 0 {
235-
d.saveBatch(ctx, idx.mapping, colID)
236+
if err = d.saveBatch(ctx, idx.mapping, colID); err != nil {
237+
return 0, err
238+
}
236239
}
237240

238241
select {
239-
case <-ctx.Done():
240-
return 0, ctx.Err()
242+
case <-ctx.Context.Done():
243+
return 0, ctx.Context.Err()
241244

242245
default:
243246
var (
244247
values []interface{}
245248
location []byte
246249
)
247-
values, location, err = kviter.Next()
248-
if err != nil {
250+
if values, location, err = kviter.Next(); err != nil {
249251
break
250252
}
251253

@@ -291,7 +293,9 @@ func (d *Driver) Save(
291293
if !ok {
292294
return errInvalidIndexType.New(i)
293295
}
294-
296+
idx.wg.Add(1)
297+
defer idx.wg.Done()
298+
ctx.Context, idx.cancel = context.WithCancel(ctx.Context)
295299
processingFile := d.processingFilePath(idx.Database(), idx.Table(), idx.ID())
296300
if err = index.CreateProcessingFile(processingFile); err != nil {
297301
return err
@@ -337,7 +341,16 @@ func (d *Driver) Save(
337341
}
338342

339343
// Delete the given index for all partitions in the iterator.
340-
func (d *Driver) Delete(idx sql.Index, partitions sql.PartitionIter) error {
344+
func (d *Driver) Delete(i sql.Index, partitions sql.PartitionIter) error {
345+
idx, ok := i.(*pilosaIndex)
346+
if !ok {
347+
return errInvalidIndexType.New(i)
348+
}
349+
if idx.cancel != nil {
350+
idx.cancel()
351+
idx.wg.Wait()
352+
}
353+
341354
if err := os.RemoveAll(filepath.Join(d.root, idx.Database(), idx.Table(), idx.ID())); err != nil {
342355
return err
343356
}

sql/index/pilosa/driver_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ func withoutMapping(a sql.Index) sql.Index {
9292
if i, ok := a.(*pilosaIndex); ok {
9393
b := *i
9494
b.mapping = nil
95+
b.cancel = nil
9596
return &b
9697
}
9798
return a
@@ -261,6 +262,41 @@ func TestDelete(t *testing.T) {
261262
require.NoError(err)
262263
}
263264

265+
func TestDeleteInProgress(t *testing.T) {
266+
require := require.New(t)
267+
setup(t)
268+
defer cleanup(t)
269+
270+
db, table, id := "db_name", "table_name", "index_id"
271+
272+
expressions := []sql.Expression{
273+
expression.NewGetFieldWithTable(0, sql.Int64, table, "lang", true),
274+
expression.NewGetFieldWithTable(1, sql.Int64, table, "hash", true),
275+
}
276+
277+
d := NewIndexDriver(tmpDir)
278+
sqlIdx, err := d.Create(db, table, id, expressions, nil)
279+
require.NoError(err)
280+
281+
it := &partitionKeyValueIter{
282+
partitions: 2,
283+
offset: 0,
284+
total: 1024,
285+
expressions: sqlIdx.Expressions(),
286+
location: slowRandLocation,
287+
}
288+
289+
go func() {
290+
if e := d.Save(sql.NewEmptyContext(), sqlIdx, it); e != nil {
291+
t.Log(e)
292+
}
293+
}()
294+
295+
time.Sleep(time.Second)
296+
err = d.Delete(sqlIdx, new(partitionIter))
297+
require.NoError(err)
298+
}
299+
264300
func TestLoadAllDirectoryDoesNotExist(t *testing.T) {
265301
require := require.New(t)
266302
setup(t)
@@ -873,6 +909,12 @@ func randLocation(partition sql.Partition, offset int) string {
873909
return string(partition.Key()) + "-" + string(b)
874910
}
875911

912+
func slowRandLocation(partition sql.Partition, offset int) string {
913+
defer time.Sleep(200 * time.Millisecond)
914+
915+
return randLocation(partition, offset)
916+
}
917+
876918
func offsetLocation(partition sql.Partition, offset int) string {
877919
return string(partition.Key()) + "-" + fmt.Sprint(offset)
878920
}

sql/index/pilosa/index.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package pilosa
22

33
import (
4+
"context"
5+
"sync"
6+
47
errors "gopkg.in/src-d/go-errors.v1"
58

69
pilosa "github.com/pilosa/go-pilosa"
@@ -12,6 +15,8 @@ import (
1215
type pilosaIndex struct {
1316
client *pilosa.Client
1417
mapping *mapping
18+
cancel context.CancelFunc
19+
wg sync.WaitGroup
1520

1621
db string
1722
table string

sql/index/pilosalib/driver.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package pilosalib
22

33
import (
4+
"context"
45
"crypto/sha1"
56
"fmt"
67
"io"
@@ -272,20 +273,21 @@ func (d *Driver) savePartition(
272273
for colID = offset; err == nil; colID++ {
273274
// commit each batch of objects (pilosa and boltdb)
274275
if colID%sql.IndexBatchSize == 0 && colID != 0 {
275-
d.saveBatch(ctx, idx.mapping, colID)
276+
if err = d.saveBatch(ctx, idx.mapping, colID); err != nil {
277+
return 0, err
278+
}
276279
}
277280

278281
select {
279-
case <-ctx.Done():
280-
return 0, ctx.Err()
282+
case <-ctx.Context.Done():
283+
return 0, ctx.Context.Err()
281284

282285
default:
283286
var (
284287
values []interface{}
285288
location []byte
286289
)
287-
values, location, err = kviter.Next()
288-
if err != nil {
290+
if values, location, err = kviter.Next(); err != nil {
289291
break
290292
}
291293

@@ -332,6 +334,9 @@ func (d *Driver) Save(
332334
return errInvalidIndexType.New(i)
333335
}
334336

337+
idx.wg.Add(1)
338+
defer idx.wg.Done()
339+
ctx.Context, idx.cancel = context.WithCancel(ctx.Context)
335340
processingFile := d.processingFilePath(i.Database(), i.Table(), i.ID())
336341
if err := index.WriteProcessingFile(
337342
processingFile,
@@ -377,14 +382,18 @@ func (d *Driver) Save(
377382

378383
// Delete the given index for all partitions in the iterator.
379384
func (d *Driver) Delete(i sql.Index, partitions sql.PartitionIter) error {
380-
if err := os.RemoveAll(filepath.Join(d.root, i.Database(), i.Table(), i.ID())); err != nil {
381-
return err
382-
}
383-
384385
idx, ok := i.(*pilosaIndex)
385386
if !ok {
386387
return errInvalidIndexType.New(i)
387388
}
389+
if idx.cancel != nil {
390+
idx.cancel()
391+
idx.wg.Wait()
392+
}
393+
394+
if err := os.RemoveAll(filepath.Join(d.root, i.Database(), i.Table(), i.ID())); err != nil {
395+
return err
396+
}
388397

389398
err := idx.index.Open()
390399
if err != nil {
@@ -435,8 +444,8 @@ func (d *Driver) savePilosa(ctx *sql.Context, colID uint64) error {
435444

436445
start := time.Now()
437446

438-
for i, frm := range d.fields {
439-
err := frm.Import(d.bitBatches[i].rows, d.bitBatches[i].cols, nil)
447+
for i, fld := range d.fields {
448+
err := fld.Import(d.bitBatches[i].rows, d.bitBatches[i].cols, nil)
440449
if err != nil {
441450
span.LogKV("error", err)
442451
return err

sql/index/pilosalib/driver_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"io/ioutil"
99
"os"
1010
"testing"
11+
"time"
1112

1213
"github.com/pilosa/pilosa"
1314
"github.com/stretchr/testify/require"
@@ -236,6 +237,41 @@ func TestDelete(t *testing.T) {
236237
require.NoError(err)
237238
}
238239

240+
func TestDeleteInProgress(t *testing.T) {
241+
require := require.New(t)
242+
setup(t)
243+
defer cleanup(t)
244+
245+
db, table, id := "db_name", "table_name", "index_id"
246+
247+
expressions := []sql.Expression{
248+
expression.NewGetFieldWithTable(0, sql.Int64, table, "lang", true),
249+
expression.NewGetFieldWithTable(1, sql.Int64, table, "hash", true),
250+
}
251+
252+
d := NewDriver(tmpDir)
253+
sqlIdx, err := d.Create(db, table, id, expressions, nil)
254+
require.NoError(err)
255+
256+
it := &partitionKeyValueIter{
257+
partitions: 2,
258+
offset: 0,
259+
total: 1024,
260+
expressions: sqlIdx.Expressions(),
261+
location: slowRandLocation,
262+
}
263+
264+
go func() {
265+
if e := d.Save(sql.NewEmptyContext(), sqlIdx, it); e != nil {
266+
t.Log(e)
267+
}
268+
}()
269+
270+
time.Sleep(time.Second)
271+
err = d.Delete(sqlIdx, new(partitionIter))
272+
require.NoError(err)
273+
}
274+
239275
func TestLoadAllDirectoryDoesNotExist(t *testing.T) {
240276
require := require.New(t)
241277
setup(t)
@@ -899,6 +935,12 @@ func randLocation(partition sql.Partition, offset int) string {
899935
return string(partition.Key()) + "-" + string(b)
900936
}
901937

938+
func slowRandLocation(partition sql.Partition, offset int) string {
939+
defer time.Sleep(200 * time.Millisecond)
940+
941+
return randLocation(partition, offset)
942+
}
943+
902944
func offsetLocation(partition sql.Partition, offset int) string {
903945
return string(partition.Key()) + "-" + fmt.Sprint(offset)
904946
}

sql/index/pilosalib/index.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package pilosalib
22

33
import (
4+
"context"
5+
"sync"
6+
47
"github.com/pilosa/pilosa"
58
errors "gopkg.in/src-d/go-errors.v1"
69
"gopkg.in/src-d/go-mysql-server.v0/sql"
@@ -15,6 +18,8 @@ var (
1518
type pilosaIndex struct {
1619
index *pilosa.Index
1720
mapping *mapping
21+
cancel context.CancelFunc
22+
wg sync.WaitGroup
1823

1924
db string
2025
table string

sql/index_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func TestIndexesByTable(t *testing.T) {
5959
r.statuses[indexKey{"oof", "rab_idx_1"}] = IndexReady
6060

6161
indexes := r.IndexesByTable("foo", "bar")
62-
require.Len(indexes, 2)
62+
require.Len(indexes, 3)
6363

6464
for i, idx := range indexes {
6565
expected := r.indexes[r.indexOrder[i]]

sql/plan/drop_index.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func (d *DropIndex) RowIter(ctx *sql.Context) (sql.RowIter, error) {
5959
}
6060
d.Catalog.ReleaseIndex(index)
6161

62-
done, err := d.Catalog.DeleteIndex(db.Name(), d.Name, false)
62+
done, err := d.Catalog.DeleteIndex(db.Name(), d.Name, true)
6363
if err != nil {
6464
return nil, err
6565
}

0 commit comments

Comments
 (0)