snapshot.go 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. package sqlitex
  2. import (
  3. "context"
  4. "runtime"
  5. "github.com/go-llsqlite/crawshaw"
  6. )
  7. // GetSnapshot returns a Snapshot that should remain available for reads until
  8. // it is garbage collected.
  9. //
  10. // This sets aside a Conn from the Pool with an open read transaction until the
  11. // Snapshot is garbage collected or the Pool is closed. Thus, until the
  12. // returned Snapshot is garbage collected, the Pool will have one fewer Conn,
  13. // and it should not be possible for the WAL to be checkpointed beyond the
  14. // point of the Snapshot.
  15. //
  16. // See sqlite.Conn.GetSnapshot and sqlite.Snapshot for more details.
  17. func (p *Pool) GetSnapshot(ctx context.Context, schema string) (*sqlite.Snapshot, error) {
  18. conn := p.Get(ctx)
  19. if conn == nil {
  20. return nil, context.Canceled
  21. }
  22. conn.SetInterrupt(nil)
  23. s, release, err := conn.GetSnapshot(schema)
  24. if err != nil {
  25. return nil, err
  26. }
  27. snapshotGCd := make(chan struct{})
  28. runtime.SetFinalizer(s, nil)
  29. runtime.SetFinalizer(s, func(s *sqlite.Snapshot) {
  30. // Free the C resources associated with the Snapshot.
  31. s.Free()
  32. close(snapshotGCd)
  33. })
  34. go func() {
  35. select {
  36. case <-p.closed:
  37. case <-snapshotGCd:
  38. }
  39. // Allow the WAL to be checkpointed past the point of
  40. // the Snapshot.
  41. release()
  42. // Return the conn to the Pool for reuse.
  43. p.Put(conn)
  44. }()
  45. return s, nil
  46. }