Example #1
0
File: uQueue.go Project: jnan77/uq
// Pop implements Pop interface
func (u *UnitedQueue) Pop(key string) (string, []byte, error) {
	key = strings.TrimPrefix(key, "/")
	key = strings.TrimSuffix(key, "/")

	parts := strings.Split(key, "/")
	if len(parts) != 2 {
		return "", nil, utils.NewError(
			utils.ErrBadKey,
			`pop key parts error: `+utils.ItoaQuick(len(parts)),
		)
	}

	tName := parts[0]
	lName := parts[1]

	u.topicsLock.RLock()
	t, ok := u.topics[tName]
	u.topicsLock.RUnlock()
	if !ok {
		// log.Printf("topic[%s] not existed.", tName)
		return "", nil, utils.NewError(
			utils.ErrTopicNotExisted,
			`queue pop`,
		)
	}

	id, data, err := t.pop(lName)
	if err != nil {
		return "", nil, err
	}

	return utils.Acatui(key, "/", id), data, nil
}
Example #2
0
func (t *topic) removeMsgData() error {
	for i := t.head; i < t.tail; i++ {
		key := utils.Acatui(t.name, ":", i)
		err := t.q.delData(key)
		if err != nil {
			log.Printf("topic[%s] del data[%s] error; %s", t.name, key, err)
			continue
		}
	}
	return nil
}
Example #3
0
func (t *topic) clean() (quit bool) {
	quit = false

	t.headLock.Lock()
	defer t.headLock.Unlock()

	// starting := t.head
	endTime := time.Now().Add(bgCleanTimeout)
	// log.Printf("topic[%s] begin to clean at %d", t.name, starting)

	// defer func() {
	// 	if t.head != starting {
	// 		log.Printf("topic[%s] garbage[%d - %d] are cleaned", t.name, starting, t.head-1)
	// 	}
	// }()

	ending := t.getEnd()
	for t.head < ending {
		select {
		case <-t.quit:
			quit = true
			// log.Printf("topic[%s] catched quit at %d", t.name, t.head)
			return
		default:
			// nothing todo
		}

		if time.Now().After(endTime) {
			// log.Printf("topic[%s] cleaning timeout, break at %d", t.name, t.head)
			return
		}

		key := utils.Acatui(t.name, ":", t.head)
		err := t.q.delData(key)
		if err != nil {
			log.Printf("topic[%s] del %s error; %s", t.name, key, err)
			return
		}

		t.head++
		err = t.exportHead()
		if err != nil {
			log.Printf("topic[%s] export head error: %s", t.name, err)
			return
		}
	}

	return
}
Example #4
0
func (t *topic) push(data []byte) error {
	t.tailLock.Lock()
	defer t.tailLock.Unlock()

	key := utils.Acatui(t.name, ":", t.tail)
	err := t.q.setData(key, data)
	if err != nil {
		return err
	}
	// log.Printf("topic[%s] %s pushed.", t.name, string(data))

	t.tail++
	err = t.exportTail()
	if err != nil {
		t.tail--
		return err
	}

	return nil
}
Example #5
0
File: uQueue.go Project: jnan77/uq
// MultiPop implements MultiPop interface
func (u *UnitedQueue) MultiPop(key string, n int) ([]string, [][]byte, error) {
	key = strings.TrimPrefix(key, "/")
	key = strings.TrimSuffix(key, "/")

	parts := strings.Split(key, "/")
	if len(parts) != 2 {
		return nil, nil, utils.NewError(
			utils.ErrBadKey,
			`mPop key parts error: `+utils.ItoaQuick(len(parts)),
		)
	}

	tName := parts[0]
	lName := parts[1]

	u.topicsLock.RLock()
	t, ok := u.topics[tName]
	u.topicsLock.RUnlock()
	if !ok {
		// log.Printf("topic[%s] not existed.", tName)
		return nil, nil, utils.NewError(
			utils.ErrTopicNotExisted,
			`queue multiPop`,
		)
	}

	ids, datas, err := t.mPop(lName, n)
	if err != nil {
		return nil, nil, err
	}

	keys := make([]string, len(ids))
	for i, id := range ids {
		keys[i] = utils.Acatui(key, "/", id)
	}
	return keys, datas, nil
}
Example #6
0
func (t *topic) mPush(datas [][]byte) error {
	t.tailLock.Lock()
	defer t.tailLock.Unlock()

	oldTail := t.tail
	for _, data := range datas {
		key := utils.Acatui(t.name, ":", t.tail)
		err := t.q.setData(key, data)
		if err != nil {
			t.tail = oldTail
			return err
		}
		// log.Printf("topic[%s] %s pushed.", t.name, string(data))
		t.tail++
	}

	err := t.exportTail()
	if err != nil {
		t.tail = oldTail
		return err
	}

	return nil
}
Example #7
0
func (t *topic) setData(id uint64, data []byte) error {
	key := utils.Acatui(t.name, ":", id)
	return t.q.setData(key, data)
}
Example #8
0
func (t *topic) getData(id uint64) ([]byte, error) {
	key := utils.Acatui(t.name, ":", id)
	return t.q.getData(key)
}