swift 2.32.0__py2.py3-none-any.whl → 2.34.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- swift/account/auditor.py +11 -0
- swift/account/reaper.py +11 -1
- swift/account/replicator.py +22 -0
- swift/account/server.py +13 -12
- swift-2.32.0.data/scripts/swift-account-audit → swift/cli/account_audit.py +6 -2
- swift-2.32.0.data/scripts/swift-config → swift/cli/config.py +1 -1
- swift-2.32.0.data/scripts/swift-dispersion-populate → swift/cli/dispersion_populate.py +6 -2
- swift-2.32.0.data/scripts/swift-drive-audit → swift/cli/drive_audit.py +12 -3
- swift-2.32.0.data/scripts/swift-get-nodes → swift/cli/get_nodes.py +6 -2
- swift/cli/info.py +131 -3
- swift-2.32.0.data/scripts/swift-oldies → swift/cli/oldies.py +6 -3
- swift-2.32.0.data/scripts/swift-orphans → swift/cli/orphans.py +7 -2
- swift-2.32.0.data/scripts/swift-recon-cron → swift/cli/recon_cron.py +9 -18
- swift-2.32.0.data/scripts/swift-reconciler-enqueue → swift/cli/reconciler_enqueue.py +2 -3
- swift/cli/relinker.py +1 -1
- swift/cli/reload.py +141 -0
- swift/cli/ringbuilder.py +24 -0
- swift/common/daemon.py +12 -2
- swift/common/db.py +14 -9
- swift/common/db_auditor.py +2 -2
- swift/common/db_replicator.py +6 -0
- swift/common/exceptions.py +12 -0
- swift/common/http_protocol.py +76 -3
- swift/common/manager.py +120 -5
- swift/common/memcached.py +24 -25
- swift/common/middleware/account_quotas.py +144 -43
- swift/common/middleware/backend_ratelimit.py +166 -24
- swift/common/middleware/catch_errors.py +1 -3
- swift/common/middleware/cname_lookup.py +3 -5
- swift/common/middleware/container_sync.py +6 -10
- swift/common/middleware/crypto/crypto_utils.py +4 -5
- swift/common/middleware/crypto/decrypter.py +4 -5
- swift/common/middleware/crypto/kms_keymaster.py +2 -1
- swift/common/middleware/proxy_logging.py +57 -43
- swift/common/middleware/ratelimit.py +6 -7
- swift/common/middleware/recon.py +6 -7
- swift/common/middleware/s3api/acl_handlers.py +10 -1
- swift/common/middleware/s3api/controllers/__init__.py +3 -0
- swift/common/middleware/s3api/controllers/acl.py +3 -2
- swift/common/middleware/s3api/controllers/logging.py +2 -2
- swift/common/middleware/s3api/controllers/multi_upload.py +31 -15
- swift/common/middleware/s3api/controllers/obj.py +20 -1
- swift/common/middleware/s3api/controllers/object_lock.py +44 -0
- swift/common/middleware/s3api/s3api.py +6 -0
- swift/common/middleware/s3api/s3request.py +190 -74
- swift/common/middleware/s3api/s3response.py +48 -8
- swift/common/middleware/s3api/s3token.py +2 -2
- swift/common/middleware/s3api/utils.py +2 -1
- swift/common/middleware/slo.py +508 -310
- swift/common/middleware/staticweb.py +45 -14
- swift/common/middleware/tempauth.py +6 -4
- swift/common/middleware/tempurl.py +134 -93
- swift/common/middleware/x_profile/exceptions.py +1 -4
- swift/common/middleware/x_profile/html_viewer.py +9 -10
- swift/common/middleware/x_profile/profile_model.py +1 -2
- swift/common/middleware/xprofile.py +1 -2
- swift/common/request_helpers.py +101 -8
- swift/common/statsd_client.py +207 -0
- swift/common/storage_policy.py +1 -1
- swift/common/swob.py +5 -2
- swift/common/utils/__init__.py +331 -1774
- swift/common/utils/base.py +138 -0
- swift/common/utils/config.py +443 -0
- swift/common/utils/logs.py +999 -0
- swift/common/utils/timestamp.py +23 -2
- swift/common/wsgi.py +19 -3
- swift/container/auditor.py +11 -0
- swift/container/backend.py +136 -31
- swift/container/reconciler.py +11 -2
- swift/container/replicator.py +64 -7
- swift/container/server.py +276 -146
- swift/container/sharder.py +86 -42
- swift/container/sync.py +11 -1
- swift/container/updater.py +12 -2
- swift/obj/auditor.py +20 -3
- swift/obj/diskfile.py +63 -25
- swift/obj/expirer.py +154 -47
- swift/obj/mem_diskfile.py +2 -1
- swift/obj/mem_server.py +1 -0
- swift/obj/reconstructor.py +28 -4
- swift/obj/replicator.py +63 -24
- swift/obj/server.py +76 -59
- swift/obj/updater.py +12 -2
- swift/obj/watchers/dark_data.py +72 -34
- swift/proxy/controllers/account.py +3 -2
- swift/proxy/controllers/base.py +254 -148
- swift/proxy/controllers/container.py +274 -289
- swift/proxy/controllers/obj.py +120 -166
- swift/proxy/server.py +17 -13
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/AUTHORS +14 -4
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/METADATA +9 -7
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/RECORD +97 -120
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/entry_points.txt +39 -0
- swift-2.34.0.dist-info/pbr.json +1 -0
- swift-2.32.0.data/scripts/swift-account-auditor +0 -23
- swift-2.32.0.data/scripts/swift-account-info +0 -52
- swift-2.32.0.data/scripts/swift-account-reaper +0 -23
- swift-2.32.0.data/scripts/swift-account-replicator +0 -34
- swift-2.32.0.data/scripts/swift-account-server +0 -23
- swift-2.32.0.data/scripts/swift-container-auditor +0 -23
- swift-2.32.0.data/scripts/swift-container-info +0 -56
- swift-2.32.0.data/scripts/swift-container-reconciler +0 -21
- swift-2.32.0.data/scripts/swift-container-replicator +0 -34
- swift-2.32.0.data/scripts/swift-container-server +0 -23
- swift-2.32.0.data/scripts/swift-container-sharder +0 -37
- swift-2.32.0.data/scripts/swift-container-sync +0 -23
- swift-2.32.0.data/scripts/swift-container-updater +0 -23
- swift-2.32.0.data/scripts/swift-dispersion-report +0 -24
- swift-2.32.0.data/scripts/swift-form-signature +0 -20
- swift-2.32.0.data/scripts/swift-init +0 -119
- swift-2.32.0.data/scripts/swift-object-auditor +0 -29
- swift-2.32.0.data/scripts/swift-object-expirer +0 -33
- swift-2.32.0.data/scripts/swift-object-info +0 -60
- swift-2.32.0.data/scripts/swift-object-reconstructor +0 -33
- swift-2.32.0.data/scripts/swift-object-relinker +0 -23
- swift-2.32.0.data/scripts/swift-object-replicator +0 -37
- swift-2.32.0.data/scripts/swift-object-server +0 -27
- swift-2.32.0.data/scripts/swift-object-updater +0 -23
- swift-2.32.0.data/scripts/swift-proxy-server +0 -23
- swift-2.32.0.data/scripts/swift-recon +0 -24
- swift-2.32.0.data/scripts/swift-ring-builder +0 -37
- swift-2.32.0.data/scripts/swift-ring-builder-analyzer +0 -22
- swift-2.32.0.data/scripts/swift-ring-composer +0 -22
- swift-2.32.0.dist-info/pbr.json +0 -1
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/LICENSE +0 -0
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/WHEEL +0 -0
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/top_level.txt +0 -0
swift/common/request_helpers.py
CHANGED
@@ -36,7 +36,8 @@ from swift.common.swob import HTTPBadRequest, \
|
|
36
36
|
HTTPServiceUnavailable, Range, is_chunked, multi_range_iterator, \
|
37
37
|
HTTPPreconditionFailed, wsgi_to_bytes, wsgi_unquote, wsgi_to_str
|
38
38
|
from swift.common.utils import split_path, validate_device_partition, \
|
39
|
-
close_if_possible,
|
39
|
+
close_if_possible, friendly_close, \
|
40
|
+
maybe_multipart_byteranges_to_document_iters, \
|
40
41
|
multipart_byteranges_to_document_iters, parse_content_type, \
|
41
42
|
parse_content_range, csv_append, list_from_csv, Spliterator, quote, \
|
42
43
|
RESERVED, config_true_value, md5, CloseableChain, select_ip_port
|
@@ -94,6 +95,39 @@ def get_param(req, name, default=None):
|
|
94
95
|
return value
|
95
96
|
|
96
97
|
|
98
|
+
def get_valid_part_num(req):
|
99
|
+
"""
|
100
|
+
Any non-range GET or HEAD request for a SLO object may include a
|
101
|
+
part-number parameter in query string. If the passed in request
|
102
|
+
includes a part-number parameter it will be parsed into a valid integer
|
103
|
+
and returned. If the passed in request does not include a part-number
|
104
|
+
param we will return None. If the part-number parameter is invalid for
|
105
|
+
the given request we will raise the appropriate HTTP exception
|
106
|
+
|
107
|
+
:param req: the request object
|
108
|
+
|
109
|
+
:returns: validated part-number value or None
|
110
|
+
:raises HTTPBadRequest: if request or part-number param is not valid
|
111
|
+
"""
|
112
|
+
part_number_param = get_param(req, 'part-number')
|
113
|
+
if part_number_param is None:
|
114
|
+
return None
|
115
|
+
try:
|
116
|
+
part_number = int(part_number_param)
|
117
|
+
if part_number <= 0:
|
118
|
+
raise ValueError
|
119
|
+
except ValueError:
|
120
|
+
raise HTTPBadRequest('Part number must be an integer greater '
|
121
|
+
'than 0')
|
122
|
+
|
123
|
+
if req.range:
|
124
|
+
raise HTTPBadRequest(req=req,
|
125
|
+
body='Range requests are not supported '
|
126
|
+
'with part number queries')
|
127
|
+
|
128
|
+
return part_number
|
129
|
+
|
130
|
+
|
97
131
|
def validate_params(req, names):
|
98
132
|
"""
|
99
133
|
Get list of parameters from an HTTP request, validating the encoding of
|
@@ -460,15 +494,17 @@ class SegmentedIterable(object):
|
|
460
494
|
:param app: WSGI application from which segments will come
|
461
495
|
|
462
496
|
:param listing_iter: iterable yielding the object segments to fetch,
|
463
|
-
along with the byte
|
464
|
-
|
497
|
+
along with the byte sub-ranges to fetch. Each yielded item should be a
|
498
|
+
dict with the following keys: ``path`` or ``raw_data``,
|
499
|
+
``first-byte``, ``last-byte``, ``hash`` (optional), ``bytes``
|
500
|
+
(optional).
|
465
501
|
|
466
|
-
If
|
502
|
+
If ``hash`` is None, no MD5 verification will be done.
|
467
503
|
|
468
|
-
If
|
504
|
+
If ``bytes`` is None, no length verification will be done.
|
469
505
|
|
470
|
-
If first-byte and last-byte are None, then the entire object
|
471
|
-
fetched.
|
506
|
+
If ``first-byte`` and ``last-byte`` are None, then the entire object
|
507
|
+
will be fetched.
|
472
508
|
|
473
509
|
:param max_get_time: maximum permitted duration of a GET request (seconds)
|
474
510
|
:param logger: logger object
|
@@ -740,7 +776,10 @@ class SegmentedIterable(object):
|
|
740
776
|
for x in mri:
|
741
777
|
yield x
|
742
778
|
finally:
|
743
|
-
|
779
|
+
# Spliterator and multi_range_iterator can't possibly know we've
|
780
|
+
# consumed the whole of the app_iter, but we want to read/close the
|
781
|
+
# final segment response
|
782
|
+
friendly_close(self.app_iter)
|
744
783
|
|
745
784
|
def validate_first_segment(self):
|
746
785
|
"""
|
@@ -900,6 +939,24 @@ def update_ignore_range_header(req, name):
|
|
900
939
|
req.headers[hdr] = csv_append(req.headers.get(hdr), name)
|
901
940
|
|
902
941
|
|
942
|
+
def resolve_ignore_range_header(req, metadata):
|
943
|
+
"""
|
944
|
+
Helper function to remove Range header from request if metadata matching
|
945
|
+
the X-Backend-Ignore-Range-If-Metadata-Present header is found.
|
946
|
+
|
947
|
+
:param req: a swob Request
|
948
|
+
:param metadata: dictionary of object metadata
|
949
|
+
"""
|
950
|
+
ignore_range_headers = set(
|
951
|
+
h.strip().lower()
|
952
|
+
for h in req.headers.get(
|
953
|
+
'X-Backend-Ignore-Range-If-Metadata-Present',
|
954
|
+
'').split(','))
|
955
|
+
if ignore_range_headers.intersection(
|
956
|
+
h.lower() for h in metadata):
|
957
|
+
req.headers.pop('Range', None)
|
958
|
+
|
959
|
+
|
903
960
|
def is_use_replication_network(headers=None):
|
904
961
|
"""
|
905
962
|
Determine if replication network should be used.
|
@@ -936,3 +993,39 @@ def get_ip_port(node, headers):
|
|
936
993
|
"""
|
937
994
|
return select_ip_port(
|
938
995
|
node, use_replication=is_use_replication_network(headers))
|
996
|
+
|
997
|
+
|
998
|
+
def is_open_expired(app, req):
|
999
|
+
"""
|
1000
|
+
Helper function to check if a request with the header 'x-open-expired'
|
1001
|
+
can access an object that has not yet been reaped by the object-expirer
|
1002
|
+
based on the allow_open_expired global config.
|
1003
|
+
|
1004
|
+
:param app: the application instance
|
1005
|
+
:param req: request object
|
1006
|
+
"""
|
1007
|
+
return (config_true_value(app.allow_open_expired) and
|
1008
|
+
config_true_value(req.headers.get('x-open-expired')))
|
1009
|
+
|
1010
|
+
|
1011
|
+
def is_backend_open_expired(request):
|
1012
|
+
"""
|
1013
|
+
Helper function to check if a request has either the headers
|
1014
|
+
'x-backend-open-expired' or 'x-backend-replication' for the backend
|
1015
|
+
to access expired objects.
|
1016
|
+
|
1017
|
+
:param request: request object
|
1018
|
+
"""
|
1019
|
+
x_backend_open_expired = config_true_value(request.headers.get(
|
1020
|
+
'x-backend-open-expired', 'false'))
|
1021
|
+
x_backend_replication = config_true_value(request.headers.get(
|
1022
|
+
'x-backend-replication', 'false'))
|
1023
|
+
return x_backend_open_expired or x_backend_replication
|
1024
|
+
|
1025
|
+
|
1026
|
+
def append_log_info(environ, log_info):
|
1027
|
+
environ.setdefault('swift.log_info', []).append(log_info)
|
1028
|
+
|
1029
|
+
|
1030
|
+
def get_log_info(environ):
|
1031
|
+
return ','.join(environ.get('swift.log_info', []))
|
@@ -0,0 +1,207 @@
|
|
1
|
+
# Copyright (c) 2010-2012 OpenStack Foundation
|
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
|
12
|
+
# implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
""" Statsd Client """
|
17
|
+
|
18
|
+
import time
|
19
|
+
import warnings
|
20
|
+
from contextlib import closing
|
21
|
+
from random import random
|
22
|
+
|
23
|
+
from eventlet.green import socket
|
24
|
+
import six
|
25
|
+
|
26
|
+
|
27
|
+
def get_statsd_client(conf=None, tail_prefix='', logger=None):
|
28
|
+
"""
|
29
|
+
Get an instance of StatsdClient using config settings.
|
30
|
+
|
31
|
+
**config and defaults**::
|
32
|
+
|
33
|
+
log_statsd_host = (disabled)
|
34
|
+
log_statsd_port = 8125
|
35
|
+
log_statsd_default_sample_rate = 1.0
|
36
|
+
log_statsd_sample_rate_factor = 1.0
|
37
|
+
log_statsd_metric_prefix = (empty-string)
|
38
|
+
|
39
|
+
:param conf: Configuration dict to read settings from
|
40
|
+
:param tail_prefix: tail prefix to pass to statsd client
|
41
|
+
:param logger: stdlib logger instance used by statsd client for logging
|
42
|
+
:return: an instance of ``StatsdClient``
|
43
|
+
|
44
|
+
"""
|
45
|
+
conf = conf or {}
|
46
|
+
|
47
|
+
host = conf.get('log_statsd_host')
|
48
|
+
port = int(conf.get('log_statsd_port', 8125))
|
49
|
+
base_prefix = conf.get('log_statsd_metric_prefix', '')
|
50
|
+
default_sample_rate = float(
|
51
|
+
conf.get('log_statsd_default_sample_rate', 1))
|
52
|
+
sample_rate_factor = float(
|
53
|
+
conf.get('log_statsd_sample_rate_factor', 1))
|
54
|
+
|
55
|
+
return StatsdClient(host, port, base_prefix=base_prefix,
|
56
|
+
tail_prefix=tail_prefix,
|
57
|
+
default_sample_rate=default_sample_rate,
|
58
|
+
sample_rate_factor=sample_rate_factor, logger=logger)
|
59
|
+
|
60
|
+
|
61
|
+
class StatsdClient(object):
|
62
|
+
def __init__(self, host, port, base_prefix='', tail_prefix='',
|
63
|
+
default_sample_rate=1, sample_rate_factor=1, logger=None):
|
64
|
+
self._host = host
|
65
|
+
self._port = port
|
66
|
+
self._base_prefix = base_prefix
|
67
|
+
self._default_sample_rate = default_sample_rate
|
68
|
+
self._sample_rate_factor = sample_rate_factor
|
69
|
+
self.random = random
|
70
|
+
self.logger = logger
|
71
|
+
self._set_prefix(tail_prefix)
|
72
|
+
self._sock_family = self._target = None
|
73
|
+
|
74
|
+
if self._host:
|
75
|
+
self._set_sock_family_and_target(self._host, self._port)
|
76
|
+
|
77
|
+
def _set_sock_family_and_target(self, host, port):
|
78
|
+
# Determine if host is IPv4 or IPv6
|
79
|
+
addr_info = None
|
80
|
+
try:
|
81
|
+
addr_info = socket.getaddrinfo(host, port, socket.AF_INET)
|
82
|
+
self._sock_family = socket.AF_INET
|
83
|
+
except socket.gaierror:
|
84
|
+
try:
|
85
|
+
addr_info = socket.getaddrinfo(host, port, socket.AF_INET6)
|
86
|
+
self._sock_family = socket.AF_INET6
|
87
|
+
except socket.gaierror:
|
88
|
+
# Don't keep the server from starting from what could be a
|
89
|
+
# transient DNS failure. Any hostname will get re-resolved as
|
90
|
+
# necessary in the .sendto() calls.
|
91
|
+
# However, we don't know if we're IPv4 or IPv6 in this case, so
|
92
|
+
# we assume legacy IPv4.
|
93
|
+
self._sock_family = socket.AF_INET
|
94
|
+
|
95
|
+
# NOTE: we use the original host value, not the DNS-resolved one
|
96
|
+
# because if host is a hostname, we don't want to cache the DNS
|
97
|
+
# resolution for the entire lifetime of this process. Let standard
|
98
|
+
# name resolution caching take effect. This should help operators use
|
99
|
+
# DNS trickery if they want.
|
100
|
+
if addr_info is not None:
|
101
|
+
# addr_info is a list of 5-tuples with the following structure:
|
102
|
+
# (family, socktype, proto, canonname, sockaddr)
|
103
|
+
# where sockaddr is the only thing of interest to us, and we only
|
104
|
+
# use the first result. We want to use the originally supplied
|
105
|
+
# host (see note above) and the remainder of the variable-length
|
106
|
+
# sockaddr: IPv4 has (address, port) while IPv6 has (address,
|
107
|
+
# port, flow info, scope id).
|
108
|
+
sockaddr = addr_info[0][-1]
|
109
|
+
self._target = (host,) + (sockaddr[1:])
|
110
|
+
else:
|
111
|
+
self._target = (host, port)
|
112
|
+
|
113
|
+
def _set_prefix(self, tail_prefix):
|
114
|
+
"""
|
115
|
+
Modifies the prefix that is added to metric names. The resulting prefix
|
116
|
+
is the concatenation of the component parts `base_prefix` and
|
117
|
+
`tail_prefix`. Only truthy components are included. Each included
|
118
|
+
component is followed by a period, e.g.::
|
119
|
+
|
120
|
+
<base_prefix>.<tail_prefix>.
|
121
|
+
<tail_prefix>.
|
122
|
+
<base_prefix>.
|
123
|
+
<the empty string>
|
124
|
+
|
125
|
+
Note: this method is expected to be called from the constructor only,
|
126
|
+
but exists to provide backwards compatible functionality for the
|
127
|
+
deprecated set_prefix() method.
|
128
|
+
|
129
|
+
:param tail_prefix: The new value of tail_prefix
|
130
|
+
"""
|
131
|
+
if tail_prefix and self._base_prefix:
|
132
|
+
self._prefix = '.'.join([self._base_prefix, tail_prefix, ''])
|
133
|
+
elif tail_prefix:
|
134
|
+
self._prefix = tail_prefix + '.'
|
135
|
+
elif self._base_prefix:
|
136
|
+
self._prefix = self._base_prefix + '.'
|
137
|
+
else:
|
138
|
+
self._prefix = ''
|
139
|
+
|
140
|
+
def set_prefix(self, tail_prefix):
|
141
|
+
"""
|
142
|
+
This method is deprecated; use the ``tail_prefix`` argument of the
|
143
|
+
constructor when instantiating the class instead.
|
144
|
+
"""
|
145
|
+
warnings.warn(
|
146
|
+
'set_prefix() is deprecated; use the ``tail_prefix`` argument of '
|
147
|
+
'the constructor when instantiating the class instead.',
|
148
|
+
DeprecationWarning, stacklevel=2
|
149
|
+
)
|
150
|
+
self._set_prefix(tail_prefix)
|
151
|
+
|
152
|
+
def _send(self, m_name, m_value, m_type, sample_rate):
|
153
|
+
if not self._host:
|
154
|
+
# StatsD not configured
|
155
|
+
return
|
156
|
+
|
157
|
+
if sample_rate is None:
|
158
|
+
sample_rate = self._default_sample_rate
|
159
|
+
sample_rate = sample_rate * self._sample_rate_factor
|
160
|
+
|
161
|
+
parts = ['%s%s:%s' % (self._prefix, m_name, m_value), m_type]
|
162
|
+
if sample_rate < 1:
|
163
|
+
if self.random() < sample_rate:
|
164
|
+
parts.append('@%s' % (sample_rate,))
|
165
|
+
else:
|
166
|
+
return
|
167
|
+
if six.PY3:
|
168
|
+
parts = [part.encode('utf-8') for part in parts]
|
169
|
+
# Ideally, we'd cache a sending socket in self, but that
|
170
|
+
# results in a socket getting shared by multiple green threads.
|
171
|
+
with closing(self._open_socket()) as sock:
|
172
|
+
try:
|
173
|
+
return sock.sendto(b'|'.join(parts), self._target)
|
174
|
+
except IOError as err:
|
175
|
+
if self.logger:
|
176
|
+
self.logger.warning(
|
177
|
+
'Error sending UDP message to %(target)r: %(err)s',
|
178
|
+
{'target': self._target, 'err': err})
|
179
|
+
|
180
|
+
def _open_socket(self):
|
181
|
+
return socket.socket(self._sock_family, socket.SOCK_DGRAM)
|
182
|
+
|
183
|
+
def update_stats(self, m_name, m_value, sample_rate=None):
|
184
|
+
return self._send(m_name, m_value, 'c', sample_rate)
|
185
|
+
|
186
|
+
def increment(self, metric, sample_rate=None):
|
187
|
+
return self.update_stats(metric, 1, sample_rate)
|
188
|
+
|
189
|
+
def decrement(self, metric, sample_rate=None):
|
190
|
+
return self.update_stats(metric, -1, sample_rate)
|
191
|
+
|
192
|
+
def _timing(self, metric, timing_ms, sample_rate):
|
193
|
+
# This method was added to disagregate timing metrics when testing
|
194
|
+
return self._send(metric, round(timing_ms, 4), 'ms', sample_rate)
|
195
|
+
|
196
|
+
def timing(self, metric, timing_ms, sample_rate=None):
|
197
|
+
return self._timing(metric, timing_ms, sample_rate)
|
198
|
+
|
199
|
+
def timing_since(self, metric, orig_time, sample_rate=None):
|
200
|
+
return self._timing(metric, (time.time() - orig_time) * 1000,
|
201
|
+
sample_rate)
|
202
|
+
|
203
|
+
def transfer_rate(self, metric, elapsed_time, byte_xfer, sample_rate=None):
|
204
|
+
if byte_xfer:
|
205
|
+
return self.timing(metric,
|
206
|
+
elapsed_time * 1000 / byte_xfer * 1000,
|
207
|
+
sample_rate)
|
swift/common/storage_policy.py
CHANGED
@@ -160,7 +160,7 @@ class BaseStoragePolicy(object):
|
|
160
160
|
object_ring=None, aliases='',
|
161
161
|
diskfile_module='egg:swift#replication.fs'):
|
162
162
|
# do not allow BaseStoragePolicy class to be instantiated directly
|
163
|
-
if type(self)
|
163
|
+
if type(self) is BaseStoragePolicy:
|
164
164
|
raise TypeError("Can't instantiate BaseStoragePolicy directly")
|
165
165
|
# policy parameter validation
|
166
166
|
try:
|
swift/common/swob.py
CHANGED
@@ -55,7 +55,7 @@ from six.moves import urllib
|
|
55
55
|
|
56
56
|
from swift.common.header_key_dict import HeaderKeyDict
|
57
57
|
from swift.common.utils import UTC, reiterate, split_path, Timestamp, pairs, \
|
58
|
-
close_if_possible, closing_if_possible, config_true_value,
|
58
|
+
close_if_possible, closing_if_possible, config_true_value, friendly_close
|
59
59
|
from swift.common.exceptions import InvalidTimestamp
|
60
60
|
|
61
61
|
|
@@ -1395,12 +1395,15 @@ class Response(object):
|
|
1395
1395
|
if empty_resp is not None:
|
1396
1396
|
self.status = empty_resp
|
1397
1397
|
self.content_length = 0
|
1398
|
+
# the existing successful response and it's app_iter have been
|
1399
|
+
# determined to not meet the conditions of the reqeust, the
|
1400
|
+
# response app_iter should be closed but not drained.
|
1398
1401
|
close_if_possible(app_iter)
|
1399
1402
|
return [b'']
|
1400
1403
|
|
1401
1404
|
if self.request and self.request.method == 'HEAD':
|
1402
1405
|
# We explicitly do NOT want to set self.content_length to 0 here
|
1403
|
-
|
1406
|
+
friendly_close(app_iter) # be friendly to our app_iter
|
1404
1407
|
return [b'']
|
1405
1408
|
|
1406
1409
|
if self.conditional_response and self.request and \
|