//This builds BinlogResponse for each transaction. func (blp *Bls) buildTxnResponse() (txnResponseList []*proto.BinlogResponse, dmlCount int64) { var line []byte var keyspaceIdStr string var keyspaceId key.KeyspaceId dmlBuffer := make([]string, 0, 10) for _, event := range blp.txnLineBuffer { line = event.LogLine if bytes.HasPrefix(line, BINLOG_BEGIN) { streamBuf := new(proto.BinlogResponse) streamBuf.Position = event.BinlogPosition streamBuf.Data.SqlType = proto.BEGIN txnResponseList = append(txnResponseList, streamBuf) continue } if bytes.HasPrefix(line, BINLOG_COMMIT) { commitEvent := blsCreateCommitEvent(event) txnResponseList = append(txnResponseList, commitEvent) continue } sqlType := proto.GetSqlType(event.firstKw) if sqlType == proto.DML { keyspaceIdStr, keyspaceId = parseKeyspaceId(line) if keyspaceIdStr == "" { continue } if !blp.keyRange.Contains(keyspaceId) { dmlBuffer = dmlBuffer[:0] continue } dmlCount += 1 dmlBuffer = append(dmlBuffer, string(line)) dmlEvent := blp.createDmlEvent(event, keyspaceIdStr) dmlEvent.Data.Sql = make([]string, len(dmlBuffer)) dmlLines := copy(dmlEvent.Data.Sql, dmlBuffer) if dmlLines < len(dmlBuffer) { log.Warningf("The entire dml buffer was not properly copied") } txnResponseList = append(txnResponseList, dmlEvent) dmlBuffer = dmlBuffer[:0] } else { //add as prefixes to the DML from last DML. //start a new dml buffer and keep adding to it. dmlBuffer = append(dmlBuffer, string(line)) } } return txnResponseList, dmlCount }
func (blp *Bls) parseEventData(sendReply proto.SendBinlogResponse, event *blsEventBuffer) { if bytes.HasPrefix(event.LogLine, BINLOG_SET_TIMESTAMP) { blp.extractEventTimestamp(event) blp.initialSeek = false if blp.inTxn { blp.txnLineBuffer = append(blp.txnLineBuffer, event) } } else if bytes.HasPrefix(event.LogLine, BINLOG_BEGIN) { blp.handleBeginEvent(event) } else if bytes.HasPrefix(event.LogLine, BINLOG_ROLLBACK) { blp.inTxn = false blp.txnLineBuffer = blp.txnLineBuffer[:0] } else if bytes.HasPrefix(event.LogLine, BINLOG_COMMIT) { blp.handleCommitEvent(sendReply, event) blp.inTxn = false blp.txnLineBuffer = blp.txnLineBuffer[:0] } else if len(event.LogLine) > 0 { if blp.inTxn && IsTxnStatement(event.LogLine, event.firstKw) { blp.txnLineBuffer = append(blp.txnLineBuffer, event) } else { sqlType := proto.GetSqlType(event.firstKw) switch sqlType { case proto.DDL: blp.handleDdlEvent(sendReply, event) case proto.DML: lineBuf := make([][]byte, 0, 10) for _, dml := range blp.txnLineBuffer { lineBuf = append(lineBuf, dml.LogLine) } // FIXME(alainjobart) in these cases, we // probably want to skip that event and keep // going. Or at least offer the option to do // so somewhere. panic(newBinlogServerError(fmt.Sprintf("DML outside a txn - len %v, dml '%v', txn buffer '%v'", len(blp.txnLineBuffer), string(event.LogLine), string(bytes.Join(lineBuf, SEMICOLON_BYTE))))) default: //Ignore these often occuring statement types. if !IgnoredStatement(event.LogLine) { log.Warningf("Unknown statement '%v'", string(event.LogLine)) } } } } }