cache.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package cachefile
  2. import (
  3. "os"
  4. "time"
  5. "github.com/sagernet/sing-box/adapter"
  6. "go.etcd.io/bbolt"
  7. )
  8. var bucketSelected = []byte("selected")
  9. var _ adapter.ClashCacheFile = (*CacheFile)(nil)
  10. type CacheFile struct {
  11. DB *bbolt.DB
  12. }
  13. func Open(path string) (*CacheFile, error) {
  14. const fileMode = 0o666
  15. options := bbolt.Options{Timeout: time.Second}
  16. db, err := bbolt.Open(path, fileMode, &options)
  17. switch err {
  18. case bbolt.ErrInvalid, bbolt.ErrChecksum, bbolt.ErrVersionMismatch:
  19. if err = os.Remove(path); err != nil {
  20. break
  21. }
  22. db, err = bbolt.Open(path, 0o666, &options)
  23. }
  24. if err != nil {
  25. return nil, err
  26. }
  27. return &CacheFile{db}, nil
  28. }
  29. func (c *CacheFile) LoadSelected(group string) string {
  30. var selected string
  31. c.DB.View(func(t *bbolt.Tx) error {
  32. bucket := t.Bucket(bucketSelected)
  33. if bucket == nil {
  34. return nil
  35. }
  36. selectedBytes := bucket.Get([]byte(group))
  37. if len(selectedBytes) > 0 {
  38. selected = string(selectedBytes)
  39. }
  40. return nil
  41. })
  42. return selected
  43. }
  44. func (c *CacheFile) StoreSelected(group, selected string) error {
  45. return c.DB.Batch(func(t *bbolt.Tx) error {
  46. bucket, err := t.CreateBucketIfNotExists(bucketSelected)
  47. if err != nil {
  48. return err
  49. }
  50. return bucket.Put([]byte(group), []byte(selected))
  51. })
  52. }
  53. func (c *CacheFile) Close() error {
  54. return c.DB.Close()
  55. }