@@ -1855,13 +1855,6 @@ func (c *Collection) Repair() *Iter {
1855
1855
cloned := session .Clone ()
1856
1856
cloned .SetMode (Strong , false )
1857
1857
defer cloned .Close ()
1858
- c = c .With (cloned )
1859
-
1860
- iter := & Iter {
1861
- session : session ,
1862
- timeout : - 1 ,
1863
- }
1864
- iter .gotReply .L = & iter .m
1865
1858
1866
1859
var result struct {
1867
1860
Cursor struct {
@@ -1874,28 +1867,10 @@ func (c *Collection) Repair() *Iter {
1874
1867
RepairCursor : c .Name ,
1875
1868
Cursor : & repairCmdCursor {batchSize },
1876
1869
}
1877
- iter .err = c .Database .Run (cmd , & result )
1878
- if iter .err != nil {
1879
- return iter
1880
- }
1881
- docs := result .Cursor .FirstBatch
1882
- for i := range docs {
1883
- iter .docData .Push (docs [i ].Data )
1884
- }
1885
- if result .Cursor .Id != 0 {
1886
- socket , err := cloned .acquireSocket (true )
1887
- if err != nil {
1888
- // Cloned session is in strong mode, and the query
1889
- // above succeeded. Should have a reserved socket.
1890
- panic ("internal error: " + err .Error ())
1891
- }
1892
- iter .server = socket .Server ()
1893
- socket .Release ()
1894
- iter .op .cursorId = result .Cursor .Id
1895
- iter .op .collection = c .FullName
1896
- iter .op .replyFunc = iter .replyFunc ()
1897
- }
1898
- return iter
1870
+
1871
+ clonedc := c .With (cloned )
1872
+ err := clonedc .Database .Run (cmd , & result )
1873
+ return clonedc .NewIter (session , result .Cursor .FirstBatch , result .Cursor .Id , err )
1899
1874
}
1900
1875
1901
1876
// FindId is a convenience helper equivalent to:
@@ -1957,7 +1932,6 @@ func (c *Collection) Pipe(pipeline interface{}) *Pipe {
1957
1932
// Iter executes the pipeline and returns an iterator capable of going
1958
1933
// over all the generated results.
1959
1934
func (p * Pipe ) Iter () * Iter {
1960
-
1961
1935
// Clone session and set it to strong mode so that the server
1962
1936
// used for the query may be safely obtained afterwards, if
1963
1937
// necessary for iteration when a cursor is received.
@@ -1966,12 +1940,6 @@ func (p *Pipe) Iter() *Iter {
1966
1940
defer cloned .Close ()
1967
1941
c := p .collection .With (cloned )
1968
1942
1969
- iter := & Iter {
1970
- session : p .session ,
1971
- timeout : - 1 ,
1972
- }
1973
- iter .gotReply .L = & iter .m
1974
-
1975
1943
var result struct {
1976
1944
// 2.4, no cursors.
1977
1945
Result []bson.Raw
@@ -1989,34 +1957,84 @@ func (p *Pipe) Iter() *Iter {
1989
1957
AllowDisk : p .allowDisk ,
1990
1958
Cursor : & pipeCmdCursor {p .batchSize },
1991
1959
}
1992
- iter . err = c .Database .Run (cmd , & result )
1993
- if e , ok := iter . err .(* QueryError ); ok && e .Message == `unrecognized field "cursor` {
1960
+ err : = c .Database .Run (cmd , & result )
1961
+ if e , ok := err .(* QueryError ); ok && e .Message == `unrecognized field "cursor` {
1994
1962
cmd .Cursor = nil
1995
1963
cmd .AllowDisk = false
1996
- iter .err = c .Database .Run (cmd , & result )
1964
+ err = c .Database .Run (cmd , & result )
1965
+ }
1966
+ firstBatch := result .Result
1967
+ if firstBatch == nil {
1968
+ firstBatch = result .Cursor .FirstBatch
1969
+ }
1970
+ return c .NewIter (p .session , firstBatch , result .Cursor .Id , err )
1971
+ }
1972
+
1973
+ // NewIter returns a newly created iterator with the provided parameters.
1974
+ // Using this method is not recommended unless the desired functionality
1975
+ // is not yet exposed via a more convenient interface (Find, Pipe, etc).
1976
+ //
1977
+ // The optional session parameter associates the lifetime of the returned
1978
+ // iterator to an arbitrary session. If nil, the iterator will be bound to
1979
+ // c's session.
1980
+ //
1981
+ // Documents in firstBatch will be individually provided by the returned
1982
+ // iterator before documents from cursorId are made available. If cursorId
1983
+ // is zero, only the documents in firstBatch are provided.
1984
+ //
1985
+ // If err is not nil, the iterator's Err method will report it after
1986
+ // exhausting documents in firstBatch.
1987
+ //
1988
+ // NewIter must be called right after the cursor id is obtained, and must not
1989
+ // be called on a collection in Eventual mode, because the cursor id is
1990
+ // associated with the specific server that returned it. The session parameter
1991
+ // may be in any mode or state, though.
1992
+ //
1993
+ func (c * Collection ) NewIter (session * Session , firstBatch []bson.Raw , cursorId int64 , err error ) * Iter {
1994
+ var server * mongoServer
1995
+ csession := c .Database .Session
1996
+ csession .m .RLock ()
1997
+ socket := csession .masterSocket
1998
+ if socket == nil {
1999
+ socket = csession .slaveSocket
1997
2000
}
1998
- if iter . err != nil {
1999
- return iter
2001
+ if socket != nil {
2002
+ server = socket . Server ()
2000
2003
}
2001
- docs := result .Result
2002
- if docs == nil {
2003
- docs = result .Cursor .FirstBatch
2004
+ csession .m .RUnlock ()
2005
+
2006
+ if server == nil {
2007
+ if csession .Mode () == Eventual {
2008
+ panic ("Collection.NewIter called in Eventual mode" )
2009
+ }
2010
+ panic ("Collection.NewIter called on a fresh session with no associated server" )
2004
2011
}
2005
- for i := range docs {
2006
- iter .docData .Push (docs [i ].Data )
2012
+
2013
+ if session == nil {
2014
+ session = csession
2007
2015
}
2008
- if result .Cursor .Id != 0 {
2009
- socket , err := cloned .acquireSocket (true )
2010
- if err != nil {
2011
- // Cloned session is in strong mode, and the query
2012
- // above succeeded. Should have a reserved socket.
2013
- panic ("internal error: " + err .Error ())
2016
+
2017
+ iter := & Iter {
2018
+ session : session ,
2019
+ server : server ,
2020
+ timeout : - 1 ,
2021
+ err : err ,
2022
+ }
2023
+ iter .gotReply .L = & iter .m
2024
+ for _ , doc := range firstBatch {
2025
+ iter .docData .Push (doc .Data )
2026
+ }
2027
+ if cursorId != 0 {
2028
+ socket , err := c .Database .Session .acquireSocket (true )
2029
+ if err == nil {
2030
+ iter .server = socket .Server ()
2031
+ socket .Release ()
2032
+ iter .op .cursorId = cursorId
2033
+ iter .op .collection = c .FullName
2034
+ iter .op .replyFunc = iter .replyFunc ()
2035
+ } else if iter .err == nil {
2036
+ iter .err = err
2014
2037
}
2015
- iter .server = socket .Server ()
2016
- socket .Release ()
2017
- iter .op .cursorId = result .Cursor .Id
2018
- iter .op .collection = c .FullName
2019
- iter .op .replyFunc = iter .replyFunc ()
2020
2038
}
2021
2039
return iter
2022
2040
}
0 commit comments