| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- package main
- import (
- "encoding/gob"
- "io"
- "log"
- "os"
- "sync"
- )
- type URLStore struct {
- urls map[string]string
- mu sync.RWMutex
- file *os.File
- }
- type record struct {
- Key, URL string
- }
- func NewURLStore(filename string) *URLStore {
- s := &URLStore{urls: make(map[string]string)}
- f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
- if err != nil {
- log.Fatal("Error opening URLStore:", err)
- }
- s.file = f
- if err := s.load(); err != nil {
- log.Println("Error loading URLStore:", err)
- }
- return s
- }
- func (s *URLStore) Get(key string) string {
- s.mu.RLock()
- defer s.mu.RUnlock()
- return s.urls[key]
- }
- func (s *URLStore) Set(key, url string) bool {
- s.mu.Lock()
- defer s.mu.Unlock()
- if _, present := s.urls[key]; present {
- return false
- }
- s.urls[key] = url
- return true
- }
- func (s *URLStore) Count() int {
- s.mu.RLock()
- defer s.mu.RUnlock()
- return len(s.urls)
- }
- func (s *URLStore) Put(url string) string {
- for {
- key := genKey(s.Count())
- if ok := s.Set(key, url); ok {
- if err := s.save(key, url); err != nil {
- log.Println("Error saving to URLStore:", err)
- }
- return key
- }
- }
- panic("shouldn't get here")
- }
- func (s *URLStore) load() error {
- if _, err := s.file.Seek(0, 0); err != nil {
- return err
- }
- d := gob.NewDecoder(s.file)
- var err error
- for err == nil {
- var r record
- if err = d.Decode(&r); err == nil {
- s.Set(r.Key, r.URL)
- }
- }
- if err == io.EOF {
- return nil
- }
- return err
- }
- func (s *URLStore) save(key, url string) error {
- e := gob.NewEncoder(s.file)
- return e.Encode(record{key, url})
- }
|