// Commit takes a storage transaction and writes any headers or indexes to make // the transacted facts visible. A storage transaction is passed in to enable // the writes to occur atomically which ensures consistency of the transacted // facts. func (p *Pipeline) Commit(tx storage.Tx) error { var ( err error log *dal.Log ) // Write the remaining block of the segment. if err = p.segment.Commit(tx); err != nil { return err } // No new facts, remove the segment. if p.segment.Count == 0 { logrus.Debugf("pipeline: no facts written to %s, removing segment", p.Domain) p.segment.Abort(tx) return nil } logrus.Debugf("pipeline: %d facts written to %s", p.segment.Count, p.Domain) // Compare and swap ID on domain's commit log. if log, err = dal.GetLog(tx, p.Domain, commitLogName); err != nil { return err } // Existing commit log, check if the head is the same. if log != nil { // TODO: determine path to handle conflicts. if log.Head != nil && !uuid.Equal(*log.Head, *p.segment.Base) { return ErrCommitConflict } } else { log = &dal.Log{ Name: commitLogName, Domain: p.Domain, } } log.Head = p.segment.UUID _, err = dal.SetLog(tx, p.Domain, log) return err }
// Init initializes the pipeline for the transaction. func (p *Pipeline) Init(tx *Transaction) error { // Get the commit log for this domain. log, err := dal.GetLog(tx.Engine, p.Domain, commitLogName) if err != nil { return err } if log == nil { log = &dal.Log{} } // Initialize new segment pointing to the head of the log. p.segment = NewSegment(tx.Engine, p.Domain, tx.ID) p.segment.Base = log.Head p.segment.Next = log.Head p.segment.Time = tx.StartTime p.engine = tx.Engine p.dedupe = !tx.options.AllowDuplicates return nil }