Exemple #1
0
// PurgeMissing removes from collections any state that refers to transaction
// documents that for whatever reason have been lost from the system (removed
// by accident or lost in a hard crash, for example).
//
// This method should very rarely be needed, if at all, and should never be
// used during the normal operation of an application. Its purpose is to put
// a system that has seen unavoidable corruption back in a working state.
func (r *Runner) PurgeMissing(collections ...string) error {
	type M map[string]interface{}
	type S []interface{}

	type TDoc struct {
		Id       interface{} "_id"
		TxnQueue []string    "txn-queue"
	}

	found := make(map[bson.ObjectId]bool)

	sort.Strings(collections)
	for _, collection := range collections {
		c := r.tc.Database.C(collection)
		iter := c.Find(nil).Select(bson.M{"_id": 1, "txn-queue": 1}).Iter()
		var tdoc TDoc
		for iter.Next(&tdoc) {
			for _, txnToken := range tdoc.TxnQueue {
				txnId := bson.ObjectIdHex(txnToken[:24])
				if found[txnId] {
					continue
				}
				if r.tc.FindId(txnId).One(nil) == nil {
					found[txnId] = true
					continue
				}
				logf("WARNING: purging from document %s/%v the missing transaction id %s", collection, tdoc.Id, txnId)
				err := c.UpdateId(tdoc.Id, M{"$pull": M{"txn-queue": M{"$regex": "^" + txnId.Hex() + "_*"}}})
				if err != nil {
					return fmt.Errorf("error purging missing transaction %s: %v", txnId.Hex(), err)
				}
			}
		}
		if err := iter.Close(); err != nil {
			return fmt.Errorf("transaction queue iteration error for %s: %v", collection, err)
		}
	}

	type StashTDoc struct {
		Id       docKey   "_id"
		TxnQueue []string "txn-queue"
	}

	iter := r.sc.Find(nil).Select(bson.M{"_id": 1, "txn-queue": 1}).Iter()
	var stdoc StashTDoc
	for iter.Next(&stdoc) {
		for _, txnToken := range stdoc.TxnQueue {
			txnId := bson.ObjectIdHex(txnToken[:24])
			if found[txnId] {
				continue
			}
			if r.tc.FindId(txnId).One(nil) == nil {
				found[txnId] = true
				continue
			}
			logf("WARNING: purging from stash document %s/%v the missing transaction id %s", stdoc.Id.C, stdoc.Id.Id, txnId)
			err := r.sc.UpdateId(stdoc.Id, M{"$pull": M{"txn-queue": M{"$regex": "^" + txnId.Hex() + "_*"}}})
			if err != nil {
				return fmt.Errorf("error purging missing transaction %s: %v", txnId.Hex(), err)
			}
		}
	}
	if err := iter.Close(); err != nil {
		return fmt.Errorf("transaction stash iteration error: %v", err)
	}

	return nil
}
Exemple #2
0
func (tt token) id() bson.ObjectId { return bson.ObjectIdHex(string(tt[:24])) }