)]}'
{"swift/common/utils.py":[{"author":{"_account_id":330,"name":"John Dickinson","email":"me@not.mn","username":"notmyname"},"change_message_id":"3b56678d48b4d7d1bc7924d0286476f01b4eeb44","unresolved":false,"context_lines":[{"line_number":1543,"context_line":""},{"line_number":1544,"context_line":"    If affinity_str is empty or all whitespace, then the resulting function"},{"line_number":1545,"context_line":"    will not alter the ordering of the nodes. However, if affinity_str"},{"line_number":1546,"context_line":"    contains an invalid value, then None is returned."},{"line_number":1547,"context_line":""},{"line_number":1548,"context_line":"    :param affinity_str: affinity config value, e.g. \"r1z2\u003d3\""},{"line_number":1549,"context_line":"                         or \"r1\u003d1, r2z1\u003d2, r2z2\u003d2\""}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAPn%2F%2FvL0%3D","line":1546,"updated":"2013-06-24 03:52:05.000000000","message":"returns None or raises ValueError?","commit_id":"78ed7b0a8e558c40056f23551e56cdb03fca9fa4"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"2dbb0894d6ccf2be253cf22e1afd85838b7b157b","unresolved":false,"context_lines":[{"line_number":1543,"context_line":""},{"line_number":1544,"context_line":"    If affinity_str is empty or all whitespace, then the resulting function"},{"line_number":1545,"context_line":"    will not alter the ordering of the nodes. However, if affinity_str"},{"line_number":1546,"context_line":"    contains an invalid value, then None is returned."},{"line_number":1547,"context_line":""},{"line_number":1548,"context_line":"    :param affinity_str: affinity config value, e.g. \"r1z2\u003d3\""},{"line_number":1549,"context_line":"                         or \"r1\u003d1, r2z1\u003d2, r2z2\u003d2\""}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAPn%2F%2FvBM%3D","line":1546,"in_reply_to":"AAAAPn%2F%2FvL0%3D","updated":"2013-06-24 05:08:47.000000000","message":"yeah :/\n\nI wanted a way to completely ignore write_affinity_node_depth when write_affinity was unset.\n\nIf this returns, say, (lambda n: True), then if someone has write_affinity unset and write_affinity_node_depth \u003d 200 * replicas, they\u0027d pull 600 nodes out of the ring and make sure each was local, only to ignore most of that.\n\nIt\u0027s less wasteful in the default case (2 * replicas), but it still bugged me that it was wasteful at all, hence the weird return value.","commit_id":"78ed7b0a8e558c40056f23551e56cdb03fca9fa4"}],"swift/proxy/controllers/base.py":[{"author":{"_account_id":6577,"name":"Sergey Kraynev","email":"sergejyit@gmail.com","username":"skraynev"},"change_message_id":"15c952122cc781e3d98d716fb04764529b51168d","unresolved":false,"context_lines":[{"line_number":631,"context_line":"            list(itertools.islice(node_iter, num_primary_nodes)))"},{"line_number":632,"context_line":"        handoff_nodes \u003d node_iter"},{"line_number":633,"context_line":"        nodes_left \u003d self.app.request_node_count(ring)"},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"        for node in primary_nodes:"},{"line_number":636,"context_line":"            if not self.error_limited(node):"},{"line_number":637,"context_line":"                yield node"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAPn%2F%2F67k%3D","line":634,"updated":"2013-06-18 08:24:32.000000000","message":"Without affinity generator will yield in first loop just handoff nodes (according new primary nodes list). Primary nodes will yield in second loop. Am I right?","commit_id":"9f01f063b75985c1345eaa6db231adf52264a3eb"},{"author":{"_account_id":6577,"name":"Sergey Kraynev","email":"sergejyit@gmail.com","username":"skraynev"},"change_message_id":"495da8e726d5b545d1573148356d999283367234","unresolved":false,"context_lines":[{"line_number":631,"context_line":"            list(itertools.islice(node_iter, num_primary_nodes)))"},{"line_number":632,"context_line":"        handoff_nodes \u003d node_iter"},{"line_number":633,"context_line":"        nodes_left \u003d self.app.request_node_count(ring)"},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"        for node in primary_nodes:"},{"line_number":636,"context_line":"            if not self.error_limited(node):"},{"line_number":637,"context_line":"                yield node"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAPn%2F%2F1DA%3D","line":634,"in_reply_to":"AAAAPn%2F%2F2tU%3D","updated":"2013-06-20 08:40:54.000000000","message":"No. Thank you very much. You gave me a detail and very helpful answer)))","commit_id":"9f01f063b75985c1345eaa6db231adf52264a3eb"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"f7104f984cce8d038ba222c7ba5b3e5a1fcd627c","unresolved":false,"context_lines":[{"line_number":631,"context_line":"            list(itertools.islice(node_iter, num_primary_nodes)))"},{"line_number":632,"context_line":"        handoff_nodes \u003d node_iter"},{"line_number":633,"context_line":"        nodes_left \u003d self.app.request_node_count(ring)"},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"        for node in primary_nodes:"},{"line_number":636,"context_line":"            if not self.error_limited(node):"},{"line_number":637,"context_line":"                yield node"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAPn%2F%2F2tU%3D","line":634,"in_reply_to":"AAAAPn%2F%2F3%2Bk%3D","updated":"2013-06-19 18:30:58.000000000","message":"So, with a custom node_iter, the \"primary\" nodes are simply the first N (usually 3) nodes that are yielded. The only time a custom node_iter is used is on the object PUT request, so the ordering of the first few nodes is irrelevant since the data will be written to all of them.\n\nThere\u0027s a few reasons not to sort the handoff nodes, but the biggest one is replication. Replication will move data to be on the primaries, but will fall back to the handoffs (in the order they come out of ring.get_more_nodes) when the primaries are unavailable. Therefore, going through the handoffs in any order other than the default one makes it less likely that you\u0027ll find the data you\u0027re looking for.\n\nNow, it\u0027s true that if you\u0027re using write_affinity, there\u0027s a short interval where the data may be on nodes that are deeper in the handoff list, but the proxy has no way of knowing if the data\u0027s been moved or not.\n\nDoes that address your concern, or am I missing something?","commit_id":"9f01f063b75985c1345eaa6db231adf52264a3eb"},{"author":{"_account_id":6577,"name":"Sergey Kraynev","email":"sergejyit@gmail.com","username":"skraynev"},"change_message_id":"88908fce47ba4efcdbb3ac95696b3b71e86e394f","unresolved":false,"context_lines":[{"line_number":631,"context_line":"            list(itertools.islice(node_iter, num_primary_nodes)))"},{"line_number":632,"context_line":"        handoff_nodes \u003d node_iter"},{"line_number":633,"context_line":"        nodes_left \u003d self.app.request_node_count(ring)"},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"        for node in primary_nodes:"},{"line_number":636,"context_line":"            if not self.error_limited(node):"},{"line_number":637,"context_line":"                yield node"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAPn%2F%2F3%2Bk%3D","line":634,"in_reply_to":"AAAAPn%2F%2F4tA%3D","updated":"2013-06-19 09:41:30.000000000","message":"Thanks for the answer. I understand my mistake. \nBut I still have some questions:\n1. Primary nodes will be sorted if read affinity is enabled. Is it so?\n2. If all primary nodes are placed in non local regions, function will yield handoffs nodes. But all handoffs nodes aren\u0027t sorted. May be add sorting for handoffs nodes too?","commit_id":"9f01f063b75985c1345eaa6db231adf52264a3eb"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7af700520058dd0b5d5b38ba09900823d56b7d02","unresolved":false,"context_lines":[{"line_number":631,"context_line":"            list(itertools.islice(node_iter, num_primary_nodes)))"},{"line_number":632,"context_line":"        handoff_nodes \u003d node_iter"},{"line_number":633,"context_line":"        nodes_left \u003d self.app.request_node_count(ring)"},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"        for node in primary_nodes:"},{"line_number":636,"context_line":"            if not self.error_limited(node):"},{"line_number":637,"context_line":"                yield node"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAPn%2F%2F4tA%3D","line":634,"in_reply_to":"AAAAPn%2F%2F67k%3D","updated":"2013-06-18 23:57:31.000000000","message":"I don\u0027t think that\u0027s right.\n\nThe primary nodes will be the first N nodes yielded from node_iter. Line 630 uses islice() to create an iterator that will yield only N nodes from node_iter, then calls list() on that iterator to realize its results immediately. The result is that the variable \"primary_nodes\" actually contains the primary nodes.","commit_id":"9f01f063b75985c1345eaa6db231adf52264a3eb"},{"author":{"_account_id":6577,"name":"Sergey Kraynev","email":"sergejyit@gmail.com","username":"skraynev"},"change_message_id":"15c952122cc781e3d98d716fb04764529b51168d","unresolved":false,"context_lines":[{"line_number":698,"context_line":"                                        {\u0027method\u0027: method, \u0027path\u0027: path})"},{"line_number":699,"context_line":""},{"line_number":700,"context_line":"    def make_requests(self, req, ring, part, method, path, headers,"},{"line_number":701,"context_line":"                      query_string\u003d\u0027\u0027, node_iter\u003dNone):"},{"line_number":702,"context_line":"        \"\"\""},{"line_number":703,"context_line":"        Sends an HTTP request to multiple nodes and aggregates the results."},{"line_number":704,"context_line":"        It attempts the primary nodes concurrently, then iterates over the"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAPn%2F%2F68U%3D","line":701,"updated":"2013-06-18 08:24:32.000000000","message":"Is this option (node_iter) used somewhere?\nI mean situation where it is called with some value besides None.","commit_id":"9f01f063b75985c1345eaa6db231adf52264a3eb"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7af700520058dd0b5d5b38ba09900823d56b7d02","unresolved":false,"context_lines":[{"line_number":698,"context_line":"                                        {\u0027method\u0027: method, \u0027path\u0027: path})"},{"line_number":699,"context_line":""},{"line_number":700,"context_line":"    def make_requests(self, req, ring, part, method, path, headers,"},{"line_number":701,"context_line":"                      query_string\u003d\u0027\u0027, node_iter\u003dNone):"},{"line_number":702,"context_line":"        \"\"\""},{"line_number":703,"context_line":"        Sends an HTTP request to multiple nodes and aggregates the results."},{"line_number":704,"context_line":"        It attempts the primary nodes concurrently, then iterates over the"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAPn%2F%2F4sw%3D","line":701,"in_reply_to":"AAAAPn%2F%2F68U%3D","updated":"2013-06-18 23:57:31.000000000","message":"I could have sworn I had one, but I guess not.\n\nI\u0027ll back this change out. Well spotted.","commit_id":"9f01f063b75985c1345eaa6db231adf52264a3eb"},{"author":{"_account_id":330,"name":"John Dickinson","email":"me@not.mn","username":"notmyname"},"change_message_id":"3b56678d48b4d7d1bc7924d0286476f01b4eeb44","unresolved":false,"context_lines":[{"line_number":623,"context_line":"            node_iter \u003d itertools.chain(ring.get_part_nodes(partition),"},{"line_number":624,"context_line":"                                        ring.get_more_nodes(partition))"},{"line_number":625,"context_line":""},{"line_number":626,"context_line":"        num_primary_nodes \u003d len(ring.get_part_nodes(partition))"},{"line_number":627,"context_line":""},{"line_number":628,"context_line":"        # Use of list() here forcibly yanks the first N nodes (the primary"},{"line_number":629,"context_line":"        # nodes) from node_iter, so the rest of its values are handoffs."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAPn%2F%2FvLg%3D","line":626,"updated":"2013-06-24 03:52:05.000000000","message":"why a second call to get_part_nodes()? This line will iterate over all of it, so storing the value above will save the extra call.\n\nIt sure would be a shame to have self._reload() called between these to primary node getters...","commit_id":"78ed7b0a8e558c40056f23551e56cdb03fca9fa4"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"2dbb0894d6ccf2be253cf22e1afd85838b7b157b","unresolved":false,"context_lines":[{"line_number":623,"context_line":"            node_iter \u003d itertools.chain(ring.get_part_nodes(partition),"},{"line_number":624,"context_line":"                                        ring.get_more_nodes(partition))"},{"line_number":625,"context_line":""},{"line_number":626,"context_line":"        num_primary_nodes \u003d len(ring.get_part_nodes(partition))"},{"line_number":627,"context_line":""},{"line_number":628,"context_line":"        # Use of list() here forcibly yanks the first N nodes (the primary"},{"line_number":629,"context_line":"        # nodes) from node_iter, so the rest of its values are handoffs."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAPn%2F%2FvBI%3D","line":626,"in_reply_to":"AAAAPn%2F%2FvLg%3D","updated":"2013-06-24 05:08:47.000000000","message":"Sloppy coding. You know, the usual. :)\n\nWill fix.","commit_id":"78ed7b0a8e558c40056f23551e56cdb03fca9fa4"}],"swift/proxy/server.py":[{"author":{"_account_id":6577,"name":"Sergey Kraynev","email":"sergejyit@gmail.com","username":"skraynev"},"change_message_id":"15c952122cc781e3d98d716fb04764529b51168d","unresolved":false,"context_lines":[{"line_number":140,"context_line":"        except ValueError as err:"},{"line_number":141,"context_line":"            # make the message a little more useful"},{"line_number":142,"context_line":"            raise ValueError(\"Invalid write_affinity value: %r (%s)\" %"},{"line_number":143,"context_line":"                             (read_affinity, err.message))"},{"line_number":144,"context_line":"        value \u003d conf.get(\u0027write_affinity_node_count\u0027,"},{"line_number":145,"context_line":"                         \u00272 * replicas\u0027).lower().split()"},{"line_number":146,"context_line":"        if len(value) \u003d\u003d 1:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAPn%2F%2F6%2FQ%3D","line":143,"updated":"2013-06-18 08:24:32.000000000","message":"Sample typo: \"write affinity\" instead \"read affinity\"","commit_id":"9f01f063b75985c1345eaa6db231adf52264a3eb"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7af700520058dd0b5d5b38ba09900823d56b7d02","unresolved":false,"context_lines":[{"line_number":140,"context_line":"        except ValueError as err:"},{"line_number":141,"context_line":"            # make the message a little more useful"},{"line_number":142,"context_line":"            raise ValueError(\"Invalid write_affinity value: %r (%s)\" %"},{"line_number":143,"context_line":"                             (read_affinity, err.message))"},{"line_number":144,"context_line":"        value \u003d conf.get(\u0027write_affinity_node_count\u0027,"},{"line_number":145,"context_line":"                         \u00272 * replicas\u0027).lower().split()"},{"line_number":146,"context_line":"        if len(value) \u003d\u003d 1:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAPn%2F%2F4rM%3D","line":143,"in_reply_to":"AAAAPn%2F%2F6%2FQ%3D","updated":"2013-06-18 23:57:31.000000000","message":"Done","commit_id":"9f01f063b75985c1345eaa6db231adf52264a3eb"}],"test/unit/proxy/controllers/test_obj.py":[{"author":{"_account_id":6577,"name":"Sergey Kraynev","email":"sergejyit@gmail.com","username":"skraynev"},"change_message_id":"99d7fd05c632b8455e8e68f13ce5919850d44400","unresolved":false,"context_lines":[{"line_number":14,"context_line":"# See the License for the specific language governing permissions and"},{"line_number":15,"context_line":"# limitations under the License."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"import mock"},{"line_number":18,"context_line":"import unittest"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from swift.proxy import server as proxy_server"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAPn%2F%2Fr6Q%3D","line":17,"updated":"2013-06-25 09:37:48.000000000","message":"unused import","commit_id":"d9f2a76973ff8af75f117d63f80abd7126ce560b"},{"author":{"_account_id":6577,"name":"Sergey Kraynev","email":"sergejyit@gmail.com","username":"skraynev"},"change_message_id":"99d7fd05c632b8455e8e68f13ce5919850d44400","unresolved":false,"context_lines":[{"line_number":18,"context_line":"import unittest"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from swift.proxy import server as proxy_server"},{"line_number":21,"context_line":"from test.unit import fake_http_connect, FakeRing, FakeMemcache"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class TestObjControllerWriteAffinity(unittest.TestCase):"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAPn%2F%2Fr6M%3D","line":21,"updated":"2013-06-25 09:37:48.000000000","message":"fake_http_connect - unused import","commit_id":"d9f2a76973ff8af75f117d63f80abd7126ce560b"}]}
