Exemple #1
0
/* do not change state in this func */
func (td *TransDi) processAckData(ackData *AckData) {
	transid := ackData.transid
	workerId := ackData.workerId
	logger.Debug("process ack: transid=%d, workerId=%d", transid, workerId)
	/* narrow window */
	msg := td.transWindow.ackOne(transid)
	if msg != nil && msg.Offset > td.ackedMinTransid {
		td.ackedMinTransid = msg.Offset
		err := td.cg.CommitUpto(msg)
		if err != nil {
			// TODO: optimized
			logger.Warning("fail to consumergroup.CommitUpto(): %s", err.Error())
			td.fatalErrorChan <- err
			return
		}
		logger.Debug("consumergroup.CommitUpTo %d", msg.Offset)
	}
	logger.Debug("transWindow size: %d", td.transWindow.window.Len())
	/* move worker */
	worker := td.transWorkers[workerId]
	worker.inWork = false
	err := worker.workIfNeed()
	if err != nil {
		logger.Fatal("fail to let worker to work: %s", err.Error())
		td.fatalErrorChan <- err
		return
	}
}
Exemple #2
0
func (z *Zookeeper) updateBrokerListAndWatch() {
	for {
		children, _, eventChan, err := z.zkConn.ChildrenW(fmt.Sprintf("%s/brokers/ids", z.cc.chroot))
		if err != nil {
			err = errors.New(fmt.Sprintf("fail to zk.ChildrenW: %s", err.Error()))
			logger.Fatal(err.Error())
			z.fatalErrorChan <- err
			return
		}
		if len(children) == 0 {
			logger.Warning("no broker found")
		} else {
			logger.Debug("using child: %s", children[0])
			val, _, err := z.zkConn.Get(fmt.Sprintf("%s/brokers/ids/%s", z.cc.chroot, children[0]))
			var brokerIdVal BrokerIdVal
			err = json.Unmarshal(val, &brokerIdVal)
			if err != nil {
				logger.Warning("fail to json.Unmarshal for broker id %s: %s", children[0], err.Error())
			}
			logger.Debug("broker id %s: host [%s] port [%d]", children[0], brokerIdVal.Host, brokerIdVal.Port)
			z.brokerIdValChan <- &brokerIdVal
		}
		<-eventChan
	}
}
Exemple #3
0
func (worker *TransWorker) run() {
	logger.Debug("worker %d start for module [%s]", worker.workerId, worker.moduleName)
	for transData := range worker.transDataChan {
		logger.Debug("worker begin: transid=%d, topic=%s, method=%s", transData.transid, transData.topic, transData.method)
		/* will block in worker.trans untile succeed in trans or reach retry limit */
		worker.trans(transData)
	}
}
Exemple #4
0
func (b *Broker) updateBrokerOffset() {
	if b.client == nil || b.client.Closed() {
		logger.Notice("broker.client not ready yet")
		return
	}
	topics, err := b.client.Topics()
	if err != nil {
		logger.Warning("fail to b.client.Topics(): %s", err.Error())
		return
	}
	for _, topic := range topics {
		partitions, err := b.client.Partitions(topic)
		if err != nil {
			logger.Warning("fail to b.client.Partitions(): %s", err.Error())
			continue
		}
		for _, partition := range partitions {
			offset, err := b.client.GetOffset(topic, partition, sarama.OffsetNewest)
			if err != nil {
				logger.Warning("fail to b.client.GetOffset topic=%s, partition=%d, err=%s", topic, partition, err.Error())
				continue
			}
			// TODO: use pool
			b.brokerOffsetChan <- &BrokerOffset{
				topic:     topic,
				partition: partition,
				offset:    offset,
			}
			logger.Debug("offset: topic=%s, partition=%d, offset=%d", topic, partition, offset)
		}
	}
}
Exemple #5
0
func (td *TransDi) run() {
	logger.Debug("transdi start for module [%s]", td.moduleName)
	for _, worker := range td.transWorkers {
		go worker.run()
	}
	td.state = WAIT_ACK_NONBLOCK
	for {
		switch td.state {
		case WAIT_ACK_NONBLOCK:
			td.waitAckNonBlock()
			continue
		case CHECK_NEED_WAIT_ACK:
			td.checkNeedWaitAck()
			continue
		case WAIT_ACK_BLOCK:
			td.waitAckBlock()
			continue
		case WAIT_ACK_AND_DI:
			td.waitAckAndDi()
			continue
		default:
			td.fatalErrorChan <- errors.New(fmt.Sprintf("invalid transdi run state: %d", td.state))
			break
		}
	}
}
Exemple #6
0
func (cc *CacheCluster) doDelFromMq(keys []interface{}, delTime, curDelay int64, doneServers map[string]interface{}, firstDel bool) (err error) {
	/* time to del ? */
	now := time.Now().Unix()
	delta := delTime + curDelay - now
	logger.Debug("delta=%d, delTime=%d, curDelay=%d, now=%d, firtDel=%t", delta, delTime, curDelay, now, firstDel)
	if delta > 0 {
		time.Sleep(time.Duration(delta) * time.Second)
		now = now + delta
	}
	err = cc.cachePool.doDel(keys, doneServers)
	if err != nil {
		/* put back to mq */
		err = cc.mqClient.addKeys(keys, doneServers, delTime, curDelay, false)
		if err != nil {
			return
		}
	} else {
		logger.Notice("del all keys done: cluster=%s, keys=%v, delay=%d", cc.clusterName, keys, curDelay)
	}
	if !firstDel {
		/* not first Del, so all delays has been in mq, we just quit and wait */
		return nil
	}
	/* ok, it is first del, we add all delays to mq here */
	ccc := cc.ccc
	delay := now - delTime
	logger.Debug("%d = %d - %d", delay, now, delTime)
	idx := sort.SearchInts(ccc.delayConfig, int(delay))
	if idx == len(ccc.delayConfig) {
		/* done */
		return nil
	}
	for ; idx < len(ccc.delayConfig); idx++ {
		if int64(ccc.delayConfig[idx]) <= delay {
			continue
		}
		// add back to mq with doneServers empty
		err = cc.mqClient.addKeys(keys, nil, delTime, int64(ccc.delayConfig[idx]), false)
		if err != nil {
			return
		}
	}
	return nil
}
func (hp *HttpProtocol) init() (err error) {
	logger.Debug("http protocol init")
	err = hp.initConfig()
	if err != nil {
		return
	}
	err = hp.initRegs()
	if err != nil {
		return
	}
	return nil
}
Exemple #8
0
func (worker *TransWorker) init() (err error) {
	logger.Debug("init trans worker for module [%s]: %d", worker.moduleName, worker.workerId)
	err = worker.initProtocol()
	if err != nil {
		return
	}
	worker.transQueue = list.New()
	worker.transDataChan = make(chan *TransData)
	worker.inWork = false
	worker.lastServerId = -1
	worker.serverNum = len(worker.backendServers)
	return nil
}
Exemple #9
0
/* Notice: this func shall ONLY be called in transdi routine */
func (worker *TransWorker) workIfNeed() (err error) {
	if !worker.inWork {
		e := worker.transQueue.Front()
		if e == nil {
			return nil
		}
		transData := e.Value.(*TransData)
		logger.Debug("add to worker chan: transid=%d, topic=%s, method=%s", transData.transid, transData.topic, transData.method)
		worker.transDataChan <- transData
		worker.inWork = true
		worker.transQueue.Remove(e)
	}
	return nil
}
Exemple #10
0
func (b *Broker) updateBrokerClient(brokerIdVal *BrokerIdVal) {
	if b.client != nil && b.client.Closed() == false {
		b.client.Close()
	}
	b.client = nil
	var err error
	b.client, err = sarama.NewClient([]string{fmt.Sprintf("%s:%d", brokerIdVal.Host, brokerIdVal.Port)}, b.brokerConfig)
	if err != nil {
		err = errors.New(fmt.Sprintf("fail to sarama.NewClient: %s", err.Error()))
		logger.Fatal(err.Error())
		b.fatalErrorChan <- err
		return
	}
	logger.Debug("success update broker client: %s:%d", brokerIdVal.Host, brokerIdVal.Port)
}
Exemple #11
0
func (worker *TransWorker) trans(transData *TransData) {
	var err error
	retry := 0
	for {
		serverId := (worker.lastServerId + 1) % (worker.serverNum)
		worker.lastServerId = serverId
		startTime := time.Now()
		err = worker.protocol.transData(worker.backendServers[serverId], transData)
		timeUsedMs := int(time.Now().Sub(startTime) / time.Millisecond)
		if err == nil {
			logger.Notice("module [%s]: worker[%d] success transData: server=%s, topic=%s, partition=%d, transid=%d, method=%s, proctime=%dms", worker.moduleName, worker.workerId, worker.backendServers[serverId], transData.topic, transData.partition, transData.transid, transData.method, timeUsedMs)
			ackData := &AckData{
				transid:  transData.transid,
				workerId: worker.workerId,
			}
			worker.ackDataChan <- ackData
			logger.Debug("add ackData: transid=%d", ackData.transid)
			return
		}
		logger.Notice("module [%s]: worker[%d] fail transData: server=%s, topic=%s, partition=%d, transid=%d, method=%s, proctime=%dms", worker.moduleName, worker.workerId, worker.backendServers[serverId], transData.topic, transData.partition, transData.transid, transData.method, timeUsedMs)
		/* check need retry */
		if worker.maxRetryTimes == -1 || retry < worker.maxRetryTimes {
			retry++
			time.Sleep(worker.failRetryInterval)
			continue
		}
		/* reatch retry limit */
		ackData := &AckData{
			transid:  transData.transid,
			workerId: worker.workerId,
		}
		worker.ackDataChan <- ackData
		logger.Debug("add ackData: transid=%d", ackData.transid)
		return
	}
}
Exemple #12
0
func (z *Zookeeper) updatePartitionAndWatch(cg, topic string, partition int32) {
	path := fmt.Sprintf("%s/consumers/%s/offsets/%s/%d", z.cc.chroot, cg, topic, partition)
	for {
		val, _, eventChan, err := z.zkConn.GetW(path)
		if err == zk.ErrNoNode {
			_, _, eventChan, err = z.zkConn.ExistsW(path)
			if err != nil {
				err = errors.New(fmt.Sprintf("fail to zk.ExistsW: path=%s, %s", path, err.Error()))
				logger.Fatal(err.Error())
				z.fatalErrorChan <- err
				return
			}
			<-eventChan
			continue
		}
		if err != nil {
			err = errors.New(fmt.Sprintf("fail to zk.GetW: path=%s, %s", path, err.Error()))
			logger.Fatal(err.Error())
			z.fatalErrorChan <- err
			return
		}
		if len(val) == 0 {
			logger.Warning("transfer partition val is empty: path=%s", path)
		} else {
			offset, err := strconv.ParseInt(string(val), 10, 64)
			if err != nil {
				err = errors.New(fmt.Sprintf("fail to transfer: strconv.ParseInt: %s", err.Error()))
				logger.Fatal(err.Error())
				z.fatalErrorChan <- err
				return
			}
			z.transferOffsetChan <- &TransferOffset{
				cg:        cg,
				topic:     topic,
				partition: partition,
				offset:    offset,
			}
			logger.Debug("see transfer: cg=%s, topic=%s, partition=%d, offset=%d", cg, topic, partition, offset)
		}
		event := <-eventChan
		// let root watcher to re-init
		if event.Type == zk.EventNotWatching {
			return
		}
	}
}
Exemple #13
0
func (d *Deleter) doDel(w http.ResponseWriter, r *http.Request) {
	/* get topic and method */
	logger.Debug("get one req: %s", r.URL.String())
	qv := r.URL.Query()
	topic := qv.Get("topic")
	if len(topic) == 0 {
		msg := fmt.Sprintf("invalid query, topic cannot be empty: %s", r.URL.String())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}
	cc, ok := d.cacheClusters[topic]
	if !ok {
		msg := fmt.Sprintf("invalid query, cache cluster is not exist: cluster [%s], %s", topic, r.URL.String())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}

	/* get post data */
	if r.ContentLength == 0 {
		logger.Warning("post data cannot be empty")
		d.response(w, http.StatusBadRequest, "post data cannot be empty")
		return
	}
	data := make([]byte, r.ContentLength)
	_, err := io.ReadFull(r.Body, data)
	if err != nil {
		msg := fmt.Sprintf("fail to read post data: %s", err.Error())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}
	/* unpack */
	buf := bytes.NewReader(data)
	buf.Seek(0, 0)
	msgr := msgp.NewReader(buf)
	reqi, err := msgr.ReadIntf()
	if err != nil {
		msg := fmt.Sprintf("fail to decode post data: %s", err.Error())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}
	req, ok := reqi.(map[string]interface{})
	if !ok {
		msg := fmt.Sprintf("invalid post data: data need map", r.URL.String())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}
	keysi, ok := req[gDelKeys]
	if !ok {
		msg := fmt.Sprintf("invalid post data: %s not exist: %s", gDelKeys, r.URL.String())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}
	keys, ok := keysi.([]interface{})
	if !ok {
		msg := fmt.Sprintf("invalid post data: %s not array: %s", gDelKeys, r.URL.String())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}
	if len(keys) == 0 {
		msg := fmt.Sprintf("invalid post data: len of %s array is 0: %s", gDelKeys, r.URL.String())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}
	delTimei, ok := req[gDelDelTime]
	if !ok {
		msg := fmt.Sprintf("invalid post data: %s not exist: %s", gDelDelTime, r.URL.String())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}
	delTime, ok := delTimei.(int64)
	if !ok {
		delTimet, ok := delTimei.(int)
		if !ok {
			delTimetu, ok := delTimei.(uint64)
			if !ok {
				msg := fmt.Sprintf("invalid post data: %s not int64 or uint64 or int: %s", gDelDelTime, r.URL.String())
				logger.Warning("%s", msg)
				d.response(w, http.StatusBadRequest, msg)
				return
			} else {
				delTime = int64(delTimetu)
			}
		} else {
			delTime = int64(delTimet)
		}
	}
	var curDelay int64
	curDelayi, ok := req[gDelCurDelay]
	if !ok {
		curDelay = 0
	} else if curDelay, ok = curDelayi.(int64); !ok {
		curDelayt, ok := curDelayi.(int)
		if !ok {
			curDelaytu, ok := curDelayi.(uint64)
			if !ok {
				msg := fmt.Sprintf("invalid post data: %s not int64 or int: %s", gDelCurDelay, r.URL.String())
				logger.Warning("%s", msg)
				d.response(w, http.StatusBadRequest, msg)
				return
			} else {
				curDelay = int64(curDelaytu)
			}
		} else {
			curDelay = int64(curDelayt)
		}
	}
	var isFromMq bool
	isFromMqi, ok := req[gDelFromMq]
	if !ok {
		isFromMq = false
	} else if isFromMq, ok = isFromMqi.(bool); !ok {
		msg := fmt.Sprintf("invalid post data: %s not bool: %s", gDelFromMq, r.URL.String())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}
	var doneServers map[string]interface{}
	doneServersi, ok := req[gDoneServers]
	if !ok {
		doneServers = make(map[string]interface{})
	} else if doneServers, ok = doneServersi.(map[string]interface{}); !ok {
		msg := fmt.Sprintf("invalid post data: %s not map[string]interface{}: %s", gDoneServers, r.URL.String())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}
	var firstDel bool
	firstDeli, ok := req[gFirstDel]
	if !ok {
		firstDel = true
	} else if firstDel, ok = firstDeli.(bool); !ok {
		msg := fmt.Sprintf("invalid post data: %s not bool: %s", gFirstDel, r.URL.String())
		logger.Warning("%s", msg)
		d.response(w, http.StatusBadRequest, msg)
		return
	}

	/* do del */
	err = cc.doDel(keys, delTime, curDelay, doneServers, isFromMq, firstDel)
	if err != nil {
		msg := fmt.Sprintf("fail to del: %s", err.Error())
		logger.Warning("%s", msg)
		d.response(w, http.StatusInternalServerError, msg)
		return
	}
	msg := fmt.Sprintf("success process: %s", r.URL.String())
	logger.Notice("%s", msg)
	d.response(w, http.StatusOK, msg)
	return
}