github.com/ledgerwatch/erigon-lib@v1.0.0/kv/remotedb/kv_remote.go (about) 1 /* 2 Copyright 2021 Erigon contributors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package remotedb 18 19 import ( 20 "bytes" 21 "context" 22 "encoding/binary" 23 "fmt" 24 "runtime" 25 26 "github.com/ledgerwatch/erigon-lib/kv/iter" 27 "github.com/ledgerwatch/erigon-lib/kv/order" 28 "github.com/ledgerwatch/log/v3" 29 "golang.org/x/sync/semaphore" 30 "google.golang.org/grpc" 31 "google.golang.org/protobuf/types/known/emptypb" 32 33 "github.com/ledgerwatch/erigon-lib/gointerfaces" 34 "github.com/ledgerwatch/erigon-lib/gointerfaces/grpcutil" 35 "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" 36 "github.com/ledgerwatch/erigon-lib/kv" 37 "github.com/ledgerwatch/erigon-lib/kv/mdbx" 38 ) 39 40 // generate the messages and services 41 type remoteOpts struct { 42 remoteKV remote.KVClient 43 log log.Logger 44 bucketsCfg mdbx.TableCfgFunc 45 DialAddress string 46 version gointerfaces.Version 47 } 48 49 var _ kv.TemporalTx = (*tx)(nil) 50 51 type DB struct { 52 remoteKV remote.KVClient 53 log log.Logger 54 buckets kv.TableCfg 55 roTxsLimiter *semaphore.Weighted 56 opts remoteOpts 57 } 58 59 type tx struct { 60 stream remote.KV_TxClient 61 ctx context.Context 62 streamCancelFn context.CancelFunc 63 db *DB 64 statelessCursors map[string]kv.Cursor 65 cursors []*remoteCursor 66 streams []kv.Closer 67 viewID, id uint64 68 streamingRequested bool 69 } 70 71 type remoteCursor struct { 72 ctx context.Context 73 stream remote.KV_TxClient 74 tx *tx 75 bucketName string 76 bucketCfg kv.TableCfgItem 77 id uint32 78 } 79 80 type remoteCursorDupSort struct { 81 *remoteCursor 82 } 83 84 func (opts remoteOpts) ReadOnly() remoteOpts { 85 return opts 86 } 87 88 func (opts remoteOpts) WithBucketsConfig(f mdbx.TableCfgFunc) remoteOpts { 89 opts.bucketsCfg = f 90 return opts 91 } 92 93 func (opts remoteOpts) Open() (*DB, error) { 94 targetSemCount := int64(runtime.GOMAXPROCS(-1)) - 1 95 if targetSemCount <= 1 { 96 targetSemCount = 2 97 } 98 99 db := &DB{ 100 opts: opts, 101 remoteKV: opts.remoteKV, 102 log: log.New("remote_db", opts.DialAddress), 103 buckets: kv.TableCfg{}, 104 roTxsLimiter: semaphore.NewWeighted(targetSemCount), // 1 less than max to allow unlocking 105 } 106 customBuckets := opts.bucketsCfg(kv.ChaindataTablesCfg) 107 for name, cfg := range customBuckets { // copy map to avoid changing global variable 108 db.buckets[name] = cfg 109 } 110 111 return db, nil 112 } 113 114 func (opts remoteOpts) MustOpen() kv.RwDB { 115 db, err := opts.Open() 116 if err != nil { 117 panic(err) 118 } 119 return db 120 } 121 122 // NewRemote defines new remove KV connection (without actually opening it) 123 // version parameters represent the version the KV client is expecting, 124 // compatibility check will be performed when the KV connection opens 125 func NewRemote(v gointerfaces.Version, logger log.Logger, remoteKV remote.KVClient) remoteOpts { 126 return remoteOpts{bucketsCfg: mdbx.WithChaindataTables, version: v, log: logger, remoteKV: remoteKV} 127 } 128 129 func (db *DB) PageSize() uint64 { panic("not implemented") } 130 func (db *DB) ReadOnly() bool { return true } 131 func (db *DB) AllTables() kv.TableCfg { return db.buckets } 132 133 func (db *DB) EnsureVersionCompatibility() bool { 134 versionReply, err := db.remoteKV.Version(context.Background(), &emptypb.Empty{}, grpc.WaitForReady(true)) 135 if err != nil { 136 db.log.Error("getting Version", "error", err) 137 return false 138 } 139 if !gointerfaces.EnsureVersion(db.opts.version, versionReply) { 140 db.log.Error("incompatible interface versions", "client", db.opts.version.String(), 141 "server", fmt.Sprintf("%d.%d.%d", versionReply.Major, versionReply.Minor, versionReply.Patch)) 142 return false 143 } 144 db.log.Info("interfaces compatible", "client", db.opts.version.String(), 145 "server", fmt.Sprintf("%d.%d.%d", versionReply.Major, versionReply.Minor, versionReply.Patch)) 146 return true 147 } 148 149 func (db *DB) Close() {} 150 151 func (db *DB) BeginRo(ctx context.Context) (txn kv.Tx, err error) { 152 select { 153 case <-ctx.Done(): 154 return nil, ctx.Err() 155 default: 156 } 157 158 if semErr := db.roTxsLimiter.Acquire(ctx, 1); semErr != nil { 159 return nil, semErr 160 } 161 162 defer func() { 163 // ensure we release the semaphore on error 164 if txn == nil { 165 db.roTxsLimiter.Release(1) 166 } 167 }() 168 169 streamCtx, streamCancelFn := context.WithCancel(ctx) // We create child context for the stream so we can cancel it to prevent leak 170 stream, err := db.remoteKV.Tx(streamCtx) 171 if err != nil { 172 streamCancelFn() 173 return nil, err 174 } 175 msg, err := stream.Recv() 176 if err != nil { 177 streamCancelFn() 178 return nil, err 179 } 180 return &tx{ctx: ctx, db: db, stream: stream, streamCancelFn: streamCancelFn, viewID: msg.ViewId, id: msg.TxId}, nil 181 } 182 func (db *DB) BeginTemporalRo(ctx context.Context) (kv.TemporalTx, error) { 183 t, err := db.BeginRo(ctx) 184 if err != nil { 185 return nil, err 186 } 187 return t.(kv.TemporalTx), nil 188 } 189 func (db *DB) BeginRw(ctx context.Context) (kv.RwTx, error) { 190 return nil, fmt.Errorf("remote db provider doesn't support .BeginRw method") 191 } 192 func (db *DB) BeginRwNosync(ctx context.Context) (kv.RwTx, error) { 193 return nil, fmt.Errorf("remote db provider doesn't support .BeginRw method") 194 } 195 func (db *DB) BeginTemporalRw(ctx context.Context) (kv.RwTx, error) { 196 return nil, fmt.Errorf("remote db provider doesn't support .BeginTemporalRw method") 197 } 198 func (db *DB) BeginTemporalRwNosync(ctx context.Context) (kv.RwTx, error) { 199 return nil, fmt.Errorf("remote db provider doesn't support .BeginTemporalRwNosync method") 200 } 201 202 func (db *DB) View(ctx context.Context, f func(tx kv.Tx) error) (err error) { 203 tx, err := db.BeginRo(ctx) 204 if err != nil { 205 return err 206 } 207 defer tx.Rollback() 208 return f(tx) 209 } 210 func (db *DB) ViewTemporal(ctx context.Context, f func(tx kv.TemporalTx) error) (err error) { 211 tx, err := db.BeginTemporalRo(ctx) 212 if err != nil { 213 return err 214 } 215 defer tx.Rollback() 216 return f(tx) 217 } 218 219 func (db *DB) Update(ctx context.Context, f func(tx kv.RwTx) error) (err error) { 220 return fmt.Errorf("remote db provider doesn't support .Update method") 221 } 222 func (db *DB) UpdateNosync(ctx context.Context, f func(tx kv.RwTx) error) (err error) { 223 return fmt.Errorf("remote db provider doesn't support .UpdateNosync method") 224 } 225 226 func (tx *tx) ViewID() uint64 { return tx.viewID } 227 func (tx *tx) CollectMetrics() {} 228 func (tx *tx) IncrementSequence(bucket string, amount uint64) (uint64, error) { 229 panic("not implemented yet") 230 } 231 func (tx *tx) ReadSequence(bucket string) (uint64, error) { 232 panic("not implemented yet") 233 } 234 func (tx *tx) Append(bucket string, k, v []byte) error { panic("no write methods") } 235 func (tx *tx) AppendDup(bucket string, k, v []byte) error { panic("no write methods") } 236 237 func (tx *tx) Commit() error { 238 panic("remote db is read-only") 239 } 240 241 func (tx *tx) Rollback() { 242 // don't close opened cursors - just close stream, server will cleanup everything well 243 tx.closeGrpcStream() 244 tx.db.roTxsLimiter.Release(1) 245 for _, c := range tx.streams { 246 c.Close() 247 } 248 } 249 func (tx *tx) DBSize() (uint64, error) { panic("not implemented") } 250 251 func (tx *tx) statelessCursor(bucket string) (kv.Cursor, error) { 252 if tx.statelessCursors == nil { 253 tx.statelessCursors = make(map[string]kv.Cursor) 254 } 255 c, ok := tx.statelessCursors[bucket] 256 if !ok { 257 var err error 258 c, err = tx.Cursor(bucket) 259 if err != nil { 260 return nil, err 261 } 262 tx.statelessCursors[bucket] = c 263 } 264 return c, nil 265 } 266 267 func (tx *tx) BucketSize(name string) (uint64, error) { panic("not implemented") } 268 269 func (tx *tx) ForEach(bucket string, fromPrefix []byte, walker func(k, v []byte) error) error { 270 it, err := tx.Range(bucket, fromPrefix, nil) 271 if err != nil { 272 return err 273 } 274 for it.HasNext() { 275 k, v, err := it.Next() 276 if err != nil { 277 return err 278 } 279 if err := walker(k, v); err != nil { 280 return err 281 } 282 } 283 return nil 284 } 285 286 func (tx *tx) ForPrefix(bucket string, prefix []byte, walker func(k, v []byte) error) error { 287 it, err := tx.Prefix(bucket, prefix) 288 if err != nil { 289 return err 290 } 291 for it.HasNext() { 292 k, v, err := it.Next() 293 if err != nil { 294 return err 295 } 296 if err := walker(k, v); err != nil { 297 return err 298 } 299 } 300 return nil 301 } 302 303 // TODO: this must be deprecated 304 func (tx *tx) ForAmount(bucket string, fromPrefix []byte, amount uint32, walker func(k, v []byte) error) error { 305 if amount == 0 { 306 return nil 307 } 308 c, err := tx.Cursor(bucket) 309 if err != nil { 310 return err 311 } 312 defer c.Close() 313 314 for k, v, err := c.Seek(fromPrefix); k != nil && amount > 0; k, v, err = c.Next() { 315 if err != nil { 316 return err 317 } 318 if err := walker(k, v); err != nil { 319 return err 320 } 321 amount-- 322 } 323 return nil 324 } 325 326 func (tx *tx) GetOne(bucket string, k []byte) (val []byte, err error) { 327 c, err := tx.statelessCursor(bucket) 328 if err != nil { 329 return nil, err 330 } 331 _, val, err = c.SeekExact(k) 332 return val, err 333 } 334 335 func (tx *tx) Has(bucket string, k []byte) (bool, error) { 336 c, err := tx.statelessCursor(bucket) 337 if err != nil { 338 return false, err 339 } 340 kk, _, err := c.Seek(k) 341 if err != nil { 342 return false, err 343 } 344 return bytes.Equal(k, kk), nil 345 } 346 347 func (c *remoteCursor) SeekExact(k []byte) (key, val []byte, err error) { 348 return c.seekExact(k) 349 } 350 351 func (c *remoteCursor) Prev() ([]byte, []byte, error) { 352 return c.prev() 353 } 354 355 func (tx *tx) Cursor(bucket string) (kv.Cursor, error) { 356 b := tx.db.buckets[bucket] 357 c := &remoteCursor{tx: tx, ctx: tx.ctx, bucketName: bucket, bucketCfg: b, stream: tx.stream} 358 tx.cursors = append(tx.cursors, c) 359 if err := c.stream.Send(&remote.Cursor{Op: remote.Op_OPEN, BucketName: c.bucketName}); err != nil { 360 return nil, err 361 } 362 msg, err := c.stream.Recv() 363 if err != nil { 364 return nil, err 365 } 366 c.id = msg.CursorId 367 return c, nil 368 } 369 370 func (tx *tx) ListBuckets() ([]string, error) { 371 return nil, fmt.Errorf("function ListBuckets is not implemented for remoteTx") 372 } 373 374 // func (c *remoteCursor) Put(k []byte, v []byte) error { panic("not supported") } 375 // func (c *remoteCursor) PutNoOverwrite(k []byte, v []byte) error { panic("not supported") } 376 // func (c *remoteCursor) Append(k []byte, v []byte) error { panic("not supported") } 377 // func (c *remoteCursor) Delete(k []byte) error { panic("not supported") } 378 // func (c *remoteCursor) DeleteCurrent() error { panic("not supported") } 379 func (c *remoteCursor) Count() (uint64, error) { 380 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_COUNT}); err != nil { 381 return 0, err 382 } 383 pair, err := c.stream.Recv() 384 if err != nil { 385 return 0, err 386 } 387 return binary.BigEndian.Uint64(pair.V), nil 388 389 } 390 391 func (c *remoteCursor) first() ([]byte, []byte, error) { 392 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_FIRST}); err != nil { 393 return []byte{}, nil, err 394 } 395 pair, err := c.stream.Recv() 396 if err != nil { 397 return []byte{}, nil, err 398 } 399 return pair.K, pair.V, nil 400 } 401 402 func (c *remoteCursor) next() ([]byte, []byte, error) { 403 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_NEXT}); err != nil { 404 return []byte{}, nil, err 405 } 406 pair, err := c.stream.Recv() 407 if err != nil { 408 return []byte{}, nil, err 409 } 410 return pair.K, pair.V, nil 411 } 412 func (c *remoteCursor) nextDup() ([]byte, []byte, error) { 413 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_NEXT_DUP}); err != nil { 414 return []byte{}, nil, err 415 } 416 pair, err := c.stream.Recv() 417 if err != nil { 418 return []byte{}, nil, err 419 } 420 return pair.K, pair.V, nil 421 } 422 func (c *remoteCursor) nextNoDup() ([]byte, []byte, error) { 423 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_NEXT_NO_DUP}); err != nil { 424 return []byte{}, nil, err 425 } 426 pair, err := c.stream.Recv() 427 if err != nil { 428 return []byte{}, nil, err 429 } 430 return pair.K, pair.V, nil 431 } 432 func (c *remoteCursor) prev() ([]byte, []byte, error) { 433 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_PREV}); err != nil { 434 return []byte{}, nil, err 435 } 436 pair, err := c.stream.Recv() 437 if err != nil { 438 return []byte{}, nil, err 439 } 440 return pair.K, pair.V, nil 441 } 442 func (c *remoteCursor) prevDup() ([]byte, []byte, error) { 443 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_PREV_DUP}); err != nil { 444 return []byte{}, nil, err 445 } 446 pair, err := c.stream.Recv() 447 if err != nil { 448 return []byte{}, nil, err 449 } 450 return pair.K, pair.V, nil 451 } 452 func (c *remoteCursor) prevNoDup() ([]byte, []byte, error) { 453 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_PREV_NO_DUP}); err != nil { 454 return []byte{}, nil, err 455 } 456 pair, err := c.stream.Recv() 457 if err != nil { 458 return []byte{}, nil, err 459 } 460 return pair.K, pair.V, nil 461 } 462 func (c *remoteCursor) last() ([]byte, []byte, error) { 463 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_LAST}); err != nil { 464 return []byte{}, nil, err 465 } 466 pair, err := c.stream.Recv() 467 if err != nil { 468 return []byte{}, nil, err 469 } 470 return pair.K, pair.V, nil 471 } 472 func (c *remoteCursor) setRange(k []byte) ([]byte, []byte, error) { 473 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_SEEK, K: k}); err != nil { 474 return []byte{}, nil, err 475 } 476 pair, err := c.stream.Recv() 477 if err != nil { 478 return []byte{}, nil, err 479 } 480 return pair.K, pair.V, nil 481 } 482 func (c *remoteCursor) seekExact(k []byte) ([]byte, []byte, error) { 483 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_SEEK_EXACT, K: k}); err != nil { 484 return []byte{}, nil, err 485 } 486 pair, err := c.stream.Recv() 487 if err != nil { 488 return []byte{}, nil, err 489 } 490 return pair.K, pair.V, nil 491 } 492 func (c *remoteCursor) getBothRange(k, v []byte) ([]byte, error) { 493 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_SEEK_BOTH, K: k, V: v}); err != nil { 494 return nil, err 495 } 496 pair, err := c.stream.Recv() 497 if err != nil { 498 return nil, err 499 } 500 return pair.V, nil 501 } 502 func (c *remoteCursor) seekBothExact(k, v []byte) ([]byte, []byte, error) { 503 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_SEEK_BOTH_EXACT, K: k, V: v}); err != nil { 504 return []byte{}, nil, err 505 } 506 pair, err := c.stream.Recv() 507 if err != nil { 508 return []byte{}, nil, err 509 } 510 return pair.K, pair.V, nil 511 } 512 func (c *remoteCursor) firstDup() ([]byte, error) { 513 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_FIRST_DUP}); err != nil { 514 return nil, err 515 } 516 pair, err := c.stream.Recv() 517 if err != nil { 518 return nil, err 519 } 520 return pair.V, nil 521 } 522 func (c *remoteCursor) lastDup() ([]byte, error) { 523 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_LAST_DUP}); err != nil { 524 return nil, err 525 } 526 pair, err := c.stream.Recv() 527 if err != nil { 528 return nil, err 529 } 530 return pair.V, nil 531 } 532 func (c *remoteCursor) getCurrent() ([]byte, []byte, error) { 533 if err := c.stream.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_CURRENT}); err != nil { 534 return []byte{}, nil, err 535 } 536 pair, err := c.stream.Recv() 537 if err != nil { 538 return []byte{}, nil, err 539 } 540 return pair.K, pair.V, nil 541 } 542 543 func (c *remoteCursor) Current() ([]byte, []byte, error) { 544 return c.getCurrent() 545 } 546 547 // Seek - doesn't start streaming (because much of code does only several .Seek calls without reading sequence of data) 548 // .Next() - does request streaming (if configured by user) 549 func (c *remoteCursor) Seek(seek []byte) ([]byte, []byte, error) { 550 return c.setRange(seek) 551 } 552 553 func (c *remoteCursor) First() ([]byte, []byte, error) { 554 return c.first() 555 } 556 557 // Next - returns next data element from server, request streaming (if configured by user) 558 func (c *remoteCursor) Next() ([]byte, []byte, error) { 559 return c.next() 560 } 561 562 func (c *remoteCursor) Last() ([]byte, []byte, error) { 563 return c.last() 564 } 565 566 func (tx *tx) closeGrpcStream() { 567 if tx.stream == nil { 568 return 569 } 570 defer tx.streamCancelFn() // hard cancel stream if graceful wasn't successful 571 572 if tx.streamingRequested { 573 // if streaming is in progress, can't use `CloseSend` - because 574 // server will not read it right not - it busy with streaming data 575 // TODO: set flag 'tx.streamingRequested' to false when got terminator from server (nil key or os.EOF) 576 tx.streamCancelFn() 577 } else { 578 // try graceful close stream 579 err := tx.stream.CloseSend() 580 if err != nil { 581 doLog := !grpcutil.IsEndOfStream(err) 582 if doLog { 583 log.Warn("couldn't send msg CloseSend to server", "err", err) 584 } 585 } else { 586 _, err = tx.stream.Recv() 587 if err != nil { 588 doLog := !grpcutil.IsEndOfStream(err) 589 if doLog { 590 log.Warn("received unexpected error from server after CloseSend", "err", err) 591 } 592 } 593 } 594 } 595 tx.stream = nil 596 tx.streamingRequested = false 597 } 598 599 func (c *remoteCursor) Close() { 600 if c.stream == nil { 601 return 602 } 603 st := c.stream 604 c.stream = nil 605 if err := st.Send(&remote.Cursor{Cursor: c.id, Op: remote.Op_CLOSE}); err == nil { 606 _, _ = st.Recv() 607 } 608 } 609 610 func (tx *tx) CursorDupSort(bucket string) (kv.CursorDupSort, error) { 611 b := tx.db.buckets[bucket] 612 c := &remoteCursor{tx: tx, ctx: tx.ctx, bucketName: bucket, bucketCfg: b, stream: tx.stream} 613 tx.cursors = append(tx.cursors, c) 614 if err := c.stream.Send(&remote.Cursor{Op: remote.Op_OPEN_DUP_SORT, BucketName: c.bucketName}); err != nil { 615 return nil, err 616 } 617 msg, err := c.stream.Recv() 618 if err != nil { 619 return nil, err 620 } 621 c.id = msg.CursorId 622 return &remoteCursorDupSort{remoteCursor: c}, nil 623 } 624 625 func (c *remoteCursorDupSort) SeekBothExact(k, v []byte) ([]byte, []byte, error) { 626 return c.seekBothExact(k, v) 627 } 628 629 func (c *remoteCursorDupSort) SeekBothRange(k, v []byte) ([]byte, error) { 630 return c.getBothRange(k, v) 631 } 632 633 func (c *remoteCursorDupSort) DeleteExact(k1, k2 []byte) error { panic("not supported") } 634 func (c *remoteCursorDupSort) AppendDup(k []byte, v []byte) error { panic("not supported") } 635 func (c *remoteCursorDupSort) PutNoDupData(k, v []byte) error { panic("not supported") } 636 func (c *remoteCursorDupSort) DeleteCurrentDuplicates() error { panic("not supported") } 637 func (c *remoteCursorDupSort) CountDuplicates() (uint64, error) { panic("not supported") } 638 639 func (c *remoteCursorDupSort) FirstDup() ([]byte, error) { return c.firstDup() } 640 func (c *remoteCursorDupSort) NextDup() ([]byte, []byte, error) { return c.nextDup() } 641 func (c *remoteCursorDupSort) NextNoDup() ([]byte, []byte, error) { return c.nextNoDup() } 642 func (c *remoteCursorDupSort) PrevDup() ([]byte, []byte, error) { return c.prevDup() } 643 func (c *remoteCursorDupSort) PrevNoDup() ([]byte, []byte, error) { return c.prevNoDup() } 644 func (c *remoteCursorDupSort) LastDup() ([]byte, error) { return c.lastDup() } 645 646 // Temporal Methods 647 func (tx *tx) DomainGetAsOf(name kv.Domain, k, k2 []byte, ts uint64) (v []byte, ok bool, err error) { 648 reply, err := tx.db.remoteKV.DomainGet(tx.ctx, &remote.DomainGetReq{TxId: tx.id, Table: string(name), K: k, K2: k2, Ts: ts}) 649 if err != nil { 650 return nil, false, err 651 } 652 return reply.V, reply.Ok, nil 653 } 654 655 func (tx *tx) DomainGet(name kv.Domain, k, k2 []byte) (v []byte, ok bool, err error) { 656 reply, err := tx.db.remoteKV.DomainGet(tx.ctx, &remote.DomainGetReq{TxId: tx.id, Table: string(name), K: k, K2: k2, Latest: true}) 657 if err != nil { 658 return nil, false, err 659 } 660 return reply.V, reply.Ok, nil 661 } 662 663 func (tx *tx) DomainRange(name kv.Domain, fromKey, toKey []byte, ts uint64, asc order.By, limit int) (it iter.KV, err error) { 664 return iter.PaginateKV(func(pageToken string) (keys, vals [][]byte, nextPageToken string, err error) { 665 reply, err := tx.db.remoteKV.DomainRange(tx.ctx, &remote.DomainRangeReq{TxId: tx.id, Table: string(name), FromKey: fromKey, ToKey: toKey, Ts: ts, OrderAscend: bool(asc), Limit: int64(limit)}) 666 if err != nil { 667 return nil, nil, "", err 668 } 669 return reply.Keys, reply.Values, reply.NextPageToken, nil 670 }), nil 671 } 672 func (tx *tx) HistoryGet(name kv.History, k []byte, ts uint64) (v []byte, ok bool, err error) { 673 reply, err := tx.db.remoteKV.HistoryGet(tx.ctx, &remote.HistoryGetReq{TxId: tx.id, Table: string(name), K: k, Ts: ts}) 674 if err != nil { 675 return nil, false, err 676 } 677 return reply.V, reply.Ok, nil 678 } 679 func (tx *tx) HistoryRange(name kv.History, fromTs, toTs int, asc order.By, limit int) (it iter.KV, err error) { 680 return iter.PaginateKV(func(pageToken string) (keys, vals [][]byte, nextPageToken string, err error) { 681 reply, err := tx.db.remoteKV.HistoryRange(tx.ctx, &remote.HistoryRangeReq{TxId: tx.id, Table: string(name), FromTs: int64(fromTs), ToTs: int64(toTs), OrderAscend: bool(asc), Limit: int64(limit)}) 682 if err != nil { 683 return nil, nil, "", err 684 } 685 return reply.Keys, reply.Values, reply.NextPageToken, nil 686 }), nil 687 } 688 689 func (tx *tx) IndexRange(name kv.InvertedIdx, k []byte, fromTs, toTs int, asc order.By, limit int) (timestamps iter.U64, err error) { 690 return iter.PaginateU64(func(pageToken string) (arr []uint64, nextPageToken string, err error) { 691 req := &remote.IndexRangeReq{TxId: tx.id, Table: string(name), K: k, FromTs: int64(fromTs), ToTs: int64(toTs), OrderAscend: bool(asc), Limit: int64(limit)} 692 reply, err := tx.db.remoteKV.IndexRange(tx.ctx, req) 693 if err != nil { 694 return nil, "", err 695 } 696 return reply.Timestamps, reply.NextPageToken, nil 697 }), nil 698 } 699 700 func (tx *tx) Prefix(table string, prefix []byte) (iter.KV, error) { 701 nextPrefix, ok := kv.NextSubtree(prefix) 702 if !ok { 703 return tx.Range(table, prefix, nil) 704 } 705 return tx.Range(table, prefix, nextPrefix) 706 } 707 708 func (tx *tx) rangeOrderLimit(table string, fromPrefix, toPrefix []byte, asc order.By, limit int) (iter.KV, error) { 709 return iter.PaginateKV(func(pageToken string) (keys [][]byte, values [][]byte, nextPageToken string, err error) { 710 req := &remote.RangeReq{TxId: tx.id, Table: table, FromPrefix: fromPrefix, ToPrefix: toPrefix, OrderAscend: bool(asc), Limit: int64(limit)} 711 reply, err := tx.db.remoteKV.Range(tx.ctx, req) 712 if err != nil { 713 return nil, nil, "", err 714 } 715 return reply.Keys, reply.Values, reply.NextPageToken, nil 716 }), nil 717 } 718 func (tx *tx) Range(table string, fromPrefix, toPrefix []byte) (iter.KV, error) { 719 return tx.rangeOrderLimit(table, fromPrefix, toPrefix, order.Asc, -1) 720 } 721 func (tx *tx) RangeAscend(table string, fromPrefix, toPrefix []byte, limit int) (iter.KV, error) { 722 return tx.rangeOrderLimit(table, fromPrefix, toPrefix, order.Asc, limit) 723 } 724 func (tx *tx) RangeDescend(table string, fromPrefix, toPrefix []byte, limit int) (iter.KV, error) { 725 return tx.rangeOrderLimit(table, fromPrefix, toPrefix, order.Desc, limit) 726 } 727 func (tx *tx) RangeDupSort(table string, key []byte, fromPrefix, toPrefix []byte, asc order.By, limit int) (iter.KV, error) { 728 panic("not implemented yet") 729 }