| 478 | |
| 479 | |
| 480 | Future<bool> LogStorageProcess::__set( |
| 481 | const Entry& entry, |
| 482 | const id::UUID& uuid) |
| 483 | { |
| 484 | Option<Snapshot> snapshot = snapshots.get(entry.name()); |
| 485 | |
| 486 | // Check the version first (if we've already got a snapshot). |
| 487 | if (snapshot.isSome() && |
| 488 | id::UUID::fromBytes(snapshot->entry.uuid()).get() != uuid) { |
| 489 | return false; |
| 490 | } |
| 491 | |
| 492 | // Check if we should try to compute a diff. |
| 493 | if (snapshot.isSome() && snapshot->diffs < diffsBetweenSnapshots) { |
| 494 | // Keep metrics for the time to calculate diffs. |
| 495 | metrics.diff.start(); |
| 496 | |
| 497 | // Construct the diff of the last snapshot. |
| 498 | Try<svn::Diff> diff = svn::diff(snapshot->entry.value(), entry.value()); |
| 499 | |
| 500 | Duration elapsed = metrics.diff.stop(); |
| 501 | |
| 502 | if (diff.isError()) { |
| 503 | // TODO(benh): Fallback and try and write a whole snapshot? |
| 504 | return Failure("Failed to construct diff: " + diff.error()); |
| 505 | } |
| 506 | |
| 507 | VLOG(1) << "Created an SVN diff in " << elapsed |
| 508 | << " of size " << Bytes(diff->data.size()) << " which is " |
| 509 | << (diff->data.size() / (double) entry.value().size()) * 100.0 |
| 510 | << "% the original size (" << Bytes(entry.value().size()) << ")"; |
| 511 | |
| 512 | // Only write the diff if it provides a reduction in size. |
| 513 | if (diff->data.size() < entry.value().size()) { |
| 514 | // Append a diff operation. |
| 515 | Operation operation; |
| 516 | operation.set_type(Operation::DIFF); |
| 517 | operation.mutable_diff()->mutable_entry()->CopyFrom(entry); |
| 518 | operation.mutable_diff()->mutable_entry()->set_value(diff->data); |
| 519 | |
| 520 | string value; |
| 521 | if (!operation.SerializeToString(&value)) { |
| 522 | return Failure("Failed to serialize DIFF Operation"); |
| 523 | } |
| 524 | |
| 525 | return writer.append(value) |
| 526 | .then(defer(self(), |
| 527 | &Self::___set, |
| 528 | entry, |
| 529 | snapshot->diffs + 1, |
| 530 | lambda::_1)); |
| 531 | } |
| 532 | } |
| 533 | |
| 534 | // Write the full snapshot. |
| 535 | Operation operation; |
| 536 | operation.set_type(Operation::SNAPSHOT); |
| 537 | operation.mutable_snapshot()->mutable_entry()->CopyFrom(entry); |