Closes every socket, which will also flush all internal region caches.
()
| 1107 | * Closes every socket, which will also flush all internal region caches. |
| 1108 | */ |
| 1109 | private Deferred<Object> disconnectEverything() { |
| 1110 | HashMap<String, RegionClient> ip2client_copy; |
| 1111 | |
| 1112 | synchronized (ip2client) { |
| 1113 | // Make a local copy so we can shutdown every Region Server client |
| 1114 | // without hold the lock while we iterate over the data structure. |
| 1115 | ip2client_copy = new HashMap<String, RegionClient>(ip2client); |
| 1116 | } |
| 1117 | |
| 1118 | final ArrayList<Deferred<Object>> d = |
| 1119 | new ArrayList<Deferred<Object>>(ip2client_copy.values().size() + 1); |
| 1120 | // Shut down all client connections, clear cache. |
| 1121 | for (final RegionClient client : ip2client_copy.values()) { |
| 1122 | d.add(client.shutdown()); |
| 1123 | } |
| 1124 | if (rootregion != null && rootregion.isAlive()) { |
| 1125 | // It's OK if we already did that in the loop above. |
| 1126 | d.add(rootregion.shutdown()); |
| 1127 | } |
| 1128 | ip2client_copy = null; |
| 1129 | |
| 1130 | final int size = d.size(); |
| 1131 | return Deferred.group(d).addCallback( |
| 1132 | new Callback<Object, ArrayList<Object>>() { |
| 1133 | public Object call(final ArrayList<Object> arg) { |
| 1134 | // Normally, now that we've shutdown() every client, all our caches should |
| 1135 | // be empty since each shutdown() generates a DISCONNECTED event, which |
| 1136 | // causes RegionClientPipeline to call removeClientFromCache(). |
| 1137 | HashMap<String, RegionClient> logme = null; |
| 1138 | synchronized (ip2client) { |
| 1139 | if (!ip2client.isEmpty()) { |
| 1140 | logme = new HashMap<String, RegionClient>(ip2client); |
| 1141 | } |
| 1142 | } |
| 1143 | if (logme != null) { |
| 1144 | // Putting this logging statement inside the synchronized block |
| 1145 | // can lead to a deadlock, since HashMap.toString() is going to |
| 1146 | // call RegionClient.toString() on each entry, and this locks the |
| 1147 | // client briefly. Other parts of the code lock clients first and |
| 1148 | // the ip2client HashMap second, so this can easily deadlock. |
| 1149 | LOG.error("Some clients are left in the client cache and haven't" |
| 1150 | + " been cleaned up: " + logme); |
| 1151 | logme = null; |
| 1152 | return disconnectEverything(); // Try again. |
| 1153 | } |
| 1154 | zkclient.disconnectZK(); |
| 1155 | return arg; |
| 1156 | } |
| 1157 | public String toString() { |
| 1158 | return "wait " + size + " RegionClient.shutdown()"; |
| 1159 | } |
| 1160 | }); |
| 1161 | } |
| 1162 | |
| 1163 | /** |
| 1164 | * Ensures that a given table/family pair really exists. |