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  }