// Upsert will insert a new Exception if nothing matching uniqueid exists // Then, it will add to instances/traces of the Exception func (exception *Exception) Upsert(trace *Trace, db *mgo.Database) (err error) { log.Printf("Upserting: %#v\n", exception) if err = db.C("exceptions").EnsureIndex(mgo.Index{Key: []string{"uniqueid"}, Unique: true}); err != nil { return } // First, we'll try to insert // Due to the unique constraint on UniqueID, this will fail if the record exists already err = db.C("exceptions").Insert(&exception) if err != nil && !mgo.IsDup(err) { // Swallow duplicate error return } // Now, we're going to push the instance to mark when this happened err = db.C("exceptions").Update(bson.M{"uniqueid": exception.UniqueId}, bson.M{ "$push": bson.M{"instances": time.Now()}, }) if err != nil { return err } // Finally, we'll add the trace (for now, unlimited) err = db.C("exceptions").Update(bson.M{"uniqueid": exception.UniqueId}, bson.M{ "$push": bson.M{"traces": &trace}, }) if err != nil { return err } return }
func Test_newUser(t *testing.T) { c, session, err := connect(users) if err != nil { t.Fatal(err) } t.Logf("Test without email") foo, err := newUser(session, "Foo", "password", "") if err != nil { t.Error(err) } t.Logf("Test with email") nemo1, err := newUser(session, "Nemo", "password", "*****@*****.**") if err != nil { t.Error(err) } t.Logf("Test duplicate user") nemo2, err := newUser(session, "Nemo", "password", "*****@*****.**") if !mgo.IsDup(err) { t.Error(err) } if err = c.Remove(foo); err != nil { t.Error(err) } if err = c.Remove(nemo1); err != nil { t.Error(err) } if err = c.Remove(nemo2); err != mgo.ErrNotFound { t.Error(err) } }
// PlatformAdd add a new platform to tsuru func PlatformAdd(name string, args map[string]string, w io.Writer) error { var ( provisioner provision.ExtensibleProvisioner ok bool ) if provisioner, ok = Provisioner.(provision.ExtensibleProvisioner); !ok { return errors.New("Provisioner is not extensible") } if name == "" { return errors.New("Platform name is required.") } p := Platform{Name: name} conn, err := db.Conn() if err != nil { return err } err = conn.Platforms().Insert(p) if err != nil { if mgo.IsDup(err) { return DuplicatePlatformError{} } return err } err = provisioner.PlatformAdd(name, args, w) if err != nil { db_err := conn.Platforms().RemoveId(p.Name) if db_err != nil { return fmt.Errorf("Caused by: %s and %s", err.Error(), db_err.Error()) } return err } return nil }
// New creates a representation of a git repository. It creates a Git // repository using the "bare-dir" setting and saves repository's meta data in // the database. func New(name string, users []string, isPublic bool) (*Repository, error) { log.Debugf("Creating repository %q", name) r := &Repository{Name: name, Users: users, IsPublic: isPublic} if v, err := r.isValid(); !v { log.Errorf("repository.New: Invalid repository %q: %s", name, err) return r, err } if err := newBare(name); err != nil { log.Errorf("repository.New: Error creating bare repository for %q: %s", name, err) return r, err } barePath := barePath(name) if barePath != "" && isPublic { ioutil.WriteFile(barePath+"/git-daemon-export-ok", []byte(""), 0644) if f, err := fs.Filesystem().Create(barePath + "/git-daemon-export-ok"); err == nil { f.Close() } } conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() err = conn.Repository().Insert(&r) if mgo.IsDup(err) { log.Errorf("repository.New: Duplicate repository %q", name) return r, fmt.Errorf("A repository with this name already exists.") } return r, err }
func (c *MongoCache) PutDistance(route Route, distance uint64) { s := c.session.Clone() defer s.Close() err := s.DB("").C("routes").Insert(NewCachedRoute(route, distance)) if err != nil && !mgo.IsDup(err) { log.Println("MongoCache: PUT error -> ", err) } }
func (c *MongoCache) PutTrip(username string, trip Trip) { s := c.session.Clone() defer s.Close() err := s.DB("").C("trips").Insert(NewCachedTrip(username, trip)) if err != nil && !mgo.IsDup(err) { log.Println("MongoCache: PUT error -> ", err) } }
// Add inserts new package and ignores if package exist already func (p *Package) Add(pr *PackageRow) (*PackageRow, error) { pr.Created = time.Now() pr.Id = bson.NewObjectId() err := p.coll.Insert(pr) if err != nil && !mgo.IsDup(err) { return nil, err } return pr, nil }
// insertUser inserts User to database. // the user with that email exist. Note that indexes musted create fo MongoDB. func (m *MgoUserManager) insertUser(u *auth.User) error { err := m.UserColl.Insert(u) if err != nil { if mgo.IsDup(err) { return auth.ErrDuplicateEmail } return err } return nil }
func (rs *controller) Post(w http.ResponseWriter, request *http.Request, p httprouter.Params) { defer request.Body.Close() data, err := ioutil.ReadAll(request.Body) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } var rule Rule err = json.Unmarshal(data, &rule) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } err = Save(&rule) if err != nil { if mgo.IsDup(err) { http.Error(w, err.Error(), http.StatusBadRequest) } else { http.Error(w, err.Error(), http.StatusInternalServerError) } return } axn, err := rule.GetAction() if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } actions.Add(axn) req, err := http.NewRequest("POST", config.RuleEndpoint(), strings.NewReader(rule.EPL)) if err != nil { mylog.Alert("rule controller POST", err) } resp, err := httpClient.Do(req) if err != nil { mylog.Alert("rule controller POST", err, resp) http.Error(w, err.Error(), http.StatusInternalServerError) return } if resp.StatusCode/100 != 2 { mylog.Alert("rule controller POST", resp.Status) http.Error(w, resp.Status, http.StatusInternalServerError) return } w.WriteHeader(http.StatusCreated) dataBack, err := json.Marshal(rule) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Write(dataBack) }
// Register adds a new node to the scheduler, registering for use in // the given team. The team parameter is optional, when set to "", the node // will be used as a fallback node. func (segregatedScheduler) Register(params map[string]string) error { conn, err := db.Conn() if err != nil { return err } defer conn.Close() node := node{ID: params["ID"], Address: params["address"], Teams: []string{params["team"]}} err = conn.Collection(schedulerCollection).Insert(node) if mgo.IsDup(err) { return errNodeAlreadyRegister } return err }
// AddNodeToScheduler adds a new node to the scheduler, registering for use in // the given team. The team parameter is optional, when set to "", the node // will be used as a fallback node. func addNodeToScheduler(n cluster.Node, team string) error { conn, err := db.Conn() if err != nil { return err } defer conn.Close() node := node{ID: n.ID, Address: n.Address, Team: team} err = conn.Collection(schedulerCollection).Insert(node) if mgo.IsDup(err) { return errNodeAlreadyRegister } return err }
func (ctx *MgoUserCtx) insertUser(u *Account, notif, app bool) error { err := ctx.userColl.Insert(u) if err != nil { if mgo.IsDup(err) { return membership.ErrDuplicateEmail } return err } if notif { return ctx.notifer.AccountAdded(u) } return nil }
func (a *AuthMongoDBCtx) insertUser(u *User, notif, app bool) error { err := a.userColl.Insert(u) if err != nil { if mgo.IsDup(err) { return ErrDuplicateEmail } return err } if notif { return a.notifer.AccountAdded(u.Email, app) } return nil }
// New creates a representation of a git repository. It creates a Git // repository using the "bare-dir" setting and saves repository's meta data in // the database. func New(name string, users []string, isPublic bool) (*Repository, error) { r := &Repository{Name: name, Users: users, IsPublic: isPublic} if v, err := r.isValid(); !v { return r, err } if err := newBare(name); err != nil { return r, err } err := db.Session.Repository().Insert(&r) if mgo.IsDup(err) { return r, fmt.Errorf("A repository with this name already exists.") } return r, err }
// PlatformAdd add a new platform to tsuru func PlatformAdd(name string, file string) error { p := Platform{Name: name} conn, err := db.Conn() if err != nil { return err } err = conn.Platforms().Insert(p) if err != nil { if mgo.IsDup(err) { return DuplicatePlatformError{} } return err } err = Provisioner.PlatformAdd(name, file) return nil }
func (m *MgoManager) insertUser(u *User) error { now := time.Now() u.LastActivity = &now if u.Profile == nil { u.Profile = &authmodel.Profile{} } u.Profile.JoinDay = u.LastActivity err := m.UserColl.Insert(u) if err != nil { if mgo.IsDup(err) { return authmodel.ErrDuplicateEmail } return err } return nil }
func (ctx *MgoGroupCtx) AddGroupDetail(name string, info membership.GroupInfo, pri map[string]bool) (membership.Grouper, error) { g := &Group{} g.Id = bson.NewObjectId() g.Name = name g.Info = info g.Privilege = pri err := ctx.groupColl.Insert(g) if err != nil { if mgo.IsDup(err) { return nil, membership.ErrDuplicateName } return nil, err } return g, nil }
// AddGroupDetail adds a group with full detail to database. func (m *MgoGroupManager) AddGroupDetail(name string, info *auth.GroupInfo, pri []string) (*auth.Group, error) { group := &auth.Group{} group.Id = bson.NewObjectId() group.Name = name group.Info = *info group.Privilege = pri err := m.GroupColl.Insert(group) if err != nil { if mgo.IsDup(err) { return nil, auth.ErrDuplicateName } return nil, err } return group, nil }
// Writes `key` in authorized_keys file (from current user) // It does not writes in the database, there is no need for that since the key // object is embedded on the user's document func addKey(name, body, username string) error { key, err := newKey(name, username, body) if err != nil { return err } conn, err := db.Conn() if err != nil { return err } defer conn.Close() err = conn.Key().Insert(key) if err != nil { if mgo.IsDup(err) { return ErrDuplicateKey } return err } return writeKey(key) }
// PlatformAdd add a new platform to tsuru func PlatformAdd(name string, args map[string]string, w io.Writer) error { if name == "" { return errors.New("Platform name is required.") } p := Platform{Name: name} conn, err := db.Conn() if err != nil { return err } err = Provisioner.PlatformAdd(name, args, w) if err != nil { return err } err = conn.Platforms().Insert(p) if err != nil { if mgo.IsDup(err) { return DuplicatePlatformError{} } return err } return nil }
// Creates a new user and write his/her keys into authorized_keys file. // // The authorized_keys file belongs to the user running the process. func New(name string, keys map[string]string) (*User, error) { log.Debugf(`Creating user "%s"`, name) u := &User{Name: name} if v, err := u.isValid(); !v { log.Errorf("user.New: %s", err.Error()) return u, err } conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() if err := conn.User().Insert(&u); err != nil { if mgo.IsDup(err) { log.Errorf("user.New: %q duplicate user", name) return u, errors.New("Could not create user: user already exists") } log.Errorf("user.New: %s", err) return u, err } return u, addKeys(keys, u.Name) }
func (m *MgoManager) AddGroupDetail(name string, pri []string, info *authmodel.GroupInfo) (*authmodel.Group, error) { group := &Group{} group.Id = bson.NewObjectId() sid := group.Id.Hex() group.Group.Id = &sid group.Name = &name group.Privileges = pri group.Info = info if group.Name == nil { return nil, authmodel.ErrInvalidEmail } err := m.GroupColl.Insert(group) if err != nil { if mgo.IsDup(err) { return nil, authmodel.ErrDuplicateName } return nil, err } return &group.Group, nil }
func CreateTeam(name string, user ...*User) error { name = strings.TrimSpace(name) if !isTeamNameValid(name) { return ErrInvalidTeamName } team := Team{ Name: name, Users: make([]string, len(user)), } for i, u := range user { team.Users[i] = u.Email } conn, err := db.Conn() if err != nil { return err } defer conn.Close() err = conn.Teams().Insert(team) if mgo.IsDup(err) { return ErrTeamAlreadyExists } return err }
func makeArticle(db *mgo.Database, p *wikiparse.Page) { a := article{} a.RevInfo.ID = p.Revisions[0].ID a.RevInfo.Timestamp = p.Revisions[0].Timestamp a.RevInfo.Contributor = p.Revisions[0].Contributor.Username a.RevInfo.ContributorID = p.Revisions[0].Contributor.ID a.RevInfo.Comment = p.Revisions[0].Comment a.Title = p.Title a.Text = p.Revisions[0].Text a.Links = wikiparse.FindLinks(a.Text) a.Files = wikiparse.FindFiles(a.Text) err := db.C(*collection).Insert(&a) if err != nil { if mgo.IsDup(err) { if *verbose == true { log.Printf("Duplicate Key Error inserting %s", a.Title) } } else { log.Printf("Error inserting %s: %s", a.Title, err) } } wg.Done() }
// NewInstallationHandler ... func NewInstallationHandler(w http.ResponseWriter, r *http.Request, c *Context) { machineId := r.PostFormValue("machine_id") xmppvoxVersion := r.PostFormValue("xmppvox_version") dosvoxInfoStr := r.PostFormValue("dosvox_info") machineInfoStr := r.PostFormValue("machine_info") if len(r.PostForm) != 4 || machineId == "" || xmppvoxVersion == "" || dosvoxInfoStr == "" || machineInfoStr == "" { http.Error(w, "Retry with POST parameters: machine_id, xmppvox_version, dosvox_info, machine_info", http.StatusBadRequest) return } var dosvoxInfo, machineInfo map[string]string err := json.Unmarshal([]byte(dosvoxInfoStr), &dosvoxInfo) if err != nil { http.Error(w, "Invalid JSON for dosvox_info", http.StatusBadRequest) return } err = json.Unmarshal([]byte(machineInfoStr), &machineInfo) if err != nil { http.Error(w, "Invalid JSON for machine_info", http.StatusBadRequest) return } i := NewInstallation(machineId, xmppvoxVersion, dosvoxInfo, machineInfo) err = c.Store.InsertInstallation(i) if mgo.IsDup(err) { http.Error(w, "Installation already registered", http.StatusBadRequest) return } switch err { case nil: fmt.Fprintln(w, machineId) default: http.Error(w, fmt.Sprintf("Failed to track install %s", machineId), http.StatusInternalServerError) log.Println(err) } }
func (f *flusher) apply(t *transaction, pull map[bson.ObjectId]*transaction) error { f.debugf("Applying transaction %s", t) if t.State != tapplying { panic(fmt.Errorf("applying transaction in invalid state: %q", t.State)) } if pull == nil { pull = map[bson.ObjectId]*transaction{t.Id: t} } // Compute the operation in which t's id may be pulled // out of txn-queue. That's on its last change, or the // first assertion. pullOp := make(map[docKey]int) for i := range t.Ops { op := &t.Ops[i] dkey := op.docKey() if _, ok := pullOp[dkey]; !ok || op.isChange() { pullOp[dkey] = i } } logRevnos := append([]int64(nil), t.Revnos...) logDoc := bson.D{{"_id", t.Id}} tt := tokenFor(t) for i := range t.Ops { op := &t.Ops[i] dkey := op.docKey() dqueue := f.queue[dkey] revno := t.Revnos[i] var opName string if debugEnabled { opName = op.name() f.debugf("Applying %s op %d (%s) on %v with txn-revno %d", t, i, opName, dkey, revno) } c := f.tc.Database.C(op.C) var revnoq, idq interface{} if revno == 0 || op.Insert != nil && revno == -1 { revnoq = bson.D{{"$exists", false}} } else { revnoq = revno } if op.Insert != nil { idq = dkey } else { idq = dkey.Id } qdoc := bson.D{{"_id", idq}, {"txn-revno", revnoq}, {"txn-queue", tt}} dontPull := tt isPullOp := pullOp[dkey] == i if isPullOp { dontPull = "" } pullAll := tokensToPull(dqueue, pull, dontPull) var d bson.D var outcome string var err error switch { case op.Update != nil: if revno < 0 { err = mgo.ErrNotFound } else { newRevno := revno + 1 logRevnos[i] = newRevno if d, err = objToDoc(op.Update); err != nil { return err } if d, err = addToDoc(d, "$pullAll", bson.D{{"txn-queue", pullAll}}); err != nil { return err } if d, err = addToDoc(d, "$set", bson.D{{"txn-revno", newRevno}}); err != nil { return err } chaos("") err = c.Update(qdoc, d) } case op.Remove: if revno < 0 { err = mgo.ErrNotFound } else { newRevno := -revno - 1 logRevnos[i] = newRevno nonce := newNonce() stash := txnInfo{} change := mgo.Change{ Update: bson.D{{"$push", bson.D{{"n", nonce}}}}, Upsert: true, ReturnNew: true, } if _, err = f.sc.FindId(dkey).Apply(change, &stash); err != nil { return err } change = mgo.Change{ Update: bson.D{{"$set", bson.D{{"txn-remove", t.Id}}}}, ReturnNew: true, } var info txnInfo if _, err = c.Find(qdoc).Apply(change, &info); err == nil { // The document still exists so the stash previously // observed was either out of date or necessarily // contained the token being applied. f.debugf("Marked document %v to be removed on revno %d with queue: %v", dkey, info.Revno, info.Queue) updated := false if !hasToken(stash.Queue, tt) { var set, unset bson.D if revno == 0 { // Missing revno in stash means -1. set = bson.D{{"txn-queue", info.Queue}} unset = bson.D{{"n", 1}, {"txn-revno", 1}} } else { set = bson.D{{"txn-queue", info.Queue}, {"txn-revno", newRevno}} unset = bson.D{{"n", 1}} } qdoc := bson.D{{"_id", dkey}, {"n", nonce}} udoc := bson.D{{"$set", set}, {"$unset", unset}} if err = f.sc.Update(qdoc, udoc); err == nil { updated = true } else if err != mgo.ErrNotFound { return err } } if updated { f.debugf("Updated stash for document %v with revno %d and queue: %v", dkey, newRevno, info.Queue) } else { f.debugf("Stash for document %v was up-to-date", dkey) } err = c.Remove(qdoc) } } case op.Insert != nil: if revno >= 0 { err = mgo.ErrNotFound } else { newRevno := -revno + 1 logRevnos[i] = newRevno if d, err = objToDoc(op.Insert); err != nil { return err } change := mgo.Change{ Update: bson.D{{"$set", bson.D{{"txn-insert", t.Id}}}}, ReturnNew: true, } chaos("") var info txnInfo if _, err = f.sc.Find(qdoc).Apply(change, &info); err == nil { f.debugf("Stash for document %v has revno %d and queue: %v", dkey, info.Revno, info.Queue) d = setInDoc(d, bson.D{{"_id", op.Id}, {"txn-revno", newRevno}, {"txn-queue", info.Queue}}) // Unlikely yet unfortunate race in here if this gets seriously // delayed. If someone inserts+removes meanwhile, this will // reinsert, and there's no way to avoid that while keeping the // collection clean or compromising sharding. applyOps can solve // the former, but it can't shard (SERVER-1439). chaos("insert") err = c.Insert(d) if err == nil || mgo.IsDup(err) { if err == nil { f.debugf("New document %v inserted with revno %d and queue: %v", dkey, info.Revno, info.Queue) } else { f.debugf("Document %v already existed", dkey) } chaos("") if err = f.sc.Remove(qdoc); err == nil { f.debugf("Stash for document %v removed", dkey) } } if pullOp[dkey] == i && len(pullAll) > 0 { _ = f.sc.UpdateId(dkey, bson.D{{"$pullAll", bson.D{{"txn-queue", pullAll}}}}) } } } case op.Assert != nil: // TODO pullAll if pullOp[dkey] == i } if err == nil { outcome = "DONE" } else if err == mgo.ErrNotFound || mgo.IsDup(err) { outcome = "MISS" err = nil } else { outcome = err.Error() } if debugEnabled { f.debugf("Applying %s op %d (%s) on %v with txn-revno %d: %s", t, i, opName, dkey, revno, outcome) } if err != nil { return err } if f.lc != nil && op.isChange() { // Add change to the log document. var dr bson.D for li := range logDoc { elem := &logDoc[li] if elem.Name == op.C { dr = elem.Value.(bson.D) break } } if dr == nil { logDoc = append(logDoc, bson.DocElem{op.C, bson.D{{"d", []interface{}{}}, {"r", []int64{}}}}) dr = logDoc[len(logDoc)-1].Value.(bson.D) } dr[0].Value = append(dr[0].Value.([]interface{}), op.Id) dr[1].Value = append(dr[1].Value.([]int64), logRevnos[i]) } } t.State = tapplied if f.lc != nil { // Insert log document into the changelog collection. f.debugf("Inserting %s into change log", t) err := f.lc.Insert(logDoc) if err != nil && !mgo.IsDup(err) { return err } } // It's been applied, so errors are ignored here. It's fine for someone // else to win the race and mark it as applied, and it's also fine for // it to remain pending until a later point when someone will perceive // it has been applied and mark it at such. f.debugf("Marking %s as applied", t) chaos("set-applied") f.tc.Update(bson.D{{"_id", t.Id}, {"s", tapplying}}, bson.D{{"$set", bson.D{{"s", tapplied}}}}) return nil }
// Create creates a blob with the given name, reading // the contents from the given reader. The sha256Hash // parameter holds the sha256 hash of the blob's contents, // encoded as ASCII hexadecimal. // // If a blob with the same content already exists in the store, // that content will be reused, its reference count // incremented, and alreadyExists will be true. // No data will have been read from r in this case. func (s *Storage) Create(sha256Hash string, r io.Reader) (alreadyExists bool, err error) { blobRef := hashName(sha256Hash) // First try to increment the file's reference count. err = s.incRefCount(blobRef) if err == nil { return true, nil } if err != mgo.ErrNotFound { return false, err } f, err := s.fs.Create(blobRef) if err != nil { return false, err } f.SetMeta(refCountMeta{RefCount: 1}) f.SetName(blobRef) if err := copyAndCheckHash(f, r, sha256Hash); err != nil { // Remove any chunks that were written while we were checking the hash. f.Abort() if closeErr := f.Close(); closeErr != nil { // TODO add mgo.ErrAborted so that we can avoid a string error check. if closeErr.Error() != "write aborted" { log.Printf("cannot clean up after hash-mismatch file write: %v", closeErr) } } return false, err } err = f.Close() if err == nil { return false, nil } if !mgo.IsDup(err) { return false, err } // We cannot close the file because of a clashing index, // which means someone else has created the blob first, // so all we need to do is increment the ref count. err = s.incRefCount(blobRef) if err == nil { // Although technically, the content already exists, // we have already read the content from the reader, // so report alreadyExists=false. return false, nil } if err != mgo.ErrNotFound { return false, fmt.Errorf("cannot increment blob ref count: %v", err) } // Unfortunately the other party has deleted the blob // in between Close and incRefCount. // The chunks we have written have already been // deleted at this point, so there's nothing we // can do except return an error. This situation // should be vanishingly unlikely in practice as // it relies on // a) two simultaneous initial uploads of the same blob. // b) one upload being removed immediately after upload. // c) the removal happening in the exact window between // f.Close and s.incRefCount. return false, fmt.Errorf("duplicate blob removed at an inopportune moment") }
app = *ctx.Params[0].(*App) default: return nil, errors.New("First parameter must be App or *App.") } conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() app.Quota = quota.Unlimited if limit, err := config.GetInt("quota:units-per-app"); err == nil { app.Quota.Limit = limit } app.Units = append(app.Units, Unit{}) err = conn.Apps().Insert(app) if mgo.IsDup(err) { return nil, ErrAppAlreadyExists } return &app, err }, Backward: func(ctx action.BWContext) { app := ctx.FWResult.(*App) conn, err := db.Conn() if err != nil { log.Errorf("Could not connect to the database: %s", err) return } defer conn.Close() conn.Apps().Remove(bson.M{"name": app.Name}) }, MinParams: 1,