| 155 | |
| 156 | |
| 157 | Future<Shared<Replica>> LogProcess::recover() |
| 158 | { |
| 159 | // The future 'recovered' is used to mark the success (or the |
| 160 | // failure) of the recovery. We do not use the future 'recovering' |
| 161 | // to do that because it can be set in other process and thus has a |
| 162 | // race condition which we want to avoid. We deliberately do not |
| 163 | // save replica in 'recovered' because it will complicate our |
| 164 | // deleting logic (see 'finalize'). |
| 165 | Future<Nothing> future = recovered.future(); |
| 166 | |
| 167 | if (future.isDiscarded()) { |
| 168 | return Failure("Not expecting discarded future"); |
| 169 | } else if (future.isFailed()) { |
| 170 | return Failure(future.failure()); |
| 171 | } else if (future.isReady()) { |
| 172 | return replica; |
| 173 | } |
| 174 | |
| 175 | // Recovery has not finished yet. Create a promise and queue it such |
| 176 | // that it can get notified once the recovery has finished (either |
| 177 | // succeeded or failed). |
| 178 | process::Promise<Shared<Replica>>* promise = |
| 179 | new process::Promise<Shared<Replica>>(); |
| 180 | |
| 181 | promises.push_back(promise); |
| 182 | |
| 183 | if (recovering.isNone()) { |
| 184 | // TODO(jieyu): At this moment, we haven't shared 'replica' to |
| 185 | // others yet. Therefore, the following 'replica.own()' call |
| 186 | // should not be blocking. In the future, we may wanna support |
| 187 | // 'release' in Shared which will provide this CHECK internally. |
| 188 | CHECK(replica.unique()); |
| 189 | |
| 190 | recovering = |
| 191 | log::recover( |
| 192 | quorum, |
| 193 | replica.own().get(), |
| 194 | network, |
| 195 | autoInitialize) |
| 196 | .onAny(defer(self(), &Self::_recover)); |
| 197 | } |
| 198 | |
| 199 | // TODO(benh): Add 'onDiscard' callback to our returned future. |
| 200 | |
| 201 | return promise->future(); |
| 202 | } |
| 203 | |
| 204 | |
| 205 | void LogProcess::_recover() |
nothing calls this directly
no test coverage detected