Mercurial > p > roundup > code
comparison roundup/backends/back_anydbm.py @ 869:6d98bec4e52e
fixed the journal bloat from multilink changes
we just log the add or remove operations, not the whole list
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Sun, 14 Jul 2002 23:18:20 +0000 |
| parents | 37fb48c3a136 |
| children | de3da99a7c02 |
comparison
equal
deleted
inserted
replaced
| 868:e8162a199d81 | 869:6d98bec4e52e |
|---|---|
| 13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 14 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" | 14 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" |
| 15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, | 15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, |
| 16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 17 # | 17 # |
| 18 #$Id: back_anydbm.py,v 1.46 2002-07-14 06:06:34 richard Exp $ | 18 #$Id: back_anydbm.py,v 1.47 2002-07-14 23:18:20 richard Exp $ |
| 19 ''' | 19 ''' |
| 20 This module defines a backend that saves the hyperdatabase in a database | 20 This module defines a backend that saves the hyperdatabase in a database |
| 21 chosen by anydbm. It is guaranteed to always be available in python | 21 chosen by anydbm. It is guaranteed to always be available in python |
| 22 versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several | 22 versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several |
| 23 serious bugs, and is not available) | 23 serious bugs, and is not available) |
| 874 | 874 |
| 875 node = self.db.getnode(self.classname, nodeid) | 875 node = self.db.getnode(self.classname, nodeid) |
| 876 if node.has_key(self.db.RETIRED_FLAG): | 876 if node.has_key(self.db.RETIRED_FLAG): |
| 877 raise IndexError | 877 raise IndexError |
| 878 num_re = re.compile('^\d+$') | 878 num_re = re.compile('^\d+$') |
| 879 for key, value in propvalues.items(): | 879 |
| 880 # if the journal value is to be different, store it in here | |
| 881 journalvalues = {} | |
| 882 | |
| 883 for propname, value in propvalues.items(): | |
| 880 # check to make sure we're not duplicating an existing key | 884 # check to make sure we're not duplicating an existing key |
| 881 if key == self.key and node[key] != value: | 885 if propname == self.key and node[propname] != value: |
| 882 try: | 886 try: |
| 883 self.lookup(value) | 887 self.lookup(value) |
| 884 except KeyError: | 888 except KeyError: |
| 885 pass | 889 pass |
| 886 else: | 890 else: |
| 887 raise ValueError, 'node with key "%s" exists'%value | 891 raise ValueError, 'node with key "%s" exists'%value |
| 888 | 892 |
| 889 # this will raise the KeyError if the property isn't valid | 893 # this will raise the KeyError if the property isn't valid |
| 890 # ... we don't use getprops() here because we only care about | 894 # ... we don't use getprops() here because we only care about |
| 891 # the writeable properties. | 895 # the writeable properties. |
| 892 prop = self.properties[key] | 896 prop = self.properties[propname] |
| 893 | 897 |
| 894 # if the value's the same as the existing value, no sense in | 898 # if the value's the same as the existing value, no sense in |
| 895 # doing anything | 899 # doing anything |
| 896 if node.has_key(key) and value == node[key]: | 900 if node.has_key(propname) and value == node[propname]: |
| 897 del propvalues[key] | 901 del propvalues[propname] |
| 898 continue | 902 continue |
| 899 | 903 |
| 900 # do stuff based on the prop type | 904 # do stuff based on the prop type |
| 901 if isinstance(prop, Link): | 905 if isinstance(prop, Link): |
| 902 link_class = self.properties[key].classname | 906 link_class = self.properties[propname].classname |
| 903 # if it isn't a number, it's a key | 907 # if it isn't a number, it's a key |
| 904 if type(value) != type(''): | 908 if type(value) != type(''): |
| 905 raise ValueError, 'link value must be String' | 909 raise ValueError, 'link value must be String' |
| 906 if not num_re.match(value): | 910 if not num_re.match(value): |
| 907 try: | 911 try: |
| 908 value = self.db.classes[link_class].lookup(value) | 912 value = self.db.classes[link_class].lookup(value) |
| 909 except (TypeError, KeyError): | 913 except (TypeError, KeyError): |
| 910 raise IndexError, 'new property "%s": %s not a %s'%( | 914 raise IndexError, 'new property "%s": %s not a %s'%( |
| 911 key, value, self.properties[key].classname) | 915 propname, value, self.properties[propname].classname) |
| 912 | 916 |
| 913 if not self.db.hasnode(link_class, value): | 917 if not self.db.hasnode(link_class, value): |
| 914 raise IndexError, '%s has no node %s'%(link_class, value) | 918 raise IndexError, '%s has no node %s'%(link_class, value) |
| 915 | 919 |
| 916 if self.do_journal and self.properties[key].do_journal: | 920 if self.do_journal and self.properties[propname].do_journal: |
| 917 # register the unlink with the old linked node | 921 # register the unlink with the old linked node |
| 918 if node[key] is not None: | 922 if node[propname] is not None: |
| 919 self.db.addjournal(link_class, node[key], 'unlink', | 923 self.db.addjournal(link_class, node[propname], 'unlink', |
| 920 (self.classname, nodeid, key)) | 924 (self.classname, nodeid, propname)) |
| 921 | 925 |
| 922 # register the link with the newly linked node | 926 # register the link with the newly linked node |
| 923 if value is not None: | 927 if value is not None: |
| 924 self.db.addjournal(link_class, value, 'link', | 928 self.db.addjournal(link_class, value, 'link', |
| 925 (self.classname, nodeid, key)) | 929 (self.classname, nodeid, propname)) |
| 926 | 930 |
| 927 elif isinstance(prop, Multilink): | 931 elif isinstance(prop, Multilink): |
| 928 if type(value) != type([]): | 932 if type(value) != type([]): |
| 929 raise TypeError, 'new property "%s" not a list of ids'%key | 933 raise TypeError, 'new property "%s" not a list of'\ |
| 930 link_class = self.properties[key].classname | 934 ' ids'%propname |
| 935 link_class = self.properties[propname].classname | |
| 931 l = [] | 936 l = [] |
| 932 for entry in value: | 937 for entry in value: |
| 933 # if it isn't a number, it's a key | 938 # if it isn't a number, it's a key |
| 934 if type(entry) != type(''): | 939 if type(entry) != type(''): |
| 935 raise ValueError, 'new property "%s" link value ' \ | 940 raise ValueError, 'new property "%s" link value ' \ |
| 936 'must be a string'%key | 941 'must be a string'%propname |
| 937 if not num_re.match(entry): | 942 if not num_re.match(entry): |
| 938 try: | 943 try: |
| 939 entry = self.db.classes[link_class].lookup(entry) | 944 entry = self.db.classes[link_class].lookup(entry) |
| 940 except (TypeError, KeyError): | 945 except (TypeError, KeyError): |
| 941 raise IndexError, 'new property "%s": %s not a %s'%( | 946 raise IndexError, 'new property "%s": %s not a %s'%( |
| 942 key, entry, self.properties[key].classname) | 947 propname, entry, |
| 948 self.properties[propname].classname) | |
| 943 l.append(entry) | 949 l.append(entry) |
| 944 value = l | 950 value = l |
| 945 propvalues[key] = value | 951 propvalues[propname] = value |
| 952 | |
| 953 # figure the journal entry for this property | |
| 954 add = [] | |
| 955 remove = [] | |
| 946 | 956 |
| 947 # handle removals | 957 # handle removals |
| 948 if node.has_key(key): | 958 if node.has_key(propname): |
| 949 l = node[key] | 959 l = node[propname] |
| 950 else: | 960 else: |
| 951 l = [] | 961 l = [] |
| 952 for id in l[:]: | 962 for id in l[:]: |
| 953 if id in value: | 963 if id in value: |
| 954 continue | 964 continue |
| 955 # register the unlink with the old linked node | 965 # register the unlink with the old linked node |
| 956 if self.do_journal and self.properties[key].do_journal: | 966 if self.do_journal and self.properties[propname].do_journal: |
| 957 self.db.addjournal(link_class, id, 'unlink', | 967 self.db.addjournal(link_class, id, 'unlink', |
| 958 (self.classname, nodeid, key)) | 968 (self.classname, nodeid, propname)) |
| 959 l.remove(id) | 969 l.remove(id) |
| 970 remove.append(id) | |
| 960 | 971 |
| 961 # handle additions | 972 # handle additions |
| 962 for id in value: | 973 for id in value: |
| 963 if not self.db.hasnode(link_class, id): | 974 if not self.db.hasnode(link_class, id): |
| 964 raise IndexError, '%s has no node %s'%( | 975 raise IndexError, '%s has no node %s'%(link_class, id) |
| 965 link_class, id) | |
| 966 if id in l: | 976 if id in l: |
| 967 continue | 977 continue |
| 968 # register the link with the newly linked node | 978 # register the link with the newly linked node |
| 969 if self.do_journal and self.properties[key].do_journal: | 979 if self.do_journal and self.properties[propname].do_journal: |
| 970 self.db.addjournal(link_class, id, 'link', | 980 self.db.addjournal(link_class, id, 'link', |
| 971 (self.classname, nodeid, key)) | 981 (self.classname, nodeid, propname)) |
| 972 l.append(id) | 982 l.append(id) |
| 983 add.append(id) | |
| 984 | |
| 985 # figure the journal entry | |
| 986 l = [] | |
| 987 if add: | |
| 988 l.append(('add', add)) | |
| 989 if remove: | |
| 990 l.append(('remove', remove)) | |
| 991 if l: | |
| 992 journalvalues[propname] = tuple(l) | |
| 973 | 993 |
| 974 elif isinstance(prop, String): | 994 elif isinstance(prop, String): |
| 975 if value is not None and type(value) != type(''): | 995 if value is not None and type(value) != type(''): |
| 976 raise TypeError, 'new property "%s" not a string'%key | 996 raise TypeError, 'new property "%s" not a string'%propname |
| 977 | 997 |
| 978 elif isinstance(prop, Password): | 998 elif isinstance(prop, Password): |
| 979 if not isinstance(value, password.Password): | 999 if not isinstance(value, password.Password): |
| 980 raise TypeError, 'new property "%s" not a Password'% key | 1000 raise TypeError, 'new property "%s" not a Password'%propname |
| 981 propvalues[key] = value | 1001 propvalues[propname] = value |
| 982 | 1002 |
| 983 elif value is not None and isinstance(prop, Date): | 1003 elif value is not None and isinstance(prop, Date): |
| 984 if not isinstance(value, date.Date): | 1004 if not isinstance(value, date.Date): |
| 985 raise TypeError, 'new property "%s" not a Date'% key | 1005 raise TypeError, 'new property "%s" not a Date'% propname |
| 986 propvalues[key] = value | 1006 propvalues[propname] = value |
| 987 | 1007 |
| 988 elif value is not None and isinstance(prop, Interval): | 1008 elif value is not None and isinstance(prop, Interval): |
| 989 if not isinstance(value, date.Interval): | 1009 if not isinstance(value, date.Interval): |
| 990 raise TypeError, 'new property "%s" not an Interval'% key | 1010 raise TypeError, 'new property "%s" not an '\ |
| 991 propvalues[key] = value | 1011 'Interval'%propname |
| 992 | 1012 propvalues[propname] = value |
| 993 node[key] = value | 1013 |
| 1014 node[propname] = value | |
| 994 | 1015 |
| 995 # nothing to do? | 1016 # nothing to do? |
| 996 if not propvalues: | 1017 if not propvalues: |
| 997 return | 1018 return |
| 998 | 1019 |
| 999 # do the set, and journal it | 1020 # do the set, and journal it |
| 1000 self.db.setnode(self.classname, nodeid, node) | 1021 self.db.setnode(self.classname, nodeid, node) |
| 1022 | |
| 1001 if self.do_journal: | 1023 if self.do_journal: |
| 1024 propvalues.update(journalvalues) | |
| 1002 self.db.addjournal(self.classname, nodeid, 'set', propvalues) | 1025 self.db.addjournal(self.classname, nodeid, 'set', propvalues) |
| 1003 | 1026 |
| 1004 self.fireReactors('set', nodeid, oldvalues) | 1027 self.fireReactors('set', nodeid, oldvalues) |
| 1005 | 1028 |
| 1006 def retire(self, nodeid): | 1029 def retire(self, nodeid): |
| 1613 properties['superseder'] = hyperdb.Multilink(classname) | 1636 properties['superseder'] = hyperdb.Multilink(classname) |
| 1614 Class.__init__(self, db, classname, **properties) | 1637 Class.__init__(self, db, classname, **properties) |
| 1615 | 1638 |
| 1616 # | 1639 # |
| 1617 #$Log: not supported by cvs2svn $ | 1640 #$Log: not supported by cvs2svn $ |
| 1641 #Revision 1.46 2002/07/14 06:06:34 richard | |
| 1642 #Did some old TODOs | |
| 1643 # | |
| 1618 #Revision 1.45 2002/07/14 04:03:14 richard | 1644 #Revision 1.45 2002/07/14 04:03:14 richard |
| 1619 #Implemented a switch to disable journalling for a Class. CGI session | 1645 #Implemented a switch to disable journalling for a Class. CGI session |
| 1620 #database now uses it. | 1646 #database now uses it. |
| 1621 # | 1647 # |
| 1622 #Revision 1.44 2002/07/14 02:05:53 richard | 1648 #Revision 1.44 2002/07/14 02:05:53 richard |
