0
0
Fork 0

fix race condition in incorrectly shared state in MultiSearch

When performing a MultiSearch, we create child SearchRequests
from the original SearchRequest.  In doing so we copy many fields.
But, copying of the SortOrder was incorrect, as this contains
state, and distint SortOrder objects must be used.  This change
introduces a Copy() method to the SearchSort interface, and
to the SortOrder types.  MultiSearch now creates a new copy of
the SortOrder for each child request.
This commit is contained in:
Marty Schoch 2017-04-06 17:49:33 -04:00
parent 957812369d
commit a78e632bd6
2 changed files with 35 additions and 1 deletions

View File

@ -432,7 +432,7 @@ func createChildSearchRequest(req *SearchRequest) *SearchRequest {
Fields: req.Fields,
Facets: req.Facets,
Explain: req.Explain,
Sort: req.Sort,
Sort: req.Sort.Copy(),
IncludeLocations: req.IncludeLocations,
}
return &rv

View File

@ -36,6 +36,8 @@ type SearchSort interface {
RequiresDocID() bool
RequiresScoring() bool
RequiresFields() []string
Copy() SearchSort
}
func ParseSearchSortObj(input map[string]interface{}) (SearchSort, error) {
@ -205,6 +207,14 @@ func (so SortOrder) UpdateVisitor(field string, term []byte) {
}
}
func (so SortOrder) Copy() SortOrder {
rv := make(SortOrder, len(so))
for i, soi := range so {
rv[i] = soi.Copy()
}
return rv
}
// Compare will compare two document matches using the specified sort order
// if both are numbers, we avoid converting back to term
func (so SortOrder) Compare(cachedScoring, cachedDesc []bool, i, j *DocumentMatch) int {
@ -475,6 +485,12 @@ func (s *SortField) MarshalJSON() ([]byte, error) {
return json.Marshal(sfm)
}
func (s *SortField) Copy() SearchSort {
var rv SortField
rv = *s
return &rv
}
// SortDocID will sort results by the document identifier
type SortDocID struct {
Desc bool
@ -512,6 +528,12 @@ func (s *SortDocID) MarshalJSON() ([]byte, error) {
return json.Marshal("_id")
}
func (s *SortDocID) Copy() SearchSort {
var rv SortDocID
rv = *s
return &rv
}
// SortScore will sort results by the document match score
type SortScore struct {
Desc bool
@ -549,6 +571,12 @@ func (s *SortScore) MarshalJSON() ([]byte, error) {
return json.Marshal("_score")
}
func (s *SortScore) Copy() SearchSort {
var rv SortScore
rv = *s
return &rv
}
var maxDistance = string(numeric.MustNewPrefixCodedInt64(math.MaxInt64, 0))
// NewSortGeoDistance creates SearchSort instance for sorting documents by
@ -675,3 +703,9 @@ func (s *SortGeoDistance) MarshalJSON() ([]byte, error) {
return json.Marshal(sfm)
}
func (s *SortGeoDistance) Copy() SearchSort {
var rv SortGeoDistance
rv = *s
return &rv
}