write_concern.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # Copyright 2014-present MongoDB, Inc.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """Tools for working with write concerns."""
  15. from bson.py3compat import integer_types, string_type
  16. from pymongo.errors import ConfigurationError
  17. class WriteConcern(object):
  18. """WriteConcern
  19. :Parameters:
  20. - `w`: (integer or string) Used with replication, write operations
  21. will block until they have been replicated to the specified number
  22. or tagged set of servers. `w=<integer>` always includes the replica
  23. set primary (e.g. w=3 means write to the primary and wait until
  24. replicated to **two** secondaries). **w=0 disables acknowledgement
  25. of write operations and can not be used with other write concern
  26. options.**
  27. - `wtimeout`: (integer) Used in conjunction with `w`. Specify a value
  28. in milliseconds to control how long to wait for write propagation
  29. to complete. If replication does not complete in the given
  30. timeframe, a timeout exception is raised.
  31. - `j`: If ``True`` block until write operations have been committed
  32. to the journal. Cannot be used in combination with `fsync`. Prior
  33. to MongoDB 2.6 this option was ignored if the server was running
  34. without journaling. Starting with MongoDB 2.6 write operations will
  35. fail with an exception if this option is used when the server is
  36. running without journaling.
  37. - `fsync`: If ``True`` and the server is running without journaling,
  38. blocks until the server has synced all data files to disk. If the
  39. server is running with journaling, this acts the same as the `j`
  40. option, blocking until write operations have been committed to the
  41. journal. Cannot be used in combination with `j`.
  42. """
  43. __slots__ = ("__document", "__acknowledged", "__server_default")
  44. def __init__(self, w=None, wtimeout=None, j=None, fsync=None):
  45. self.__document = {}
  46. self.__acknowledged = True
  47. if wtimeout is not None:
  48. if not isinstance(wtimeout, integer_types):
  49. raise TypeError("wtimeout must be an integer")
  50. if wtimeout < 0:
  51. raise ValueError("wtimeout cannot be less than 0")
  52. self.__document["wtimeout"] = wtimeout
  53. if j is not None:
  54. if not isinstance(j, bool):
  55. raise TypeError("j must be True or False")
  56. self.__document["j"] = j
  57. if fsync is not None:
  58. if not isinstance(fsync, bool):
  59. raise TypeError("fsync must be True or False")
  60. if j and fsync:
  61. raise ConfigurationError("Can't set both j "
  62. "and fsync at the same time")
  63. self.__document["fsync"] = fsync
  64. if w == 0 and j is True:
  65. raise ConfigurationError("Cannot set w to 0 and j to True")
  66. if w is not None:
  67. if isinstance(w, integer_types):
  68. if w < 0:
  69. raise ValueError("w cannot be less than 0")
  70. self.__acknowledged = w > 0
  71. elif not isinstance(w, string_type):
  72. raise TypeError("w must be an integer or string")
  73. self.__document["w"] = w
  74. self.__server_default = not self.__document
  75. @property
  76. def is_server_default(self):
  77. """Does this WriteConcern match the server default."""
  78. return self.__server_default
  79. @property
  80. def document(self):
  81. """The document representation of this write concern.
  82. .. note::
  83. :class:`WriteConcern` is immutable. Mutating the value of
  84. :attr:`document` does not mutate this :class:`WriteConcern`.
  85. """
  86. return self.__document.copy()
  87. @property
  88. def acknowledged(self):
  89. """If ``True`` write operations will wait for acknowledgement before
  90. returning.
  91. """
  92. return self.__acknowledged
  93. def __repr__(self):
  94. return ("WriteConcern(%s)" % (
  95. ", ".join("%s=%s" % kvt for kvt in self.__document.items()),))
  96. def __eq__(self, other):
  97. if isinstance(other, WriteConcern):
  98. return self.__document == other.document
  99. return NotImplemented
  100. def __ne__(self, other):
  101. if isinstance(other, WriteConcern):
  102. return self.__document != other.document
  103. return NotImplemented
  104. DEFAULT_WRITE_CONCERN = WriteConcern()