Example #1
0
// RemoveChange, see ExpectationsStore interface.
func (s *SQLExpectationsStore) RemoveChange(changedDigests map[string][]string) (retErr error) {
	defer timer.New("removing exp change").Stop()

	const markRemovedStmt = `UPDATE exp_test_change
	                         SET removed = IF(removed IS NULL, ?, removed)
	                         WHERE (name=?) AND (digest=?)`

	// start a transaction
	tx, err := s.vdb.DB.Begin()
	if err != nil {
		return err
	}

	defer func() { retErr = database.CommitOrRollback(tx, retErr) }()

	// Mark all the digests as removed.
	now := util.TimeStampMs()
	for testName, digests := range changedDigests {
		for _, digest := range digests {
			if _, err = tx.Exec(markRemovedStmt, now, testName, digest); err != nil {
				return err
			}
		}
	}

	return nil
}
Example #2
0
// GetBuildIDFromDB retrieves the ID for the given build from the database
// as specified by the given master, builder, and build number.
func GetBuildIDFromDB(builder, master string, buildNumber int) (rvid int, rverr error) {
	tx, err := DB.Beginx()
	if err != nil {
		return -1, err
	}
	// Defer committing/rolling back the transaction.
	defer func() {
		rverr = database.CommitOrRollback(tx, rverr)
	}()
	return GetBuildIDFromDBTx(builder, master, buildNumber, tx)
}
Example #3
0
// replaceIntoDB inserts or updates the Build in the database.
func (b *Build) replaceIntoDB() (rv error) {
	tx, err := DB.Beginx()
	if err != nil {
		return fmt.Errorf("Unable to push build into database - Could not begin transaction: %v", err)
	}

	// Defer committing/rolling back the transaction.
	defer func() {
		rv = database.CommitOrRollback(tx, rv)
	}()

	// Insert the build.
	return b.replaceIntoDBTx(tx)
}
Example #4
0
func ReplaceMultipleBuildsIntoDB(builds []*Build) (rv error) {
	tx, err := DB.Beginx()
	if err != nil {
		return fmt.Errorf("Unable to push builds into database - Could not begin transaction: %v", err)
	}

	// Defer committing/rolling back the transaction.
	defer func() {
		rv = database.CommitOrRollback(tx, rv)
	}()

	// Insert the builds.
	for _, b := range builds {
		if err := b.replaceIntoDBTx(tx); err != nil {
			return err
		}
	}
	return nil
}
Example #5
0
func ReplaceMultipleBuildsIntoDB(builds []*Build) (rv error) {
	defer metrics.NewTimer("buildbot.ReplaceMultipleBuildsIntoDB").Stop()
	tx, err := DB.Beginx()
	if err != nil {
		return fmt.Errorf("Unable to push builds into database - Could not begin transaction: %v", err)
	}

	// Defer committing/rolling back the transaction.
	defer func() {
		rv = database.CommitOrRollback(tx, rv)
	}()

	// Insert the builds.
	// TODO(borenet): Insert/update all of the builds at once.
	for _, b := range builds {
		if err := b.replaceIntoDBTx(tx); err != nil {
			return err
		}
	}
	return nil
}
Example #6
0
// replaceIntoDB inserts or updates the Alert in the database.
func (a *Alert) replaceIntoDB() (rv error) {
	tx, err := DB.Beginx()
	if err != nil {
		return fmt.Errorf("Unable to push Alert into database - Could not begin transaction: %v", err)
	}
	defer func() { rv = database.CommitOrRollback(tx, rv) }()

	// Insert the alert itself.
	active := 0
	if a.DismissedAt == 0 {
		active = 1
	}
	res, err := tx.Exec(fmt.Sprintf("REPLACE INTO %s (id,active,name,triggered,category,message,nag,snoozedUntil,dismissedAt,autoDismiss,lastFired) VALUES (?,?,?,?,?,?,?,?,?,?,?);", TABLE_ALERTS), a.Id, active, a.Name, a.Triggered, a.Category, a.Message, a.Nag, a.SnoozedUntil, a.DismissedAt, a.AutoDismiss, a.LastFired)
	if err != nil {
		return fmt.Errorf("Failed to push alert into database: %v", err)
	}
	id, err := res.LastInsertId()
	if err != nil {
		return fmt.Errorf("Failed to push alert into database; LastInsertId failed: %v", err)
	}
	a.Id = id

	// Comments.

	// First, delete existing comments so we don't have leftovers hanging around from before.
	if _, err := tx.Exec(fmt.Sprintf("DELETE FROM %s WHERE alertId = ?;", TABLE_COMMENTS), a.Id); err != nil {
		return fmt.Errorf("Failed to delete comments from database: %v", err)
	}
	// Actually insert the comments.
	if len(a.Comments) > 0 {
		commentFields := 4
		commentTmpl := util.RepeatJoin("?", ",", commentFields)
		commentsTmpl := util.RepeatJoin(fmt.Sprintf("(%s)", commentTmpl), ",", len(a.Comments))
		flattenedComments := make([]interface{}, 0, commentFields*len(a.Comments))
		for _, c := range a.Comments {
			flattenedComments = append(flattenedComments, a.Id, c.User, c.Time, c.Message)
		}
		if _, err := tx.Exec(fmt.Sprintf("INSERT INTO %s (alertId,user,time,message) VALUES %s;", TABLE_COMMENTS, commentsTmpl), flattenedComments...); err != nil {
			return fmt.Errorf("Unable to push comments into database: %v", err)
		}
	}

	// Actions.

	// First, delete existing actions so we don't have leftovers hanging around from before.
	if _, err := tx.Exec(fmt.Sprintf("DELETE FROM %s WHERE alertId = ?;", TABLE_ACTIONS), a.Id); err != nil {
		return fmt.Errorf("Failed to delete actions from database: %v", err)
	}
	// Actually insert the actions.
	if len(a.Actions) > 0 {
		actionFields := 2
		actionTmpl := util.RepeatJoin("?", ",", actionFields)
		actionsTmpl := util.RepeatJoin(fmt.Sprintf("(%s)", actionTmpl), ",", len(a.Actions))
		flattenedActions := make([]interface{}, 0, actionFields*len(a.Actions))
		for _, action := range a.Actions {
			flattenedActions = append(flattenedActions, a.Id, action.String())
		}
		if _, err := tx.Exec(fmt.Sprintf("INSERT INTO %s (alertId,action) VALUES %s;", TABLE_ACTIONS, actionsTmpl), flattenedActions...); err != nil {
			return fmt.Errorf("Unable to push actions into database: %v", err)
		}
	}

	// the transaction is committed during the deferred function.
	return nil
}
Example #7
0
// AddChangeWithTimeStamp adds changed tests to the database with the
// given time stamp. This is primarily for migration purposes.
func (s *SQLExpectationsStore) AddChangeWithTimeStamp(changedTests map[string]types.TestClassification, userId string, undoID int, timeStamp int64) (retErr error) {
	defer timer.New("adding exp change").Stop()

	// Count the number of values to add.
	changeCount := 0
	for _, digests := range changedTests {
		changeCount += len(digests)
	}

	const (
		insertChange = `INSERT INTO exp_change (userid, ts, undo_changeid) VALUES (?, ?, ?)`
		insertDigest = `INSERT INTO exp_test_change (changeid, name, digest, label) VALUES`
	)

	// start a transaction
	tx, err := s.vdb.DB.Begin()
	if err != nil {
		return err
	}

	defer func() { retErr = database.CommitOrRollback(tx, retErr) }()

	// create the change record
	result, err := tx.Exec(insertChange, userId, timeStamp, undoID)
	if err != nil {
		return err
	}
	changeId, err := result.LastInsertId()
	if err != nil {
		return err
	}

	// If there are not changed records then we stop here.
	if changeCount == 0 {
		return nil
	}

	// Assemble the INSERT values.
	valuesStr := ""
	vals := []interface{}{}
	for testName, digests := range changedTests {
		for d, label := range digests {
			valuesStr += "(?, ?, ?, ?),"
			vals = append(vals, changeId, testName, d, label.String())
		}
	}
	valuesStr = valuesStr[:len(valuesStr)-1]

	// insert all the changes
	prepStmt, err := tx.Prepare(insertDigest + valuesStr)
	if err != nil {
		return err
	}
	defer util.Close(prepStmt)

	_, err = prepStmt.Exec(vals...)
	if err != nil {
		return err
	}
	return nil
}