| 256 | |
| 257 | |
| 258 | Future<Nothing> LogStorageProcess::_start( |
| 259 | const Option<Log::Position>& position) |
| 260 | { |
| 261 | CHECK_SOME(starting); |
| 262 | |
| 263 | if (position.isNone()) { |
| 264 | VLOG(2) << "Writer failed to get elected, retrying"; |
| 265 | |
| 266 | starting = None(); // Reset 'starting' so we try again. |
| 267 | return start(); // TODO(benh): Don't try again forever? |
| 268 | } |
| 269 | |
| 270 | VLOG(2) << "Writer got elected at position " << position->identity(); |
| 271 | |
| 272 | // Now read and apply log entries. Since 'start' can be called |
| 273 | // multiple times (i.e., since we reset 'starting' after getting a |
| 274 | // None position returned after 'set', 'expunge', etc) we need to |
| 275 | // check and see if we've already successfully read the log at least |
| 276 | // once by checking 'index'. If we haven't yet read the log (i.e., |
| 277 | // this is the first call to 'start' and 'index' is None) then we |
| 278 | // get the beginning of the log first so we can read from that up to |
| 279 | // what ever position was known at the time we started the |
| 280 | // writer. Note that it should always be safe to read a truncated |
| 281 | // entry since a subsequent operation in the log should invalidate |
| 282 | // that entry when we read it instead. |
| 283 | if (index.isSome()) { |
| 284 | // If we've started before (i.e., have an 'index' position) we |
| 285 | // should also expect to know the last 'truncated' position. |
| 286 | CHECK_SOME(truncated); |
| 287 | return reader.read(index.get(), position.get()) |
| 288 | .then(defer(self(), &Self::apply, lambda::_1)); |
| 289 | } |
| 290 | |
| 291 | return reader.beginning() |
| 292 | .then(defer(self(), &Self::__start, lambda::_1, position.get())); |
| 293 | } |
| 294 | |
| 295 | |
| 296 | Future<Nothing> LogStorageProcess::__start( |