github.com/TeaOSLab/EdgeNode@v1.3.8/internal/caches/writer_memory.go (about) 1 package caches 2 3 import ( 4 "errors" 5 "github.com/TeaOSLab/EdgeNode/internal/utils/fasttime" 6 "github.com/cespare/xxhash/v2" 7 "github.com/iwind/TeaGo/types" 8 "sync" 9 "sync/atomic" 10 ) 11 12 type MemoryWriter struct { 13 storage *MemoryStorage 14 15 key string 16 expiredAt int64 17 headerSize int64 18 bodySize int64 19 status int 20 isDirty bool 21 22 expectedBodySize int64 23 maxSize int64 24 25 hash uint64 26 item *MemoryItem 27 endFunc func(valueItem *MemoryItem) 28 once sync.Once 29 } 30 31 func NewMemoryWriter(memoryStorage *MemoryStorage, key string, expiredAt int64, status int, isDirty bool, expectedBodySize int64, maxSize int64, endFunc func(valueItem *MemoryItem)) *MemoryWriter { 32 var valueItem = &MemoryItem{ 33 ExpiresAt: expiredAt, 34 ModifiedAt: fasttime.Now().Unix(), 35 Status: status, 36 } 37 38 if expectedBodySize > 0 { 39 valueItem.BodyValue = make([]byte, 0, expectedBodySize) 40 } 41 42 var w = &MemoryWriter{ 43 storage: memoryStorage, 44 key: key, 45 expiredAt: expiredAt, 46 item: valueItem, 47 status: status, 48 isDirty: isDirty, 49 expectedBodySize: expectedBodySize, 50 maxSize: maxSize, 51 endFunc: endFunc, 52 } 53 54 w.hash = w.calculateHash(key) 55 56 return w 57 } 58 59 // WriteHeader 写入数据 60 func (this *MemoryWriter) WriteHeader(data []byte) (n int, err error) { 61 this.headerSize += int64(len(data)) 62 this.item.HeaderValue = append(this.item.HeaderValue, data...) 63 return len(data), nil 64 } 65 66 // Write 写入数据 67 func (this *MemoryWriter) Write(data []byte) (n int, err error) { 68 var l = len(data) 69 if l == 0 { 70 return 71 } 72 73 if this.item.IsPrepared { 74 if this.item.WriteOffset+int64(l) > this.expectedBodySize { 75 err = ErrWritingUnavailable 76 return 77 } 78 copy(this.item.BodyValue[this.item.WriteOffset:], data) 79 this.item.WriteOffset += int64(l) 80 } else { 81 this.item.BodyValue = append(this.item.BodyValue, data...) 82 } 83 84 this.bodySize += int64(l) 85 86 // 检查尺寸 87 if this.maxSize > 0 && this.bodySize > this.maxSize { 88 err = ErrEntityTooLarge 89 this.storage.IgnoreKey(this.key, this.maxSize) 90 return l, err 91 } 92 93 return l, nil 94 } 95 96 // WriteAt 在指定位置写入数据 97 func (this *MemoryWriter) WriteAt(offset int64, b []byte) error { 98 _ = b 99 _ = offset 100 return errors.New("not supported") 101 } 102 103 // HeaderSize 数据尺寸 104 func (this *MemoryWriter) HeaderSize() int64 { 105 return this.headerSize 106 } 107 108 // BodySize 主体内容尺寸 109 func (this *MemoryWriter) BodySize() int64 { 110 return this.bodySize 111 } 112 113 // Close 关闭 114 func (this *MemoryWriter) Close() error { 115 // 需要在Locker之外 116 defer this.once.Do(func() { 117 this.endFunc(this.item) 118 }) 119 120 if this.item == nil { 121 return nil 122 } 123 124 // check content length 125 if this.expectedBodySize > 0 && this.bodySize != this.expectedBodySize { 126 this.storage.locker.Lock() 127 delete(this.storage.valuesMap, this.hash) 128 this.storage.locker.Unlock() 129 return ErrUnexpectedContentLength 130 } 131 132 this.storage.locker.Lock() 133 this.item.IsDone = true 134 var err error 135 if this.isDirty { 136 if this.storage.parentStorage != nil { 137 this.storage.valuesMap[this.hash] = this.item 138 139 select { 140 case this.storage.dirtyChan <- types.String(this.bodySize) + "@" + this.key: 141 atomic.AddInt64(&this.storage.totalDirtySize, this.bodySize) 142 default: 143 // remove from values map 144 delete(this.storage.valuesMap, this.hash) 145 146 err = ErrWritingQueueFull 147 } 148 } else { 149 this.storage.valuesMap[this.hash] = this.item 150 } 151 } else { 152 this.storage.valuesMap[this.hash] = this.item 153 } 154 155 this.storage.locker.Unlock() 156 157 return err 158 } 159 160 // Discard 丢弃 161 func (this *MemoryWriter) Discard() error { 162 // 需要在Locker之外 163 defer this.once.Do(func() { 164 this.endFunc(this.item) 165 }) 166 167 this.storage.locker.Lock() 168 delete(this.storage.valuesMap, this.hash) 169 this.storage.locker.Unlock() 170 return nil 171 } 172 173 // Key 获取Key 174 func (this *MemoryWriter) Key() string { 175 return this.key 176 } 177 178 // ExpiredAt 过期时间 179 func (this *MemoryWriter) ExpiredAt() int64 { 180 return this.expiredAt 181 } 182 183 // ItemType 内容类型 184 func (this *MemoryWriter) ItemType() ItemType { 185 return ItemTypeMemory 186 } 187 188 // 计算Key Hash 189 func (this *MemoryWriter) calculateHash(key string) uint64 { 190 return xxhash.Sum64String(key) 191 }