Coverage Report - com.allanbank.mongodb.Durability
 
Classes in this File Line Coverage Branch Coverage Complexity
Durability
97%
109/112
94%
74/78
2.87
 
 1  
 /*
 2  
  * #%L
 3  
  * Durability.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;
 21  
 
 22  
 import java.io.Serializable;
 23  
 import java.io.StringWriter;
 24  
 
 25  
 import com.allanbank.mongodb.bson.Document;
 26  
 import com.allanbank.mongodb.bson.Element;
 27  
 import com.allanbank.mongodb.bson.NumericElement;
 28  
 import com.allanbank.mongodb.bson.builder.BuilderFactory;
 29  
 import com.allanbank.mongodb.bson.builder.DocumentBuilder;
 30  
 import com.allanbank.mongodb.bson.element.JsonSerializationVisitor;
 31  
 import com.allanbank.mongodb.bson.element.StringElement;
 32  
 import com.allanbank.mongodb.bson.element.SymbolElement;
 33  
 import com.allanbank.mongodb.bson.impl.ImmutableDocument;
 34  
 import com.allanbank.mongodb.bson.json.Json;
 35  
 import com.allanbank.mongodb.error.JsonParseException;
 36  
 
 37  
 /**
 38  
  * Represents the required durability of writes (inserts, updates, and deletes)
 39  
  * on the server.
 40  
  * <ul>
 41  
  * <li>The lowest durability ({@link #NONE}) has no guarantees that the data
 42  
  * will survive a catastrophic server failure.
 43  
  * <li>The next level of durability ({@link #ACK}) ensures that the data has
 44  
  * been received by the server.
 45  
  * <li>The next level of durability ({@link #journalDurable(int)}) ensures that
 46  
  * the data is written to the server's journal before returning.
 47  
  * <li>Next level ({@link #fsyncDurable(int)}) is to ensure that the data has
 48  
  * been fsync()'d to the server's disk.
 49  
  * <li>For the highest level of durability ({@link #replicaDurable(int)}), the
 50  
  * server ensure that the data has been received by 1 to
 51  
  * {@link #replicaDurable(int, int) N} replicas in the replica set. Fine grain
 52  
  * control can be achieved by specifying a {@link #replicaDurable(String, int)
 53  
  * replication mode} instead of a count.</li>
 54  
  * </ul>
 55  
  * <p>
 56  
  * Generally, increasing the level of durability decreases performance.
 57  
  * </p>
 58  
  * 
 59  
  * @see <a href="http://www.mongodb.org/display/DOCS/Data+Center+Awareness">Data
 60  
  *      Center Awareness</a>
 61  
  * @api.yes This class is part of the driver's API. Public and protected members
 62  
  *          will be deprecated for at least 1 non-bugfix release (version
 63  
  *          numbers are &lt;major&gt;.&lt;minor&gt;.&lt;bugfix&gt;) before being
 64  
  *          removed or modified.
 65  
  * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved
 66  
  */
 67  
 public class Durability implements Serializable {
 68  
 
 69  
     /** The durability that says no durability is required. */
 70  1
     public final static Durability ACK = new Durability(true, false, false, 1,
 71  
             null, 0);
 72  
 
 73  
     /**
 74  
      * Built in replication mode indicating that more than 50% of the MongoDB
 75  
      * replica set servers have received a write.
 76  
      */
 77  
     public final static String MAJORITY_MODE = "majority";
 78  
 
 79  
     /** The durability that says no durability is required. */
 80  1
     public final static Durability NONE = new Durability(false, false, false,
 81  
             0, null, 0);
 82  
 
 83  
     /** Serialization version for the class. */
 84  
     private static final long serialVersionUID = -6474266523435876385L;
 85  
 
 86  
     /**
 87  
      * Creates an fsync() durability.
 88  
      * <p>
 89  
      * Will cause the server to wait for the write to be sync'd to disk. If the
 90  
      * server is running with journaling enabled then only the journal will have
 91  
      * been sync'd to disk. If running without journaling enabled then will wait
 92  
      * for all data files to be sync'd to disk.
 93  
      * 
 94  
      * @param waitTimeoutMillis
 95  
      *            The number of milliseconds to wait for the durability
 96  
      *            requirements to be satisfied.
 97  
      * @return A durability that will ensure that the data has been fsync()'d to
 98  
      *         the server's disk.
 99  
      */
 100  
     public static Durability fsyncDurable(final int waitTimeoutMillis) {
 101  14
         return new Durability(true, false, 0, waitTimeoutMillis);
 102  
     }
 103  
 
 104  
     /**
 105  
      * Creates an journal durability.
 106  
      * <p>
 107  
      * Will cause the server to wait for the write to be sync'd to disk as part
 108  
      * of the journal. As of MongoDB 2.6 this mode will cause a TBD exception to
 109  
      * be thrown if the server is configured without journaling enabled. Prior
 110  
      * to MongoDB 2.6 this mode would silently degrade to {@link #ACK}.
 111  
      * </p>
 112  
      * 
 113  
      * @param waitTimeoutMillis
 114  
      *            The number of milliseconds to wait for the durability
 115  
      *            requirements to be satisfied.
 116  
      * @return A durability that will ensure the data is written to the server's
 117  
      *         journal before returning.
 118  
      */
 119  
     public static Durability journalDurable(final int waitTimeoutMillis) {
 120  21
         return new Durability(false, true, 0, waitTimeoutMillis);
 121  
     }
 122  
 
 123  
     /**
 124  
      * Creates a multiple replica durability.
 125  
      * 
 126  
      * @param ensureJournaled
 127  
      *            If true then ensure that the write has been committed to the
 128  
      *            journal in addition to replicated.
 129  
      * @param minimumReplicas
 130  
      *            The minimum number of replicas to wait for.
 131  
      * @param waitTimeoutMillis
 132  
      *            The number of milliseconds to wait for the durability
 133  
      *            requirements to be satisfied.
 134  
      * @return A durability that will ensure the data is written to at least
 135  
      *         <tt>minimumReplicas</tt> of server's replicas before returning.
 136  
      */
 137  
     public static Durability replicaDurable(final boolean ensureJournaled,
 138  
             final int minimumReplicas, final int waitTimeoutMillis) {
 139  4
         return new Durability(false, ensureJournaled, minimumReplicas,
 140  
                 waitTimeoutMillis);
 141  
     }
 142  
 
 143  
     /**
 144  
      * Creates a multiple replica durability.
 145  
      * 
 146  
      * @param ensureJournaled
 147  
      *            If true then ensure that the write has been committed to the
 148  
      *            journal in addition to replicated.
 149  
      * @param waitForReplicasByMode
 150  
      *            If the value is non-<code>null</code> then wait for the
 151  
      *            specified replication mode configured on the server. A
 152  
      *            built-in mode of {@link #MAJORITY_MODE} is also supported.
 153  
      * @param waitTimeoutMillis
 154  
      *            The number of milliseconds to wait for the durability
 155  
      *            requirements to be satisfied.
 156  
      * @return A durability that will ensure the data is written to at least
 157  
      *         <tt>minimumReplicas</tt> of server's replicas before returning.
 158  
      */
 159  
     public static Durability replicaDurable(final boolean ensureJournaled,
 160  
             final String waitForReplicasByMode, final int waitTimeoutMillis) {
 161  5
         return new Durability(false, ensureJournaled, waitForReplicasByMode,
 162  
                 waitTimeoutMillis);
 163  
     }
 164  
 
 165  
     /**
 166  
      * Creates a single replica durability. This is a 'w' value of 2.
 167  
      * 
 168  
      * @param waitTimeoutMillis
 169  
      *            The number of milliseconds to wait for the durability
 170  
      *            requirements to be satisfied.
 171  
      * @return A durability that will ensure the data is written to at least one
 172  
      *         of server's replicas before returning.
 173  
      */
 174  
     public static Durability replicaDurable(final int waitTimeoutMillis) {
 175  6
         return new Durability(false, false, 2, waitTimeoutMillis);
 176  
     }
 177  
 
 178  
     /**
 179  
      * Creates a multiple replica durability.
 180  
      * 
 181  
      * @param minimumReplicas
 182  
      *            The minimum number of replicas to wait for.
 183  
      * @param waitTimeoutMillis
 184  
      *            The number of milliseconds to wait for the durability
 185  
      *            requirements to be satisfied.
 186  
      * @return A durability that will ensure the data is written to at least
 187  
      *         <tt>minimumReplicas</tt> of server's replicas before returning.
 188  
      */
 189  
     public static Durability replicaDurable(final int minimumReplicas,
 190  
             final int waitTimeoutMillis) {
 191  10
         return new Durability(false, false, minimumReplicas, waitTimeoutMillis);
 192  
     }
 193  
 
 194  
     /**
 195  
      * Creates a multiple replica durability.
 196  
      * 
 197  
      * @param waitForReplicasByMode
 198  
      *            If the value is non-<code>null</code> then wait for the
 199  
      *            specified replication mode configured on the server. A
 200  
      *            built-in mode of {@link #MAJORITY_MODE} is also supported.
 201  
      * @param waitTimeoutMillis
 202  
      *            The number of milliseconds to wait for the durability
 203  
      *            requirements to be satisfied.
 204  
      * @return A durability that will ensure the data is written to at least
 205  
      *         <tt>minimumReplicas</tt> of server's replicas before returning.
 206  
      */
 207  
     public static Durability replicaDurable(final String waitForReplicasByMode,
 208  
             final int waitTimeoutMillis) {
 209  8
         return new Durability(false, false, waitForReplicasByMode,
 210  
                 waitTimeoutMillis);
 211  
     }
 212  
 
 213  
     /**
 214  
      * Converts a string into a Durability, if possible.
 215  
      * <p>
 216  
      * Two forms of strings can be converted:
 217  
      * <ul>
 218  
      * <li>A name of the constant (ignoring case):
 219  
      * <ul>
 220  
      * <li>{@code ACK}</li>
 221  
      * <li>{@code NONE}</li>
 222  
      * <li>{@code SAFE} - for compatibility with the MongoDB Inc. driver,
 223  
      * returns {@link #ACK}.</li>
 224  
      * </ul>
 225  
      * </li>
 226  
      * <li>A JSON document representation of the Durability. The following
 227  
      * fields are allowed in the document and the values for each should match
 228  
      * those for a {@code getlasterror} command:
 229  
      * <ul>
 230  
      * <li>{@code w}</li>
 231  
      * <li>{@code wtimeout}</li>
 232  
      * <li>{@code fsync}</li>
 233  
      * <li>{@code j}</li>
 234  
      * <li>{@code getlasterror}</li>
 235  
      * </ul>
 236  
      * If present the {@code getlasterror} field is ignored. An example JSON
 237  
      * document might look like: <blockquote>
 238  
      * 
 239  
      * <pre>
 240  
      * <code>
 241  
      * { w : 'majority', wtimeout : 10000 }
 242  
      * </code>
 243  
      * </pre>
 244  
      * 
 245  
      * <blockquote></li>
 246  
      * </ul>
 247  
      * </p>
 248  
      * <p>
 249  
      * If the string is not parse-able in either of these forms then null is
 250  
      * returned.
 251  
      * </p>
 252  
      * 
 253  
      * @param value
 254  
      *            The string representation of the Durability.
 255  
      * @return The Durability represented by the string.
 256  
      */
 257  
     public static Durability valueOf(final String value) {
 258  
 
 259  35
         Durability result = null;
 260  
 
 261  35
         if ("ACK".equalsIgnoreCase(value) || "SAFE".equalsIgnoreCase(value)) {
 262  2
             result = ACK;
 263  
         }
 264  33
         else if ("NONE".equalsIgnoreCase(value)) {
 265  1
             result = NONE;
 266  
         }
 267  
         else {
 268  
             // Try and parse as JSON.
 269  
             try {
 270  32
                 boolean waitForReply = false;
 271  32
                 boolean waitForFsync = false;
 272  32
                 boolean waitForJournal = false;
 273  32
                 int waitForReplicas = 0;
 274  32
                 String waitForReplicasByMode = null;
 275  32
                 int waitTimeoutMillis = 0;
 276  
 
 277  32
                 final Document d = Json.parse(value);
 278  31
                 for (final Element e : d) {
 279  
                     // Skip the getlasterror element.
 280  68
                     if (!"getlasterror".equalsIgnoreCase(e.getName())) {
 281  44
                         if ("w".equalsIgnoreCase(e.getName())) {
 282  26
                             waitForReply = true;
 283  26
                             if (e instanceof NumericElement) {
 284  22
                                 waitForReplicas = ((NumericElement) e)
 285  
                                         .getIntValue();
 286  
                             }
 287  4
                             else if (e instanceof StringElement) {
 288  3
                                 waitForReplicasByMode = ((StringElement) e)
 289  
                                         .getValue();
 290  
                             }
 291  1
                             else if (e instanceof SymbolElement) {
 292  1
                                 waitForReplicasByMode = ((SymbolElement) e)
 293  
                                         .getSymbol();
 294  
                             }
 295  
                             else {
 296  
                                 // Unknown 'w' value type.
 297  0
                                 return null;
 298  
                             }
 299  
                         }
 300  18
                         else if ("wtimeout".equalsIgnoreCase(e.getName())) {
 301  10
                             if (e instanceof NumericElement) {
 302  9
                                 waitTimeoutMillis = ((NumericElement) e)
 303  
                                         .getIntValue();
 304  
                             }
 305  
                             else {
 306  
                                 // Unknown 'wtimeout' value type.
 307  1
                                 return null;
 308  
                             }
 309  
                         }
 310  8
                         else if ("fsync".equalsIgnoreCase(e.getName())) {
 311  1
                             waitForReply = true;
 312  1
                             waitForFsync = true;
 313  
                         }
 314  7
                         else if ("j".equalsIgnoreCase(e.getName())) {
 315  5
                             waitForReply = true;
 316  5
                             waitForJournal = true;
 317  
                         }
 318  
                         else {
 319  
                             // Unknown field.
 320  2
                             return null;
 321  
                         }
 322  
                     }
 323  65
                 }
 324  
 
 325  28
                 result = new Durability(waitForReply, waitForFsync,
 326  
                         waitForJournal, waitForReplicas, waitForReplicasByMode,
 327  
                         waitTimeoutMillis);
 328  
             }
 329  1
             catch (final JsonParseException error) {
 330  
                 // Ignore and return null.
 331  1
                 error.getCause(); // Shhh PMD.
 332  28
             }
 333  
         }
 334  
 
 335  32
         return result;
 336  
     }
 337  
 
 338  
     /** The durability in document form. */
 339  
     private Document myAsDocument;
 340  
 
 341  
     /**
 342  
      * True if the durability requires that the response wait for an fsync() of
 343  
      * the data to complete, false otherwise.
 344  
      */
 345  
     private final boolean myWaitForFsync;
 346  
 
 347  
     /**
 348  
      * True if if the durability requires that the response wait for the data to
 349  
      * be written to the server's journal, false otherwise.
 350  
      */
 351  
     private final boolean myWaitForJournal;
 352  
 
 353  
     /**
 354  
      * If the value is value greater than zero the durability requires that the
 355  
      * response wait for the data to be received by a replica and the number of
 356  
      * replicas of the data to wait for.
 357  
      */
 358  
     private final int myWaitForReplicas;
 359  
 
 360  
     /**
 361  
      * If the value is non-<code>null</code> then wait for the specified
 362  
      * replication mode configured on the server. A built-in mode of
 363  
      * {@link #MAJORITY_MODE} is also supported.
 364  
      * 
 365  
      * @see <a
 366  
      *      href="http://www.mongodb.org/display/DOCS/Data+Center+Awareness">Data
 367  
      *      Center Awareness</a>
 368  
      */
 369  
     private final String myWaitForReplicasByMode;
 370  
 
 371  
     /**
 372  
      * True if the durability requires that the response wait for a reply from
 373  
      * the server but no special server processing.
 374  
      */
 375  
     private final boolean myWaitForReply;
 376  
 
 377  
     /**
 378  
      * The number of milliseconds to wait for the durability requirements to be
 379  
      * satisfied.
 380  
      */
 381  
     private final int myWaitTimeoutMillis;
 382  
 
 383  
     /**
 384  
      * Create a new Durability.
 385  
      * 
 386  
      * @param waitForFsync
 387  
      *            True if the durability requires that the response wait for an
 388  
      *            fsync() of the data to complete, false otherwise.
 389  
      * @param waitForJournal
 390  
      *            True if if the durability requires that the response wait for
 391  
      *            the data to be written to the server's journal, false
 392  
      *            otherwise.
 393  
      * @param waitForReplicas
 394  
      *            If the value is value greater than zero the durability
 395  
      *            requires that the response wait for the data to be received by
 396  
      *            a replica and the number of replicas of the data to wait for.
 397  
      * @param waitTimeoutMillis
 398  
      *            The number of milliseconds to wait for the durability
 399  
      *            requirements to be satisfied.
 400  
      */
 401  
     protected Durability(final boolean waitForFsync,
 402  
             final boolean waitForJournal, final int waitForReplicas,
 403  
             final int waitTimeoutMillis) {
 404  447
         this(true, waitForFsync, waitForJournal, waitForReplicas, null,
 405  
                 waitTimeoutMillis);
 406  447
     }
 407  
 
 408  
     /**
 409  
      * Create a new Durability.
 410  
      * 
 411  
      * @param waitForFsync
 412  
      *            True if the durability requires that the response wait for an
 413  
      *            fsync() of the data to complete, false otherwise.
 414  
      * @param waitForJournal
 415  
      *            True if if the durability requires that the response wait for
 416  
      *            the data to be written to the server's journal, false
 417  
      *            otherwise.
 418  
      * @param waitForReplicasByMode
 419  
      *            If the value is non-<code>null</code> then wait for the
 420  
      *            specified replication mode configured on the server. A
 421  
      *            built-in mode of {@link #MAJORITY_MODE} is also supported.
 422  
      * @param waitTimeoutMillis
 423  
      *            The number of milliseconds to wait for the durability
 424  
      *            requirements to be satisfied.
 425  
      */
 426  
     protected Durability(final boolean waitForFsync,
 427  
             final boolean waitForJournal, final String waitForReplicasByMode,
 428  
             final int waitTimeoutMillis) {
 429  125
         this(true, waitForFsync, waitForJournal, 0, waitForReplicasByMode,
 430  
                 waitTimeoutMillis);
 431  125
     }
 432  
 
 433  
     /**
 434  
      * Create a new Durability.
 435  
      * 
 436  
      * @param waitForReply
 437  
      *            True if the durability requires a reply from the server.
 438  
      * @param waitForFsync
 439  
      *            True if the durability requires that the response wait for an
 440  
      *            fsync() of the data to complete, false otherwise.
 441  
      * @param waitForJournal
 442  
      *            True if if the durability requires that the response wait for
 443  
      *            the data to be written to the server's journal, false
 444  
      *            otherwise.
 445  
      * @param waitForReplicas
 446  
      *            If the value is value greater than zero the durability
 447  
      *            requires that the response wait for the data to be received by
 448  
      *            a replica and the number of replicas of the data to wait for.
 449  
      * @param waitForReplicasByMode
 450  
      *            If the value is non-<code>null</code> then wait for the
 451  
      *            specified replication mode configured on the server. A
 452  
      *            built-in mode of {@link #MAJORITY_MODE} is also supported.
 453  
      * @param waitTimeoutMillis
 454  
      *            The number of milliseconds to wait for the durability
 455  
      *            requirements to be satisfied.
 456  
      */
 457  
     private Durability(final boolean waitForReply, final boolean waitForFsync,
 458  
             final boolean waitForJournal, final int waitForReplicas,
 459  602
             final String waitForReplicasByMode, final int waitTimeoutMillis) {
 460  602
         myWaitForReply = waitForReply;
 461  602
         myWaitForFsync = waitForFsync;
 462  602
         myWaitForJournal = waitForJournal;
 463  602
         myWaitForReplicas = waitForReplicas;
 464  602
         myWaitTimeoutMillis = waitTimeoutMillis;
 465  602
         myWaitForReplicasByMode = waitForReplicasByMode;
 466  602
     }
 467  
 
 468  
     /**
 469  
      * Returns a suitable getlasterror command's document.
 470  
      * 
 471  
      * @return The getlasterror command's document.
 472  
      */
 473  
     public Document asDocument() {
 474  119
         if (myAsDocument == null) {
 475  18
             final DocumentBuilder builder = BuilderFactory.start();
 476  18
             builder.addInteger("getlasterror", 1);
 477  18
             if (isWaitForJournal()) {
 478  7
                 builder.addBoolean("j", true);
 479  
             }
 480  18
             if (isWaitForFsync()) {
 481  2
                 builder.addBoolean("fsync", true);
 482  
             }
 483  18
             if (getWaitTimeoutMillis() > 0) {
 484  16
                 builder.addInteger("wtimeout", getWaitTimeoutMillis());
 485  
             }
 486  
 
 487  18
             if (getWaitForReplicas() >= 1) {
 488  7
                 builder.addInteger("w", getWaitForReplicas());
 489  
             }
 490  11
             else if (getWaitForReplicasByMode() != null) {
 491  5
                 builder.addString("w", getWaitForReplicasByMode());
 492  
             }
 493  
 
 494  18
             myAsDocument = new ImmutableDocument(builder);
 495  
         }
 496  119
         return myAsDocument;
 497  
     }
 498  
 
 499  
     /**
 500  
      * Determines if the passed object is of this same type as this object and
 501  
      * if so that its fields are equal.
 502  
      * 
 503  
      * @param object
 504  
      *            The object to compare to.
 505  
      * 
 506  
      * @see java.lang.Object#equals(java.lang.Object)
 507  
      */
 508  
     @Override
 509  
     public boolean equals(final Object object) {
 510  33420
         boolean result = false;
 511  33420
         if (this == object) {
 512  339
             result = true;
 513  
         }
 514  33081
         else if ((object != null) && (getClass() == object.getClass())) {
 515  32573
             final Durability other = (Durability) object;
 516  
 
 517  32573
             result = (myWaitForReply == other.myWaitForReply)
 518  
                     && (myWaitForFsync == other.myWaitForFsync)
 519  
                     && (myWaitForJournal == other.myWaitForJournal)
 520  
                     && (myWaitForReplicas == other.myWaitForReplicas)
 521  
                     && (myWaitTimeoutMillis == other.myWaitTimeoutMillis)
 522  
                     && nullSafeEquals(myWaitForReplicasByMode,
 523  
                             other.myWaitForReplicasByMode);
 524  
         }
 525  33420
         return result;
 526  
     }
 527  
 
 528  
     /**
 529  
      * Returns if (value greater than zero) the durability requires that the
 530  
      * response wait for the data to be received by a replica and the number of
 531  
      * replicas of the data to wait for.
 532  
      * 
 533  
      * @return If (value greater than zero) the durability requires that the
 534  
      *         response wait for the data to be received by a replica and the
 535  
      *         number of replicas of the data to wait for.
 536  
      */
 537  
     public int getWaitForReplicas() {
 538  36
         return myWaitForReplicas;
 539  
     }
 540  
 
 541  
     /**
 542  
      * If the value is non-<code>null</code> then wait for the specified
 543  
      * replication mode configured on the server. A built-in mode of
 544  
      * {@link #MAJORITY_MODE} is also supported.
 545  
      * 
 546  
      * @return If the value is non-null then wait for the specified replication
 547  
      *         mode configured on the server.
 548  
      * @see <a
 549  
      *      href="http://www.mongodb.org/display/DOCS/Data+Center+Awareness">Data
 550  
      *      Center Awareness</a>
 551  
      */
 552  
     public String getWaitForReplicasByMode() {
 553  24
         return myWaitForReplicasByMode;
 554  
     }
 555  
 
 556  
     /**
 557  
      * Returns the number of milliseconds to wait for the durability
 558  
      * requirements to be satisfied.
 559  
      * 
 560  
      * @return The number of milliseconds to wait for the durability
 561  
      *         requirements to be satisfied.
 562  
      */
 563  
     public int getWaitTimeoutMillis() {
 564  45
         return myWaitTimeoutMillis;
 565  
     }
 566  
 
 567  
     /**
 568  
      * Computes a reasonable hash code.
 569  
      * 
 570  
      * @return The hash code value.
 571  
      */
 572  
     @Override
 573  
     public int hashCode() {
 574  64770
         int result = 1;
 575  64770
         result = (31 * result) + (myWaitForReply ? 1 : 3);
 576  64770
         result = (31 * result) + (myWaitForFsync ? 1 : 3);
 577  64770
         result = (31 * result) + (myWaitForJournal ? 1 : 3);
 578  64770
         result = (31 * result)
 579  
                 + ((myWaitForReplicasByMode != null) ? myWaitForReplicasByMode
 580  
                         .hashCode() : 3);
 581  64770
         result = (31 * result) + myWaitForReplicas;
 582  64770
         result = (31 * result) + myWaitTimeoutMillis;
 583  64770
         return result;
 584  
     }
 585  
 
 586  
     /**
 587  
      * Returns if the durability requires that the response wait for an fsync()
 588  
      * of the data on the server to complete.
 589  
      * 
 590  
      * @return True if the durability requires that the response wait for an
 591  
      *         fsync() of the data to complete, false otherwise.
 592  
      */
 593  
     public boolean isWaitForFsync() {
 594  29
         return myWaitForFsync;
 595  
     }
 596  
 
 597  
     /**
 598  
      * Returns if the durability requires that the response wait for the data to
 599  
      * be written to the server's journal.
 600  
      * 
 601  
      * @return True if if the durability requires that the response wait for the
 602  
      *         data to be written to the server's journal, false otherwise.
 603  
      */
 604  
     public boolean isWaitForJournal() {
 605  29
         return myWaitForJournal;
 606  
     }
 607  
 
 608  
     /**
 609  
      * Returns if the durability requires that the response wait for a reply
 610  
      * from the server but potentially no special server processing.
 611  
      * 
 612  
      * @return True if the durability requires that the response wait for a
 613  
      *         reply from the server but potentially no special server
 614  
      *         processing.
 615  
      */
 616  
     public boolean isWaitForReply() {
 617  7
         return myWaitForReply;
 618  
     }
 619  
 
 620  
     /**
 621  
      * {@inheritDoc}
 622  
      * <p>
 623  
      * Overriden to return the durability as JSON text.
 624  
      * </p>
 625  
      */
 626  
     @Override
 627  
     public String toString() {
 628  
         String result;
 629  1
         if (NONE.equals(this)) {
 630  0
             result = "NONE";
 631  
         }
 632  1
         else if (ACK.equals(this)) {
 633  0
             result = "ACK";
 634  
         }
 635  
         else {
 636  
             // Render as a JSON Document on a single line.
 637  1
             final StringWriter sink = new StringWriter();
 638  1
             final JsonSerializationVisitor visitor = new JsonSerializationVisitor(
 639  
                     sink, true);
 640  1
             asDocument().accept(visitor);
 641  
 
 642  1
             result = sink.toString();
 643  
         }
 644  1
         return result;
 645  
     }
 646  
 
 647  
     /**
 648  
      * Does a null safe equals comparison.
 649  
      * 
 650  
      * @param rhs
 651  
      *            The right-hand-side of the comparison.
 652  
      * @param lhs
 653  
      *            The left-hand-side of the comparison.
 654  
      * @return True if the rhs equals the lhs. Note: nullSafeEquals(null, null)
 655  
      *         returns true.
 656  
      */
 657  
     protected boolean nullSafeEquals(final Object rhs, final Object lhs) {
 658  331
         return (rhs == lhs) || ((rhs != null) && rhs.equals(lhs));
 659  
     }
 660  
 
 661  
     /**
 662  
      * Hook into serialization to replace <tt>this</tt> object with the local
 663  
      * {@link #ACK} or {@link #NONE} instance as appropriate.
 664  
      * 
 665  
      * @return Either the {@link #ACK} or {@link #NONE} instance if
 666  
      *         <tt>this</tt> instance equals one of those instances otherwise
 667  
      *         <tt>this</tt> instance.
 668  
      */
 669  
     private Object readResolve() {
 670  4
         if (this.equals(ACK)) {
 671  2
             return ACK;
 672  
         }
 673  2
         else if (this.equals(NONE)) {
 674  1
             return NONE;
 675  
         }
 676  
         else {
 677  1
             return this;
 678  
         }
 679  
     }
 680  
 }