Skip to content

Commit ca78e9a

Browse files
authored
fix: DictSupplementaryFileContainer increment refcount in _assign_unique_name (#513)
`DictSupplementaryFileContainer_store_refcount` is designed to track how many `_name_map` entries reference the same content hash, so `delete_file()` can free the underlying bytes only when the last reference is removed. The refcount is never incremented, so files are never freed. Previously, because `_assign_unique_name()` never increments `_store_refcount`, the count stays at 0 after any `add_file()`. Every `delete_file()` decrements to -1 and the equality check `== 0` is never true, so `_store[hash]` and `_store_refcount[hash]` are never cleaned up. Every file ever added leaks indefinitely. This fixes this bug by incrementing `_store_refcount[sha] += 1` inside `_assign_unique_name()` when a new `_name_map` entry is created (the first branch of the `while True` loop). Also decrement it (and skip the increment) inside the second branch when a duplicate name already maps to the same hash. Fixes #495
1 parent be31bd0 commit ca78e9a

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

sdk/basyx/aas/adapter/aasx.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,7 @@ def rename_file(self, old_name: str, new_name: str) -> str:
880880
if new_name == old_name:
881881
return new_name
882882
file_hash, file_content_type = self._name_map[old_name]
883+
self._store_refcount[file_hash] -= 1
883884
del self._name_map[old_name]
884885
return self._assign_unique_name(new_name, file_hash, file_content_type)
885886

@@ -889,6 +890,7 @@ def _assign_unique_name(self, name: str, sha: bytes, content_type: str) -> str:
889890
while True:
890891
if new_name not in self._name_map:
891892
self._name_map[new_name] = (sha, content_type)
893+
self._store_refcount[sha] += 1
892894
return new_name
893895
elif self._name_map[new_name] == (sha, content_type):
894896
return new_name

sdk/test/adapter/aasx/test_aasx.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,24 @@ def test_supplementary_file_container(self) -> None:
8989
with self.assertRaises(KeyError):
9090
container.write_file(duplicate_file, file_content)
9191

92+
def test_supplementary_file_container_refcount(self) -> None:
93+
container = aasx.DictSupplementaryFileContainer()
94+
data = b"test content"
95+
name1 = container.add_file("/file1.bin", io.BytesIO(data), "application/octet-stream")
96+
name2 = container.add_file("/file2.bin", io.BytesIO(data), "application/octet-stream")
97+
content_hash = container.get_sha256(name1)
98+
99+
# Both names point to same content — backing store must be present
100+
self.assertIn(content_hash, container._store)
101+
102+
# Deleting one reference must NOT free the backing store
103+
container.delete_file(name1)
104+
self.assertIn(content_hash, container._store)
105+
106+
# Deleting the last reference must free the backing store
107+
container.delete_file(name2)
108+
self.assertNotIn(content_hash, container._store)
109+
92110

93111
class AASXWriterTest(unittest.TestCase):
94112
def test_write_missing_aas_objects(self):

0 commit comments

Comments
 (0)