mongo 2.0.5 → 2.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/mongo/auth/cr/conversation.rb +0 -1
- data/lib/mongo/client.rb +19 -5
- data/lib/mongo/cluster.rb +84 -16
- data/lib/mongo/cluster/topology.rb +3 -4
- data/lib/mongo/cluster/topology/replica_set.rb +75 -0
- data/lib/mongo/cluster/topology/sharded.rb +60 -0
- data/lib/mongo/cluster/topology/single.rb +51 -0
- data/lib/mongo/cluster/topology/unknown.rb +62 -0
- data/lib/mongo/error/invalid_bulk_operation.rb +2 -1
- data/lib/mongo/event.rb +9 -9
- data/lib/mongo/event/{server_added.rb → description_changed.rb} +6 -5
- data/lib/mongo/event/{server_removed.rb → standalone_discovered.rb} +15 -15
- data/lib/mongo/operation/aggregate.rb +6 -5
- data/lib/mongo/operation/command.rb +5 -6
- data/lib/mongo/operation/kill_cursors.rb +3 -2
- data/lib/mongo/operation/map_reduce.rb +6 -5
- data/lib/mongo/operation/read/collections_info.rb +5 -4
- data/lib/mongo/operation/read/get_more.rb +8 -7
- data/lib/mongo/operation/read/indexes.rb +4 -3
- data/lib/mongo/operation/read/list_collections.rb +5 -4
- data/lib/mongo/operation/read/list_indexes.rb +7 -6
- data/lib/mongo/operation/read/query.rb +8 -7
- data/lib/mongo/operation/read_preferrable.rb +6 -2
- data/lib/mongo/operation/write/bulk/bulk_delete.rb +13 -12
- data/lib/mongo/operation/write/bulk/bulk_insert.rb +10 -9
- data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +2 -2
- data/lib/mongo/operation/write/bulk/bulk_update.rb +12 -11
- data/lib/mongo/operation/write/create_index.rb +8 -7
- data/lib/mongo/operation/write/create_user.rb +4 -3
- data/lib/mongo/operation/write/delete.rb +13 -12
- data/lib/mongo/operation/write/drop_index.rb +6 -5
- data/lib/mongo/operation/write/insert.rb +8 -7
- data/lib/mongo/operation/write/insert/result.rb +1 -1
- data/lib/mongo/operation/write/remove_user.rb +4 -3
- data/lib/mongo/operation/write/update.rb +10 -9
- data/lib/mongo/operation/write/update_user.rb +4 -3
- data/lib/mongo/server.rb +8 -15
- data/lib/mongo/server/context.rb +2 -2
- data/lib/mongo/server/description.rb +65 -3
- data/lib/mongo/server/description/features.rb +2 -1
- data/lib/mongo/server/description/inspector.rb +5 -5
- data/lib/mongo/server/description/inspector/{server_added.rb → description_changed.rb} +3 -5
- data/lib/mongo/server/description/inspector/{server_removed.rb → standalone_discovered.rb} +12 -15
- data/lib/mongo/version.rb +1 -1
- data/spec/mongo/auth/cr_spec.rb +1 -1
- data/spec/mongo/auth/ldap_spec.rb +1 -1
- data/spec/mongo/auth/scram_spec.rb +1 -1
- data/spec/mongo/auth/x509_spec.rb +1 -1
- data/spec/mongo/client_spec.rb +4 -0
- data/spec/mongo/cluster/topology/replica_set_spec.rb +254 -4
- data/spec/mongo/cluster/topology/sharded_spec.rb +70 -19
- data/spec/mongo/cluster/topology/single_spec.rb +25 -4
- data/spec/mongo/cluster/topology/unknown_spec.rb +167 -0
- data/spec/mongo/cluster/topology_spec.rb +6 -6
- data/spec/mongo/cluster_spec.rb +179 -1
- data/spec/mongo/operation/read_preferrable_spec.rb +81 -28
- data/spec/mongo/operation/write/bulk/bulk_delete_spec.rb +1 -0
- data/spec/mongo/server/connection_pool_spec.rb +10 -10
- data/spec/mongo/server/connection_spec.rb +1 -1
- data/spec/mongo/server/description/features_spec.rb +23 -3
- data/spec/mongo/server/description/inspector/description_changed_spec.rb +78 -0
- data/spec/mongo/server/description_spec.rb +238 -0
- data/spec/mongo/server/monitor_spec.rb +1 -1
- data/spec/mongo/server_discovery_and_monitoring_spec.rb +20 -4
- data/spec/mongo/server_selection_spec.rb +2 -2
- data/spec/mongo/server_spec.rb +12 -8
- data/spec/support/authorization.rb +8 -8
- data/spec/support/sdam/rs/discover_passives.yml +36 -0
- data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +2 -2
- data/spec/support/sdam/rs/primary_becomes_standalone.yml +1 -1
- data/spec/support/sdam/rs/primary_changes_set_name.yml +2 -2
- data/spec/support/sdam/rs/primary_disconnect.yml +1 -1
- data/spec/support/sdam/rs/primary_wrong_set_name.yml +1 -1
- data/spec/support/sdam/rs/secondary_wrong_set_name.yml +1 -1
- data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +2 -2
- data/spec/support/sdam/sharded/single_mongos.yml +33 -0
- data/spec/support/shared/operation.rb +12 -4
- data/spec/support/shared/server_selector.rb +1 -1
- metadata +12 -10
- metadata.gz.sig +0 -0
- data/spec/mongo/server/description/inspector/server_added_spec.rb +0 -92
- data/spec/mongo/server/description/inspector/server_removed_spec.rb +0 -95
@@ -72,6 +72,7 @@ module Mongo
|
|
72
72
|
# @since 2.0.0
|
73
73
|
def initialize(options, seeds = [])
|
74
74
|
@options = options
|
75
|
+
@seeds = seeds
|
75
76
|
end
|
76
77
|
|
77
78
|
# An unknown topology is not a replica set.
|
@@ -139,6 +140,67 @@ module Mongo
|
|
139
140
|
# @since 2.0.0
|
140
141
|
def unknown?; true; end
|
141
142
|
|
143
|
+
# Whether a server description's hosts may be added to the cluster.
|
144
|
+
#
|
145
|
+
# @example Check if a description's hosts may be added to the cluster.
|
146
|
+
# topology.add_hosts?(description, servers)
|
147
|
+
#
|
148
|
+
# @param [ Mongo::Server::Description ] description The description.
|
149
|
+
# @param [ Array<Mongo::Server> ] servers The cluster servers.
|
150
|
+
#
|
151
|
+
# @return [ true, false ] Whether a description's hosts may be added.
|
152
|
+
#
|
153
|
+
# @since 2.0.6
|
154
|
+
def add_hosts?(description, servers)
|
155
|
+
!(description.unknown? || description.ghost?)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Whether a description can be used to remove hosts from the cluster.
|
159
|
+
#
|
160
|
+
# @example Check if a description can be used to remove hosts from the cluster.
|
161
|
+
# topology.remove_hosts?(description)
|
162
|
+
#
|
163
|
+
# @param [ Mongo::Server::Description ] description The description.
|
164
|
+
#
|
165
|
+
# @return [ true, false ] Whether hosts may be removed from the cluster.
|
166
|
+
#
|
167
|
+
# @since 2.0.6
|
168
|
+
def remove_hosts?(description)
|
169
|
+
description.standalone?
|
170
|
+
end
|
171
|
+
|
172
|
+
# Whether a specific server in the cluster can be removed, given a description.
|
173
|
+
#
|
174
|
+
# @example Check if a specific server can be removed from the cluster.
|
175
|
+
# topology.remove_server?(description, server)
|
176
|
+
#
|
177
|
+
# @param [ Mongo::Server::Description ] description The description.
|
178
|
+
# @param [ Mongo::Serve ] server The server in question.
|
179
|
+
#
|
180
|
+
# @return [ true, false ] Whether the server can be removed from the cluster.
|
181
|
+
#
|
182
|
+
# @since 2.0.6
|
183
|
+
def remove_server?(description, server)
|
184
|
+
description.standalone? && description.is_server?(server)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Notify the topology that a standalone was discovered.
|
188
|
+
#
|
189
|
+
# @example Notify the topology that a standalone was discovered.
|
190
|
+
# topology.standalone_discovered
|
191
|
+
#
|
192
|
+
# @return [ Topology::Unknown, Topology::Single ] Either self or a
|
193
|
+
# new Single topology.
|
194
|
+
#
|
195
|
+
# @since 2.0.6
|
196
|
+
def standalone_discovered
|
197
|
+
if @seeds.size == 1
|
198
|
+
Single.new(options, @seeds)
|
199
|
+
else
|
200
|
+
self
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
142
204
|
private
|
143
205
|
|
144
206
|
def initialize_replica_set(description, servers)
|
@@ -25,7 +25,8 @@ module Mongo
|
|
25
25
|
# @example Instantiate the exception.
|
26
26
|
# Mongo::Error::InvalidBulkOperation.new(name)
|
27
27
|
#
|
28
|
-
# @param [ String ]
|
28
|
+
# @param [ String ] type The bulk operation type.
|
29
|
+
# @param [ Hash ] operation The bulk operation.
|
29
30
|
#
|
30
31
|
# @since 2.0.0
|
31
32
|
def initialize(type, operation)
|
data/lib/mongo/event.rb
CHANGED
@@ -16,25 +16,25 @@ require 'mongo/event/listeners'
|
|
16
16
|
require 'mongo/event/publisher'
|
17
17
|
require 'mongo/event/subscriber'
|
18
18
|
require 'mongo/event/primary_elected'
|
19
|
-
require 'mongo/event/
|
20
|
-
require 'mongo/event/
|
19
|
+
require 'mongo/event/description_changed'
|
20
|
+
require 'mongo/event/standalone_discovered'
|
21
21
|
|
22
22
|
module Mongo
|
23
23
|
module Event
|
24
24
|
|
25
|
-
# When a
|
25
|
+
# When a standalone is discovered.
|
26
26
|
#
|
27
|
-
# @since 2.0.
|
28
|
-
|
27
|
+
# @since 2.0.6
|
28
|
+
STANDALONE_DISCOVERED = 'standalone_discovered'.freeze
|
29
29
|
|
30
|
-
# When a server is
|
30
|
+
# When a server is elected primary.
|
31
31
|
#
|
32
32
|
# @since 2.0.0
|
33
|
-
|
33
|
+
PRIMARY_ELECTED = 'primary_elected'.freeze
|
34
34
|
|
35
35
|
# When a server is to be removed from a cluster.
|
36
36
|
#
|
37
|
-
# @since 2.0.
|
38
|
-
|
37
|
+
# @since 2.0.6
|
38
|
+
DESCRIPTION_CHANGED = 'description_changed'.freeze
|
39
39
|
end
|
40
40
|
end
|
@@ -16,10 +16,10 @@
|
|
16
16
|
module Mongo
|
17
17
|
module Event
|
18
18
|
|
19
|
-
# This handles
|
19
|
+
# This handles a change in description.
|
20
20
|
#
|
21
|
-
# @since 2.0.
|
22
|
-
class
|
21
|
+
# @since 2.0.6
|
22
|
+
class DescriptionChanged
|
23
23
|
|
24
24
|
# @return [ Mongo::Cluster ] cluster The event publisher.
|
25
25
|
attr_reader :cluster
|
@@ -45,8 +45,9 @@ module Mongo
|
|
45
45
|
# @param [ Address ] address The added host.
|
46
46
|
#
|
47
47
|
# @since 2.0.0
|
48
|
-
def handle(
|
49
|
-
cluster.
|
48
|
+
def handle(updated)
|
49
|
+
cluster.add_hosts(updated)
|
50
|
+
cluster.remove_hosts(updated)
|
50
51
|
end
|
51
52
|
end
|
52
53
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C)
|
1
|
+
# Copyright (C) 2015 MongoDB, Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -15,38 +15,38 @@
|
|
15
15
|
module Mongo
|
16
16
|
module Event
|
17
17
|
|
18
|
-
# This handles
|
18
|
+
# This handles when a standalone is discovered.
|
19
19
|
#
|
20
|
-
# @since 2.0.
|
21
|
-
class
|
22
|
-
include Loggable
|
20
|
+
# @since 2.0.6
|
21
|
+
class StandaloneDiscovered
|
23
22
|
|
24
23
|
# @return [ Mongo::Cluster ] cluster The event publisher.
|
25
24
|
attr_reader :cluster
|
26
25
|
|
27
|
-
# Initialize the new
|
26
|
+
# Initialize the new standalone discovered event handler.
|
28
27
|
#
|
29
28
|
# @example Create the new handler.
|
30
|
-
#
|
29
|
+
# StandaloneDiscovered.new(cluster)
|
31
30
|
#
|
32
31
|
# @param [ Mongo::Cluster ] cluster The cluster to publish from.
|
33
32
|
#
|
34
|
-
# @since 2.0.
|
33
|
+
# @since 2.0.6
|
35
34
|
def initialize(cluster)
|
36
35
|
@cluster = cluster
|
37
36
|
end
|
38
37
|
|
39
|
-
# This event
|
40
|
-
#
|
38
|
+
# This event tells the cluster to notify its topology that a standalone
|
39
|
+
# was discovered.
|
41
40
|
#
|
42
41
|
# @example Handle the event.
|
43
|
-
#
|
42
|
+
# standalone_discovered.handle(description)
|
44
43
|
#
|
45
|
-
# @param [
|
44
|
+
# @param [ Server::Description ] description The description of the
|
45
|
+
# server.
|
46
46
|
#
|
47
|
-
# @since 2.0.
|
48
|
-
def handle(
|
49
|
-
cluster.
|
47
|
+
# @since 2.0.6
|
48
|
+
def handle(description)
|
49
|
+
cluster.standalone_discovered
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
@@ -31,12 +31,13 @@ module Mongo
|
|
31
31
|
# :db_name => 'test_db'
|
32
32
|
# })
|
33
33
|
#
|
34
|
-
#
|
34
|
+
# Initialization:
|
35
|
+
# param [ Hash ] spec The specifications for the operation.
|
35
36
|
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
37
|
+
# option spec :selector [ Hash ] The aggregate selector.
|
38
|
+
# option spec :db_name [ String ] The name of the database on which
|
39
|
+
# the operation should be executed.
|
40
|
+
# option spec :options [ Hash ] Options for the aggregate command.
|
40
41
|
#
|
41
42
|
# @since 2.0.0
|
42
43
|
class Aggregate
|
@@ -20,14 +20,13 @@ module Mongo
|
|
20
20
|
# @example Create the command operation.
|
21
21
|
# Mongo::Operation::Command.new({ :selector => { :isMaster => 1 } })
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# Initialization:
|
24
|
+
# param [ Hash ] spec The specifications for the command.
|
24
25
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
# @option spec :selector [ Hash ] The command selector.
|
28
|
-
# @option spec :db_name [ String ] The name of the database on which
|
26
|
+
# option spec :selector [ Hash ] The command selector.
|
27
|
+
# option spec :db_name [ String ] The name of the database on which
|
29
28
|
# the command should be executed.
|
30
|
-
#
|
29
|
+
# option spec :options [ Hash ] Options for the command.
|
31
30
|
#
|
32
31
|
# @since 2.0.0
|
33
32
|
class Command
|
@@ -20,9 +20,10 @@ module Mongo
|
|
20
20
|
# @example Create the kill cursors operation.
|
21
21
|
# Mongo::Operation::KillCursor.new({ :cursor_ids => [1, 2] })
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# Initialization:
|
24
|
+
# param [ Hash ] spec The specifications for the operation.
|
24
25
|
#
|
25
|
-
#
|
26
|
+
# option spec :cursor_ids [ Array ] The ids of cursors to kill.
|
26
27
|
#
|
27
28
|
# @since 2.0.0
|
28
29
|
class KillCursors
|
@@ -33,12 +33,13 @@ module Mongo
|
|
33
33
|
# :db_name => 'test_db'
|
34
34
|
# })
|
35
35
|
#
|
36
|
-
#
|
36
|
+
# Initialization:
|
37
|
+
# param [ Hash ] spec The specifications for the operation.
|
37
38
|
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
39
|
+
# option spec :selector [ Hash ] The map reduce selector.
|
40
|
+
# option spec :db_name [ String ] The name of the database on which
|
41
|
+
# the operation should be executed.
|
42
|
+
# option spec :options [ Hash ] Options for the map reduce command.
|
42
43
|
#
|
43
44
|
# @since 2.0.0
|
44
45
|
class MapReduce
|
@@ -21,11 +21,12 @@ module Mongo
|
|
21
21
|
# @example Create the collection names operation.
|
22
22
|
# Read::CollectionNames.new(:db_name => 'test-db')
|
23
23
|
#
|
24
|
-
#
|
24
|
+
# Initialization:
|
25
|
+
# param [ Hash ] spec The specifications for the collection names operation.
|
25
26
|
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
27
|
+
# option spec :db_name [ String ] The name of the database whose collection
|
28
|
+
# names is requested.
|
29
|
+
# option spec :options [ Hash ] Options for the operation.
|
29
30
|
#
|
30
31
|
# @since 2.0.0
|
31
32
|
class CollectionsInfo
|
@@ -26,14 +26,15 @@ module Mongo
|
|
26
26
|
# :coll_name => 'test_coll'
|
27
27
|
# })
|
28
28
|
#
|
29
|
-
#
|
29
|
+
# Initialization:
|
30
|
+
# param [ Hash ] spec The specifications for the operation.
|
30
31
|
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
32
|
+
# option spec :to_return [ Integer ] The number of results to return.
|
33
|
+
# option spec :cursor_id [ Integer ] The id of the cursor.
|
34
|
+
# option spec :db_name [ String ] The name of the database on which
|
35
|
+
# the operation should be executed.
|
36
|
+
# option spec :coll_name [ String ] The name of the collection on which
|
37
|
+
# the operation should be executed.
|
37
38
|
#
|
38
39
|
# @since 2.0.0
|
39
40
|
class GetMore
|
@@ -23,10 +23,11 @@ module Mongo
|
|
23
23
|
# @example Instantiate the operation.
|
24
24
|
# Read::Indexes.new(:db_name => 'test', :coll_name => 'test_coll')
|
25
25
|
#
|
26
|
-
#
|
26
|
+
# Initialization:
|
27
|
+
# param [ Hash ] spec The specifications for the insert.
|
27
28
|
#
|
28
|
-
#
|
29
|
-
#
|
29
|
+
# option spec :db_name [ String ] The name of the database.
|
30
|
+
# option spec :coll_name [ String ] The name of the collection.
|
30
31
|
#
|
31
32
|
# @since 2.0.0
|
32
33
|
class Indexes
|
@@ -25,11 +25,12 @@ module Mongo
|
|
25
25
|
#
|
26
26
|
# @note A command is actually a query on the virtual '$cmd' collection.
|
27
27
|
#
|
28
|
-
#
|
28
|
+
# Initialization:
|
29
|
+
# param [ Hash ] spec The specifications for the command.
|
29
30
|
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
31
|
+
# option spec :db_name [ String ] The name of the database whose list of
|
32
|
+
# collection names is requested.
|
33
|
+
# option spec :options [ Hash ] Options for the command.
|
33
34
|
#
|
34
35
|
# @since 2.0.0
|
35
36
|
class ListCollections
|
@@ -25,13 +25,14 @@ module Mongo
|
|
25
25
|
#
|
26
26
|
# @note A command is actually a query on the virtual '$cmd' collection.
|
27
27
|
#
|
28
|
-
#
|
28
|
+
# Initialization:
|
29
|
+
# param [ Hash ] spec The specifications for the command.
|
29
30
|
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
31
|
+
# option spec :coll_name [ Hash ] The name of the collection whose index
|
32
|
+
# info is requested.
|
33
|
+
# option spec :db_name [ String ] The name of the database on which
|
34
|
+
# the command should be executed.
|
35
|
+
# option spec :options [ Hash ] Options for the command.
|
35
36
|
#
|
36
37
|
# @since 2.0.0
|
37
38
|
class ListIndexes
|
@@ -26,14 +26,15 @@ module Mongo
|
|
26
26
|
# :options => { :limit => 2 }
|
27
27
|
# })
|
28
28
|
#
|
29
|
-
#
|
29
|
+
# Initialization:
|
30
|
+
# param [ Hash ] spec The specifications for the query.
|
30
31
|
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
32
|
+
# option spec :selector [ Hash ] The query selector.
|
33
|
+
# option spec :db_name [ String ] The name of the database on which
|
34
|
+
# the query should be run.
|
35
|
+
# option spec :coll_name [ String ] The name of the collection on which
|
36
|
+
# the query should be run.
|
37
|
+
# option spec :options [ Hash ] Options for the query.
|
37
38
|
#
|
38
39
|
# @since 2.0.0
|
39
40
|
class Query
|
@@ -22,7 +22,7 @@ module Mongo
|
|
22
22
|
|
23
23
|
# The constant for slave ok flags.
|
24
24
|
#
|
25
|
-
# @since 2.0.
|
25
|
+
# @since 2.0.6
|
26
26
|
SLAVE_OK = :slave_ok
|
27
27
|
|
28
28
|
private
|
@@ -36,8 +36,12 @@ module Mongo
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
def slave_ok?(context)
|
40
|
+
(context.cluster.single? && !context.mongos?) || read.slave_ok?
|
41
|
+
end
|
42
|
+
|
39
43
|
def update_options(context)
|
40
|
-
if
|
44
|
+
if slave_ok?(context)
|
41
45
|
options.dup.tap do |opts|
|
42
46
|
(opts[:flags] ||= []) << SLAVE_OK
|
43
47
|
end
|
@@ -31,19 +31,20 @@ module Mongo
|
|
31
31
|
# :write_concern => write_concern
|
32
32
|
# })
|
33
33
|
#
|
34
|
-
#
|
34
|
+
# Initialization:
|
35
|
+
# param [ Hash ] spec The specifications for the delete.
|
35
36
|
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
37
|
+
# option spec :deletes [ Array ] The delete documents.
|
38
|
+
# option spec :db_name [ String ] The name of the database on which
|
39
|
+
# the delete should be executed.
|
40
|
+
# option spec :coll_name [ String ] The name of the collection on which
|
41
|
+
# the delete should be executed.
|
42
|
+
# option spec :write_concern [ Mongo::WriteConcern ] The write concern
|
43
|
+
# for this operation.
|
44
|
+
# option spec :ordered [ true, false ] Whether the operations should be
|
45
|
+
# executed in order.
|
46
|
+
# option spec :options [Hash] Options for the command, if it ends up being a
|
47
|
+
# write command.
|
47
48
|
#
|
48
49
|
# @since 2.0.0
|
49
50
|
class BulkDelete
|