func (r *Runner) Run(ops []Op, id bson.ObjectId, info interface{}) (err error) {
	const efmt = "error in transaction op %d: %s"
	for i := range ops {
		op := &ops[i]
		if op.C == "" || op.Id == nil {
			return fmt.Errorf(efmt, i, "C or Id missing")
		}
		changes := 0
		if op.Insert != nil {
			changes++
		}
		if op.Update != nil {
			changes++
		}
		if op.Remove {
			changes++
		}
		if changes > 1 {
			return fmt.Errorf(efmt, i, "more than one of Insert/Update/Remove set")
		}
		if changes == 0 && op.Assert == nil {
			return fmt.Errorf(efmt, i, "none of Assert/Insert/Update/Remove set")
		}
	}
	if id == "" {
		id = bson.NewObjectId()
	}

	// Insert transaction sooner rather than later, to stay on the safer side.
	t := transaction{
		Id:    id,
		Ops:   ops,
		State: tpreparing,
		Info:  info,
	}
	if err = r.tc.Insert(&t); err != nil {
		return err
	}
	if err = flush(r, &t); err != nil {
		return err
	}
	if t.State == taborted {
		return ErrAborted
	} else if t.State != tapplied {
		panic(fmt.Errorf("invalid state for %s after flush: %q", &t, t.State))
	}
	return nil
}
func (r *Runner) Run(ops []Op, id bson.ObjectId, info interface{}) (err error) {
	const efmt = "error in transaction op %d: %s"
	for i := range ops {
		op := &ops[i]
		if op.C == "" || op.Id == nil {
			return fmt.Errorf(efmt, i, "C or Id missing")
		}
		changes := 0
		if op.Insert != nil {
			changes++
		}
		if op.Update != nil {
			changes++
		}
		if op.Remove {
			changes++
		}
		if changes > 1 {
			return fmt.Errorf(efmt, i, "more than one of Insert/Update/Remove set")
		}
		if changes == 0 && op.Assert == nil {
			return fmt.Errorf(efmt, i, "none of Assert/Insert/Update/Remove set")
		}
	}
	if id == "" {
		id = bson.NewObjectId()
	}

	
	t := transaction{
		Id:    id,
		Ops:   ops,
		State: tpreparing,
		Info:  info,
	}
	if err = r.tc.Insert(&t); err != nil {
		return err
	}
	if err = flush(r, &t); err != nil {
		return err
	}
	if t.State == taborted {
		return ErrAborted
	} else if t.State != tapplied {
		panic(fmt.Errorf("invalid state for %s after flush: %q", &t, t.State))
	}
	return nil
}
func ( r * Runner ) Run ( ops [ ] Op , id bson . ObjectId , info interface { } ) ( err error ) { const efmt = " " for i := range ops { op := & ops [ i ] if op . C == " " || op . Id == nil { return fmt . Errorf ( efmt , i , " " ) } changes := 0 if op . Insert != nil { changes ++ } if op . Update != nil { changes ++ } if op . Remove { changes ++ } if changes > 1 { return fmt . Errorf ( efmt , i , " " ) } if changes == 0 && op . Assert == nil { return fmt . Errorf ( efmt , i , " " ) } } if id == " " { id = bson . NewObjectId ( ) } // Insert transaction sooner rather than later, to stay on the safer side. t := transaction { Id : id , Ops : ops , State : tpreparing , Info : info , } if err = r . tc . Insert ( & t ) ; err != nil { return err } if err = flush ( r , & t ) ; err != nil { return err } if t . State == taborted { return ErrAborted } else if t . State != tapplied { panic ( fmt . Errorf ( " " , & t , t . State ) ) } return nil }
// Run creates a new transaction with ops and runs it immediately.
// The id parameter specifies the transaction id, and may be written
// down ahead of time to later verify the success of the change and
// resume it, when the procedure is interrupted for any reason. If
// empty, a random id will be generated.
// The info parameter, if not nil, is included under the "i"
// field of the transaction document.
//
// Operations across documents are not atomically applied, but are
// guaranteed to be eventually all applied in the order provided or
// all aborted, as long as the affected documents are only modified
// through transactions. If documents are simultaneously modified
// by transactions and out of transactions the behavior is undefined.
//
// If Run returns no errors, all operations were applied successfully.
// If it returns ErrAborted, one or more operations can't be applied
// and the transaction was entirely aborted with no changes performed.
// Otherwise, if the transaction is interrupted while running for any
// reason, it may be resumed explicitly or by attempting to apply
// another transaction on any of the documents targeted by ops, as
// long as the interruption was made after the transaction document
// itself was inserted. Run Resume with the obtained transaction id
// to confirm whether the transaction was applied or not.
//
// Any number of transactions may be run concurrently, with one
// runner or many.
Run creates a new transaction with ops and runs it immediately . The id parameter specifies the transaction id and may be written down ahead of time to later verify the success of the change and resume it when the procedure is interrupted for any reason . If empty a random id will be generated . The info parameter if not nil is included under the i field of the transaction document . Operations across documents are not atomically applied but are guaranteed to be eventually all applied in the order provided or all aborted as long as the affected documents are only modified through transactions . If documents are simultaneously modified by transactions and out of transactions the behavior is undefined . If Run returns no errors all operations were applied successfully . If it returns ErrAborted one or more operations can t be applied and the transaction was entirely aborted with no changes performed . Otherwise if the transaction is interrupted while running for any reason it may be resumed explicitly or by attempting to apply another transaction on any of the documents targeted by ops as long as the interruption was made after the transaction document itself was inserted . Run Resume with the obtained transaction id to confirm whether the transaction was applied or not . Any number of transactions may be run concurrently with one runner or many .