// RuntimeMap generates an automatic runtime map function based on the given // rcv function. // // If there was an error in the rcv function, it will return "nil" and the // message will be dropped. func RuntimeMap(rcv RcvFunc) MapFunc { return func(msg Msg, ctx MapContext) (cells MappedCells) { defer func() { if r := recover(); r != nil { glog.Errorf("runtime map cannot find the mapped cells") cells = nil } }() q := ctx.(*qee) rCtx := runtimeRcvContext{ qee: q, state: state.NewTransactional(q.app.newState()), } if err := rcv(msg, rCtx); err != nil { return nil } for _, d := range rCtx.state.Dicts() { d.ForEach(func(k string, v interface{}) bool { cells = append(cells, CellKey{Dict: d.Name(), Key: k}) return true }) } return } }
func (a *app) initQee() { a.qee = &qee{ dataCh: newMsgChannel(a.hive.config.DataChBufSize), ctrlCh: make(chan cmdAndChannel, a.hive.config.CmdChBufSize), placementCh: make(chan placementRes, a.hive.config.CmdChBufSize), hive: a.hive, app: a, bees: make(map[uint64]*bee), state: state.NewTransactional(a.newState()), pendingCells: make(map[CellKey]*pendingCells), } }
func (b *bee) handleMsgLeader(mhs []msgAndHandler) { usetx := b.app.transactional() if usetx && len(mhs) > 1 { b.stateL2 = state.NewTransactional(b.stateL1) b.stateL1.BeginTx() } for i := range mhs { if usetx { b.BeginTx() } mh := mhs[i] if glog.V(2) { glog.Infof("%v handles message %v", b, mh.msg) } b.callRcv(mh) if usetx { var err error if b.stateL2 == nil { err = b.CommitTx() } else if len(b.msgBufL1) == 0 && b.stateL2.HasEmptyTx() { // If there is no pending L1 message and there is no state change, // emit the buffered messages in L2 as a shortcut. b.throttle(b.msgBufL2) b.resetTx(b.stateL2, &b.msgBufL2) } else { err = b.commitTxL2() } if err != nil && err != state.ErrNoTx { glog.Errorf("%v cannot commit a transaction: %v", b, err) } } } if !usetx || b.stateL2 == nil { return } b.stateL2 = nil if err := b.CommitTx(); err != nil && err != state.ErrNoTx { glog.Errorf("%v cannot commit a transaction: %v", b, err) } }
func (b *bee) setState(s state.State) { b.stateL1 = state.NewTransactional(s) }
func BenchmarkBeePersistence(b *testing.B) { b.StopTimer() log.SetOutput(ioutil.Discard) hive := &hive{ id: 1, config: HiveConfig{ StatePath: "/tmp/bhtest_bench_bee", RaftTick: 100 * time.Millisecond, RaftHBTicks: 1, RaftElectTicks: 5, RaftInFlights: 1, RaftFsyncTick: 1 * time.Second, }, collector: &noOpStatCollector{}, } removeState(hive.config.StatePath) hive.ticker = randtime.NewTicker(hive.config.RaftTick, 0) hive.registry = newRegistry(hive.String()) ncfg := raft.Config{ ID: hive.id, Name: hive.String(), Send: hive.sendRaft, Ticker: hive.ticker.C, } hive.node = raft.StartMultiNode(ncfg) bee := bee{ beeID: 1, beeColony: Colony{ ID: 1, Leader: 1, }, hive: hive, app: &app{ name: "test", flags: appFlagTransactional | appFlagPersistent, }, stateL1: state.NewTransactional(state.NewInMem()), dataCh: newMsgChannel(uint(b.N)), batchSize: 1024, } bee.becomeLeader() hive.registry.addBee(BeeInfo{ ID: 1, Hive: 1, App: "test", Colony: bee.colony(), }) if err := bee.createGroup(); err != nil { b.Fatal(err) } b.StartTimer() h := benchBeeHandler{data: []byte{1, 1, 1, 1}} mhs := make([]msgAndHandler, bee.batchSize) for j := uint(0); j < bee.batchSize; j++ { mhs[j] = msgAndHandler{ msg: &msg{}, handler: h, } } for i := uint(0); i < uint(b.N); i += bee.batchSize { bee.handleMsg(mhs) } b.StopTimer() time.Sleep(1 * time.Second) hive.node.Stop() }
func newMockContext() *mockContext { ctx := &mockContext{ Transactional: state.NewTransactional(state.NewInMem()), } return ctx }