Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: experimental support for diskcache-style (sqlite backed) sconsign #4619

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 43 additions & 28 deletions SCons/SConsign.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@
import time

import SCons.dblite
import SCons.sdiskcache
import SCons.Warnings
from SCons.compat import PICKLE_PROTOCOL
from SCons.Util import print_time

DEBUG = False

def corrupt_dblite_warning(filename) -> None:
SCons.Warnings.warn(
Expand All @@ -54,8 +56,9 @@ def corrupt_dblite_warning(filename) -> None:
# "DB_Name" is the base name of the database file (minus any
# extension the underlying DB module will add).
DataBase = {}
DB_Module = SCons.dblite
DB_Name = None
#DB_Module = SCons.dblite
DB_Module = SCons.sdiskcache
DB_Name = ".sconsign"
DB_sync_list = []

def current_sconsign_filename():
Expand All @@ -71,6 +74,17 @@ def current_sconsign_filename():
return ".sconsign"
return ".sconsign_" + current_hash_algorithm

# a debugging decorator, not for production usage
def dbwrap(func):
def wrapper(dnode):
db, mode = func(dnode)
if DEBUG:
print(f"Get_DataBase returns {db=}, {mode=}")
return db, mode

return wrapper

@dbwrap
def Get_DataBase(dir):
global DB_Name

Expand All @@ -86,7 +100,8 @@ def Get_DataBase(dir):
return DataBase[d], mode
except KeyError:
path = d.entry_abspath(DB_Name)
try: db = DataBase[d] = DB_Module.open(path, mode)
try:
db = DataBase[d] = DB_Module.open(path, mode)
except OSError:
pass
else:
Expand Down Expand Up @@ -126,13 +141,13 @@ def write() -> None:
try:
syncmethod = db.sync
except AttributeError:
pass # Not all dbm modules have sync() methods.
pass # Not all dbm modules have sync() methods.
else:
syncmethod()
try:
closemethod = db.close
except AttributeError:
pass # Not all dbm modules have close() methods.
pass # Not all dbm modules have close() methods.
else:
closemethod()

Expand All @@ -142,20 +157,21 @@ def write() -> None:


class SConsignEntry:
"""
Wrapper class for the generic entry in a .sconsign file.
"""Wrapper class for the generic entry in an sconsign file.

The Node subclass populates it with attributes as it pleases.

XXX As coded below, we do expect a '.binfo' attribute to be added,
but we'll probably generalize this in the next refactorings.
"""

__slots__ = ("binfo", "ninfo", "__weakref__")
current_version_id = 2

def __init__(self) -> None:
# Create an object attribute from the class attribute so it ends up
# in the pickled data in the .sconsign file.
#_version_id = self.current_version_id
# _version_id = self.current_version_id
pass

def convert_to_sconsign(self) -> None:
Expand Down Expand Up @@ -199,15 +215,11 @@ def __init__(self) -> None:
self.to_be_merged = {}

def get_entry(self, filename):
"""
Fetch the specified entry attribute.
"""
"""Fetch the specified entry attribute."""
return self.entries[filename]

def set_entry(self, filename, obj) -> None:
"""
Set the entry.
"""
"""Set the entry."""
self.entries[filename] = obj
self.dirty = True

Expand Down Expand Up @@ -261,16 +273,21 @@ def __init__(self, dir) -> None:
except KeyError:
pass
else:
try:
self.entries = pickle.loads(rawentries)
if not isinstance(self.entries, dict):
self.entries = {}
raise TypeError
except KeyboardInterrupt:
raise
except Exception as e:
SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
"Ignoring corrupt sconsign entry : %s (%s)\n"%(self.dir.get_tpath(), e))
if DEBUG:
print(f"rawentries is a {type(rawentries)}")
if isinstance(rawentries, dict):
self.entries = rawentries
else:
try:
self.entries = pickle.loads(rawentries)
if not isinstance(self.entries, dict):
self.entries = {}
raise TypeError
except KeyboardInterrupt:
raise
except Exception as e:
SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
"Ignoring corrupt sconsign entry : %s (%s)\n"%(self.dir.get_tpath(), e))
for key, entry in self.entries.items():
entry.convert_from_sconsign(dir, key)

Expand Down Expand Up @@ -421,11 +438,9 @@ def write(self, sync: int=1) -> None:


def File(name, dbm_module=None) -> None:
"""
Arrange for all signatures to be stored in a global .sconsign.db*
file.
"""
"""Store the SCons signatures in a global .sconsign.* database."""
global ForDirectory, DB_Name, DB_Module

if name is None:
ForDirectory = DirFile
DB_Module = None
Expand Down
6 changes: 4 additions & 2 deletions SCons/SConsignTests.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,13 +300,15 @@ def test_SConsignFile(self) -> None:
assert SCons.SConsign.DB_Name == ".sconsign", SCons.SConsign.DB_Name
else:
assert SCons.SConsign.DB_Name == ".sconsign_{}".format(get_current_hash_algorithm_used()), SCons.SConsign.DB_Name
assert SCons.SConsign.DB_Module is SCons.dblite, SCons.SConsign.DB_Module
#assert SCons.SConsign.DB_Module is SCons.dblite, SCons.SConsign.DB_Module
assert SCons.SConsign.DB_Module is SCons.sdiskcache, SCons.SConsign.DB_Module

SCons.SConsign.File(file)

assert SCons.SConsign.DataBase == {}, SCons.SConsign.DataBase
assert SCons.SConsign.DB_Name is file, SCons.SConsign.DB_Name
assert SCons.SConsign.DB_Module is SCons.dblite, SCons.SConsign.DB_Module
#assert SCons.SConsign.DB_Module is SCons.dblite, SCons.SConsign.DB_Module
assert SCons.SConsign.DB_Module is SCons.sdiskcache, SCons.SConsign.DB_Module

SCons.SConsign.File(None)

Expand Down
Loading
Loading