| 116 | } |
| 117 | |
| 118 | void BufRendezvous::ConsumeBuf(const string& key, const string& device_name, |
| 119 | const uint64 device_incarnation, |
| 120 | const ConsumerCallback& done) { |
| 121 | // Check the incarnation in the request matches the current device |
| 122 | // incarnation of the producer. |
| 123 | Device* device; |
| 124 | Status consumebuf_status = dev_mgr_->LookupDevice(device_name, &device); |
| 125 | if (consumebuf_status.ok() && |
| 126 | device->attributes().incarnation() != device_incarnation) { |
| 127 | consumebuf_status = errors::FailedPrecondition( |
| 128 | "RecvBuf expects a different device incarnation: ", device_incarnation, |
| 129 | " vs. ", device->attributes().incarnation(), |
| 130 | ". Your worker job that contains the device (\"", device_name, |
| 131 | "\") was probably restarted. Check your " |
| 132 | "worker job for the reason why it was restarted."); |
| 133 | } |
| 134 | if (!consumebuf_status.ok()) { |
| 135 | done(consumebuf_status, nullptr); |
| 136 | return; |
| 137 | } |
| 138 | |
| 139 | Hook* existing_hook = nullptr; |
| 140 | do { |
| 141 | mutex_lock l(mu_); |
| 142 | if (!status_.ok()) { |
| 143 | consumebuf_status = status_; |
| 144 | break; |
| 145 | } |
| 146 | auto it = hook_table_.find(key); |
| 147 | if (it != hook_table_.end()) { |
| 148 | // Prepare to consume immediately. |
| 149 | if (it->second->cons_cb) { |
| 150 | consumebuf_status = |
| 151 | errors::Internal("Second consumer arrived for key ", key); |
| 152 | break; |
| 153 | } |
| 154 | existing_hook = it->second; |
| 155 | hook_table_.erase(it); |
| 156 | existing_hook->cons_cb = done; |
| 157 | } else { |
| 158 | // Hang consumer callback on the Hook. |
| 159 | Hook* h = new Hook; |
| 160 | hook_table_[key] = h; |
| 161 | h->cons_cb = done; |
| 162 | return; |
| 163 | } |
| 164 | } while (false); |
| 165 | if (existing_hook) { |
| 166 | existing_hook->cons_cb(Status::OK(), existing_hook); |
| 167 | return; |
| 168 | } |
| 169 | if (!consumebuf_status.ok()) { |
| 170 | done(consumebuf_status, nullptr); |
| 171 | return; |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | /*static*/ |