)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"7aff81661ac71419a5c706f6a6f0593d20844119","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     feipeng \u003cfeipeng1@huawei.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2016-02-19 10:03:00 +0800"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add Redis_driver.rst"},{"line_number":8,"context_line":"Add Redis DB Driver and Redis PubSub Driver"},{"line_number":9,"context_line":"Change-Id: I7e6624313dda8176a8e2dc94c8ef1854f329dc6e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":7,"id":"bae84128_4de92180","line":7,"updated":"2016-02-21 01:42:16.000000000","message":"A blank line is needed here.","commit_id":"db050f4d6a743d8fd41524e6439754ecb2d6c15e"}],"doc/source/specs/redis_driver.rst":[{"author":{"_account_id":11343,"name":"Gal Sagie","email":"gal.sagie@gmail.com","username":"GalSagie"},"change_message_id":"52bffa6303d71327122b4e19e40840f09078cefa","unresolved":false,"context_lines":[{"line_number":8,"context_line":"Redis Driver Spec"},{"line_number":9,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Include the URL of your launchpad RFE:"},{"line_number":12,"context_line":"Add a DataBase support for DragonFlow"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Problem Description"}],"source_content_type":"text/x-rst","patch_set":1,"id":"7a5de9d1_dc6743e7","line":11,"updated":"2016-01-31 11:55:14.000000000","message":"You need to add a launchpad blueprint, when done add the link to it here.\n\nSee this page:\nhttps://blueprints.launchpad.net/dragonflow\n\njust add a new one with \"redis-db-driver\" , put your self as assignee and add the link in this spec","commit_id":"23d6072a879af84868155e806cea5b89ef85637b"},{"author":{"_account_id":11343,"name":"Gal Sagie","email":"gal.sagie@gmail.com","username":"GalSagie"},"change_message_id":"52bffa6303d71327122b4e19e40840f09078cefa","unresolved":false,"context_lines":[{"line_number":15,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":16,"context_line":"Dragonflow will use Publish/Subscribe as a method to realize communication between different component."},{"line_number":17,"context_line":"Redis DB has a good performance of Publish/Subscribe."},{"line_number":18,"context_line":"So,We need a driver for Redis DB,meanwhile,if other DB which support Publish/Subscribe only needs overwrite new APIS added here."},{"line_number":19,"context_line":"dragonflow will have a efficient way to realize communication between different component with Redis driver."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"Proposed Change"}],"source_content_type":"text/x-rst","patch_set":1,"id":"7a5de9d1_9c5d4b17","line":18,"updated":"2016-01-31 11:55:14.000000000","message":"please use lines that wrap at 80 chars (or around it)","commit_id":"23d6072a879af84868155e806cea5b89ef85637b"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"1496ed5da217d846cee33f5c44150903e66e9017","unresolved":false,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":"Populating a Database API"},{"line_number":28,"context_line":"-------------------------"},{"line_number":29,"context_line":"Basic operation for Redis DB,including add/delete/get and so on.Realization based on Grokzen lib"},{"line_number":30,"context_line":"The following diagram shows which components will populate Redis DB Cluster with driver."},{"line_number":31,"context_line":""},{"line_number":32,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"7a5de9d1_ca241161","line":29,"range":{"start_line":29,"start_character":52,"end_line":29,"end_character":53},"updated":"2016-02-02 04:54:23.000000000","message":"and modify","commit_id":"23d6072a879af84868155e806cea5b89ef85637b"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"1496ed5da217d846cee33f5c44150903e66e9017","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    |                  |            |                |"},{"line_number":38,"context_line":"    |                  |            |                |        +------------------+"},{"line_number":39,"context_line":"    |                  |            |  realize       |        | Redis DB Cluster |"},{"line_number":40,"context_line":"    +------------------+            |  add/del/get   +------\u003e |                  |"},{"line_number":41,"context_line":"                                    |  using DB API  |        |                  |"},{"line_number":42,"context_line":"    +------------------+            |                |        |                  |"},{"line_number":43,"context_line":"    |                  |            |                |        +------------------+"}],"source_content_type":"text/x-rst","patch_set":1,"id":"7a5de9d1_cadbb14d","line":40,"range":{"start_line":40,"start_character":56,"end_line":40,"end_character":59},"updated":"2016-02-02 04:54:23.000000000","message":"RPC ? Rest?\nWill the driver connect only one redis db node or all of nodes?","commit_id":"23d6072a879af84868155e806cea5b89ef85637b"},{"author":{"_account_id":11343,"name":"Gal Sagie","email":"gal.sagie@gmail.com","username":"GalSagie"},"change_message_id":"52bffa6303d71327122b4e19e40840f09078cefa","unresolved":false,"context_lines":[{"line_number":98,"context_line":""},{"line_number":99,"context_line":"type: One of the following: \u0027subscribe\u0027, \u0027unsubscribe\u0027, \u0027psubscribe\u0027, \u0027punsubscribe\u0027, \u0027message\u0027, \u0027pmessage\u0027"},{"line_number":100,"context_line":"channel: The channel [un]subscribed to or the channel a message was published to"},{"line_number":101,"context_line":"pattern: The pattern that matched a published message\u0027s channel. Will be None in all cases except for \u0027pmessage\u0027 types."},{"line_number":102,"context_line":"data: The message data. With [un]subscribe messages, this value will be the number of channels and patterns the connection is currently subscribed to."},{"line_number":103,"context_line":"      With [p]message messages, this value will be the actual published message."},{"line_number":104,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"7a5de9d1_1ca87bda","line":101,"updated":"2016-01-31 11:55:14.000000000","message":"is the filtering of the topics are done in the client side(subscriber) or in the server side (publisher)?","commit_id":"23d6072a879af84868155e806cea5b89ef85637b"},{"author":{"_account_id":11343,"name":"Gal Sagie","email":"gal.sagie@gmail.com","username":"GalSagie"},"change_message_id":"52bffa6303d71327122b4e19e40840f09078cefa","unresolved":false,"context_lines":[{"line_number":108,"context_line":""},{"line_number":109,"context_line":"Subscribe Thread For Reading Messages"},{"line_number":110,"context_line":"-------------------------------------"},{"line_number":111,"context_line":"The subscribe thread is in charge to receiving the notifications and sending"},{"line_number":112,"context_line":"them back to the controller.Realization is based on andymccurdy lib."},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"The subscribe thread loop is depicted in the following diagram:"}],"source_content_type":"text/x-rst","patch_set":1,"id":"7a5de9d1_dcae63e5","line":111,"updated":"2016-01-31 11:55:14.000000000","message":"You will need to add this similar to the pub/sub mechanism that Eran is adding.","commit_id":"23d6072a879af84868155e806cea5b89ef85637b"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"1496ed5da217d846cee33f5c44150903e66e9017","unresolved":false,"context_lines":[{"line_number":108,"context_line":""},{"line_number":109,"context_line":"Subscribe Thread For Reading Messages"},{"line_number":110,"context_line":"-------------------------------------"},{"line_number":111,"context_line":"The subscribe thread is in charge to receiving the notifications and sending"},{"line_number":112,"context_line":"them back to the controller.Realization is based on andymccurdy lib."},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"The subscribe thread loop is depicted in the following diagram:"}],"source_content_type":"text/x-rst","patch_set":1,"id":"7a5de9d1_8a4299ac","line":111,"range":{"start_line":111,"start_character":34,"end_line":111,"end_character":36},"updated":"2016-02-02 04:54:23.000000000","message":"of","commit_id":"23d6072a879af84868155e806cea5b89ef85637b"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"1496ed5da217d846cee33f5c44150903e66e9017","unresolved":false,"context_lines":[{"line_number":153,"context_line":""},{"line_number":154,"context_line":"driver only does connection fix,throw exception when connection is recovered,driver will clear all subscription"},{"line_number":155,"context_line":"and user of Subscription do resubscribe."},{"line_number":156,"context_line":""},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"Exception"},{"line_number":159,"context_line":"---------"}],"source_content_type":"text/x-rst","patch_set":1,"id":"7a5de9d1_0a630943","line":156,"range":{"start_line":156,"start_character":0,"end_line":156,"end_character":0},"updated":"2016-02-02 04:54:23.000000000","message":"How the driver setup connections with db node and pub/sub server when startup?","commit_id":"23d6072a879af84868155e806cea5b89ef85637b"},{"author":{"_account_id":11364,"name":"Fei Rao","email":"milo.frao@gmail.com","username":"milo.frao"},"change_message_id":"3e8d4d8fb3a1e24ce8741bfc7888fc6ed4cac9ae","unresolved":false,"context_lines":[{"line_number":27,"context_line":"here we just need to overwrite those APIs already existed,"},{"line_number":28,"context_line":"and add new APIS for the Publish/Subscribe,based on andymccurdy lib and Grokzen lib."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"Populating a Database API"},{"line_number":31,"context_line":"-------------------------"},{"line_number":32,"context_line":"Basic operation for Redis DB,including add/delete/get/modify and so on."},{"line_number":33,"context_line":"Realization is based on Grokzen lib."},{"line_number":34,"context_line":"The following diagram shows which components will populate Redis DB Cluster with driver."}],"source_content_type":"text/x-rst","patch_set":2,"id":"dae33548_777f0be0","line":31,"range":{"start_line":30,"start_character":0,"end_line":31,"end_character":25},"updated":"2016-02-18 08:44:19.000000000","message":"Can you please append the Redis deploy(installation/configuration/...)","commit_id":"0d9f522f153ced7137738946da9a848debbdf466"},{"author":{"_account_id":11364,"name":"Fei Rao","email":"milo.frao@gmail.com","username":"milo.frao"},"change_message_id":"3e8d4d8fb3a1e24ce8741bfc7888fc6ed4cac9ae","unresolved":false,"context_lines":[{"line_number":34,"context_line":"The following diagram shows which components will populate Redis DB Cluster with driver."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    +------------------+            +----------------+"},{"line_number":38,"context_line":"    |Neutron server    |            |   Redis Driver |"},{"line_number":39,"context_line":"    |                  | func call  |                |"},{"line_number":40,"context_line":"    | Plugins          +----------\u003e |                |"},{"line_number":41,"context_line":"    |                  |            |                |"},{"line_number":42,"context_line":"    |                  |            |                |        +------------------+"},{"line_number":43,"context_line":"    |                  |            |  realize       |        | Redis DB Cluster |"},{"line_number":44,"context_line":"    +------------------+            |  add/del/get   +------\u003e |                  |"},{"line_number":45,"context_line":"                                    |  using DB API  |        |                  |"},{"line_number":46,"context_line":"    +------------------+            |                |        |                  |"},{"line_number":47,"context_line":"    |                  |            |                |        +------------------+"},{"line_number":48,"context_line":"    | Compute Node     | func call  |                |"},{"line_number":49,"context_line":"    |                  +----------\u003e |                |"},{"line_number":50,"context_line":"    | Applications     |            |                |"},{"line_number":51,"context_line":"    |                  |            |                |"},{"line_number":52,"context_line":"    |                  |            |                |"},{"line_number":53,"context_line":"    +------------------+            +----------------+"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"dae33548_f7ae7b2c","line":53,"range":{"start_line":37,"start_character":0,"end_line":53,"end_character":54},"updated":"2016-02-18 08:44:19.000000000","message":"All the drivers have the similar base work flow with Dragonflow pub/sub mechanism. Could you please describe more details of Redis, such as Redis server configuration, integration etc.","commit_id":"0d9f522f153ced7137738946da9a848debbdf466"},{"author":{"_account_id":11364,"name":"Fei Rao","email":"milo.frao@gmail.com","username":"milo.frao"},"change_message_id":"3e8d4d8fb3a1e24ce8741bfc7888fc6ed4cac9ae","unresolved":false,"context_lines":[{"line_number":173,"context_line":""},{"line_number":174,"context_line":"Exception"},{"line_number":175,"context_line":"---------"},{"line_number":176,"context_line":"First Notice:exception of cluster client and single client are different,need processed separately."},{"line_number":177,"context_line":"case1:populate db failed"},{"line_number":178,"context_line":"If add operation is failed,driver will delete what you add,"},{"line_number":179,"context_line":"driver will check connection and reconnect if reason is connection lost,"},{"line_number":180,"context_line":"driver will try several times( for example 3),if all trials failed,"},{"line_number":181,"context_line":"driver will return failed,if reason is not connection"},{"line_number":182,"context_line":"problem,driver will also return failed directly.You should return failed to up level,"},{"line_number":183,"context_line":"do not publish,if driver returned failed."},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"If delete operation is failed,the process is same as above,"},{"line_number":186,"context_line":"except for driver will not rollback delete operation."},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"case2:publish failed"},{"line_number":189,"context_line":"If this happened,"},{"line_number":190,"context_line":"driver will return failed and check connection also reconnect if reason is connection lost."},{"line_number":191,"context_line":"If driver return failed,user of API should undo what you done before publish and return failed"},{"line_number":192,"context_line":"to up level"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"case3:subscribe failed"},{"line_number":195,"context_line":"If this happened,"},{"line_number":196,"context_line":"driver will return failed and check connection also reconnect if reason is connection lost."},{"line_number":197,"context_line":"If driver return failed, user of api return failed to up level."},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"case4:subscribe listen exception"},{"line_number":200,"context_line":"If this happened,"},{"line_number":201,"context_line":"Driver will clear all subscription and then try reconnect,"},{"line_number":202,"context_line":"after fix connection then send a message to subscriber, tell that you subscribed is recovered,,"},{"line_number":203,"context_line":"subscriber should get data from DB, according to what it subscribed."},{"line_number":204,"context_line":"if subscriber get data from DB failed,may be can write dummy flow"},{"line_number":205,"context_line":"to ovs,avoiding wrong packet path and waiting for packet in process to fix packet path."},{"line_number":206,"context_line":"This may not so efficient, but it can fix the data consistent problem."},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"References"},{"line_number":209,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":2,"id":"dae33548_77954b31","line":206,"range":{"start_line":176,"start_character":0,"end_line":206,"end_character":70},"updated":"2016-02-18 08:44:19.000000000","message":"Redis is one of the drivers of Dragonflow pub/sub mechanism. and the pub/sub common modules will not do the special process for Redis driver. So I suggest to take these use case as a common implementation part.","commit_id":"0d9f522f153ced7137738946da9a848debbdf466"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"3bc90274cc4f5b76c03f1fff07348c59359a7a70","unresolved":false,"context_lines":[{"line_number":15,"context_line":"Problem Description"},{"line_number":16,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":17,"context_line":"Dragonflow will use Publish/Subscribe as a method to realize communication between components."},{"line_number":18,"context_line":"Redis DB has a good performance of Publish/Subscribe."},{"line_number":19,"context_line":"So,We need a driver for Redis DB,meanwhile,"},{"line_number":20,"context_line":"if other DB which support Publish/Subscribe only needs overwrite new APIS added here."},{"line_number":21,"context_line":"dragonflow will have a efficient way to realize communication between different component."}],"source_content_type":"text/x-rst","patch_set":7,"id":"dae33548_a0574f25","line":18,"range":{"start_line":18,"start_character":0,"end_line":18,"end_character":8},"updated":"2016-02-19 05:22:38.000000000","message":"Besides the PUB/SUB, How does Redis provide data persistence according to your solution? I always use Redis cluster as the distributed cache, but I don\u0027t know how to make the data persistent IN ALL TIME. I think it is very important for Dragonflow as it stores the virtual topology not temporary data.","commit_id":"db050f4d6a743d8fd41524e6439754ecb2d6c15e"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":25,"context_line":""},{"line_number":26,"context_line":"As dragonflow already has a class for DB API,"},{"line_number":27,"context_line":"here we just need to overwrite those APIs already existed,"},{"line_number":28,"context_line":"and add new APIS for the Publish/Subscribe,based on andymccurdy lib and Grokzen lib."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"Populating a Database API"},{"line_number":31,"context_line":"-------------------------"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_d4c0f57e","line":28,"range":{"start_line":28,"start_character":33,"end_line":28,"end_character":48},"updated":"2016-02-22 12:32:32.000000000","message":"Need space here","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":25,"context_line":""},{"line_number":26,"context_line":"As dragonflow already has a class for DB API,"},{"line_number":27,"context_line":"here we just need to overwrite those APIs already existed,"},{"line_number":28,"context_line":"and add new APIS for the Publish/Subscribe,based on andymccurdy lib and Grokzen lib."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"Populating a Database API"},{"line_number":31,"context_line":"-------------------------"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_865e4074","line":28,"range":{"start_line":28,"start_character":52,"end_line":28,"end_character":83},"updated":"2016-02-22 15:31:23.000000000","message":"Please include links to the libraries. Especially since anymccurdy and Grokzen are the authors, and not the library names.","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":"Publish API"},{"line_number":59,"context_line":"-----------"},{"line_number":60,"context_line":"The new API  realizes publish function with channel,based on andymccurdy lib"},{"line_number":61,"context_line":"The following diagram shows how Neutron config changes are published to all local controllers."},{"line_number":62,"context_line":"It is only a example."},{"line_number":63,"context_line":""}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_d447551b","line":60,"range":{"start_line":60,"start_character":44,"end_line":60,"end_character":57},"updated":"2016-02-22 12:32:32.000000000","message":"need space here","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":"Publish API"},{"line_number":59,"context_line":"-----------"},{"line_number":60,"context_line":"The new API  realizes publish function with channel,based on andymccurdy lib"},{"line_number":61,"context_line":"The following diagram shows how Neutron config changes are published to all local controllers."},{"line_number":62,"context_line":"It is only a example."},{"line_number":63,"context_line":""}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_b442910e","line":60,"range":{"start_line":60,"start_character":11,"end_line":60,"end_character":13},"updated":"2016-02-22 12:32:32.000000000","message":"two spaces to one","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":79,"context_line":"r \u003d redis.StrictRedis(...)"},{"line_number":80,"context_line":"p \u003d r.pubsub()"},{"line_number":81,"context_line":"r.publish(\u0027my-first-channel\u0027, \u0027some data\u0027)/* my-first-channel is channel name,"},{"line_number":82,"context_line":"                                          some data is what you want to publish */"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"Special Notice:"},{"line_number":85,"context_line":"\u0027Some data\u0027  will be coded into json pattern.."}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_09e40339","line":82,"updated":"2016-02-22 15:31:23.000000000","message":"Please provide more detail. What transport is used to publish data? What does the driver support? UDP? TCP?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":82,"context_line":"                                          some data is what you want to publish */"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"Special Notice:"},{"line_number":85,"context_line":"\u0027Some data\u0027  will be coded into json pattern.."},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"Subscribe API"},{"line_number":88,"context_line":"-------------"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_945cadee","line":85,"range":{"start_line":85,"start_character":11,"end_line":85,"end_character":13},"updated":"2016-02-22 12:32:32.000000000","message":"two spaces to one","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":87,"context_line":"Subscribe API"},{"line_number":88,"context_line":"-------------"},{"line_number":89,"context_line":"If you want to receive message that you publish,you first should do a subscription,if you"},{"line_number":90,"context_line":"do not wan to to receive message,you should withdraw subscription."},{"line_number":91,"context_line":"Realization is based on andymccurdy lib."},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"Here is a example of subscription process:"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_94130d0d","line":90,"range":{"start_line":90,"start_character":7,"end_line":90,"end_character":10},"updated":"2016-02-22 12:32:32.000000000","message":"want ?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":103,"context_line":"{\u0027channel\u0027: \u0027my-first-channel\u0027, \u0027data\u0027: \u0027some data\u0027, \u0027pattern\u0027: None, \u0027type\u0027: \u0027message\u0027}"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"type: One of the following: \u0027subscribe\u0027, \u0027unsubscribe\u0027, \u0027psubscribe\u0027, \u0027punsubscribe\u0027,"},{"line_number":106,"context_line":"                           \u0027message\u0027, \u0027pmessage\u0027"},{"line_number":107,"context_line":"channel: The channel [un]subscribed to or the channel a message was published to"},{"line_number":108,"context_line":"pattern: The pattern that matched a published message\u0027s channel."},{"line_number":109,"context_line":"         Will be None in all cases except for \u0027pmessage\u0027 types."}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_86d5a0ba","line":106,"updated":"2016-02-22 15:31:23.000000000","message":"What is the meaning of each option? What\u0027s the difference e.g. between subscribe and psubscrieb?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":110,"context_line":"data:"},{"line_number":111,"context_line":"   The message data. With [un]subscribe messages,"},{"line_number":112,"context_line":"   this value will be the number of channels and patterns the connection is currently subscribed to."},{"line_number":113,"context_line":"   With [p]message messages, this value will be the actual published message."},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"Special Notice:"},{"line_number":116,"context_line":"This message is only processed by driver.."}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_86bac06c","line":113,"updated":"2016-02-22 15:31:23.000000000","message":"Where does the driver filter messages by topic?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":114,"context_line":""},{"line_number":115,"context_line":"Special Notice:"},{"line_number":116,"context_line":"This message is only processed by driver.."},{"line_number":117,"context_line":"Message data  will be decoded by driver and send into queue.."},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Subscribe Thread For Reading Messages"},{"line_number":120,"context_line":"-------------------------------------"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_d41c7515","line":117,"range":{"start_line":117,"start_character":12,"end_line":117,"end_character":14},"updated":"2016-02-22 12:32:32.000000000","message":"two spaces to one","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":119,"context_line":"Subscribe Thread For Reading Messages"},{"line_number":120,"context_line":"-------------------------------------"},{"line_number":121,"context_line":"The subscribe thread is in charge of receiving the notifications and sending"},{"line_number":122,"context_line":"them back to the controller.Realization is based on andymccurdy lib."},{"line_number":123,"context_line":""},{"line_number":124,"context_line":"The subscribe thread loop is depicted in the following diagram:"},{"line_number":125,"context_line":""}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_94e14d01","line":122,"range":{"start_line":122,"start_character":17,"end_line":122,"end_character":39},"updated":"2016-02-22 12:32:32.000000000","message":"add space hre","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":127,"context_line":"                                                                           +---------------+"},{"line_number":128,"context_line":"                                                                           |               |"},{"line_number":129,"context_line":"                                                                           |   Process     |"},{"line_number":130,"context_line":"      +-----------------+                       +-----------------+fuc call|   Function1   |"},{"line_number":131,"context_line":"      |                 |                       |                 +--------\u003e               |"},{"line_number":132,"context_line":"      | Subscribe Thread|                       | Message Dispatch|        +---------------+"},{"line_number":133,"context_line":"      |                 |                       |                 |"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_14eeddeb","line":130,"range":{"start_line":130,"start_character":67,"end_line":130,"end_character":70},"updated":"2016-02-22 12:32:32.000000000","message":"typo","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":149,"context_line":"Realization Example:"},{"line_number":150,"context_line":"while True:"},{"line_number":151,"context_line":"  for message in p.listen():"},{"line_number":152,"context_line":"  # classify the message channel content,send to different message queue for channel"},{"line_number":153,"context_line":""},{"line_number":154,"context_line":"Special Notice:"},{"line_number":155,"context_line":"Not only three Process Functions."}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_94b82de7","line":152,"range":{"start_line":152,"start_character":33,"end_line":152,"end_character":45},"updated":"2016-02-22 12:32:32.000000000","message":"add space","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":161,"context_line":"--------------------"},{"line_number":162,"context_line":"This resubscription should be done only when connection to DB server is recovered."},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"driver only does connection fix,throw exception when connection is recovered,driver will clear all subscription"},{"line_number":165,"context_line":"and user of Subscription do resubscribe."},{"line_number":166,"context_line":""},{"line_number":167,"context_line":"Connection Setup"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_b4ac51a1","line":164,"range":{"start_line":164,"start_character":67,"end_line":164,"end_character":84},"updated":"2016-02-22 12:32:32.000000000","message":"need space","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":166,"context_line":""},{"line_number":167,"context_line":"Connection Setup"},{"line_number":168,"context_line":"-----------------"},{"line_number":169,"context_line":"When driver is initialized,will connect to all db nodes for read/write/get/modify operation."},{"line_number":170,"context_line":"But for pub/sub,driver will connect to one db node for one pub or one sub."},{"line_number":171,"context_line":"Driver guarantee connections for pub/sub will be scattered among db nodes."},{"line_number":172,"context_line":""}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_f47d391d","line":169,"range":{"start_line":169,"start_character":15,"end_line":169,"end_character":31},"updated":"2016-02-22 12:32:32.000000000","message":"no space\nmay be use it here like \", it will connect\"","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":167,"context_line":"Connection Setup"},{"line_number":168,"context_line":"-----------------"},{"line_number":169,"context_line":"When driver is initialized,will connect to all db nodes for read/write/get/modify operation."},{"line_number":170,"context_line":"But for pub/sub,driver will connect to one db node for one pub or one sub."},{"line_number":171,"context_line":"Driver guarantee connections for pub/sub will be scattered among db nodes."},{"line_number":172,"context_line":""},{"line_number":173,"context_line":""}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_461c3877","line":170,"range":{"start_line":170,"start_character":39,"end_line":170,"end_character":50},"updated":"2016-02-22 15:31:23.000000000","message":"I think this is different than the current behaviour of other drivers (zmq). It connects to all publishers. This helps with reliability. Consider changing.","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":167,"context_line":"Connection Setup"},{"line_number":168,"context_line":"-----------------"},{"line_number":169,"context_line":"When driver is initialized,will connect to all db nodes for read/write/get/modify operation."},{"line_number":170,"context_line":"But for pub/sub,driver will connect to one db node for one pub or one sub."},{"line_number":171,"context_line":"Driver guarantee connections for pub/sub will be scattered among db nodes."},{"line_number":172,"context_line":""},{"line_number":173,"context_line":""}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_14737d4e","line":170,"range":{"start_line":170,"start_character":12,"end_line":170,"end_character":22},"updated":"2016-02-22 12:32:32.000000000","message":"no space","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":173,"context_line":""},{"line_number":174,"context_line":"Exception"},{"line_number":175,"context_line":"---------"},{"line_number":176,"context_line":"First Notice:exception of cluster client and single client are different,need processed separately."},{"line_number":177,"context_line":"case1:populate db failed"},{"line_number":178,"context_line":"If add operation is failed,driver will delete what you add,"},{"line_number":179,"context_line":"driver will check connection and reconnect if reason is connection lost,"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_d478f52d","line":176,"range":{"start_line":176,"start_character":63,"end_line":176,"end_character":77},"updated":"2016-02-22 12:32:32.000000000","message":"no space","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":175,"context_line":"---------"},{"line_number":176,"context_line":"First Notice:exception of cluster client and single client are different,need processed separately."},{"line_number":177,"context_line":"case1:populate db failed"},{"line_number":178,"context_line":"If add operation is failed,driver will delete what you add,"},{"line_number":179,"context_line":"driver will check connection and reconnect if reason is connection lost,"},{"line_number":180,"context_line":"driver will try several times( for example 3),if all trials failed,"},{"line_number":181,"context_line":"driver will return failed,if reason is not connection"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_b49a9161","line":178,"range":{"start_line":178,"start_character":20,"end_line":178,"end_character":33},"updated":"2016-02-22 12:32:32.000000000","message":"again","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":177,"context_line":"case1:populate db failed"},{"line_number":178,"context_line":"If add operation is failed,driver will delete what you add,"},{"line_number":179,"context_line":"driver will check connection and reconnect if reason is connection lost,"},{"line_number":180,"context_line":"driver will try several times( for example 3),if all trials failed,"},{"line_number":181,"context_line":"driver will return failed,if reason is not connection"},{"line_number":182,"context_line":"problem,driver will also return failed directly.You should return failed to up level,"},{"line_number":183,"context_line":"do not publish,if driver returned failed."}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_14aa5d70","line":180,"range":{"start_line":180,"start_character":45,"end_line":180,"end_character":48},"updated":"2016-02-22 12:32:32.000000000","message":"again","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":178,"context_line":"If add operation is failed,driver will delete what you add,"},{"line_number":179,"context_line":"driver will check connection and reconnect if reason is connection lost,"},{"line_number":180,"context_line":"driver will try several times( for example 3),if all trials failed,"},{"line_number":181,"context_line":"driver will return failed,if reason is not connection"},{"line_number":182,"context_line":"problem,driver will also return failed directly.You should return failed to up level,"},{"line_number":183,"context_line":"do not publish,if driver returned failed."},{"line_number":184,"context_line":""}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_f4cb7951","line":181,"range":{"start_line":181,"start_character":19,"end_line":181,"end_character":28},"updated":"2016-02-22 12:32:32.000000000","message":"again","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":179,"context_line":"driver will check connection and reconnect if reason is connection lost,"},{"line_number":180,"context_line":"driver will try several times( for example 3),if all trials failed,"},{"line_number":181,"context_line":"driver will return failed,if reason is not connection"},{"line_number":182,"context_line":"problem,driver will also return failed directly.You should return failed to up level,"},{"line_number":183,"context_line":"do not publish,if driver returned failed."},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"If delete operation is failed,the process is same as above,"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_d4c63548","line":182,"range":{"start_line":182,"start_character":39,"end_line":182,"end_character":51},"updated":"2016-02-22 12:32:32.000000000","message":"again","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":180,"context_line":"driver will try several times( for example 3),if all trials failed,"},{"line_number":181,"context_line":"driver will return failed,if reason is not connection"},{"line_number":182,"context_line":"problem,driver will also return failed directly.You should return failed to up level,"},{"line_number":183,"context_line":"do not publish,if driver returned failed."},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"If delete operation is failed,the process is same as above,"},{"line_number":186,"context_line":"except for driver will not rollback delete operation."}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_b4e8d1b5","line":183,"range":{"start_line":183,"start_character":7,"end_line":183,"end_character":17},"updated":"2016-02-22 12:32:32.000000000","message":"same here","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":182,"context_line":"problem,driver will also return failed directly.You should return failed to up level,"},{"line_number":183,"context_line":"do not publish,if driver returned failed."},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"If delete operation is failed,the process is same as above,"},{"line_number":186,"context_line":"except for driver will not rollback delete operation."},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"case2:publish failed"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_d4cd955e","line":185,"range":{"start_line":185,"start_character":23,"end_line":185,"end_character":33},"updated":"2016-02-22 12:32:32.000000000","message":"same here","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":18903,"name":"Yuli","email":"stremovsky@gmail.com","username":"yuli"},"change_message_id":"ea89fc1083dab997fdd01f0543aaff69ba86be4c","unresolved":false,"context_lines":[{"line_number":188,"context_line":"case2:publish failed"},{"line_number":189,"context_line":"If this happened,"},{"line_number":190,"context_line":"driver will return failed and check connection also reconnect if reason is connection lost."},{"line_number":191,"context_line":"If driver return failed,user of API should undo what you done before publish and return failed"},{"line_number":192,"context_line":"to up level"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"case3:subscribe failed"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_b4ff3166","line":191,"range":{"start_line":191,"start_character":17,"end_line":191,"end_character":28},"updated":"2016-02-22 12:32:32.000000000","message":"no space","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":201,"context_line":"Driver will clear all subscription and then try reconnect,"},{"line_number":202,"context_line":"after fix connection then send a message to subscriber, tell that you subscribed is recovered,,"},{"line_number":203,"context_line":"subscriber should get data from DB, according to what it subscribed."},{"line_number":204,"context_line":"if subscriber get data from DB failed,may be can write dummy flow"},{"line_number":205,"context_line":"to ovs,avoiding wrong packet path and waiting for packet in process to fix packet path."},{"line_number":206,"context_line":"This may not so efficient, but it can fix the data consistent problem."},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"References"},{"line_number":209,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":10,"id":"bae84128_493bab9c","line":206,"range":{"start_line":204,"start_character":0,"end_line":206,"end_character":70},"updated":"2016-02-22 15:31:23.000000000","message":"This isn\u0027t specific to redis. How is it handled today?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"b3bc0274d7a597a541d79f9ece0132b6bdb04bf9","unresolved":false,"context_lines":[{"line_number":26,"context_line":"As dragonflow already has a class for DB API,"},{"line_number":27,"context_line":"here we just need to overwrite those APIs already existed,"},{"line_number":28,"context_line":"and add new APIS for the Publish/Subscribe, based on andymccurdy lib."},{"line_number":29,"context_line":"https://github.com/andymccurdy/redis-py"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"Populating a Database API"},{"line_number":32,"context_line":"-------------------------"}],"source_content_type":"text/x-rst","patch_set":17,"id":"9aed3d3a_588a3c1c","line":29,"range":{"start_line":29,"start_character":0,"end_line":29,"end_character":39},"updated":"2016-02-29 07:48:08.000000000","message":"Please add it as a reference and mark it here as [x]","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"5bf2edea3c01c3c8b32e94785437924834e70eb9","unresolved":false,"context_lines":[{"line_number":26,"context_line":"As dragonflow already has a class for DB API,"},{"line_number":27,"context_line":"here we just need to overwrite those APIs already existed,"},{"line_number":28,"context_line":"and add new APIS for the Publish/Subscribe, based on andymccurdy lib."},{"line_number":29,"context_line":"https://github.com/andymccurdy/redis-py"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"Populating a Database API"},{"line_number":32,"context_line":"-------------------------"}],"source_content_type":"text/x-rst","patch_set":18,"id":"9aed3d3a_79329060","line":29,"range":{"start_line":29,"start_character":0,"end_line":29,"end_character":39},"updated":"2016-02-29 14:23:27.000000000","message":"Please number your references and list it here as [2]","commit_id":"03de23aff0423436b5e03f6aa56c8f5a74c6b3f3"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"5bf2edea3c01c3c8b32e94785437924834e70eb9","unresolved":false,"context_lines":[{"line_number":60,"context_line":"-----------"},{"line_number":61,"context_line":"The new API realizes publish function with channel, based on andymccurdy lib"},{"line_number":62,"context_line":"The following diagram shows how Neutron config changes are published to all local controllers."},{"line_number":63,"context_line":"It is only a example."},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"+---------------+"},{"line_number":66,"context_line":"|               |                                          +-----------------+"}],"source_content_type":"text/x-rst","patch_set":18,"id":"9aed3d3a_799c500f","line":63,"range":{"start_line":63,"start_character":13,"end_line":63,"end_character":20},"updated":"2016-02-29 14:23:27.000000000","message":"Here as well same as for the DB we have a PubSub API class that should be extended by drivers \n\nPlease add it as a reference","commit_id":"03de23aff0423436b5e03f6aa56c8f5a74c6b3f3"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"5bf2edea3c01c3c8b32e94785437924834e70eb9","unresolved":false,"context_lines":[{"line_number":117,"context_line":"This message is only processed by driver."},{"line_number":118,"context_line":"Message data will be decoded by driver and send into queue.."},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"Subscribe Thread For Reading Messages"},{"line_number":121,"context_line":"-------------------------------------"},{"line_number":122,"context_line":"The subscribe thread is in charge of receiving the notifications and sending"},{"line_number":123,"context_line":"them back to the controller. Realization is based on andymccurdy lib."},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"The subscribe thread loop is depicted in the following diagram:"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"                                                                           +---------------+"},{"line_number":129,"context_line":"                                                                           |               |"},{"line_number":130,"context_line":"                                                                           |   Process     |"},{"line_number":131,"context_line":"      +-----------------+                       +-----------------+fun call|   Function1   |"},{"line_number":132,"context_line":"      |                 |                       |                 +--------\u003e               |"},{"line_number":133,"context_line":"      | Subscribe Thread|                       | Message Dispatch|        +---------------+"},{"line_number":134,"context_line":"      |                 |                       |                 |"},{"line_number":135,"context_line":"      |Wait For Message |                       |                 |"},{"line_number":136,"context_line":"      |                 |                       | Read Message    |         +----------------+"},{"line_number":137,"context_line":"      |                 | Send into Queue       | From Queue      |fun call |   Process      |"},{"line_number":138,"context_line":"      | New Message     +-----------------------\u003e                 +--------\u003e|   Function2    |"},{"line_number":139,"context_line":"      |                 |                       | Dispatch Message|         |                |"},{"line_number":140,"context_line":"      |                 |                       |                 |         +----------------+"},{"line_number":141,"context_line":"      |                 |                       |                 |"},{"line_number":142,"context_line":"      |                 |                       |                 |"},{"line_number":143,"context_line":"      |                 |                       |                 |         +---------------+"},{"line_number":144,"context_line":"      |                 |                       |                 | fun call|  Process      |"},{"line_number":145,"context_line":"      |                 |                       |                 +---------\u003e  Function3    |"},{"line_number":146,"context_line":"      |                 |                       |                 |         |               |"},{"line_number":147,"context_line":"      +-----------------+                       +-----------------+         |               |"},{"line_number":148,"context_line":"                                                                            +---------------+"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"Realization Example:"},{"line_number":151,"context_line":"while True:"},{"line_number":152,"context_line":"  for message in p.listen():"},{"line_number":153,"context_line":"  # classify the message channel content, send to different message queue for channel"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"Special Notice:"},{"line_number":156,"context_line":"Not only three Process Functions."},{"line_number":157,"context_line":"Driver Subscriber thread is only one thread to do message dispatch according to channel."},{"line_number":158,"context_line":"listen() is a generator that blocks until a message is available."},{"line_number":159,"context_line":""},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"Subscriber managment"}],"source_content_type":"text/x-rst","patch_set":18,"id":"9aed3d3a_1961c405","line":158,"range":{"start_line":120,"start_character":0,"end_line":158,"end_character":53},"updated":"2016-02-29 14:23:27.000000000","message":"This is already covered in the pubsub spec just add it as reference","commit_id":"03de23aff0423436b5e03f6aa56c8f5a74c6b3f3"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"5bf2edea3c01c3c8b32e94785437924834e70eb9","unresolved":false,"context_lines":[{"line_number":209,"context_line":"References"},{"line_number":210,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"http://redis.io/commands"},{"line_number":213,"context_line":"https://github.com/andymccurdy/redis-py"},{"line_number":214,"context_line":"https://github.com/Grokzen/redis-py-cluster"}],"source_content_type":"text/x-rst","patch_set":18,"id":"9aed3d3a_d958fc8c","line":212,"updated":"2016-02-29 14:23:27.000000000","message":"please add numbers [1] [2] [3]","commit_id":"03de23aff0423436b5e03f6aa56c8f5a74c6b3f3"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8469abbd4adbd4144154b94769e09b02cd1cebff","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    |                  |            |                |"},{"line_number":53,"context_line":"    +------------------+            +----------------+"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":""},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"Publish API"}],"source_content_type":"text/x-rst","patch_set":19,"id":"7af24918_3cad0d89","line":55,"updated":"2016-03-06 08:42:18.000000000","message":"Please elaborate on Redis\u0027 cluster. Explain the issue with keys, slots, and cluster node master members.\n\nAn external link is also sufficient, e.g. http://redis.io/topics/cluster-tutorial.","commit_id":"1d102cf696f9fbb7d04bb81f480d85fd7de0ea69"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8469abbd4adbd4144154b94769e09b02cd1cebff","unresolved":false,"context_lines":[{"line_number":80,"context_line":"p \u003d r.pubsub()"},{"line_number":81,"context_line":"r.publish(\u0027my-first-channel\u0027, \u0027some data\u0027)/* my-first-channel is channel name,"},{"line_number":82,"context_line":"                                          some data is what you want to publish */"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"Special Notice:"},{"line_number":85,"context_line":"\u0027Some data\u0027 will be coded into json pattern.."},{"line_number":86,"context_line":""}],"source_content_type":"text/x-rst","patch_set":19,"id":"7af24918_3c76ad3e","line":83,"updated":"2016-03-06 08:42:18.000000000","message":"Please add more detail as to how the publisher works. I understand a cluster member is selected at random, and it propagates the event within the cluster, and thus to all subscribers?","commit_id":"1d102cf696f9fbb7d04bb81f480d85fd7de0ea69"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8469abbd4adbd4144154b94769e09b02cd1cebff","unresolved":false,"context_lines":[{"line_number":103,"context_line":"{\u0027channel\u0027: \u0027my-first-channel\u0027, \u0027data\u0027: \u0027some data\u0027, \u0027pattern\u0027: None, \u0027type\u0027: \u0027message\u0027}"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"type: One of the following: \u0027subscribe\u0027, \u0027unsubscribe\u0027, \u0027psubscribe\u0027, \u0027punsubscribe\u0027,"},{"line_number":106,"context_line":"                           \u0027message\u0027, \u0027pmessage\u0027"},{"line_number":107,"context_line":"channel: The channel [un]subscribed to or the channel a message was published to"},{"line_number":108,"context_line":"pattern: The pattern that matched a published message\u0027s channel."},{"line_number":109,"context_line":"         Will be None in all cases except for \u0027pmessage\u0027 types."}],"source_content_type":"text/x-rst","patch_set":19,"id":"7af24918_1c73f14e","line":106,"updated":"2016-03-06 08:42:18.000000000","message":"What is the meaning of each type? What\u0027s the difference between a type and its p-version?","commit_id":"1d102cf696f9fbb7d04bb81f480d85fd7de0ea69"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8469abbd4adbd4144154b94769e09b02cd1cebff","unresolved":false,"context_lines":[{"line_number":203,"context_line":"subscriber should get data from DB, according to what it subscribed."},{"line_number":204,"context_line":"if subscriber get data from DB failed,may be can write dummy flow"},{"line_number":205,"context_line":"to ovs,avoiding wrong packet path and waiting for packet in process to fix packet path."},{"line_number":206,"context_line":"This may not so efficient, but it can fix the data consistent problem."},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"References"},{"line_number":209,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":19,"id":"7af24918_5c93b94f","line":206,"updated":"2016-03-06 08:42:18.000000000","message":"Is this solution specific to Redis? How is it different than what we have today?","commit_id":"1d102cf696f9fbb7d04bb81f480d85fd7de0ea69"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"dbdff9aefc19d723e3e8c26c7a33e25a0d553669","unresolved":false,"context_lines":[{"line_number":205,"context_line":"Driver will clear all subscription and then try reconnect,"},{"line_number":206,"context_line":"after fix connection then send a message to subscriber, tell that you subscribed is recovered,,"},{"line_number":207,"context_line":"subscriber should get data from DB, according to what it subscribed."},{"line_number":208,"context_line":"if subscriber get data from DB failed,may be can write dummy flow"},{"line_number":209,"context_line":"to ovs,avoiding wrong packet path and waiting for packet in process to fix packet path."},{"line_number":210,"context_line":"This may not so efficient, but it can fix the data consistent problem."},{"line_number":211,"context_line":""}],"source_content_type":"text/x-rst","patch_set":25,"id":"5aef4532_9c216fa2","line":208,"range":{"start_line":208,"start_character":38,"end_line":208,"end_character":60},"updated":"2016-03-09 05:24:02.000000000","message":"If there are alternatives, please list them as such. (That should also make the text clear enough to answer my next comment.)","commit_id":"325c5b11e1edadaca0572f5cb458f837f78235d5"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"dbdff9aefc19d723e3e8c26c7a33e25a0d553669","unresolved":false,"context_lines":[{"line_number":207,"context_line":"subscriber should get data from DB, according to what it subscribed."},{"line_number":208,"context_line":"if subscriber get data from DB failed,may be can write dummy flow"},{"line_number":209,"context_line":"to ovs,avoiding wrong packet path and waiting for packet in process to fix packet path."},{"line_number":210,"context_line":"This may not so efficient, but it can fix the data consistent problem."},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"References"},{"line_number":213,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":25,"id":"5aef4532_3c03fb0e","line":210,"updated":"2016-03-09 05:24:02.000000000","message":"I think this part is still incomplete. Please comment or add some content: Is this solution specific to Redis? How is it different from what we have today?","commit_id":"325c5b11e1edadaca0572f5cb458f837f78235d5"}],"dragonflow/db/drivers/redis_calckey.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":51,"context_line":"\r"},{"line_number":52,"context_line":"RedisClusterHashSlots \u003d 16384\r"},{"line_number":53,"context_line":"\r"},{"line_number":54,"context_line":"def crc16(data):\r"},{"line_number":55,"context_line":"    crc \u003d 0\r"},{"line_number":56,"context_line":"    for byte in data.encode(\"utf-8\"):\r"},{"line_number":57,"context_line":"        crc \u003d ((crc \u003c\u003c 8) \u0026 0xff00) ^ XMODEMCRC16Lookup[((crc \u003e\u003e 8) \u0026 0xff) ^ ord(byte)]\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_29caa76d","line":54,"updated":"2016-02-22 15:31:23.000000000","message":"Why not use an existing python crc library?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"}],"dragonflow/db/drivers/redis_db_driver.py":[{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"3bc90274cc4f5b76c03f1fff07348c59359a7a70","unresolved":false,"context_lines":[{"line_number":67,"context_line":"            return res\r"},{"line_number":68,"context_line":"        except Exception, exception:\r"},{"line_number":69,"context_line":"            raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)\r"},{"line_number":70,"context_line":"            \r"},{"line_number":71,"context_line":"    def create_key(self, table, key, value,topic\u003dNone):\r"},{"line_number":72,"context_line":"        local_key \u003d (\u0027{\u0027+table + \u0027.\u0027 + topic + \u0027}\u0027 + \u0027.\u0027+key)\r"},{"line_number":73,"context_line":"        try:\r"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_20821fc9","line":70,"updated":"2016-02-19 05:22:38.000000000","message":"pls remove it.","commit_id":"db050f4d6a743d8fd41524e6439754ecb2d6c15e"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"3bc90274cc4f5b76c03f1fff07348c59359a7a70","unresolved":false,"context_lines":[{"line_number":125,"context_line":"                redis.exceptions.BusyLoadingError):\r"},{"line_number":126,"context_line":"            return False\r"},{"line_number":127,"context_line":"        return True\r"},{"line_number":128,"context_line":"        \r"},{"line_number":129,"context_line":"    def register_topic_for_notification(self, topic):\r"},{"line_number":130,"context_line":"        # TODO(gsagie) implement this\r"},{"line_number":131,"context_line":"        pass\r"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_00871bd8","line":128,"updated":"2016-02-19 05:22:38.000000000","message":"ditto","commit_id":"db050f4d6a743d8fd41524e6439754ecb2d6c15e"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":27,"context_line":"        self.client \u003d []\r"},{"line_number":28,"context_line":"        self.remote \u003d []\r"},{"line_number":29,"context_line":"# need realize connection to DBcluster,record DB Cluster Slot\r"},{"line_number":30,"context_line":"    redis_mgt \u003d RedisMgt()\r"},{"line_number":31,"context_line":"    def initialize(self, db_ip, db_port, **args):\r"},{"line_number":32,"context_line":"        # get remote ip port list\r"},{"line_number":33,"context_line":"        self.redis_mgt.init_default_node(db_ip, db_port)\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_451feeb6","line":30,"range":{"start_line":30,"start_character":4,"end_line":30,"end_character":13},"updated":"2016-02-23 12:53:41.000000000","message":"1) please put static members  at the start of class definition\n2）why use static member?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    redis_mgt \u003d RedisMgt()\r"},{"line_number":31,"context_line":"    def initialize(self, db_ip, db_port, **args):\r"},{"line_number":32,"context_line":"        # get remote ip port list\r"},{"line_number":33,"context_line":"        self.redis_mgt.init_default_node(db_ip, db_port)\r"},{"line_number":34,"context_line":"        self.redis_mgt.get_cluster_topology()\r"},{"line_number":35,"context_line":"        self.remote \u003d self.redis_mgt.get_master_list()\r"},{"line_number":36,"context_line":"        for i in range(len(self.remote)):\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_09d8831c","line":33,"range":{"start_line":33,"start_character":0,"end_line":33,"end_character":56},"updated":"2016-02-22 15:31:23.000000000","message":"You have set redis_mgt to be a static member, yet you access it here via self. Is this by design?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        self.remote \u003d self.redis_mgt.get_master_list()\r"},{"line_number":36,"context_line":"        for i in range(len(self.remote)):\r"},{"line_number":37,"context_line":"            ip_port \u003d self.remote[i][\u0027ip_port\u0027].split(\u0027:\u0027)\r"},{"line_number":38,"context_line":"            self.client.append(redis.client.StrictRedis(host\u003dip_port[0],port\u003dip_port[1])\r"},{"line_number":39,"context_line":"\r"},{"line_number":40,"context_line":"    @staticmethod\r"},{"line_number":41,"context_line":"    def get_redis_mgt():\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_fb0e8f8a","line":38,"range":{"start_line":38,"start_character":24,"end_line":38,"end_character":30},"updated":"2016-02-23 12:53:41.000000000","message":"What will you do, if one of the db node goes down?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":39,"context_line":"\r"},{"line_number":40,"context_line":"    @staticmethod\r"},{"line_number":41,"context_line":"    def get_redis_mgt():\r"},{"line_number":42,"context_line":"        return redis_mgt\r"},{"line_number":43,"context_line":"\r"},{"line_number":44,"context_line":"    def support_publish_subscribe(self):\r"},{"line_number":45,"context_line":"        return True\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_e9d27fff","line":42,"range":{"start_line":42,"start_character":0,"end_line":42,"end_character":24},"updated":"2016-02-22 15:31:23.000000000","message":"Why is redis_mgt a static member?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":45,"context_line":"        return True\r"},{"line_number":46,"context_line":"\r"},{"line_number":47,"context_line":"    def get_index_from_ip_port(self,ip_port):\r"},{"line_number":48,"context_line":"        i \u003d 0\r"},{"line_number":49,"context_line":"        for i in range(len(self.remote)):\r"},{"line_number":50,"context_line":"            if self.remote[i][\u0027ip_port\u0027] \u003d\u003d ip_port:\r"},{"line_number":51,"context_line":"                return i\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_d140dc36","line":48,"range":{"start_line":48,"start_character":7,"end_line":48,"end_character":13},"updated":"2016-02-23 12:53:41.000000000","message":"redundant statement.","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":53,"context_line":"\r"},{"line_number":54,"context_line":"    # return nil is not found\r"},{"line_number":55,"context_line":"    def get_key(self, table, key,topic\u003dNone):\r"},{"line_number":56,"context_line":"        if topic is None:\r"},{"line_number":57,"context_line":"            local_key \u003d (\u0027{\u0027+table + \u0027.\u0027 + \u0027*\u0027 + \u0027}\u0027 + \u0027.\u0027+key)\r"},{"line_number":58,"context_line":"        else:\r"},{"line_number":59,"context_line":"            local_key \u003d (\u0027{\u0027+table + \u0027.\u0027 + topic + \u0027}\u0027 + \u0027.\u0027+key)\r"},{"line_number":60,"context_line":"        try:\r"},{"line_number":61,"context_line":"            ip_port \u003d self.redis_mgt.assign_to_node(local_key)\r"},{"line_number":62,"context_line":"            i \u003d self.get_index_from_ip_port(ip_port)\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_6f7aeff2","line":59,"range":{"start_line":56,"start_character":0,"end_line":59,"end_character":65},"updated":"2016-02-22 15:31:23.000000000","message":"This code repeats a lot. Consider moving to a method.","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":64,"context_line":"                raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)\r"},{"line_number":65,"context_line":"            return self.client[i].get(local_key)\r"},{"line_number":66,"context_line":"        except Exception, exception:\r"},{"line_number":67,"context_line":"            raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)\r"},{"line_number":68,"context_line":"\r"},{"line_number":69,"context_line":"    def set_key(self, table, key, value,topic\u003dNone):\r"},{"line_number":70,"context_line":"        if topic is None:\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_bb1ec76d","line":67,"range":{"start_line":67,"start_character":46,"end_line":67,"end_character":49},"updated":"2016-02-23 12:53:41.000000000","message":"Log the original exception for debug easily.","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":68,"context_line":"\r"},{"line_number":69,"context_line":"    def set_key(self, table, key, value,topic\u003dNone):\r"},{"line_number":70,"context_line":"        if topic is None:\r"},{"line_number":71,"context_line":"            local_key \u003d (\u0027{\u0027+table + \u0027.\u0027 + \u0027*\u0027 + \u0027}\u0027 + \u0027.\u0027+key)\r"},{"line_number":72,"context_line":"        else:\r"},{"line_number":73,"context_line":"            local_key \u003d (\u0027{\u0027+table + \u0027.\u0027 + topic + \u0027}\u0027 + \u0027.\u0027+key)\r"},{"line_number":74,"context_line":"        try:\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_46124258","line":71,"range":{"start_line":71,"start_character":12,"end_line":71,"end_character":63},"updated":"2016-02-23 12:53:41.000000000","message":"when set key, can the topic be none?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":85,"context_line":"            \r"},{"line_number":86,"context_line":"    def create_key(self, table, key, value,topic\u003dNone):\r"},{"line_number":87,"context_line":"        if topic is None:\r"},{"line_number":88,"context_line":"            local_key \u003d (\u0027{\u0027+table + \u0027.\u0027 + \u0027*\u0027 + \u0027}\u0027 + \u0027.\u0027+key)\r"},{"line_number":89,"context_line":"        else:\r"},{"line_number":90,"context_line":"            local_key \u003d (\u0027{\u0027+table + \u0027.\u0027 + topic + \u0027}\u0027 + \u0027.\u0027+key)\r"},{"line_number":91,"context_line":"        try:\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_e64ef66d","line":88,"range":{"start_line":88,"start_character":27,"end_line":88,"end_character":49},"updated":"2016-02-23 12:53:41.000000000","message":"topic here shouldn\u0027t be none.","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":120,"context_line":"        else:\r"},{"line_number":121,"context_line":"            local_key \u003d (\u0027{\u0027+table + \u0027.\u0027 + topic + \u0027}\u0027 + \u0027.\u0027+\u0027*\u0027)\r"},{"line_number":122,"context_line":"        try:\r"},{"line_number":123,"context_line":"            ip_port \u003d self.redis_mgt.assign_to_node(local_key)\r"},{"line_number":124,"context_line":"            i \u003d self.get_index_from_ip_port(ip_port)\r"},{"line_number":125,"context_line":"            if i is None:\r"},{"line_number":126,"context_line":"                raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)\r"},{"line_number":127,"context_line":"            return self.client[i].get(local_key)\r"},{"line_number":128,"context_line":"        except Exception, exception:\r"},{"line_number":129,"context_line":"             raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)\r"},{"line_number":130,"context_line":"\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_ccd7c9bd","line":127,"range":{"start_line":123,"start_character":0,"end_line":127,"end_character":48},"updated":"2016-02-22 15:31:23.000000000","message":"The code to find a client repeats many times. Consider moving to a method.\n\nAdditionally, it looks like you always select a client by IP. Consider keeping clients in a dictionary ip -\u003e client, rather than a list. It should make the code a bit clearer.","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"class RedisDbDriver(db_api.DbApi):"},{"line_number":24,"context_line":"    redis_mgt \u003d RedisMgt()"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    def __init__(self):"},{"line_number":27,"context_line":"        super(RedisDbDriver, self).__init__()"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_e4e07d2b","line":24,"updated":"2016-02-24 09:13:28.000000000","message":"Why is this member static?","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    def __init__(self):"},{"line_number":27,"context_line":"        super(RedisDbDriver, self).__init__()"},{"line_number":28,"context_line":"        self.client \u003d {}"},{"line_number":29,"context_line":"        self.remote \u003d []"},{"line_number":30,"context_line":"# need realize connection to DBcluster,record DB Cluster Slot"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"    def initialize(self, db_ip, db_port, **args):"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_64d3cd60","line":29,"range":{"start_line":28,"start_character":0,"end_line":29,"end_character":24},"updated":"2016-02-24 09:13:28.000000000","message":"Rename to plurals. (e.g. clients, remotes)","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":34,"context_line":"        RedisDbDriver.redis_mgt.init_default_node(db_ip, db_port)"},{"line_number":35,"context_line":"        RedisDbDriver.redis_mgt.get_cluster_topology()"},{"line_number":36,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.get_master_list()"},{"line_number":37,"context_line":"        for i in range(len(self.remote)):"},{"line_number":38,"context_line":"            ip_port \u003d self.remote[i][\u0027ip_port\u0027].split(\u0027:\u0027)"},{"line_number":39,"context_line":"            self.client[self.remote[i][\u0027ip_port\u0027]] \u003d \\"},{"line_number":40,"context_line":"                redis.client.StrictRedis(host\u003dip_port[0], port\u003dip_port[1])"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_c449f932","line":37,"updated":"2016-02-24 09:13:28.000000000","message":"Since i is used only to index self.remote, consider changing for loop to:\n    for remote in self.remote:\nand change references self.remote[i] -\u003e remote.\n\nThis pattern here a few times.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    @staticmethod"},{"line_number":43,"context_line":"    def get_redis_mgt():"},{"line_number":44,"context_line":"        return RedisDbDriver.redis_mgt"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def support_publish_subscribe(self):"},{"line_number":47,"context_line":"        return True"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_a4b5d57e","line":44,"updated":"2016-02-24 09:13:28.000000000","message":"This getter is sometimes used, and sometimes redis_mgt directly. I think it\u0027s redundant.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":47,"context_line":"        return True"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    # return nil is not found"},{"line_number":50,"context_line":"    def get_key(self, table, key, topic\u003dNone):"},{"line_number":51,"context_line":"        if topic is None:"},{"line_number":52,"context_line":"            res \u003d []"},{"line_number":53,"context_line":"            local_key \u003d self.uuid_to_key(table, key, \u0027*\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_04ec81f1","line":50,"updated":"2016-02-24 09:13:28.000000000","message":"The logic in this method appears very similar in both cases. Consider uniting.\n\nAdditionally, topic can be set to a default by:\n    topic \u003d topic if topic else \u0027*\u0027","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":66,"context_line":"            local_key \u003d self.uuid_to_key(table, key, topic)"},{"line_number":67,"context_line":"            try:"},{"line_number":68,"context_line":"                ip_port \u003d RedisDbDriver.redis_mgt.get_node_by_key(local_key)"},{"line_number":69,"context_line":"                if self.client[ip_port] is None:"},{"line_number":70,"context_line":"                    raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)"},{"line_number":71,"context_line":"                return self.client[ip_port].get(local_key)"},{"line_number":72,"context_line":"            except Exception as e:"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_04d641f0","line":69,"updated":"2016-02-24 09:13:28.000000000","message":"If I understand the code correctly, if this condition is ever true, it will raise a KeyError.\n\nIf you really need this sort of test, use:\n    if ip_port in self.client:\n\nIn any case, I think this test can be waived.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":70,"context_line":"                    raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)"},{"line_number":71,"context_line":"                return self.client[ip_port].get(local_key)"},{"line_number":72,"context_line":"            except Exception as e:"},{"line_number":73,"context_line":"                LOG.erro(\"exception %s keys %s\" % e % local_key)"},{"line_number":74,"context_line":"                raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def set_key(self, table, key, value, topic\u003dNone):"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_2420a5f6","line":73,"updated":"2016-02-24 09:13:28.000000000","message":"Typo - error.\nExcept clause still hides original exception.\nExcept clause catches exception from line 70, and raises a different exception of same type.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":84,"context_line":"                self.client[ip_port].delete(local_key)"},{"line_number":85,"context_line":"            return res"},{"line_number":86,"context_line":"        except Exception as e:"},{"line_number":87,"context_line":"            LOG.erro(\"exception %s keys %s\" % e % local_key)"},{"line_number":88,"context_line":"            raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    def create_key(self, table, key, value, topic\u003dNone):"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_64662d2b","line":87,"updated":"2016-02-24 09:13:28.000000000","message":"See above re: type, exceptions, existence testing.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":90,"context_line":"    def create_key(self, table, key, value, topic\u003dNone):"},{"line_number":91,"context_line":"        local_key \u003d self.uuid_to_key(table, key, topic)"},{"line_number":92,"context_line":"        try:"},{"line_number":93,"context_line":"            ip_port \u003d RedisDbDriver.redis_mgt.get_node_by_key(local_key)"},{"line_number":94,"context_line":"            if self.client[ip_port] is None:"},{"line_number":95,"context_line":"                raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)"},{"line_number":96,"context_line":"            res \u003d self.client[ip_port].set(local_key, value)"},{"line_number":97,"context_line":"            if not res:"},{"line_number":98,"context_line":"                self.client[ip_port].delete(local_key)"},{"line_number":99,"context_line":"            return res"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_441e8970","line":96,"range":{"start_line":93,"start_character":0,"end_line":96,"end_character":60},"updated":"2016-02-24 09:13:28.000000000","message":"The code for selecting a client repeats many times. Should be moved to a method.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":98,"context_line":"                self.client[ip_port].delete(local_key)"},{"line_number":99,"context_line":"            return res"},{"line_number":100,"context_line":"        except Exception as e:"},{"line_number":101,"context_line":"            LOG.erro(\"exception %s keys %s\" % e % local_key)"},{"line_number":102,"context_line":"            raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    # return 0 means not found"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_047c81b3","line":101,"updated":"2016-02-24 09:13:28.000000000","message":"See above re: type, exceptions, existence testing.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":102,"context_line":"            raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    # return 0 means not found"},{"line_number":105,"context_line":"    def delete_key(self, table, key, topic\u003dNone):"},{"line_number":106,"context_line":"        if topic is None:"},{"line_number":107,"context_line":"            local_key \u003d self.uuid_to_key(table, key, \u0027*\u0027)"},{"line_number":108,"context_line":"            ip_port \u003d RedisDbDriver.redis_mgt.get_node_by_key(local_key)"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_777edd6a","line":105,"updated":"2016-02-24 09:13:28.000000000","message":"Same here re: similar logic if topic is None or not.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":157,"context_line":"    def uuid_to_key(self, table, key, topic):"},{"line_number":158,"context_line":"        if topic is None:"},{"line_number":159,"context_line":"            local_key \u003d (\u0027{\u0027 + table + \u0027.\u0027 + \u0027*\u0027 + \u0027}\u0027 + \u0027.\u0027 + key)"},{"line_number":160,"context_line":"            LOG.erro(\"keys %s\" % local_key)"},{"line_number":161,"context_line":"            raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)"},{"line_number":162,"context_line":"        else:"},{"line_number":163,"context_line":"            local_key \u003d (\u0027{\u0027 + table + \u0027.\u0027 + topic + \u0027}\u0027 + \u0027.\u0027 + key)"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_77f53deb","line":160,"updated":"2016-02-24 09:13:28.000000000","message":"This exception is always raised when topic is None.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"efd41756c2f6d923a241d73eb7d5b3c4052fc58c","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        # get remote ip port list"},{"line_number":33,"context_line":"        RedisDbDriver.redis_mgt.init_default_node(db_ip, db_port)"},{"line_number":34,"context_line":"        RedisDbDriver.redis_mgt.get_cluster_topology()"},{"line_number":35,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.get_master_list()"},{"line_number":36,"context_line":"        for i in range(len(self.remote)):"},{"line_number":37,"context_line":"            ip_port \u003d self.remote[i][\u0027ip_port\u0027].split(\u0027:\u0027)"},{"line_number":38,"context_line":"            self.client[self.remote[i][\u0027ip_port\u0027]] \u003d \\"}],"source_content_type":"text/x-python","patch_set":15,"id":"bae84128_04859a58","line":35,"range":{"start_line":35,"start_character":13,"end_line":35,"end_character":19},"updated":"2016-02-24 10:28:39.000000000","message":"it is a list, so I suggest to change its name to \u0027remote_server_list\u0027 or other similar name. \u0027remote\u0027 is a little bit ambiguous.","commit_id":"8d4c78d4008c7f40d72b9ea3aec4883567930449"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"efd41756c2f6d923a241d73eb7d5b3c4052fc58c","unresolved":false,"context_lines":[{"line_number":45,"context_line":"    def support_publish_subscribe(self):"},{"line_number":46,"context_line":"        return True"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    # return nil is not found"},{"line_number":49,"context_line":"    def get_key(self, table, key, topic\u003dNone):"},{"line_number":50,"context_line":"        if topic is None:"},{"line_number":51,"context_line":"            res \u003d []"}],"source_content_type":"text/x-python","patch_set":15,"id":"bae84128_641e260d","line":48,"range":{"start_line":48,"start_character":3,"end_line":48,"end_character":29},"updated":"2016-02-24 10:28:39.000000000","message":"put it to the right position, for example,\n\nif local_keys is None:\n    # return nil is not found","commit_id":"8d4c78d4008c7f40d72b9ea3aec4883567930449"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"efd41756c2f6d923a241d73eb7d5b3c4052fc58c","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    def get_key(self, table, key, topic\u003dNone):"},{"line_number":50,"context_line":"        if topic is None:"},{"line_number":51,"context_line":"            res \u003d []"},{"line_number":52,"context_line":"            local_key \u003d self.uuid_to_key(table, key, \u0027*\u0027)"},{"line_number":53,"context_line":"            try:"},{"line_number":54,"context_line":"                ip_port \u003d RedisDbDriver.redis_mgt.get_node_by_key(local_key)"},{"line_number":55,"context_line":"                local_keys \u003d self.client[ip_port].keys(local_key)"}],"source_content_type":"text/x-python","patch_set":15,"id":"bae84128_84988a79","line":52,"range":{"start_line":52,"start_character":54,"end_line":52,"end_character":55},"updated":"2016-02-24 10:28:39.000000000","message":"Could it be a constant, like FOR_ALL_KEYS?\nI don\u0027t like it that spreads every where.","commit_id":"8d4c78d4008c7f40d72b9ea3aec4883567930449"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"efd41756c2f6d923a241d73eb7d5b3c4052fc58c","unresolved":false,"context_lines":[{"line_number":100,"context_line":"            LOG.erro(\"exception %s keys %s\" % e % local_key)"},{"line_number":101,"context_line":"            raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"    # return 0 means not found"},{"line_number":104,"context_line":"    def delete_key(self, table, key, topic\u003dNone):"},{"line_number":105,"context_line":"        if topic is None:"},{"line_number":106,"context_line":"            local_key \u003d self.uuid_to_key(table, key, \u0027*\u0027)"}],"source_content_type":"text/x-python","patch_set":15,"id":"bae84128_a414aee8","line":103,"range":{"start_line":103,"start_character":2,"end_line":103,"end_character":30},"updated":"2016-02-24 10:28:39.000000000","message":"move to the right position.","commit_id":"8d4c78d4008c7f40d72b9ea3aec4883567930449"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"efd41756c2f6d923a241d73eb7d5b3c4052fc58c","unresolved":false,"context_lines":[{"line_number":121,"context_line":"                LOG.erro(\"exception %s keys %s\" % e % local_key)"},{"line_number":122,"context_line":"                raise df_exceptions.DBKeyNotFound(key\u003dlocal_key)"},{"line_number":123,"context_line":""},{"line_number":124,"context_line":"    # return nil is not found"},{"line_number":125,"context_line":"    def get_all_entries(self, table, topic\u003dNone):"},{"line_number":126,"context_line":"        res \u003d []"},{"line_number":127,"context_line":"        if topic is None:"}],"source_content_type":"text/x-python","patch_set":15,"id":"bae84128_24841e09","line":124,"updated":"2016-02-24 10:28:39.000000000","message":"ditto","commit_id":"8d4c78d4008c7f40d72b9ea3aec4883567930449"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"efd41756c2f6d923a241d73eb7d5b3c4052fc58c","unresolved":false,"context_lines":[{"line_number":149,"context_line":"    def allocate_unique_key(self):"},{"line_number":150,"context_line":"        pass"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"        # no need to realize"},{"line_number":153,"context_line":"    def register_notification_callback(self, callback, topics\u003dNone):"},{"line_number":154,"context_line":"        pass"},{"line_number":155,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"bae84128_440b227d","line":152,"range":{"start_line":152,"start_character":8,"end_line":152,"end_character":28},"updated":"2016-02-24 10:28:39.000000000","message":"suggest to put it into the function comment.","commit_id":"8d4c78d4008c7f40d72b9ea3aec4883567930449"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"efd41756c2f6d923a241d73eb7d5b3c4052fc58c","unresolved":false,"context_lines":[{"line_number":162,"context_line":"            local_key \u003d (\u0027{\u0027 + table + \u0027.\u0027 + topic + \u0027}\u0027 + \u0027.\u0027 + key)"},{"line_number":163,"context_line":"        return local_key"},{"line_number":164,"context_line":""},{"line_number":165,"context_line":"    def check_connection(self, ip_port):"},{"line_number":166,"context_line":"        try:"},{"line_number":167,"context_line":"            if self.client[ip_port] is None:"},{"line_number":168,"context_line":"                raise redis.exceptions.ConnectionError"}],"source_content_type":"text/x-python","patch_set":15,"id":"bae84128_24853ece","line":165,"range":{"start_line":165,"start_character":8,"end_line":165,"end_character":24},"updated":"2016-02-24 10:28:39.000000000","message":"this is a private function, please use the name \u0027_check_connection()\u0027.","commit_id":"8d4c78d4008c7f40d72b9ea3aec4883567930449"},{"author":{"_account_id":20188,"name":"zhuweiqiong","email":"zhuweiqiong@huawei.com","username":"zhuweiqiong"},"change_message_id":"68cdcdefcba2d9ed74de2c1a25d889ee0a86f641","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        self.remote_server_lists \u003d RedisDbDriver.redis_mgt.get_master_list()"},{"line_number":36,"context_line":"        for remote in self.remote_server_lists:"},{"line_number":37,"context_line":"            ip_port \u003d remote[\u0027ip_port\u0027].split(\u0027:\u0027)"},{"line_number":38,"context_line":"            self.clients[self.remote_server_lists[\u0027ip_port\u0027]] \u003d \\"},{"line_number":39,"context_line":"                redis.client.StrictRedis(host\u003dip_port[0], port\u003dip_port[1])"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    def support_publish_subscribe(self):"}],"source_content_type":"text/x-python","patch_set":17,"id":"9aed3d3a_d383f802","line":38,"range":{"start_line":38,"start_character":24,"end_line":38,"end_character":60},"updated":"2016-02-27 01:32:55.000000000","message":"remote_server_lists is a list, but you use it as a dict","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"},{"author":{"_account_id":20188,"name":"zhuweiqiong","email":"zhuweiqiong@huawei.com","username":"zhuweiqiong"},"change_message_id":"68cdcdefcba2d9ed74de2c1a25d889ee0a86f641","unresolved":false,"context_lines":[{"line_number":42,"context_line":"        return True"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    def get_key(self, table, key, topic\u003dNone):"},{"line_number":45,"context_line":"        local_topic \u003d topic if topic else \u0027*\u0027"},{"line_number":46,"context_line":"        local_key \u003d self.uuid_to_key(table, key, local_topic)"},{"line_number":47,"context_line":"        if topic is None:"},{"line_number":48,"context_line":"            res \u003d []"}],"source_content_type":"text/x-python","patch_set":17,"id":"9aed3d3a_f378bc2d","line":45,"range":{"start_line":45,"start_character":42,"end_line":45,"end_character":45},"updated":"2016-02-27 01:32:55.000000000","message":"should not add \u0027*\u0027 in key","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"},{"author":{"_account_id":20188,"name":"zhuweiqiong","email":"zhuweiqiong@huawei.com","username":"zhuweiqiong"},"change_message_id":"68cdcdefcba2d9ed74de2c1a25d889ee0a86f641","unresolved":false,"context_lines":[{"line_number":138,"context_line":"    def register_notification_callback(self, callback, topics\u003dNone):"},{"line_number":139,"context_line":"        pass"},{"line_number":140,"context_line":""},{"line_number":141,"context_line":"    def uuid_to_key(self, table, key, topic):"},{"line_number":142,"context_line":"        if topic is None:"},{"line_number":143,"context_line":"            raise Exception(\u0027uuid to key failed topic is none\u0027)"},{"line_number":144,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":17,"id":"9aed3d3a_53f40885","line":141,"range":{"start_line":141,"start_character":8,"end_line":141,"end_character":45},"updated":"2016-02-27 01:32:55.000000000","message":"This method should be a private method","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"a5b7038a7f6d48769c33e6a5982571c17eb3b05a","unresolved":false,"context_lines":[{"line_number":140,"context_line":""},{"line_number":141,"context_line":"    def uuid_to_key(self, table, key, topic):"},{"line_number":142,"context_line":"        if topic is None:"},{"line_number":143,"context_line":"            raise Exception(\u0027uuid to key failed topic is none\u0027)"},{"line_number":144,"context_line":"        else:"},{"line_number":145,"context_line":"            local_key \u003d (\u0027{\u0027 + table + \u0027.\u0027 + topic + \u0027}\u0027 + \u0027.\u0027 + key)"},{"line_number":146,"context_line":"        return local_key"}],"source_content_type":"text/x-python","patch_set":17,"id":"bae84128_26933b51","line":143,"range":{"start_line":143,"start_character":18,"end_line":143,"end_character":27},"updated":"2016-02-25 09:51:42.000000000","message":"Please do not use python basic exception class in db driver. Please see dragonflow/common/exceptions.py","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"a5b7038a7f6d48769c33e6a5982571c17eb3b05a","unresolved":false,"context_lines":[{"line_number":148,"context_line":"    def check_connection(self, ip_port):"},{"line_number":149,"context_line":"        try:"},{"line_number":150,"context_line":"            if self.clients[ip_port] is None:"},{"line_number":151,"context_line":"                raise redis.exceptions.ConnectionError"},{"line_number":152,"context_line":"            self.clients[ip_port].get(None)"},{"line_number":153,"context_line":"        except (redis.exceptions.ConnectionError,"},{"line_number":154,"context_line":"                redis.exceptions.BusyLoadingError):"}],"source_content_type":"text/x-python","patch_set":17,"id":"bae84128_a6c62b47","line":151,"range":{"start_line":151,"start_character":16,"end_line":151,"end_character":54},"updated":"2016-02-25 09:51:42.000000000","message":"Why not just return False?","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"}],"dragonflow/db/drivers/redis_mgt.py":[{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"3bc90274cc4f5b76c03f1fff07348c59359a7a70","unresolved":false,"context_lines":[{"line_number":40,"context_line":"\r"},{"line_number":41,"context_line":"    def _load_so(self):\r"},{"line_number":42,"context_line":"        try:\r"},{"line_number":43,"context_line":"            lib \u003d cdll.LoadLibrary(self.so_path)\r"},{"line_number":44,"context_line":"            self.calc_key \u003d lib.HASH_SLOT\r"},{"line_number":45,"context_line":"            self.calc_key.restype \u003d c_int\r"},{"line_number":46,"context_line":"            self.calc_key.argtypes \u003d [c_char_p, c_int]\r"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_20e7bfad","line":43,"updated":"2016-02-19 05:22:38.000000000","message":"Suggest to build such a library via source in devstack and install it in the operating system and then describe it in detail in spec.\n\nI don\u0027t think it is good to add binary file into project.","commit_id":"db050f4d6a743d8fd41524e6439754ecb2d6c15e"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"1b7ba88019591a0bf5e56af6f1273819b2359ca3","unresolved":false,"context_lines":[{"line_number":40,"context_line":"\r"},{"line_number":41,"context_line":"    def _load_so(self):\r"},{"line_number":42,"context_line":"        try:\r"},{"line_number":43,"context_line":"            lib \u003d cdll.LoadLibrary(self.so_path)\r"},{"line_number":44,"context_line":"            self.calc_key \u003d lib.HASH_SLOT\r"},{"line_number":45,"context_line":"            self.calc_key.restype \u003d c_int\r"},{"line_number":46,"context_line":"            self.calc_key.argtypes \u003d [c_char_p, c_int]\r"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_35021f70","line":43,"in_reply_to":"dae33548_20e7bfad","updated":"2016-02-21 07:31:05.000000000","message":"I agree please remove the binary build it or download it from somewhere else","commit_id":"db050f4d6a743d8fd41524e6439754ecb2d6c15e"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":17,"context_line":"from collections import defaultdict\r"},{"line_number":18,"context_line":"\r"},{"line_number":19,"context_line":"from oslo_log import log\r"},{"line_number":20,"context_line":"from ctypes import *\r"},{"line_number":21,"context_line":"import string\r"},{"line_number":22,"context_line":"import random\r"},{"line_number":23,"context_line":"import redis_calckey\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_6fbdcf67","line":20,"updated":"2016-02-22 15:31:23.000000000","message":"Consider using \u0027import ctypes\u0027 and qualifying imported elements (e.g. calling with ctypes.func).","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":66,"context_line":"    def get_cluster_topology(self):\r"},{"line_number":67,"context_line":"        self.cluster_nodes \u003d self.nodes()\r"},{"line_number":68,"context_line":"        self.master_list \u003d self._parse_to_masterlist()\r"},{"line_number":69,"context_line":"        LOG.info(self.master_list)\r"},{"line_number":70,"context_line":"\r"},{"line_number":71,"context_line":"    def _parse_node_line(self, line):\r"},{"line_number":72,"context_line":"        line_items \u003d line.split(\u0027 \u0027)\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_afe99782","line":69,"range":{"start_line":69,"start_character":0,"end_line":69,"end_character":34},"updated":"2016-02-22 15:31:23.000000000","message":"Consider adding a message string, to give context when the list is printed to the log.","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":76,"context_line":"\r"},{"line_number":77,"context_line":"        return ret\r"},{"line_number":78,"context_line":"\r"},{"line_number":79,"context_line":"    def nodes(self):\r"},{"line_number":80,"context_line":"        raw \u003d self.default_node.execute_command(\u0027cluster nodes\u0027)\r"},{"line_number":81,"context_line":"        ret \u003d {}\r"},{"line_number":82,"context_line":"\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_05e04628","line":79,"range":{"start_line":79,"start_character":8,"end_line":79,"end_character":13},"updated":"2016-02-23 12:53:41.000000000","message":"Think about a better name (verb + object), i.e, get_nodes(self)","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":110,"context_line":"    def _make_host(self, host, port):\r"},{"line_number":111,"context_line":"        return \u0027%s:%s\u0027 % (host, port)\r"},{"line_number":112,"context_line":"\r"},{"line_number":113,"context_line":"    def slots(self):\r"},{"line_number":114,"context_line":"        slots_info \u003d self.default_node.execute_command(\u0027cluster slots\u0027)\r"},{"line_number":115,"context_line":"        master_slots \u003d defaultdict(list)\r"},{"line_number":116,"context_line":"        slave_slots \u003d defaultdict(list)\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_255e2a12","line":113,"range":{"start_line":113,"start_character":8,"end_line":113,"end_character":13},"updated":"2016-02-23 12:53:41.000000000","message":"Think about a better name (verb + object)","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":134,"context_line":"    def key_to_slot(self, key):\r"},{"line_number":135,"context_line":"        return self.calc_key(key, len(key))\r"},{"line_number":136,"context_line":"\r"},{"line_number":137,"context_line":"    def assign_to_node(self, key):\r"},{"line_number":138,"context_line":"        slot \u003d self.key_to_slot(key)\r"},{"line_number":139,"context_line":"        ip_port \u003d None\r"},{"line_number":140,"context_line":"        for node in self.master_list:\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_807c32b6","line":137,"range":{"start_line":137,"start_character":8,"end_line":137,"end_character":22},"updated":"2016-02-23 12:53:41.000000000","message":"from the name, I hardly get the purpose of the method. consider giving it a better name.","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":138,"context_line":"        slot \u003d self.key_to_slot(key)\r"},{"line_number":139,"context_line":"        ip_port \u003d None\r"},{"line_number":140,"context_line":"        for node in self.master_list:\r"},{"line_number":141,"context_line":"            if node[\u0027slot\u0027][0] \u003c slot and slot \u003c node[\u0027slot\u0027][1]:\r"},{"line_number":142,"context_line":"                ip_port \u003d node[\u0027ip_port\u0027]\r"},{"line_number":143,"context_line":"                break\r"},{"line_number":144,"context_line":"\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_608beec3","line":141,"range":{"start_line":141,"start_character":30,"end_line":141,"end_character":41},"updated":"2016-02-23 12:53:41.000000000","message":"What if \u003d\u003d ?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":48,"context_line":"            self.default_node \u003d redis.StrictRedis(host, port)"},{"line_number":49,"context_line":"            RedisMgt.check_connection(self.default_node)"},{"line_number":50,"context_line":"        except Exception as e:"},{"line_number":51,"context_line":"            LOG.warning(e)"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def get_cluster_topology(self):"},{"line_number":54,"context_line":"        self.cluster_nodes \u003d self._get_cluster_nodes()"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_572f593e","line":51,"updated":"2016-02-24 09:13:28.000000000","message":"Consider adding context to this warning.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":96,"context_line":"    def _make_host(self, host, port):"},{"line_number":97,"context_line":"        return \u0027%s:%s\u0027 % (host, port)"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"    def _get_cluster_slots(self):"},{"line_number":100,"context_line":"        slots_info \u003d self.default_node.execute_command(\u0027cluster slots\u0027)"},{"line_number":101,"context_line":"        master_slots \u003d defaultdict(list)"},{"line_number":102,"context_line":"        slave_slots \u003d defaultdict(list)"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_17583155","line":99,"updated":"2016-02-24 09:13:28.000000000","message":"This (private) method appears unused.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":119,"context_line":"            \u0027slave\u0027: slave_slots"},{"line_number":120,"context_line":"        }"},{"line_number":121,"context_line":""},{"line_number":122,"context_line":"    def key_to_slot(self, key):"},{"line_number":123,"context_line":"        return self.calc_key(key)"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    def get_node_by_key(self, key):"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_3ad9dc57","line":122,"updated":"2016-02-24 09:13:28.000000000","message":"Is this a private method? If so, prefix it with _ (e.g. _key_to_slot).","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":122,"context_line":"    def key_to_slot(self, key):"},{"line_number":123,"context_line":"        return self.calc_key(key)"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    def get_node_by_key(self, key):"},{"line_number":126,"context_line":"        slot \u003d self.key_to_slot(key)"},{"line_number":127,"context_line":"        ip_port \u003d None"},{"line_number":128,"context_line":"        for node in self.master_list:"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_daea70da","line":125,"updated":"2016-02-24 09:13:28.000000000","message":"Method returns ip_port, rather than a node.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":151,"context_line":"        return len(self.master_list)"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def pubsub_select_node(self):"},{"line_number":154,"context_line":"        LOG.info(self.random_str)"},{"line_number":155,"context_line":"        num \u003d hash(self.random_str) % self.get_master_nodes_num()"},{"line_number":156,"context_line":"        ip_port \u003d self.master_list[num][\u0027ip_port\u0027]"},{"line_number":157,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_b7006535","line":154,"updated":"2016-02-24 09:13:28.000000000","message":"Change to log-level debug. Add context to the log message.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"}],"dragonflow/db/pubsub_drivers/redis_db_pubsub_driver.py":[{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"1b7ba88019591a0bf5e56af6f1273819b2359ca3","unresolved":false,"context_lines":[{"line_number":43,"context_line":"        super(RedisPublisherAgent, self).__init__()\r"},{"line_number":44,"context_line":"        self.remote \u003d []\r"},{"line_number":45,"context_line":"        self.client \u003d None\r"},{"line_number":46,"context_line":"        self._queue \u003d eventlet.queue.PriorityQueue()\r"},{"line_number":47,"context_line":"\r"},{"line_number":48,"context_line":"    def initialize(self, ip, is_neutron_server, publish_port\u003d8866, **args):\r"},{"line_number":49,"context_line":"        # find a publisher server node\r"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_95d20bff","line":46,"range":{"start_line":46,"start_character":22,"end_line":46,"end_character":37},"updated":"2016-02-21 07:31:05.000000000","message":"This queue is not multi process \n\nYou will have multi process q-svc running they are forked usually to the number of core on the neutron api machine.\n\nYou have two option here \n1) Create a multiprocess queue ( our test showd that it is unstable )\n2) Use inter process pipe (please see the eample we did with ZMQ)\n\nPlease contact me and we could discuss it","commit_id":"db050f4d6a743d8fd41524e6439754ecb2d6c15e"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"1b7ba88019591a0bf5e56af6f1273819b2359ca3","unresolved":false,"context_lines":[{"line_number":78,"context_line":"        self.plugin_updates_port \u003d \"\"\r"},{"line_number":79,"context_line":"        self.pub_sub \u003d None\r"},{"line_number":80,"context_line":"\r"},{"line_number":81,"context_line":"    def initialize(self, ip, callback, plugin_port\u003d8866, cont_port\u003d8867):\r"},{"line_number":82,"context_line":"        # find a subscriber server node and run daemon\r"},{"line_number":83,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.pubsub_select_node()\r"},{"line_number":84,"context_line":"        ip_port \u003d self.remote.split(\u0027:\u0027)\r"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_d5e653b3","line":81,"range":{"start_line":81,"start_character":8,"end_line":81,"end_character":19},"updated":"2016-02-21 07:31:05.000000000","message":"Please look at the api interface is different and you are not using this variables any way","commit_id":"db050f4d6a743d8fd41524e6439754ecb2d6c15e"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"1b7ba88019591a0bf5e56af6f1273819b2359ca3","unresolved":false,"context_lines":[{"line_number":78,"context_line":"        self.plugin_updates_port \u003d \"\"\r"},{"line_number":79,"context_line":"        self.pub_sub \u003d None\r"},{"line_number":80,"context_line":"\r"},{"line_number":81,"context_line":"    def initialize(self, ip, callback, plugin_port\u003d8866, cont_port\u003d8867):\r"},{"line_number":82,"context_line":"        # find a subscriber server node and run daemon\r"},{"line_number":83,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.pubsub_select_node()\r"},{"line_number":84,"context_line":"        ip_port \u003d self.remote.split(\u0027:\u0027)\r"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_35d5ffb8","line":81,"range":{"start_line":81,"start_character":44,"end_line":81,"end_character":45},"updated":"2016-02-21 07:31:05.000000000","message":"This interface a change","commit_id":"db050f4d6a743d8fd41524e6439754ecb2d6c15e"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"1b7ba88019591a0bf5e56af6f1273819b2359ca3","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        # find a subscriber server node and run daemon\r"},{"line_number":83,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.pubsub_select_node()\r"},{"line_number":84,"context_line":"        ip_port \u003d self.remote.split(\u0027:\u0027)\r"},{"line_number":85,"context_line":"        self.client\u003d redis.client.StrictRedis(host\u003dip_port[0],port\u003dip_port[1])\r"},{"line_number":86,"context_line":"        self.ip \u003d ip_port[0]\r"},{"line_number":87,"context_line":"        self.plugin_updates_port \u003d ip_port[1]\r"},{"line_number":88,"context_line":"        self.pub_sub \u003d self.client.pubsub()\r"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_55a08343","line":85,"range":{"start_line":85,"start_character":52,"end_line":85,"end_character":76},"updated":"2016-02-21 07:31:05.000000000","message":"Please use self.uri_list\n\nand the register_listen_address  \n\nPlease look at the pub sub API interface","commit_id":"db050f4d6a743d8fd41524e6439754ecb2d6c15e"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":48,"context_line":"        self.config \u003d None\r"},{"line_number":49,"context_line":"\r"},{"line_number":50,"context_line":"    def initialize(self, ip, is_neutron_server, publish_port\u003d8866, **args):\r"},{"line_number":51,"context_line":"        # find a publisher server node\r"},{"line_number":52,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.pubsub_select_node()\r"},{"line_number":53,"context_line":"        ip_port \u003d self.remote.split(\u0027:\u0027)\r"},{"line_number":54,"context_line":"        self.client\u003d redis.client.StrictRedis(host\u003dip_port[0],port\u003dip_port[1])\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_7af74bf5","line":51,"updated":"2016-02-22 15:31:23.000000000","message":"Consider calling super(RedisPublisherAgent, self).initialize(...).","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"4fb734502abda4da33e6d3a66079ea3106c06417","unresolved":false,"context_lines":[{"line_number":51,"context_line":"        # find a publisher server node\r"},{"line_number":52,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.pubsub_select_node()\r"},{"line_number":53,"context_line":"        ip_port \u003d self.remote.split(\u0027:\u0027)\r"},{"line_number":54,"context_line":"        self.client\u003d redis.client.StrictRedis(host\u003dip_port[0],port\u003dip_port[1])\r"},{"line_number":55,"context_line":"        self.daemon \u003d df_utils.DFDaemon()\r"},{"line_number":56,"context_line":"        self.inproc_client \u003d None\r"},{"line_number":57,"context_line":"\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_db4e2b6e","line":54,"range":{"start_line":54,"start_character":34,"end_line":54,"end_character":45},"updated":"2016-02-23 12:53:41.000000000","message":"What if this redis node is down?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":52,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.pubsub_select_node()\r"},{"line_number":53,"context_line":"        ip_port \u003d self.remote.split(\u0027:\u0027)\r"},{"line_number":54,"context_line":"        self.client\u003d redis.client.StrictRedis(host\u003dip_port[0],port\u003dip_port[1])\r"},{"line_number":55,"context_line":"        self.daemon \u003d df_utils.DFDaemon()\r"},{"line_number":56,"context_line":"        self.inproc_client \u003d None\r"},{"line_number":57,"context_line":"\r"},{"line_number":58,"context_line":"        if self.config:\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_fa8cfb80","line":55,"updated":"2016-02-22 15:31:23.000000000","message":"Isn\u0027t this provided by the abstract class?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":63,"context_line":"    def send_event(self, update, topic\u003dNone):\r"},{"line_number":64,"context_line":"        if self.is_daemonize:\r"},{"line_number":65,"context_line":"            if not self.inproc_client:\r"},{"line_number":66,"context_line":"                context \u003d zmq.Context()\r"},{"line_number":67,"context_line":"                self.inproc_client \u003d context.socket(zmq.PUSH)\r"},{"line_number":68,"context_line":"                self.inproc_client.connect(\u0027tcp://127.0.0.1:%d\u0027 % self.inproc_port)\r"},{"line_number":69,"context_line":"\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_7aa90bdf","line":66,"updated":"2016-02-22 15:31:23.000000000","message":"Doesn\u0027t redis have an IPC pub/sub solution? Why use zmq over TCP for local communication, and not ipc?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":96,"context_line":"        self.plugin_updates_port \u003d \"\"\r"},{"line_number":97,"context_line":"        self.pub_sub \u003d None\r"},{"line_number":98,"context_line":"\r"},{"line_number":99,"context_line":"    def initialize(self, callback, config\u003dNone, **args):\r"},{"line_number":100,"context_line":"        # find a subscriber server node and run daemon\r"},{"line_number":101,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.pubsub_select_node()\r"},{"line_number":102,"context_line":"        ip_port \u003d self.remote.split(\u0027:\u0027)\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_1ae9df14","line":99,"updated":"2016-02-22 15:31:23.000000000","message":"Consider calling super(RedisPublisherAgent, self).initialize(...).","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b4ff364821f49332f6a3a04434381f7c9bfebef7","unresolved":false,"context_lines":[{"line_number":105,"context_line":"        self.plugin_updates_port \u003d ip_port[1]\r"},{"line_number":106,"context_line":"        self.pub_sub \u003d self.client.pubsub()\r"},{"line_number":107,"context_line":"        self.db_changes_callback \u003d callback\r"},{"line_number":108,"context_line":"        self.daemon \u003d df_utils.DFDaemon()\r"},{"line_number":109,"context_line":"\r"},{"line_number":110,"context_line":"    def register_topic(self, topic):\r"},{"line_number":111,"context_line":"        self.pub_sub.subscribe(topic)\r"}],"source_content_type":"text/x-python","patch_set":10,"id":"bae84128_7ace2bb5","line":108,"updated":"2016-02-22 15:31:23.000000000","message":"Isn\u0027t this provided by the parent class?","commit_id":"adec6ca8b9bc1fde1c33ee98833b5f121e4c9dfc"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":55,"context_line":"                                                    trasport_proto,"},{"line_number":56,"context_line":"                                                    **args)"},{"line_number":57,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.pubsub_select_node()"},{"line_number":58,"context_line":"        ip_port \u003d self.remote.split(\u0027:\u0027)"},{"line_number":59,"context_line":"        self.client \u003d redis.client.StrictRedis(host\u003dip_port[0],"},{"line_number":60,"context_line":"                                               port\u003dip_port[1])"},{"line_number":61,"context_line":"        self.inproc_client \u003d None"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_1a9338fb","line":58,"updated":"2016-02-24 09:13:28.000000000","message":"self.remote is a list, yet treated here as string.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"39ce96989b54df419894f20882604c6f9f822578","unresolved":false,"context_lines":[{"line_number":71,"context_line":"                context \u003d zmq.Context()"},{"line_number":72,"context_line":"                self.inproc_client \u003d context.socket(zmq.PUSH)"},{"line_number":73,"context_line":"                self.inproc_client.connect(\u0027tcp://127.0.0.1:%d\u0027"},{"line_number":74,"context_line":"                                           % self.inproc_port)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"            if topic:"},{"line_number":77,"context_line":"                update.topic \u003d topic"}],"source_content_type":"text/x-python","patch_set":14,"id":"bae84128_1a81788f","line":74,"updated":"2016-02-24 09:13:28.000000000","message":"You didn\u0027t answer about the Redis inter-proc method.","commit_id":"ca1f2bdeddad350cc4dcd6aa28fc455d6324d847"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"efd41756c2f6d923a241d73eb7d5b3c4052fc58c","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        self.inproc_client \u003d None"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        if self.config:"},{"line_number":64,"context_line":"            self.inproc_port \u003d self.config.publisher_port + 1"},{"line_number":65,"context_line":"        else:"},{"line_number":66,"context_line":"            self.inproc_port \u003d 8867"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"bae84128_c4a9f225","line":64,"range":{"start_line":64,"start_character":31,"end_line":64,"end_character":61},"updated":"2016-02-24 10:28:39.000000000","message":"+1 is not good. what if this port is occupied by other processes? suggest to make it as another option.","commit_id":"8d4c78d4008c7f40d72b9ea3aec4883567930449"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"efd41756c2f6d923a241d73eb7d5b3c4052fc58c","unresolved":false,"context_lines":[{"line_number":63,"context_line":"        if self.config:"},{"line_number":64,"context_line":"            self.inproc_port \u003d self.config.publisher_port + 1"},{"line_number":65,"context_line":"        else:"},{"line_number":66,"context_line":"            self.inproc_port \u003d 8867"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def send_event(self, update, topic\u003dNone):"},{"line_number":69,"context_line":"        if self.is_daemonize:"}],"source_content_type":"text/x-python","patch_set":15,"id":"bae84128_2446de7a","line":66,"range":{"start_line":66,"start_character":31,"end_line":66,"end_character":35},"updated":"2016-02-24 10:28:39.000000000","message":"use option and make 8867 as the default value.","commit_id":"8d4c78d4008c7f40d72b9ea3aec4883567930449"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"efd41756c2f6d923a241d73eb7d5b3c4052fc58c","unresolved":false,"context_lines":[{"line_number":137,"context_line":"                        continue"},{"line_number":138,"context_line":"                    if \u0027message\u0027 \u003d\u003d data[\u0027type\u0027]:"},{"line_number":139,"context_line":"                        entries \u003d jsonutils.loads(data[\u0027data\u0027])"},{"line_number":140,"context_line":"                        # entries \u003d [table, key, action, value]"},{"line_number":141,"context_line":"                        self.db_changes_callback(entries[0],"},{"line_number":142,"context_line":"                                                 entries[1],"},{"line_number":143,"context_line":"                                                 entries[2],"}],"source_content_type":"text/x-python","patch_set":15,"id":"bae84128_4411625c","line":140,"range":{"start_line":140,"start_character":23,"end_line":140,"end_character":63},"updated":"2016-02-24 10:28:39.000000000","message":"remove it?","commit_id":"8d4c78d4008c7f40d72b9ea3aec4883567930449"},{"author":{"_account_id":20188,"name":"zhuweiqiong","email":"zhuweiqiong@huawei.com","username":"zhuweiqiong"},"change_message_id":"d008df39444f50ed107330d5f4395e4b05cbbbdf","unresolved":false,"context_lines":[{"line_number":16,"context_line":"from dragonflow.db.drivers.redis_db_driver import RedisDbDriver"},{"line_number":17,"context_line":"from dragonflow.db import pub_sub_api"},{"line_number":18,"context_line":"import eventlet"},{"line_number":19,"context_line":"from eventlet.green import zmq"},{"line_number":20,"context_line":"from oslo_log import log as logging"},{"line_number":21,"context_line":"from oslo_serialization import jsonutils"},{"line_number":22,"context_line":"import redis"}],"source_content_type":"text/x-python","patch_set":17,"id":"9aed3d3a_d613e664","line":19,"range":{"start_line":19,"start_character":0,"end_line":19,"end_character":30},"updated":"2016-02-27 02:12:03.000000000","message":"why import zeromq","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"a72ff5ec3abd7810db0d8ee13897520fa1b4905f","unresolved":false,"context_lines":[{"line_number":56,"context_line":"                                                    **args)"},{"line_number":57,"context_line":"        self.remote \u003d RedisDbDriver.redis_mgt.pubsub_select_node()"},{"line_number":58,"context_line":"        ip_port \u003d self.remote.split(\u0027:\u0027)"},{"line_number":59,"context_line":"        self.client \u003d redis.client.StrictRedis(host\u003dip_port[0],"},{"line_number":60,"context_line":"                                               port\u003dip_port[1])"},{"line_number":61,"context_line":"        self.inproc_client \u003d None"},{"line_number":62,"context_line":""}],"source_content_type":"text/x-python","patch_set":17,"id":"9aed3d3a_3bd7724c","line":59,"range":{"start_line":59,"start_character":35,"end_line":59,"end_character":46},"updated":"2016-02-29 07:59:27.000000000","message":"I am still learning how redis works.\nFew questions:\n\n1) What transport is Redis using, will it bind a local socket ?\n2) Can we have multi publisher from different process on the same host ? If no we need the inproc communication if not we could just send from each Neutron server process","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"a72ff5ec3abd7810db0d8ee13897520fa1b4905f","unresolved":false,"context_lines":[{"line_number":60,"context_line":"                                               port\u003dip_port[1])"},{"line_number":61,"context_line":"        self.inproc_client \u003d None"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        if self.config:"},{"line_number":64,"context_line":"            self.inproc_port \u003d self.config.publisher_port + 1"},{"line_number":65,"context_line":"        else:"},{"line_number":66,"context_line":"            self.inproc_port \u003d 8867"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def send_event(self, update, topic\u003dNone):"},{"line_number":69,"context_line":"        if self.is_daemonize:"}],"source_content_type":"text/x-python","patch_set":17,"id":"9aed3d3a_dbb12649","line":66,"range":{"start_line":63,"start_character":8,"end_line":66,"end_character":35},"updated":"2016-02-29 07:59:27.000000000","message":"Please look at @omer ZMQ driver update patch \nWe can use the unix pipe for the inproc messages \n\nhttps://review.openstack.org/#/c/281336/14/dragonflow/db/pubsub_drivers/zmq_pubsub_driver.py","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"},{"author":{"_account_id":20188,"name":"zhuweiqiong","email":"zhuweiqiong@huawei.com","username":"zhuweiqiong"},"change_message_id":"38d5ff1a6ddf320d0051a01117fdf97c01e5a3c8","unresolved":false,"context_lines":[{"line_number":63,"context_line":"        if self.config:"},{"line_number":64,"context_line":"            self.inproc_port \u003d self.config.publisher_port + 1"},{"line_number":65,"context_line":"        else:"},{"line_number":66,"context_line":"            self.inproc_port \u003d 8867"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def send_event(self, update, topic\u003dNone):"},{"line_number":69,"context_line":"        if self.is_daemonize:"}],"source_content_type":"text/x-python","patch_set":17,"id":"9aed3d3a_76d49a46","line":66,"range":{"start_line":66,"start_character":12,"end_line":66,"end_character":35},"updated":"2016-02-27 01:57:24.000000000","message":"This port is used for pubsub of Redis, so you should not use 8867 as default","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"},{"author":{"_account_id":20188,"name":"zhuweiqiong","email":"zhuweiqiong@huawei.com","username":"zhuweiqiong"},"change_message_id":"38d5ff1a6ddf320d0051a01117fdf97c01e5a3c8","unresolved":false,"context_lines":[{"line_number":70,"context_line":"            if not self.inproc_client:"},{"line_number":71,"context_line":"                context \u003d zmq.Context()"},{"line_number":72,"context_line":"                self.inproc_client \u003d context.socket(zmq.PUSH)"},{"line_number":73,"context_line":"                self.inproc_client.connect(\u0027tcp://127.0.0.1:%d\u0027"},{"line_number":74,"context_line":"                                           % self.inproc_port)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"            if topic:"}],"source_content_type":"text/x-python","patch_set":17,"id":"9aed3d3a_f678aa2d","line":73,"range":{"start_line":73,"start_character":16,"end_line":73,"end_character":63},"updated":"2016-02-27 01:57:24.000000000","message":"Why 127.0.0.1? It is not fit for Redis pubsub","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"},{"author":{"_account_id":20188,"name":"zhuweiqiong","email":"zhuweiqiong@huawei.com","username":"zhuweiqiong"},"change_message_id":"38d5ff1a6ddf320d0051a01117fdf97c01e5a3c8","unresolved":false,"context_lines":[{"line_number":82,"context_line":"    def run(self):"},{"line_number":83,"context_line":"        context \u003d zmq.Context()"},{"line_number":84,"context_line":"        inproc_server \u003d context.socket(zmq.PULL)"},{"line_number":85,"context_line":"        inproc_server.bind(\u0027tcp://127.0.0.1:%d\u0027 % self.inproc_port)"},{"line_number":86,"context_line":"        eventlet.sleep(0.2)"},{"line_number":87,"context_line":"        while True:"},{"line_number":88,"context_line":"            event \u003d inproc_server.recv()"}],"source_content_type":"text/x-python","patch_set":17,"id":"9aed3d3a_f6c6ea47","line":85,"range":{"start_line":85,"start_character":8,"end_line":85,"end_character":67},"updated":"2016-02-27 01:57:24.000000000","message":"As mentioned above","commit_id":"12c829fe4e1f1a1c1bdde6f232072a3bbe83c3a8"}]}
