github.com/mithrandie/csvq@v1.18.1/lib/file/container.go (about) 1 package file 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "strings" 8 "time" 9 ) 10 11 type Container struct { 12 m map[string]*Handler 13 } 14 15 func NewContainer() *Container { 16 return &Container{ 17 m: make(map[string]*Handler), 18 } 19 } 20 21 func (c *Container) Keys() []string { 22 l := make([]string, 0, len(c.m)) 23 for k := range c.m { 24 l = append(l, k) 25 } 26 return l 27 } 28 29 func (c *Container) Add(path string, handler *Handler) error { 30 key := strings.ToUpper(path) 31 if _, ok := c.m[key]; ok { 32 return errors.New(fmt.Sprintf("file %s already opened", path)) 33 } 34 c.m[key] = handler 35 return nil 36 } 37 38 func (c *Container) Remove(path string) { 39 key := strings.ToUpper(path) 40 if _, ok := c.m[key]; ok { 41 delete(c.m, key) 42 } 43 } 44 45 func (c *Container) CreateHandlerWithoutLock(ctx context.Context, path string, defaultWaitTimeout time.Duration, retryDelay time.Duration) (*Handler, error) { 46 return c.createHandler(ctx, path, defaultWaitTimeout, retryDelay, NewHandlerWithoutLock) 47 } 48 49 func (c *Container) CreateHandlerForRead(ctx context.Context, path string, defaultWaitTimeout time.Duration, retryDelay time.Duration) (*Handler, error) { 50 return c.createHandler(ctx, path, defaultWaitTimeout, retryDelay, NewHandlerForRead) 51 } 52 53 func (c *Container) CreateHandlerForCreate(path string) (*Handler, error) { 54 return c.createHandler(nil, path, DefaultWaitTimeout, DefaultRetryDelay, newHandlerForCreate) 55 } 56 57 func (c *Container) CreateHandlerForUpdate(ctx context.Context, path string, defaultWaitTimeout time.Duration, retryDelay time.Duration) (*Handler, error) { 58 return c.createHandler(ctx, path, defaultWaitTimeout, retryDelay, NewHandlerForUpdate) 59 } 60 61 func (c *Container) createHandler(ctx context.Context, path string, defaultWaitTimeout time.Duration, retryDelay time.Duration, fn func(context.Context, string, time.Duration, time.Duration) (*Handler, error)) (*Handler, error) { 62 h, err := fn(ctx, path, defaultWaitTimeout, retryDelay) 63 if err != nil { 64 return nil, err 65 } 66 67 if err := c.Add(h.path, h); err != nil { 68 return h, closeIsolatedHandler(h, err) 69 } 70 return h, nil 71 } 72 73 func (c *Container) Close(h *Handler) error { 74 if h == nil { 75 return nil 76 } 77 78 key := strings.ToUpper(h.Path()) 79 if _, ok := c.m[key]; ok { 80 if err := c.m[key].close(); err != nil { 81 return err 82 } 83 c.Remove(h.Path()) 84 } 85 return nil 86 } 87 88 func (c *Container) Commit(h *Handler) error { 89 if h == nil { 90 return nil 91 } 92 93 key := strings.ToUpper(h.Path()) 94 if _, ok := c.m[key]; ok { 95 if err := c.m[key].commit(); err != nil { 96 return err 97 } 98 c.Remove(h.Path()) 99 } 100 return nil 101 } 102 103 func (c *Container) CloseWithErrors(h *Handler) (err error) { 104 if h == nil { 105 return nil 106 } 107 108 key := strings.ToUpper(h.Path()) 109 if _, ok := c.m[key]; ok { 110 err = c.m[key].closeWithErrors() 111 c.Remove(h.Path()) 112 } 113 return 114 } 115 116 func (c *Container) CloseAll() error { 117 for k := range c.m { 118 if err := c.Close(c.m[k]); err != nil { 119 return err 120 } 121 } 122 return nil 123 } 124 125 func (c *Container) CloseAllWithErrors() error { 126 var errs []error 127 for k := range c.m { 128 if err := c.CloseWithErrors(c.m[k]); err != nil { 129 errs = append(errs, err.(*ForcedUnlockError).Errors...) 130 } 131 } 132 133 return NewForcedUnlockError(errs) 134 }