~juju-qa/ubuntu/xenial/juju/2.0-rc2

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/state/refcounts_ns.go

  • Committer: Nicholas Skaggs
  • Date: 2016-09-30 14:39:30 UTC
  • mfrom: (1.8.1)
  • Revision ID: nicholas.skaggs@canonical.com-20160930143930-vwwhrefh6ftckccy
import upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
        RefCount int `bson:"refcount"`
34
34
}
35
35
 
 
36
var (
 
37
        errRefcountChanged = errors.New("refcount changed")
 
38
)
 
39
 
36
40
// nsRefcounts exposes methods for safely manipulating reference count
37
41
// documents. (You can also manipulate them unsafely via the Just*
38
42
// methods that don't keep track of DB state.)
64
68
}
65
69
 
66
70
// CreateOrIncrefOp returns a txn.Op that creates a refcount document as
67
 
// configured with a value of 1; or increments any such refcount doc
 
71
// configured with a specified value; or increments any such refcount doc
68
72
// that already exists.
69
 
func (ns nsRefcounts_) CreateOrIncRefOp(coll mongo.Collection, key string) (txn.Op, error) {
 
73
func (ns nsRefcounts_) CreateOrIncRefOp(coll mongo.Collection, key string, n int) (txn.Op, error) {
70
74
        if exists, err := ns.exists(coll, key); err != nil {
71
75
                return txn.Op{}, errors.Trace(err)
72
76
        } else if !exists {
73
 
                return ns.JustCreateOp(coll.Name(), key, 1), nil
 
77
                return ns.JustCreateOp(coll.Name(), key, n), nil
74
78
        }
75
 
        return ns.JustIncRefOp(coll.Name(), key), nil
 
79
        return ns.JustIncRefOp(coll.Name(), key, n), nil
76
80
}
77
81
 
78
82
// StrictIncRefOp returns a txn.Op that increments the value of a
79
83
// refcount doc, or returns an error if it does not exist.
80
 
func (ns nsRefcounts_) StrictIncRefOp(coll mongo.Collection, key string) (txn.Op, error) {
 
84
func (ns nsRefcounts_) StrictIncRefOp(coll mongo.Collection, key string, n int) (txn.Op, error) {
81
85
        if exists, err := ns.exists(coll, key); err != nil {
82
86
                return txn.Op{}, errors.Trace(err)
83
87
        } else if !exists {
84
 
                return txn.Op{}, errors.New("refcount does not exist")
 
88
                return txn.Op{}, errors.New("does not exist")
85
89
        }
86
 
        return ns.JustIncRefOp(coll.Name(), key), nil
 
90
        return ns.JustIncRefOp(coll.Name(), key, n), nil
87
91
}
88
92
 
89
93
// AliveDecRefOp returns a txn.Op that decrements the value of a
123
127
                return txn.Op{}, errors.Trace(err)
124
128
        }
125
129
        if refcount != value {
126
 
                return txn.Op{}, errors.New("refcount changed")
 
130
                return txn.Op{}, errRefcountChanged
127
131
        }
128
132
        return ns.JustRemoveOp(coll.Name(), key, value), nil
129
133
}
130
134
 
 
135
// CurrentOp returns the current reference count value, and a txn.Op that
 
136
// asserts that the refcount has that value, or an error. If the refcount
 
137
// doc does not exist, then the op will assert that the document does not
 
138
// exist instead, and no error is returned.
 
139
func (ns nsRefcounts_) CurrentOp(coll mongo.Collection, key string) (txn.Op, int, error) {
 
140
        refcount, err := ns.read(coll, key)
 
141
        if errors.IsNotFound(err) {
 
142
                return txn.Op{
 
143
                        C:      coll.Name(),
 
144
                        Id:     key,
 
145
                        Assert: txn.DocMissing,
 
146
                }, 0, nil
 
147
        }
 
148
        if err != nil {
 
149
                return txn.Op{}, -1, errors.Trace(err)
 
150
        }
 
151
        return txn.Op{
 
152
                C:      coll.Name(),
 
153
                Id:     key,
 
154
                Assert: bson.D{{"refcount", refcount}},
 
155
        }, refcount, nil
 
156
}
 
157
 
131
158
// JustCreateOp returns a txn.Op that creates a refcount document as
132
159
// configured, *without* checking database state for sanity first.
133
160
// You should avoid using this method in most cases.
141
168
}
142
169
 
143
170
// JustIncRefOp returns a txn.Op that increments a refcount document by
144
 
// 1, as configured, *without* checking database state for sanity first.
145
 
// You should avoid using this method in most cases.
146
 
func (nsRefcounts_) JustIncRefOp(collName, key string) txn.Op {
 
171
// the specified amount, as configured, *without* checking database state
 
172
// for sanity first. You should avoid using this method in most cases.
 
173
func (nsRefcounts_) JustIncRefOp(collName, key string, n int) txn.Op {
147
174
        return txn.Op{
148
175
                C:      collName,
149
176
                Id:     key,
150
177
                Assert: txn.DocExists,
151
 
                Update: bson.D{{"$inc", bson.D{{"refcount", 1}}}},
 
178
                Update: bson.D{{"$inc", bson.D{{"refcount", n}}}},
152
179
        }
153
180
}
154
181
 
194
221
func (nsRefcounts_) read(coll mongo.Collection, key string) (int, error) {
195
222
        var doc refcountDoc
196
223
        if err := coll.FindId(key).One(&doc); err == mgo.ErrNotFound {
197
 
                return 0, errors.NotFoundf("refcount")
 
224
                return 0, errors.NotFoundf("refcount %q", key)
198
225
        } else if err != nil {
199
226
                return 0, errors.Trace(err)
200
227
        }