Skip to content

Commit

Permalink
Refactored cursor code and fix CSHARP-24 Make Cursors reusable.
Browse files Browse the repository at this point in the history
  • Loading branch information
lanwin committed May 14, 2010
1 parent b7c31a9 commit ce20f4b
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 89 deletions.
157 changes: 69 additions & 88 deletions source/MongoDB/Cursor_1.cs
Expand Up @@ -34,7 +34,6 @@ public class Cursor<T> : ICursor<T> where T : class
public Cursor(ISerializationFactory serializationFactory, Connection connection, string fullCollectionName)
{
//Todo: should be internal
Id = -1;
_connection = connection;
FullCollectionName = fullCollectionName;
_serializationFactory = serializationFactory;
Expand Down Expand Up @@ -173,11 +172,10 @@ public Cursor(ISerializationFactory serializationFactory, Connection connection,
/// </summary>
/// <returns></returns>
public Document Explain(){
//Fixme Return a single Document and not T
TryModify();
_specOpts["$explain"] = true;

var explainResult = GetQueryRepley<Document>();
var explainResult = RetrieveData<Document>();
try
{
var explain = explainResult.Documents.FirstOrDefault();
Expand Down Expand Up @@ -207,47 +205,63 @@ public Cursor(ISerializationFactory serializationFactory, Connection connection,
/// </summary>
/// <value>The documents.</value>
public IEnumerable<T> Documents {
get {
if (_reply == null)
RetrieveData();
if (_reply == null)
throw new InvalidOperationException("Expecting reply but get null");

var documents = _reply.Documents;
var documentCount = 0;
var shouldBreak = false;

while (!shouldBreak) {
foreach (var document in documents)
if ((_limit == 0) || (_limit != 0 && documentCount < _limit)) {
documentCount++;
yield return document;
} else
yield break;

if (Id != 0) {
RetrieveMoreData();
documents = _reply.Documents;
if (documents == null)
shouldBreak = true;
} else
shouldBreak = true;
}
get {
do
{
_reply = RetrieveData<T>();

if(_reply == null)
throw new InvalidOperationException("Expecting reply but get null");

//if(_limit < 0)
//_limit = _limit * -1;

Id = _reply.CursorId;

foreach(var document in _reply.Documents)
yield return document;
}
while(Id > 0 && _limit<CursorPosition);
}
}

/// <summary>
/// Gets the cursor position.
/// </summary>
/// <value>The cursor position.</value>
public int CursorPosition
{
get
{
if(_reply == null)
return 0;

return _reply.StartingFrom + _reply.NumberReturned;
}
}

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
if (Id == 0)
//All server side resources disposed of.
return;
if(Id == 0)
return; //All server side resources disposed of.

KillCursor(Id);
}

/// <summary>
/// Optionses the specified options.
/// </summary>
/// <param name = "options">The options.</param>
/// <returns></returns>
public ICursor<T> Options(QueryOptions options){
TryModify();
_options = options;
return this;
}

/// <summary>
/// Kills the cursor.
/// </summary>
Expand All @@ -256,87 +270,54 @@ private void KillCursor(long cursorId)
var killCursorsMessage = new KillCursorsMessage(cursorId);

try {
_connection.SendMessage(killCursorsMessage);
_connection.SendMessage(killCursorsMessage);
Id = 0;
} catch (IOException exception) {
throw new MongoConnectionException("Could not read data, communication failure", _connection, exception);
}
}

/// <summary>
/// Optionses the specified options.
/// </summary>
/// <param name = "options">The options.</param>
/// <returns></returns>
public ICursor<T> Options(QueryOptions options){
TryModify();
_options = options;
return this;
}

/// <summary>
/// Gets the query repley.
/// Retrieves the data.
/// </summary>
/// <typeparam name="TReply">The type of the reply.</typeparam>
/// <returns></returns>
private ReplyMessage<TReply> GetQueryRepley<TReply>() where TReply : class
private ReplyMessage<TReply> RetrieveData<TReply>() where TReply : class
{
var writerSettings = _serializationFactory.GetBsonWriterSettings(typeof(T));
_isModifiable = false;

IRequestMessage message;

var query = new QueryMessage(writerSettings)
if(Id <= 0)
{
FullCollectionName = FullCollectionName,
Query = BuildSpec(),
NumberToReturn = _limit,
NumberToSkip = _skip,
Options = _options
};
var writerSettings = _serializationFactory.GetBsonWriterSettings(typeof(T));

if(_fields != null)
query.ReturnFieldSelector = _fields;
message = new QueryMessage(writerSettings)
{
FullCollectionName = FullCollectionName,
Query = BuildSpec(),
NumberToReturn = _limit,
NumberToSkip = _skip,
Options = _options,
ReturnFieldSelector = _fields
};
}
else
{
message = new GetMoreMessage(FullCollectionName, Id, _limit);
}

var readerSettings = _serializationFactory.GetBsonReaderSettings(typeof(T));

try
{
return _connection.SendTwoWayMessage<TReply>(query, readerSettings);
return _connection.SendTwoWayMessage<TReply>(message, readerSettings);
}
catch(IOException exception)
{
throw new MongoConnectionException("Could not read data, communication failure", _connection, exception);
}
}

/// <summary>
/// Retrieves the data.
/// </summary>
private void RetrieveData(){
_reply = GetQueryRepley<T>();

Id = _reply.CursorId;

if(_limit < 0)
_limit = _limit * -1;

_isModifiable = false;
}

/// <summary>
/// Retrieves the more data.
/// </summary>
private void RetrieveMoreData(){
var getMoreMessage = new GetMoreMessage(FullCollectionName, Id, _limit);

var readerSettings = _serializationFactory.GetBsonReaderSettings(typeof(T));

try {
_reply = _connection.SendTwoWayMessage<T>(getMoreMessage, readerSettings);
Id = _reply.CursorId;
} catch (IOException exception) {
Id = 0;
throw new MongoConnectionException("Could not read data, communication failure", _connection, exception);
}
}

/// <summary>
/// Tries the modify.
Expand Down
2 changes: 1 addition & 1 deletion source/MongoDB/Obsolete/Cursor.cs
Expand Up @@ -4,7 +4,7 @@ namespace MongoDB
{
/// <summary>
/// <see cref="ICursor"/>
/// </summary>
/// </summary>
public class Cursor : ICursor
{
private readonly ICursor<Document> _cursor;
Expand Down

0 comments on commit ce20f4b

Please sign in to comment.