View Javadoc
1   /*
2    * #%L
3    * KillCursors.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  import java.util.Arrays;
24  
25  import com.allanbank.mongodb.ReadPreference;
26  import com.allanbank.mongodb.bson.io.BsonInputStream;
27  import com.allanbank.mongodb.bson.io.BsonOutputStream;
28  import com.allanbank.mongodb.bson.io.BufferingBsonOutputStream;
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-OPKILLCURSORS"
36   * >killcursor</a>s that a client no longer needs.
37   * 
38   * <pre>
39   * <code>
40   * struct {
41   *     MsgHeader header;            // standard message header
42   *     int32     ZERO;              // 0 - reserved for future use
43   *     int32     numberOfCursorIDs; // number of cursorIDs in message
44   *     int64*    cursorIDs;         // sequence of cursorIDs to close
45   * }
46   * </code>
47   * </pre>
48   * 
49   * @api.no This class is <b>NOT</b> part of the drivers API. This class may be
50   *         mutated in incompatible ways between any two releases of the driver.
51   * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved
52   */
53  public class KillCursors extends AbstractMessage {
54  
55      /** The ids of the cursors to be killed. */
56      private final long[] myCursorIds;
57  
58      /**
59       * Creates a new KillCursors.
60       * 
61       * @param in
62       *            The stream to read the kill_cursors message from.
63       * @throws IOException
64       *             On a failure reading the kill_cursors message.
65       */
66      public KillCursors(final BsonInputStream in) throws IOException {
67          init(".");
68  
69          in.readInt(); // 0 - reserved.
70          final int numberOfCursors = in.readInt();
71          myCursorIds = new long[numberOfCursors];
72          for (int i = 0; i < numberOfCursors; ++i) {
73              myCursorIds[i] = in.readLong();
74          }
75      }
76  
77      /**
78       * Creates a new KillCursors.
79       * 
80       * @param cursorIds
81       *            The ids of the cursors to kill.
82       * @param readPreference
83       *            The preferences for which server to send the request.
84       */
85      public KillCursors(final long[] cursorIds,
86              final ReadPreference readPreference) {
87          super("", "", readPreference);
88          myCursorIds = Arrays.copyOf(cursorIds, cursorIds.length);
89      }
90  
91      /**
92       * Determines if the passed object is of this same type as this object and
93       * if so that its fields are equal.
94       * 
95       * @param object
96       *            The object to compare to.
97       * 
98       * @see java.lang.Object#equals(java.lang.Object)
99       */
100     @Override
101     public boolean equals(final Object object) {
102         boolean result = false;
103         if (this == object) {
104             result = true;
105         }
106         else if ((object != null) && (getClass() == object.getClass())) {
107             final KillCursors other = (KillCursors) object;
108 
109             // Base class fields are always the same ""."".
110             result = Arrays.equals(myCursorIds, other.myCursorIds);
111         }
112         return result;
113     }
114 
115     /**
116      * Returns the ids of the cursors to be killed.
117      * 
118      * @return The ids of the cursors to be killed.
119      */
120     public long[] getCursorIds() {
121         return Arrays.copyOf(myCursorIds, myCursorIds.length);
122     }
123 
124     /**
125      * {@inheritDoc}
126      * <p>
127      * Overridden to return the name of the operation: "KILL_CURSORS".
128      * </p>
129      */
130     @Override
131     public String getOperationName() {
132         return Operation.KILL_CURSORS.name();
133     }
134 
135     /**
136      * Computes a reasonable hash code.
137      * 
138      * @return The hash code value.
139      */
140     @Override
141     public int hashCode() {
142         int result = 1;
143         result = (31 * result) + super.hashCode();
144         result = (31 * result) + Arrays.hashCode(myCursorIds);
145         return result;
146     }
147 
148     /**
149      * {@inheritDoc}
150      * <p>
151      * Overridden to return the size of the {@link KillCursors}.
152      * </p>
153      */
154     @Override
155     public int size() {
156 
157         int size = HEADER_SIZE + 8; // See below.
158         // size += 4; // 0 - reserved
159         // size += 4; // number of cursors.
160         size += (8 * myCursorIds.length);
161 
162         return size;
163     }
164 
165     /**
166      * {@inheritDoc}
167      * <p>
168      * Overrridden to ensure the size of the cursors ids array is not too large.
169      * </p>
170      */
171     @Override
172     public void validateSize(final int maxDocumentSize)
173             throws DocumentToLargeException {
174         if (maxDocumentSize < (myCursorIds.length * 8)) {
175             throw new DocumentToLargeException((myCursorIds.length * 8),
176                     maxDocumentSize, null);
177         }
178     }
179 
180     /**
181      * {@inheritDoc}
182      * <p>
183      * Overridden to write the kill_cursors message.
184      * </p>
185      * 
186      * @see Message#write(int, BsonOutputStream)
187      */
188     @Override
189     public void write(final int messageId, final BsonOutputStream out)
190             throws IOException {
191         int size = HEADER_SIZE;
192         size += 4; // 0 - reserved
193         size += 4; // number of cursors.
194         size += (8 * myCursorIds.length);
195 
196         writeHeader(out, messageId, 0, Operation.KILL_CURSORS, size);
197         out.writeInt(0);
198         out.writeInt(myCursorIds.length);
199         for (final long myCursorId : myCursorIds) {
200             out.writeLong(myCursorId);
201         }
202     }
203 
204     /**
205      * {@inheritDoc}
206      * <p>
207      * Overridden to write the kill_cursors message.
208      * </p>
209      * 
210      * @see Message#write(int, BsonOutputStream)
211      */
212     @Override
213     public void write(final int messageId, final BufferingBsonOutputStream out)
214             throws IOException {
215         final long start = writeHeader(out, messageId, 0,
216                 Operation.KILL_CURSORS);
217         out.writeInt(0);
218         out.writeInt(myCursorIds.length);
219         for (final long myCursorId : myCursorIds) {
220             out.writeLong(myCursorId);
221         }
222         finishHeader(out, start);
223 
224         out.flushBuffer();
225     }
226 }