func (q *atomicMutationQueue) dequeueUptoSeqno(vbucket Vbucket, seqno Seqno, datach chan *MutationKeys) { //every DEQUEUE_POLL_INTERVAL milliseconds, check for new mutations ticker := time.NewTicker(time.Millisecond * DEQUEUE_POLL_INTERVAL) var dequeueSeq Seqno for _ = range ticker.C { for platform.LoadPointer(&q.head[vbucket]) != platform.LoadPointer(&q.tail[vbucket]) { //if queue is nonempty head := (*node)(platform.LoadPointer(&q.head[vbucket])) //copy the mutation pointer m := head.next.mutation if seqno >= m.meta.seqno { //free mutation pointer head.next.mutation = nil //move head to next platform.StorePointer(&q.head[vbucket], unsafe.Pointer(head.next)) platform.AddInt64(&q.size[vbucket], -1) //send mutation to caller dequeueSeq = m.meta.seqno datach <- m } //once the seqno is reached, close the channel if seqno <= dequeueSeq { ticker.Stop() close(datach) return } } } }
//PeekHead returns reference to a vbucket's mutation at head of queue without dequeue func (q *atomicMutationQueue) PeekHead(vbucket Vbucket) *MutationKeys { if platform.LoadPointer(&q.head[vbucket]) != platform.LoadPointer(&q.tail[vbucket]) { //if queue is nonempty head := (*node)(platform.LoadPointer(&q.head[vbucket])) return head.mutation } return nil }
//Enqueue will enqueue the mutation reference for given vbucket. //Caller should not free the mutation till it is dequeued. //Mutation will not be copied internally by the queue. //caller can call appch to force this call to return. Otherwise //this is a blocking call till there is a slot available for enqueue. func (q *atomicMutationQueue) Enqueue(mutation *MutationKeys, vbucket Vbucket, appch StopChannel) error { if vbucket < 0 || vbucket > Vbucket(q.numVbuckets)-1 { return errors.New("vbucket out of range") } //no more requests are taken once queue //is marked as destroyed if q.isDestroyed { return nil } //create a new node n := q.allocNode(vbucket, appch) if n == nil { return nil } n.mutation = mutation n.next = nil //point tail's next to new node tail := (*node)(platform.LoadPointer(&q.tail[vbucket])) tail.next = n //update tail to new node platform.StorePointer(&q.tail[vbucket], unsafe.Pointer(tail.next)) platform.AddInt64(&q.size[vbucket], 1) return nil }
//DequeueSingleElement dequeues a single element and returns. //Returns nil in case of empty queue. func (q *atomicMutationQueue) DequeueSingleElement(vbucket Vbucket) *MutationKeys { if platform.LoadPointer(&q.head[vbucket]) != platform.LoadPointer(&q.tail[vbucket]) { //if queue is nonempty head := (*node)(platform.LoadPointer(&q.head[vbucket])) //copy the mutation pointer m := head.next.mutation //free mutation pointer head.next.mutation = nil //move head to next platform.StorePointer(&q.head[vbucket], unsafe.Pointer(head.next)) platform.AddInt64(&q.size[vbucket], -1) return m } return nil }
//popFreeList removes a node from freelist and returns to caller. //if freelist is empty, it returns nil. func (q *atomicMutationQueue) popFreeList(vbucket Vbucket) *node { if q.free[vbucket] != (*node)(platform.LoadPointer(&q.head[vbucket])) { n := q.free[vbucket] q.free[vbucket] = q.free[vbucket].next n.mutation = nil n.next = nil return n } else { return nil } }
func (c *GsiClient) setBucketHash(bucketn string, crc64 uint64) { for { ptr := platform.LoadPointer(&c.bucketHash) oldm := (*map[string]uint64)(ptr) newm := map[string]uint64{} for k, v := range *oldm { newm[k] = v } newm[bucketn] = crc64 if platform.CompareAndSwapPointer(&c.bucketHash, ptr, unsafe.Pointer(&newm)) { return } } }
func (b *Bucket) replaceConnPools(with []*connectionPool) { for { old := platform.LoadPointer(&b.connPools) if platform.CompareAndSwapPointer(&b.connPools, old, unsafe.Pointer(&with)) { if old != nil { for _, pool := range *(*[]*connectionPool)(old) { if pool != nil { pool.Close() } } } return } } }
func (h *ConfigHolder) Load() Config { confptr := platform.LoadPointer(&h.ptr) return *(*Config)(confptr) }
func getBlockPool() *sync.Pool { return (*sync.Pool)(platform.LoadPointer(&blockPool)) }
func (c *GsiClient) getBucketHash(bucketn string) (uint64, bool) { bucketHash := (*map[string]uint64)(platform.LoadPointer(&c.bucketHash)) crc64, ok := (*bucketHash)[bucketn] return crc64, ok }
func (b Bucket) getConnPools() []*connectionPool { return *(*[]*connectionPool)(platform.LoadPointer(&b.connPools)) }
// Nodes returns teh current list of nodes servicing this bucket. func (b Bucket) Nodes() []Node { return *(*[]Node)(platform.LoadPointer(&b.nodeList)) }
// VBServerMap returns the current VBucketServerMap. func (b *Bucket) VBServerMap() *VBucketServerMap { return (*VBucketServerMap)(platform.LoadPointer(&(b.vBucketServerMap))) }
func (h IndexerStatsHolder) Get() *IndexerStats { return (*IndexerStats)(platform.LoadPointer(&h.ptr)) }