(self)
| 600 | shadowed_segments.remove(segment) |
| 601 | |
| 602 | def write_index(self): |
| 603 | def flush_and_sync(fd): |
| 604 | fd.flush() |
| 605 | os.fsync(fd.fileno()) |
| 606 | |
| 607 | def rename_tmp(file): |
| 608 | os.replace(file + ".tmp", file) |
| 609 | |
| 610 | hints = {"version": 2, "segments": self.segments, "compact": self.compact, "shadow_index": self.shadow_index} |
| 611 | integrity = { |
| 612 | # Integrity version started at 2, the current hints version. |
| 613 | # Thus, integrity version == hints version, for now. |
| 614 | "version": 2 |
| 615 | } |
| 616 | transaction_id = self.io.get_segments_transaction_id() |
| 617 | assert transaction_id is not None |
| 618 | |
| 619 | # Write hints file |
| 620 | hints_name = "hints.%d" % transaction_id |
| 621 | hints_file = os.path.join(self.path, hints_name) |
| 622 | with IntegrityCheckedFile(hints_file + ".tmp", filename=hints_name, write=True) as fd: |
| 623 | msgpack.pack(hints, fd) |
| 624 | flush_and_sync(fd) |
| 625 | integrity["hints"] = fd.integrity_data |
| 626 | |
| 627 | # Write repository index |
| 628 | index_name = "index.%d" % transaction_id |
| 629 | index_file = os.path.join(self.path, index_name) |
| 630 | with IntegrityCheckedFile(index_file + ".tmp", filename=index_name, write=True) as fd: |
| 631 | # XXX: Consider using SyncFile for index write-outs. |
| 632 | self.index.write(fd) |
| 633 | flush_and_sync(fd) |
| 634 | integrity["index"] = fd.integrity_data |
| 635 | |
| 636 | # Write integrity file, containing checksums of the hints and index files |
| 637 | integrity_name = "integrity.%d" % transaction_id |
| 638 | integrity_file = os.path.join(self.path, integrity_name) |
| 639 | with open(integrity_file + ".tmp", "wb") as fd: |
| 640 | msgpack.pack(integrity, fd) |
| 641 | flush_and_sync(fd) |
| 642 | |
| 643 | # Rename the integrity file first |
| 644 | rename_tmp(integrity_file) |
| 645 | sync_dir(self.path) |
| 646 | # Rename the others after the integrity file is hypothetically on disk |
| 647 | rename_tmp(hints_file) |
| 648 | rename_tmp(index_file) |
| 649 | sync_dir(self.path) |
| 650 | |
| 651 | # Remove old auxiliary files |
| 652 | current = ".%d" % transaction_id |
| 653 | for name in os.listdir(self.path): |
| 654 | if not name.startswith(("index.", "hints.", "integrity.")): |
| 655 | continue |
| 656 | if name.endswith(current): |
| 657 | continue |
| 658 | os.unlink(os.path.join(self.path, name)) |
| 659 | self.index = None |
no test coverage detected