| 67 | } |
| 68 | |
| 69 | func (seg *segment) set(key, value []byte, hashVal uint64, expireSeconds int) (err error) { |
| 70 | if len(key) > 65535 { |
| 71 | return ErrLargeKey |
| 72 | } |
| 73 | maxKeyValLen := len(seg.rb.data)/4 - ENTRY_HDR_SIZE |
| 74 | if len(key)+len(value) > maxKeyValLen { |
| 75 | // Do not accept large entry. |
| 76 | return ErrLargeEntry |
| 77 | } |
| 78 | now := seg.timer.Now() |
| 79 | expireAt := uint32(0) |
| 80 | if expireSeconds > 0 { |
| 81 | expireAt = now + uint32(expireSeconds) |
| 82 | } |
| 83 | |
| 84 | slotId := uint8(hashVal >> 8) |
| 85 | hash16 := uint16(hashVal >> 16) |
| 86 | slot := seg.getSlot(slotId) |
| 87 | idx, match := seg.lookup(slot, hash16, key) |
| 88 | |
| 89 | var hdrBuf [ENTRY_HDR_SIZE]byte |
| 90 | hdr := (*entryHdr)(unsafe.Pointer(&hdrBuf[0])) |
| 91 | if match { |
| 92 | matchedPtr := &slot[idx] |
| 93 | seg.rb.ReadAt(hdrBuf[:], matchedPtr.offset) |
| 94 | hdr.slotId = slotId |
| 95 | hdr.hash16 = hash16 |
| 96 | hdr.keyLen = uint16(len(key)) |
| 97 | originAccessTime := hdr.accessTime |
| 98 | hdr.accessTime = now |
| 99 | hdr.expireAt = expireAt |
| 100 | hdr.valLen = uint32(len(value)) |
| 101 | if hdr.valCap >= hdr.valLen { |
| 102 | // in place overwrite |
| 103 | atomic.AddInt64(&seg.totalTime, int64(hdr.accessTime)-int64(originAccessTime)) |
| 104 | seg.rb.WriteAt(hdrBuf[:], matchedPtr.offset) |
| 105 | seg.rb.WriteAt(value, matchedPtr.offset+ENTRY_HDR_SIZE+int64(hdr.keyLen)) |
| 106 | atomic.AddInt64(&seg.overwrites, 1) |
| 107 | return |
| 108 | } |
| 109 | // avoid unnecessary memory copy. |
| 110 | seg.delEntryPtr(slotId, slot, idx) |
| 111 | match = false |
| 112 | // increase capacity and limit entry len. |
| 113 | for hdr.valCap < hdr.valLen { |
| 114 | hdr.valCap *= 2 |
| 115 | } |
| 116 | if hdr.valCap > uint32(maxKeyValLen-len(key)) { |
| 117 | hdr.valCap = uint32(maxKeyValLen - len(key)) |
| 118 | } |
| 119 | } else { |
| 120 | hdr.slotId = slotId |
| 121 | hdr.hash16 = hash16 |
| 122 | hdr.keyLen = uint16(len(key)) |
| 123 | hdr.accessTime = now |
| 124 | hdr.expireAt = expireAt |
| 125 | hdr.valLen = uint32(len(value)) |
| 126 | hdr.valCap = uint32(len(value)) |