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 }