View Javadoc
1   /*
2    * #%L
3    * GetMore.java - mongodb-async-driver - Allanbank Consulting, Inc.
4    * %%
5    * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.allanbank.mongodb.client.message;
21  
22  import java.io.IOException;
23  
24  import com.allanbank.mongodb.ReadPreference;
25  import com.allanbank.mongodb.bson.io.BsonInputStream;
26  import com.allanbank.mongodb.bson.io.BsonOutputStream;
27  import com.allanbank.mongodb.bson.io.BufferingBsonOutputStream;
28  import com.allanbank.mongodb.bson.io.StringEncoder;
29  import com.allanbank.mongodb.client.Message;
30  import com.allanbank.mongodb.client.Operation;
31  import com.allanbank.mongodb.error.DocumentToLargeException;
32  
33  /**
34   * Message to <a href=
35   * "http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-OPGETMORE"
36   * >getmore</a> documents from a cursor. The format of the message is:
37   * 
38   * <pre>
39   * <code>
40   * struct {
41   *     MsgHeader header;             // standard message header
42   *     int32     ZERO;               // 0 - reserved for future use
43   *     cstring   fullCollectionName; // "dbname.collectionname"
44   *     int32     numberToReturn;     // number of documents to return
45   *     int64     cursorID;           // cursorID from the OP_REPLY
46   * }
47   * </code>
48   * </pre>
49   * 
50   * 
51   * @api.no This class is <b>NOT</b> part of the drivers API. This class may be
52   *         mutated in incompatible ways between any two releases of the driver.
53   * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved
54   */
55  public class GetMore extends AbstractMessage {
56  
57      /** The id for the cursor. */
58      private final long myCursorId;
59  
60      /** The number of documents to be returned. */
61      private final int myNumberToReturn;
62  
63      /**
64       * Creates a new GetMore.
65       * 
66       * @param in
67       *            The stream to read the get_more message from.
68       * @throws IOException
69       *             On a failure reading the get_more message.
70       */
71      public GetMore(final BsonInputStream in) throws IOException {
72          in.readInt(); // reserved - 0.
73          init(in.readCString());
74          myNumberToReturn = in.readInt();
75          myCursorId = in.readLong();
76      }
77  
78      /**
79       * Creates a new GetMore.
80       * 
81       * @param databaseName
82       *            The name of the database.
83       * @param collectionName
84       *            The name of the collection.
85       * @param cursorId
86       *            The id of the cursor.
87       * @param numberToReturn
88       *            The number of documents to return.
89       * @param readPreference
90       *            The preferences for which server to send the request.
91       */
92      public GetMore(final String databaseName, final String collectionName,
93              final long cursorId, final int numberToReturn,
94              final ReadPreference readPreference) {
95          super(databaseName, collectionName, readPreference);
96  
97          myCursorId = cursorId;
98          myNumberToReturn = numberToReturn;
99      }
100 
101     /**
102      * Determines if the passed object is of this same type as this object and
103      * if so that its fields are equal.
104      * 
105      * @param object
106      *            The object to compare to.
107      * 
108      * @see java.lang.Object#equals(java.lang.Object)
109      */
110     @Override
111     public boolean equals(final Object object) {
112         boolean result = false;
113         if (this == object) {
114             result = true;
115         }
116         else if ((object != null) && (getClass() == object.getClass())) {
117             final GetMore other = (GetMore) object;
118 
119             result = super.equals(object) && (myCursorId == other.myCursorId)
120                     && (myNumberToReturn == other.myNumberToReturn);
121         }
122         return result;
123     }
124 
125     /**
126      * Returns the id of the cursor to get more documents from.
127      * 
128      * @return The id of the cursor to get more documents from.
129      */
130     public long getCursorId() {
131         return myCursorId;
132     }
133 
134     /**
135      * Return the number of documents to return from the cursor.
136      * 
137      * @return The number of documents to return from the cursor.
138      */
139     public int getNumberToReturn() {
140         return myNumberToReturn;
141     }
142 
143     /**
144      * {@inheritDoc}
145      * <p>
146      * Overridden to return the name of the operation: "GET_MORE".
147      * </p>
148      */
149     @Override
150     public String getOperationName() {
151         return Operation.GET_MORE.name();
152     }
153 
154     /**
155      * Computes a reasonable hash code.
156      * 
157      * @return The hash code value.
158      */
159     @Override
160     public int hashCode() {
161         int result = 1;
162         result = (31 * result) + super.hashCode();
163         result = (31 * result) + (int) (myCursorId >> Integer.SIZE);
164         result = (31 * result) + (int) myCursorId;
165         result = (31 * result) + myNumberToReturn;
166         return result;
167     }
168 
169     /**
170      * {@inheritDoc}
171      * <p>
172      * Overridden to return the size of the {@link GetMore}.
173      * </p>
174      */
175     @Override
176     public int size() {
177         int size = HEADER_SIZE + 18; // See below.
178         // size += 4; // reserved - 0;
179         size += StringEncoder.utf8Size(myDatabaseName);
180         // size += 1; // StringEncoder.utf8Size(".");
181         size += StringEncoder.utf8Size(myCollectionName);
182         // size += 1; // \0 on the CString.
183         // size += 4; // numberToReturn - int32
184         // size += 8; // cursorId - long(64)
185 
186         return size;
187     }
188 
189     /**
190      * {@inheritDoc}
191      * <p>
192      * Overrridden to be a no-op since the size of a GetMore is fixed.
193      * </p>
194      */
195     @Override
196     public void validateSize(final int maxDocumentSize)
197             throws DocumentToLargeException {
198         // Can't be too large.
199     }
200 
201     /**
202      * {@inheritDoc}
203      * <p>
204      * Overridden to write a get_more message.
205      * </p>
206      * 
207      * @see Message#write(int, BsonOutputStream)
208      */
209     @Override
210     public void write(final int messageId, final BsonOutputStream out)
211             throws IOException {
212         int size = HEADER_SIZE;
213         size += 4; // reserved - 0;
214         size += out.sizeOfCString(myDatabaseName, ".", myCollectionName);
215         size += 4; // numberToReturn - int32
216         size += 8; // cursorId - long(64)
217 
218         writeHeader(out, messageId, 0, Operation.GET_MORE, size);
219         out.writeInt(0);
220         out.writeCString(myDatabaseName, ".", myCollectionName);
221         out.writeInt(myNumberToReturn);
222         out.writeLong(myCursorId);
223     }
224 
225     /**
226      * {@inheritDoc}
227      * <p>
228      * Overridden to write a get_more message.
229      * </p>
230      * 
231      * @see Message#write(int, BsonOutputStream)
232      */
233     @Override
234     public void write(final int messageId, final BufferingBsonOutputStream out)
235             throws IOException {
236 
237         final long start = writeHeader(out, messageId, 0, Operation.GET_MORE);
238         out.writeInt(0);
239         out.writeCString(myDatabaseName, ".", myCollectionName);
240         out.writeInt(myNumberToReturn);
241         out.writeLong(myCursorId);
242         finishHeader(out, start);
243 
244         out.flushBuffer();
245     }
246 }