@@ -111,6 +111,8 @@ type LocalCache struct {
111
111
112
112
// plists are posting lists in memory. They can be discarded to reclaim space.
113
113
plists map [string ]* List
114
+
115
+ postings map [string ]* pb.PostingList
114
116
}
115
117
116
118
// NewLocalCache returns a new LocalCache instance.
@@ -120,13 +122,17 @@ func NewLocalCache(startTs uint64) *LocalCache {
120
122
deltas : make (map [string ][]byte ),
121
123
plists : make (map [string ]* List ),
122
124
maxVersions : make (map [string ]uint64 ),
125
+ postings : make (map [string ]* pb.PostingList ),
123
126
}
124
127
}
125
128
126
129
// NoCache returns a new LocalCache instance, which won't cache anything. Useful to pass startTs
127
130
// around.
128
131
func NoCache (startTs uint64 ) * LocalCache {
129
- return & LocalCache {startTs : startTs }
132
+ return & LocalCache {
133
+ startTs : startTs ,
134
+ postings : make (map [string ]* pb.PostingList ),
135
+ }
130
136
}
131
137
132
138
func (lc * LocalCache ) getNoStore (key string ) * List {
@@ -138,6 +144,20 @@ func (lc *LocalCache) getNoStore(key string) *List {
138
144
return nil
139
145
}
140
146
147
+ // SetIfAbsent adds the list for the specified key to the cache. If a list for the same
148
+ // key already exists, the cache will not be modified and the existing list
149
+ // will be returned instead. This behavior is meant to prevent the goroutines
150
+ // using the cache from ending up with an orphaned version of a list.
151
+ func (lc * LocalCache ) SetPostingIfAbsent (key string , updated * pb.PostingList ) * pb.PostingList {
152
+ lc .Lock ()
153
+ defer lc .Unlock ()
154
+ if pl , ok := lc .postings [key ]; ok {
155
+ return pl
156
+ }
157
+ lc .postings [key ] = updated
158
+ return updated
159
+ }
160
+
141
161
// SetIfAbsent adds the list for the specified key to the cache. If a list for the same
142
162
// key already exists, the cache will not be modified and the existing list
143
163
// will be returned instead. This behavior is meant to prevent the goroutines
@@ -200,8 +220,10 @@ func (lc *LocalCache) GetBatchSinglePosting(keys [][]byte) ([]*pb.PostingList, e
200
220
remaining_keys := make ([][]byte , 0 )
201
221
lc .RLock ()
202
222
for i , key := range keys {
203
- pl := & pb.PostingList {}
204
- if delta , ok := lc .deltas [string (key )]; ok && len (delta ) > 0 {
223
+ if pl , ok := lc .postings [string (key )]; ok && pl != nil {
224
+ results [i ] = pl
225
+ } else if delta , ok := lc .deltas [string (key )]; ok && len (delta ) > 0 {
226
+ pl := & pb.PostingList {}
205
227
err := pl .Unmarshal (delta )
206
228
if err != nil {
207
229
results [i ] = pl
@@ -214,6 +236,10 @@ func (lc *LocalCache) GetBatchSinglePosting(keys [][]byte) ([]*pb.PostingList, e
214
236
215
237
txn := pstore .NewTransactionAt (lc .startTs , false )
216
238
items , err := txn .GetBatch (remaining_keys )
239
+ if err != nil {
240
+ fmt .Println (err , keys )
241
+ return nil , err
242
+ }
217
243
idx := 0
218
244
219
245
for i := 0 ; i < len (results ); i ++ {
@@ -245,6 +271,7 @@ func (lc *LocalCache) GetBatchSinglePosting(keys [][]byte) ([]*pb.PostingList, e
245
271
}
246
272
pl .Postings = pl .Postings [:idx ]
247
273
results [i ] = pl
274
+ lc .SetPostingIfAbsent (string (keys [i ]), pl )
248
275
}
249
276
250
277
return results , err
@@ -311,6 +338,7 @@ func (lc *LocalCache) GetSinglePosting(key []byte) (*pb.PostingList, error) {
311
338
}
312
339
}
313
340
pl .Postings = pl .Postings [:idx ]
341
+ lc .SetPostingIfAbsent (string (key ), pl )
314
342
return pl , nil
315
343
}
316
344
0 commit comments