예제 #1
0
파일: reader.go 프로젝트: tav/gcloud-golang
// handleCellValue returns a Row if the cell value includes a commit, otherwise nil.
func (cr *chunkReader) handleCellValue(cc *btspb.ReadRowsResponse_CellChunk) Row {
	if cc.ValueSize > 0 {
		// ValueSize is specified so expect a split value of ValueSize bytes
		if cr.curVal == nil {
			cr.curVal = make([]byte, 0, cc.ValueSize)
		}
		cr.curVal = append(cr.curVal, cc.Value...)
		cr.state = cellInProgress
	} else {
		// This cell is either the complete value or the last chunk of a split
		if cr.curVal == nil {
			cr.curVal = cc.Value
		} else {
			cr.curVal = append(cr.curVal, cc.Value...)
		}
		cr.finishCell()

		if cc.GetCommitRow() {
			return cr.commitRow()
		} else {
			cr.state = rowInProgress
		}
	}

	return nil
}
예제 #2
0
파일: reader.go 프로젝트: tav/gcloud-golang
func (cr *chunkReader) validateCellInProgress(cc *btspb.ReadRowsResponse_CellChunk) error {
	if err := cr.validateRowStatus(cc); err != nil {
		return err
	}
	if cr.curVal == nil {
		return fmt.Errorf("no cached cell while CELL_IN_PROGRESS %v", cc)
	}
	if cc.GetResetRow() == false && cr.isAnyKeyPresent(cc) {
		return fmt.Errorf("cell key components found while CELL_IN_PROGRESS %v", cc)
	}
	return nil
}
예제 #3
0
파일: reader.go 프로젝트: tav/gcloud-golang
func (cr *chunkReader) validateNewRow(cc *btspb.ReadRowsResponse_CellChunk) error {
	if cc.GetResetRow() {
		return fmt.Errorf("reset_row not allowed between rows")
	}
	if cc.RowKey == nil || cc.FamilyName == nil || cc.Qualifier == nil {
		return fmt.Errorf("missing key field for new row %v", cc)
	}
	if cr.lastKey != "" && cr.lastKey >= string(cc.RowKey) {
		return fmt.Errorf("out of order row key: %q, %q", cr.lastKey, string(cc.RowKey))
	}
	return nil
}
예제 #4
0
파일: reader.go 프로젝트: tav/gcloud-golang
// Validate a RowStatus, commit or reset, if present.
func (cr *chunkReader) validateRowStatus(cc *btspb.ReadRowsResponse_CellChunk) error {
	// Resets can't be specified with any other part of a cell
	if cc.GetResetRow() && (cr.isAnyKeyPresent(cc) ||
		cc.Value != nil ||
		cc.ValueSize != 0 ||
		cc.Labels != nil) {
		return fmt.Errorf("reset must not be specified with other fields %v", cc)
	}
	if cc.GetCommitRow() && cc.ValueSize > 0 {
		return fmt.Errorf("commit row found in between chunks in a cell")
	}
	return nil
}
예제 #5
0
파일: reader.go 프로젝트: tav/gcloud-golang
// Process takes a cell chunk and returns a new Row if the given chunk
// completes a Row, or nil otherwise.
func (cr *chunkReader) Process(cc *btspb.ReadRowsResponse_CellChunk) (Row, error) {
	var row Row
	switch cr.state {
	case newRow:
		if err := cr.validateNewRow(cc); err != nil {
			return nil, err
		}

		cr.curRow = make(Row)
		cr.curKey = cc.RowKey
		cr.curFam = cc.FamilyName.Value
		cr.curQual = cc.Qualifier.Value
		cr.curTS = cc.TimestampMicros
		row = cr.handleCellValue(cc)

	case rowInProgress:
		if err := cr.validateRowInProgress(cc); err != nil {
			return nil, err
		}

		if cc.GetResetRow() {
			cr.resetToNewRow()
			return nil, nil
		}

		if cc.FamilyName != nil {
			cr.curFam = cc.FamilyName.Value
		}
		if cc.Qualifier != nil {
			cr.curQual = cc.Qualifier.Value
		}
		cr.curTS = cc.TimestampMicros
		row = cr.handleCellValue(cc)

	case cellInProgress:
		if err := cr.validateCellInProgress(cc); err != nil {
			return nil, err
		}
		if cc.GetResetRow() {
			cr.resetToNewRow()
			return nil, nil
		}
		row = cr.handleCellValue(cc)
	}

	return row, nil
}