store.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package main
  2. import (
  3. "encoding/gob"
  4. "io"
  5. "log"
  6. "os"
  7. "sync"
  8. )
  9. type URLStore struct {
  10. urls map[string]string
  11. mu sync.RWMutex
  12. file *os.File
  13. }
  14. type record struct {
  15. Key, URL string
  16. }
  17. func NewURLStore(filename string) *URLStore {
  18. s := &URLStore{urls: make(map[string]string)}
  19. f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
  20. if err != nil {
  21. log.Fatal("Error opening URLStore:", err)
  22. }
  23. s.file = f
  24. if err := s.load(); err != nil {
  25. log.Println("Error loading URLStore:", err)
  26. }
  27. return s
  28. }
  29. func (s *URLStore) Get(key string) string {
  30. s.mu.RLock()
  31. defer s.mu.RUnlock()
  32. return s.urls[key]
  33. }
  34. func (s *URLStore) Set(key, url string) bool {
  35. s.mu.Lock()
  36. defer s.mu.Unlock()
  37. if _, present := s.urls[key]; present {
  38. return false
  39. }
  40. s.urls[key] = url
  41. return true
  42. }
  43. func (s *URLStore) Count() int {
  44. s.mu.RLock()
  45. defer s.mu.RUnlock()
  46. return len(s.urls)
  47. }
  48. func (s *URLStore) Put(url string) string {
  49. for {
  50. key := genKey(s.Count())
  51. if ok := s.Set(key, url); ok {
  52. if err := s.save(key, url); err != nil {
  53. log.Println("Error saving to URLStore:", err)
  54. }
  55. return key
  56. }
  57. }
  58. panic("shouldn't get here")
  59. }
  60. func (s *URLStore) load() error {
  61. if _, err := s.file.Seek(0, 0); err != nil {
  62. return err
  63. }
  64. d := gob.NewDecoder(s.file)
  65. var err error
  66. for err == nil {
  67. var r record
  68. if err = d.Decode(&r); err == nil {
  69. s.Set(r.Key, r.URL)
  70. }
  71. }
  72. if err == io.EOF {
  73. return nil
  74. }
  75. return err
  76. }
  77. func (s *URLStore) save(key, url string) error {
  78. e := gob.NewEncoder(s.file)
  79. return e.Encode(record{key, url})
  80. }