Changeset 3509
- Timestamp:
- 09/04/07 21:19:49 (1 year ago)
- Files:
-
- trunk/Durus (added)
- trunk/Durus/SchevoDurus.egg-info (added)
- trunk/Durus/SchevoDurus.egg-info/paster_plugins.txt (added)
- trunk/Durus/schevodurus (added)
- trunk/Durus/schevodurus/__init__.py (added)
- trunk/Durus/schevodurus/backend.py (added)
- trunk/Durus/schevodurus/backend_test_classes.py (added)
- trunk/Durus/schevodurus/test (added)
- trunk/Durus/schevodurus/test/__init__.py (added)
- trunk/Durus/schevodurus/test/test_durus_backend.py (added)
- trunk/Durus/setup.cfg (added)
- trunk/Durus/setup.py (added)
- trunk/Policy/schevopolicy/test/base.py (modified) (1 diff)
- trunk/Policy/schevopolicy/wrapper.py (modified) (1 diff)
- trunk/Schevo/doc/SchevoCommandLineTool.txt (modified) (3 diffs)
- trunk/Schevo/doc/SchevoInternalDatabaseStructures.txt (modified) (3 diffs)
- trunk/Schevo/schevo/backend.py (added)
- trunk/Schevo/schevo/database.py (modified) (4 diffs)
- trunk/Schevo/schevo/database1.py (modified) (11 diffs)
- trunk/Schevo/schevo/database2.py (modified) (48 diffs)
- trunk/Schevo/schevo/error.py (modified) (1 diff)
- trunk/Schevo/schevo/script/backends.py (added)
- trunk/Schevo/schevo/script/db.py (modified) (2 diffs)
- trunk/Schevo/schevo/script/db_compare.py (modified) (1 diff)
- trunk/Schevo/schevo/script/db_convert.py (modified) (2 diffs)
- trunk/Schevo/schevo/script/db_copy.py (added)
- trunk/Schevo/schevo/script/db_create.py (modified) (3 diffs)
- trunk/Schevo/schevo/script/db_evolve.py (modified) (1 diff)
- trunk/Schevo/schevo/script/db_inject.py (modified) (1 diff)
- trunk/Schevo/schevo/script/db_update.py (modified) (1 diff)
- trunk/Schevo/schevo/script/opt.py (modified) (1 diff)
- trunk/Schevo/schevo/script/shell.py (modified) (1 diff)
- trunk/Schevo/schevo/store/backend.py (added)
- trunk/Schevo/schevo/store/backend_test_classes.py (added)
- trunk/Schevo/schevo/store/tests/test_store_btree.py (added)
- trunk/Schevo/schevo/store/tests/test_store_client_storage.py (added)
- trunk/Schevo/schevo/store/tests/test_store_connection.py (added)
- trunk/Schevo/schevo/store/tests/test_store_file_storage.py (added)
- trunk/Schevo/schevo/store/tests/test_store_history.py (added)
- trunk/Schevo/schevo/store/tests/test_store_persistent.py (added)
- trunk/Schevo/schevo/store/tests/test_store_persistent_set.py (added)
- trunk/Schevo/schevo/store/tests/test_store_serialize.py (added)
- trunk/Schevo/schevo/store/tests/test_store_storage.py (added)
- trunk/Schevo/schevo/store/tests/test_store_storage_server.py (added)
- trunk/Schevo/schevo/store/tests/test_store_utils.py (added)
- trunk/Schevo/schevo/test/base.py (modified) (17 diffs)
- trunk/Schevo/schevo/test/library.py (added)
- trunk/Schevo/schevo/test/test_bank.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_calculated_field_unicode.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_change.py (modified) (5 diffs)
- trunk/Schevo/schevo/test/test_constant.py (modified) (2 diffs)
- trunk/Schevo/schevo/test/test_convert_format.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_database.py (modified) (3 diffs)
- trunk/Schevo/schevo/test/test_database_namespace.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_default_values.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_entity_extent.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_entity_subclass.py (modified) (3 diffs)
- trunk/Schevo/schevo/test/test_equivalent.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_evolve.py (modified) (7 diffs)
- trunk/Schevo/schevo/test/test_extent_name_override.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_extent_without_fields.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_extentmethod.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_field_entity.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_field_entitylist.py (modified) (2 diffs)
- trunk/Schevo/schevo/test/test_field_entityset.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_field_entitysetset.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_field_maps.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_icon.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_label.py (modified) (3 diffs)
- trunk/Schevo/schevo/test/test_links.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_on_delete.py (modified) (14 diffs)
- trunk/Schevo/schevo/test/test_populate.py (modified) (5 diffs)
- trunk/Schevo/schevo/test/test_prefix.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_query.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_relax_index.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_schema.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_store_btree.py (deleted)
- trunk/Schevo/schevo/test/test_store_client_storage.py (deleted)
- trunk/Schevo/schevo/test/test_store_connection.py (deleted)
- trunk/Schevo/schevo/test/test_store_file_storage.py (deleted)
- trunk/Schevo/schevo/test/test_store_history.py (deleted)
- trunk/Schevo/schevo/test/test_store_persistent.py (deleted)
- trunk/Schevo/schevo/test/test_store_persistent_set.py (deleted)
- trunk/Schevo/schevo/test/test_store_serialize.py (deleted)
- trunk/Schevo/schevo/test/test_store_storage.py (deleted)
- trunk/Schevo/schevo/test/test_store_storage_server.py (deleted)
- trunk/Schevo/schevo/test/test_store_utils.py (deleted)
- trunk/Schevo/schevo/test/test_transaction.py (modified) (2 diffs)
- trunk/Schevo/schevo/test/test_transaction_before_after.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_transaction_cdu_subclass.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_transaction_field_reorder.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_transaction_require_changes.py (modified) (1 diff)
- trunk/Schevo/schevo/test/test_view.py (modified) (1 diff)
- trunk/Schevo/schevo/trace.py (modified) (1 diff)
- trunk/Schevo/setup.py (modified) (2 diffs)
- trunk/Wsgi/schevowsgi/dbopener.py (modified) (1 diff)
- trunk/Zodb (added)
- trunk/Zodb/SchevoZodb.egg-info (added)
- trunk/Zodb/SchevoZodb.egg-info/paster_plugins.txt (added)
- trunk/Zodb/schevozodb (added)
- trunk/Zodb/schevozodb/__init__.py (added)
- trunk/Zodb/schevozodb/backend.py (added)
- trunk/Zodb/schevozodb/backend_test_classes.py (added)
- trunk/Zodb/schevozodb/test (added)
- trunk/Zodb/schevozodb/test/__init__.py (added)
- trunk/Zodb/schevozodb/test/test_zodb_backend.py (added)
- trunk/Zodb/setup.cfg (added)
- trunk/Zodb/setup.py (added)
- trunk/apps/Twitabit (modified) (1 prop)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/Policy/schevopolicy/test/base.py
r3383 r3509 44 44 _use_db_cache = False 45 45 46 def _open(self, suffix='' ):46 def _open(self, suffix='', reopening=False): 47 47 db = super(TestClass, self)._open(suffix) 48 48 db_name = 'db' + suffix trunk/Policy/schevopolicy/wrapper.py
r3426 r3509 131 131 132 132 def _open_file(self, db_alias, db_filename): 133 db = database.open(db_filename , label=db_alias)133 db = database.open(db_filename) 134 134 return db 135 135 trunk/Schevo/doc/SchevoCommandLineTool.txt
r3191 r3509 54 54 Common options 55 55 -------------- 56 57 The following options are available to all commands. 56 58 57 59 **-h**, **--help**: … … 66 68 optimized Python modules. 67 69 70 **-B NAME**, **--backend=NAME**: 71 72 Use the named storage backend when creating or opening a 73 database. Use the `schevo backends`_ command to view a list of 74 backends and their available arguments. 75 76 You do not need to specify a backend if you desire to use the 77 default ``durus`` backend. You also do not need to specify a 78 backend when using an existing database as Schevo has an 79 auto-detection mechanism that determines it for you. 80 81 **-A ARGS**, **--backend-args=ARGS**: 82 83 Pass the given comma-separated arguments to the backend. Use the 84 `schevo backends`_ command to view a list of backends and their 85 available arguments. 86 87 88 schevo backends 89 --------------- 90 91 Usage: ``schevo backends`` 92 93 Prints a list of available storage backends and their available 94 arguments. 95 68 96 69 97 schevo db compare … … 96 124 97 125 Convert to a specific format. (Default: latest format.) 126 127 128 schevo db copy 129 -------------- 130 131 Usage: ``schevo db copy [options] SRCFILE DESTFILE`` 132 133 Copies the internal structures verbatim from `SRCFILE` to 134 `DESTFILE`. 135 136 `SRCFILE`: The database file to copy the internal structures from. 137 138 `DESTFILE`: The empty file to copy internal structures to. 139 140 Backend options given apply to `DESTFILE`. The backend for `SRCFILE` 141 is determined automatically. 98 142 99 143 trunk/Schevo/doc/SchevoInternalDatabaseStructures.txt
r3112 r3509 15 15 16 16 'SCHEVO': PersistentDict{ 17 'label': <db-label>, [*] 17 18 'format': <db-format>, 18 19 'version': <schema-version>, … … 38 39 }, 39 40 }, 40 'related_entities': PersistentDict{ [ 2+]41 'related_entities': PersistentDict{ [**] 41 42 <field-id>: <related-entity-set>, 42 43 ..., … … 66 67 } 67 68 68 ``[2]`` indicates that the structure is only present in databases of format 69 2 or higher. 69 ``[*]``: Labels are not present in older databases, and a default 70 label is assumed if a persistent label is not assigned. 71 72 ``[**]``: The related entities structure is only present in databases 73 of format 2 or higher. 70 74 71 75 trunk/Schevo/schevo/database.py
r3306 r3509 7 7 from schevo.lib import optimize 8 8 9 10 9 from schevo import database1 11 10 from schevo import database2 11 from schevo.error import DatabaseAlreadyExists, DatabaseDoesNotExist 12 12 from schevo.field import not_fget 13 13 from schevo import icon 14 from schevo.label import relabel 14 15 from schevo.store.connection import Connection 15 16 from schevo.store.file_storage import FileStorage 17 from schevo.trace import log 16 18 17 19 … … 31 33 32 34 33 def convert_format(filename_or_fp, format): 34 """Convert database to a new storage format. 35 36 - `filename_or_fp`: The filename or file pointer to convert. 37 - `format`: The format to convert to. 38 """ 39 if isinstance(filename_or_fp, basestring): 40 # If it's a string, assume it's a filename. 41 fs = FileStorage(filename_or_fp) 42 # Since it's an actual filesystem file, close the FileStorage after 43 # the entire conversion is done. 44 close_when_done = True 45 else: 46 # Otherwise, assume it's a file-like object. 47 fs = FileStorage(fp=filename_or_fp) 48 # Since StringIO and similar file-liike objects' values cannot be 49 # inspected after closing, do not explicitly close the FileStorage 50 # object when conversion is done. 51 close_when_done = False 35 def convert_format(filename, backend_name=None, backend_args={}, format=None): 36 """Convert database to a new internal structure format. 37 38 - `filename`: Filename of the database to convert. 39 - `backend_name`: (optional) Name of the backend to use when 40 opening the database. 41 - `backend_args`: (optional) Arguments to pass to the backend. 42 - `format`: (optional) Format to convert internal structure to. 43 If not given, the most recent format available will be used. 44 """ 45 backend = new_backend(filename, backend_name, backend_args) 52 46 # Check the format of the database. 53 conn = Connection(fs) 54 root = conn.get_root() 47 root = backend.get_root() 55 48 # XXX: Better error checking might be handy. 49 # XXX: So might data structure verification. 56 50 schevo = root['SCHEVO'] 57 51 original_format = schevo['format'] 52 if format is None: 53 format = max(format_converter) 58 54 # Convert one version at a time, ensuring that failures result in a 59 55 # rollback to the database's original state. 60 56 try: 61 try: 62 for new_format in xrange(original_format + 1, format + 1): 63 converter = format_converter[new_format] 64 converter(conn) 65 except: 66 conn.abort() 67 raise 68 else: 69 conn.commit() 70 finally: 71 if close_when_done: 72 fs.close() 57 for new_format in xrange(original_format + 1, format + 1): 58 converter = format_converter[new_format] 59 converter(backend) 60 except: 61 backend.abort() 62 raise 63 else: 64 backend.commit() 65 66 67 def copy(src_filename, dest_filename, dest_backend_name, dest_backend_args={}): 68 """Copy internal structures verbatim from a source database to a 69 new destination database. 70 71 To see progress of the copy operation, turn on tracing as 72 described in `schevo.trace` 73 74 - `src_filename`: Filename of the source database. Schevo must be 75 able to open the source database using backend autodetection, 76 and by using default backend arguments. 77 - `dest_filename`: Filename of the destination database. This file 78 may exist if it is in the format used by the destination 79 backend, but must not already contain a Schevo database. 80 - `dest_backend_name`: Name of the backend to use when creating 81 the destination database. 82 - `dest_backend_args`: (optional) Arguments to pass to the 83 backend. 84 """ 85 src_backend = new_backend(src_filename) 86 # Make sure the source backend is in the proper format. 87 assert log(1, 'Checking source', src_filename) 88 src_root = src_backend.get_root() 89 if 'SCHEVO' not in src_root: 90 src_backend.close() 91 raise DatabaseDoesNotExist( 92 'No schevo database in file %r.' % src_filename) 93 if src_root['SCHEVO']['format'] != 2: 94 src_backend.close() 95 raise DatabaseFormatMismatch('Database must be in format 2.') 96 # Make sure the destination backend does not have a database. 97 assert log(1, 'Checking destination', src_filename) 98 dest_backend = new_backend( 99 dest_filename, dest_backend_name, dest_backend_args) 100 dest_root = dest_backend.get_root() 101 if 'SCHEVO' in dest_root: 102 src_backend.close() 103 dest_backend.close() 104 raise DatabaseAlreadyExists( 105 'Schevo database already in file %r.' % dest_filename) 106 assert log(1, 'Start copying structures.') 107 d_btree = dest_backend.BTree 108 d_pdict = dest_backend.PDict 109 d_plist = dest_backend.PList 110 s_btree = src_backend.BTree 111 assert log(2, 'Creating SCHEVO key.') 112 src_SCHEVO = src_root['SCHEVO'] 113 dest_SCHEVO = dest_root['SCHEVO'] = d_pdict() 114 assert log(2, 'Copying lightweight structures.') 115 if 'label' in src_SCHEVO: 116 dest_SCHEVO['label'] = src_SCHEVO['label'] 117 dest_SCHEVO['format'] = 2 118 dest_SCHEVO['version'] = src_SCHEVO['version'] 119 dest_SCHEVO['schema_source'] = src_SCHEVO['schema_source'] 120 dest_SCHEVO['extent_name_id'] = d_pdict( 121 src_SCHEVO['extent_name_id'].iteritems()) 122 assert log(2, 'Copying extents.') 123 dest_extents = dest_SCHEVO['extents'] = d_pdict() 124 def copy_btree(src): 125 """Used for copying indices structure.""" 126 copy = d_btree() 127 for key, value in src.iteritems(): 128 if isinstance(value, s_btree): 129 value = copy_btree(value) 130 copy[key] = value 131 return copy 132 for extent_id, src_extent in src_SCHEVO['extents'].iteritems(): 133 extent_name = src_extent['name'] 134 assert log(2, 'Creating extent', extent_name) 135 dest_extent = dest_extents[extent_id] = d_pdict() 136 assert log(2, 'Copying lightweight structures for', extent_name) 137 dest_extent['entity_field_ids'] = src_extent['entity_field_ids'] 138 dest_extent['field_id_name'] = d_pdict( 139 src_extent['field_id_name'].iteritems()) 140 dest_extent['field_name_id'] = d_pdict( 141 src_extent['field_name_id'].iteritems()) 142 dest_extent['id'] = src_extent['id'] 143 dest_extent['len'] = src_extent['len'] 144 dest_extent['name'] = src_extent['name'] 145 dest_extent['next_oid'] = src_extent['next_oid'] 146 assert log(2, 'Copying', len(src_extent['entities']), 'entities in', 147 extent_name) 148 dest_entities = dest_extent['entities'] = d_btree() 149 for entity_oid, src_entity in src_extent['entities'].iteritems(): 150 assert log(3, 'Copying', entity_oid) 151 dest_entity = dest_entities[entity_oid] = d_pdict() 152 dest_entity['rev'] = src_entity['rev'] 153 dest_entity['fields'] = d_pdict(src_entity['fields'].iteritems()) 154 dest_entity['link_count'] = src_entity['link_count'] 155 src_links = src_entity['links'] 156 dest_links = dest_entity['links'] = d_pdict() 157 for key, value in src_links.iteritems(): 158 links = dest_links[key] = d_btree() 159 links.update(src_links[key].iteritems()) 160 dest_entity['related_entities'] = d_pdict( 161 src_entity['related_entities'].iteritems()) 162 assert log(2, 'Copying indices for', extent_name) 163 dest_extent['index_map'] = d_pdict(src_extent['index_map'].iteritems()) 164 dest_extent['normalized_index_map'] = d_pdict( 165 src_extent['normalized_index_map'].iteritems()) 166 dest_indices = dest_extent['indices'] = d_btree() 167 for index_spec, src_index_data in src_extent['indices'].iteritems(): 168 unique, src_index_tree = src_index_data 169 dest_indices[index_spec] = (unique, copy_btree(src_index_tree)) 170 assert log(2, 'Done copying', extent_name, '-- committing to disk') 171 dest_backend.commit() 172 # Finalize. 173 assert log(1, 'Close source.') 174 src_backend.close() 175 assert log(1, 'Pack destination.') 176 dest_backend.pack() 177 assert log(1, 'Close destination.') 178 dest_backend.close() 179 180 181 def create(filename, backend_name, backend_args={}, 182 schema_source=None, schema_version=None, initialize=True, 183 format=None, label=u'Schevo Database'): 184 """Create a new database and return it. 185 186 - `filename`: Filename of the new database. 187 - `backend_name`: Name of the backend to use when creating the 188 database. 189 - `backend_args`: (optional) Arguments to pass to the backend. 190 - `schema_source`: (optional) Schema source code to synchronize 191 the new database with. If `None` is given, the database will 192 exist but will contain no extents. 193 - `schema_version`: (optional) Version of the schema being used to 194 create the database. If `None` is given, `1` is assumed. 195 - `initialize`: `True` (default) if the new database should be 196 populated with initial values defined in the schema. 197 - `format`: (optional) Internal structure format to use. If 198 `None` is given, the latest format will be used. 199 - `label`: (optional) The label to give the new database. 200 """ 201 backend = new_backend(filename, backend_name, backend_args) 202 # Make sure the database doesn't already exist. 203 root = backend.get_root() 204 if 'SCHEVO' in root: 205 backend.close() 206 raise DatabaseAlreadyExists( 207 'Use evolve, update, or open on this database.') 208 # Continue creating the new database. 209 Database = format_dbclass[format] 210 db = Database(backend) 211 db._sync( 212 schema_source = schema_source, 213 schema_version = schema_version, 214 initialize = initialize, 215 ) 216 # Apply label. 217 relabel(db, label) 218 # Install icon support. 219 icon.install(db) 220 db._on_open() 221 return db 73 222 74 223 … … 131 280 132 281 133 def inject(filename, schema_source, version): 134 """Inject a new schema and schema version into a database file. DANGEROUS! 282 def inject(filename, schema_source, version, 283 backend_name=None, backend_args=None): 284 """Inject a new schema and schema version into a database 285 file. DANGEROUS! 135 286 136 287 PLEASE USE WITH CAUTION; this is not intended to be used in normal course … … 143 294 144 295 - `filename`: Filename of database to inject new schema into. 145 - `schema_source`: The new schema source to inject into the database. 146 - `version`: The new version number of the database schema to inject. 147 """ 148 fs = FileStorage(filename) 149 conn = Connection(fs) 150 root = conn.get_root() 296 - `schema_source`: The new schema source to inject into the 297 database. 298 - `version`: The new version number of the database schema to 299 inject. 300 - `backend_name`: (optional) Name of the backend to use when 301 opening the database, if auto-detection is not desired. 302 - `backend_args`: (optional) Arguments to pass to the backend. 303 """ 304 backend = new_backend(filename, backend_name, backend_args) 305 root = backend.get_root() 151 306 schevo = root['SCHEVO'] 152 307 schevo['schema_source'] = schema_source 153 308 schevo['version'] = version 154 conn.commit() 155 fs.close() 156 157 158 def open(filename=None, schema_source=None, schema_version=None, 159 initialize=True, label='', fp=None, cache_size=100000, 160 format_for_new=None): 161 """Return an open database by opening an existing database or creating 162 a new one. 163 164 If a new database is created, it is assumed that the `schema_source` given 165 is schema version 1. 166 167 - `filename`: Filename of database to create or open, or None if using `fp`. 168 - `schema_source`: Schema source to create a new database with, or None 169 if not creating a new database. 170 - `schema_version`: Schema version to create a new database with, if 171 skipping evolution from version 1. 172 - `initialize`: If True, will create initial values in the database if 173 creating a new database. 174 - `label`: The label of the database, to be used for a return value when 175 the open database instance is passed to `schevo.label.label`. 176 - `fp`: A file-like object, such as a StringIO instance, to use instead of 177 opening a file in the filesystem. None if using `filename`. 178 - `cache_size`: The number of Python objects that the stoage backend 179 will cache in memory before re-ghosting old objects. 180 - `format_for_new`: The version number of the database format to use when 181 creating a new database, or None to use the default format. 182 """ 183 # Create a FileStorage instance for the database based on `fp` or 184 # `filename` arguments. 185 if fp is not None: 186 fs = FileStorage(fp=fp) 309 backend.commit() 310 backend.close() 311 312 313 def new_backend(filename, backend_name=None, backend_args=None): 314 """Return a new database backend instance for a file. 315 316 - `filename`: Name of the file to open with the backend. 317 - `backend_name`: Name of the backend to use. If the file already 318 exists and `None` is given, then the backend is auto-detected if 319 possible, or an exception is raised. If the file does not 320 already exist and `None` is given, an exception is raised. 321 - `backend_args`: (optional) Arguments to pass to the backend. 322 """ 323 from schevo.backend import backends 324 if backend_name: 325 # Determine backend class by name. 326 BackendClass = backends[backend_name] 327 additional_args = {} 187 328 else: 188 fs = FileStorage(filename) 189 # Create a Connection instance for the file storage, with a specific 190 # cache size. 191 conn = Connection(fs, cache_size) 329 # In absence of name, determine backend class by file. 330 BackendClass = None 331 for BC in backends.itervalues(): 332 usable = BC.usable_by_backend(filename) 333 if usable: 334 BackendClass = BC 335 usable, additional_args = usable 336 break 337 if BackendClass is None: 338 raise IOError('No suitable backends found for %r' % filename) 339 # Convert backend args to a dictionary. 340 if backend_args is None: 341 backend_args = {} 342 elif isinstance(backend_args, basestring): 343 backend_args = BackendClass.args_from_string(backend_args) 344 backend_args.update(additional_args) 345 return BackendClass(filename, **backend_args) 346 347 348 def open(filename, backend_name=None, backend_args={}): 349 """Open an existing database and return it. 350 351 - `filename`: Name of the file containing the database. 352 - `backend_name`: (optional) Name of the backend to use if 353 auto-detection is not desired. 354 - `backend_args`: (optional) Arguments to pass to the backend. 355 """ 356 backend = new_backend(filename, backend_name, backend_args) 357 # Make sure the database already exists. 358 root = backend.get_root() 359 if 'SCHEVO' not in root: 360 backend.close() 361 raise DatabaseDoesNotExist('Use create to create a new database.') 192 362 # Determine the version of the database. 193 root = conn.get_root() 194 if 'SCHEVO' in root: 195 schevo = root['SCHEVO'] 196 format = schevo['format'] 197 else: 198 format = format_for_new 363 schevo = root['SCHEVO'] 364 format = schevo['format'] 199 365 # Determine database class based on format number. 200 366 Database = format_dbclass[format] 201 367 # Create the Database instance. 202 db = Database(conn) 203 if label: 204 db.label = label 205 # Synchronize it with the given schema source. 206 db._sync( 207 schema_source, schema_version=schema_version, initialize=initialize) 368 db = Database(backend) 369 db._sync() 208 370 # Install icon support and finalize opening of database. 209 371 icon.install(db) trunk/Schevo/schevo/database1.py
r3306 r3509 15 15 from schevo.field import Entity as EntityField 16 16 from schevo.placeholder import Placeholder 17 from schevo.store.btree import BTree18 from schevo.store.persistent_dict import PersistentDict as PDict19 17 from schevo.trace import log 20 18 … … 65 63 links_created = [] 66 64 lc_append = links_created.append 65 BTree = self._BTree 66 PDict = self._PDict 67 67 try: 68 68 if oid is None: … … 111 111 else: 112 112 relaxed = None 113 _index_add(extent_map, index_spec, relaxed, oid, field_values) 113 _index_add(extent_map, index_spec, relaxed, oid, field_values, 114 BTree) 114 115 ia_append((extent_map, index_spec, oid, field_values)) 115 116 # Update links from this entity to another entity. … … 178 179 deletes.update([(extent_name_id[del_entity_cls.__name__], del_oid) 179 180 for del_entity_cls, del_oid in tx._known_deletes]) 180 for (other_extent_id, other_field_id), others in links.ite ms():181 for (other_extent_id, other_field_id), others in links.iteritems(): 181 182 for other_oid in others: 182 183 if (other_extent_id, other_oid) in deletes: … … 291 292 # Return all of them. 292 293 assert log(2, 'Return all oids.') 293 return entity_maps.keys()294 return list(entity_maps.keys()) 294 295 extent_name_id = self._extent_name_id 295 296 indices = extent_map['indices'] 296 assert log(3, 'indices.keys()', indices.keys())297 297 normalized_index_map = extent_map['normalized_index_map'] 298 assert log(3, 'normalized_index_map.keys()',299 normalized_index_map.keys())300 298 entity_field_ids = extent_map['entity_field_ids'] 301 299 field_name_id = extent_map['field_name_id'] … … 346 344 if field_value not in branch: 347 345 # No matches found. 348 assert log(3, field_value, 'not found in', branch.keys())349 346 match = False 350 347 break … … 353 350 # Now we're at a leaf that matches all of the 354 351 # criteria, so return the OIDs in that leaf. 355 results = branch.keys()352 results = list(branch.keys()) 356 353 else: 357 354 # Fields aren't indexed, so use brute force. … … 407 404 lc_append = links_created.append 408 405 ld_append = links_deleted.append 406 BTree = self._BTree 409 407 try: 410 408 # Get old values for use in a potential inversion. … … 479 477 else: 480 478 relaxed = None 481 _index_add(extent_map, index_spec, relaxed, oid, field_values) 479 _index_add(extent_map, index_spec, relaxed, oid, field_values, 480 BTree) 482 481 ia_append((extent_map, index_spec, oid, field_values)) 483 482 # Update links from this entity to another entity. … … 520 519 _index_remove(_e, _i, _o, _f) 521 520 for _e, _i, _r, _o, _f in indices_removed: 522 _index_add(_e, _i, _r, _o, _f )521 _index_add(_e, _i, _r, _o, _f, BTree) 523 522 for other_entity_map, links, link_key, oid in links_created: 524 523 del links[link_key][oid] … … 532 531 """Create or update Schevo structures in the database.""" 533 532 root = self._root 534 if 'SCHEVO' not in root.keys(): 533 PDict = self._PDict 534 if 'SCHEVO' not in root: 535 535 schevo = root['SCHEVO'] = PDict() 536 536 schevo['format'] = 1 trunk/Schevo/schevo/database2.py
r3382 r3509 28 28 import schevo.schema 29 29 from schevo.signal import TransactionExecuted 30 from schevo.store.btree import BTree31 from schevo.store.persistent_dict import PersistentDict as PDict32 from schevo.store.persistent_list import PersistentList as PList33 30 from schevo.trace import log 34 31 from schevo.transaction import ( … … 37 34 38 35 class Database(base.Database): 39 """Schevo database, format 2 , using schevo.store as an object store.36 """Schevo database, format 2. 40 37 41 38 See doc/SchevoInternalDatabaseStructures.txt for detailed information on … … 43 40 """ 44 41 45 label = 'Schevo Database'46 47 42 # By default, don't dispatch signals. Set to True to dispatch 48 43 # TransactionExecuted signals. … … 53 48 write_lock = dummy_lock 54 49 55 def __init__(self, connection):50 def __init__(self, backend): 56 51 """Create a database. 57 52 58 - ` connection`: The Durus connectionto use.53 - `backend`: The storage backend instance to use. 59 54 """ 60 self.connection = connection 61 self._root = connection.get_root() 55 self.backend = backend 56 self._BTree = backend.BTree 57 self._PDict = backend.PDict 58 self._PList = backend.PList 59 self._root = backend.get_root() 62 60 # Shortcuts to coarse-grained commit and rollback. 63 self._commit = connection.commit64 self._rollback = connection.abort61 self._commit = backend.commit 62 self._rollback = backend.rollback 65 63 # Keep track of schema modules remembered. 66 64 self._remembered = [] … … 98 96 p.pop().close() 99 97 assert log(1, 'Closing storage.') 100 self.connection.storage.close() 101 del self.connection 98 self.backend.close() 102 99 remembered = self._remembered 103 100 while remembered: … … 227 224 """Pack the database.""" 228 225 if os.environ.get('SCHEVO_NOPACK', '').strip() != '1': 229 self. connection.pack()226 self.backend.pack() 230 227 231 228 def populate(self, sample_name=''): … … 245 242 def version(self): 246 243 return self._root['SCHEVO']['version'] 244 245 def _get_label(self): 246 SCHEVO = self._root['SCHEVO'] 247 if 'label' not in SCHEVO: 248 # Older database, no label stored in it. 249 return u'Schevo Database' 250 else: 251 return SCHEVO['label'] 252 253 def _set_label(self, new_label): 254 if self._executing: 255 raise error.DatabaseExecutingTransaction( 256 'Cannot change database label while executing a transaction.') 257 self._root['SCHEVO']['label'] = unicode(new_label) 258 self._commit() 259 260 label = property(_get_label, _set_label) 261 _label = property(_get_label, _set_label) 247 262 248 263 def _append_change(self, typ, extent_name, oid): … … 327 342 links_created = [] 328 343 lc_append = links_created.append 344 BTree = self._BTree 345 PDict = self._PDict 329 346 try: 330 347 if oid is None: … … 369 386 else: 370 387 relaxed = None 371 _index_add(extent_map, index_spec, relaxed, oid, field_values) 388 _index_add(extent_map, index_spec, relaxed, oid, field_values, 389 BTree) 372 390 ia_append((extent_map, index_spec, oid, field_values)) 373 391 # Update links from this entity to another entity. … … 438 456 deletes.update([(extent_name_id[del_entity_cls.__name__], del_oid) 439 457 for del_entity_cls, del_oid in tx._known_deletes]) 440 for (other_extent_id, other_field_id), others in links.ite ms():458 for (other_extent_id, other_field_id), others in links.iteritems(): 441 459 for other_oid in others: 442 460 if (other_extent_id, other_oid) in deletes: … … 472 490 other_extent_map = extent_maps_by_id[other_extent_id] 473 491 if other_oid in other_extent_map['entities']: 474 other_entity_map = other_extent_map['entities'][other_oid] 492 other_entity_map = other_extent_map[ 493 'entities'][other_oid] 475 494 links = other_entity_map['links'] 476 495 other_links = links[link_key] … … 528 547 # If no more transactions have relaxed this index, enforce it. 529 548 if not txns: 549 BTree = self._BTree 530 550 for _extent_map, _index_spec, _oid, _field_values in added: 531 _index_validate(_extent_map, _index_spec, _oid, _field_values) 551 _index_validate(_extent_map, _index_spec, _oid, _field_values, 552 BTree) 532 553 533 554 def _entity(self, extent_name, oid): … … 599 620 btree = entity_links.get(key, {}) 600 621 if return_count: 601 count = len(btree .keys()) # XXX Optimization opportunity.602 assert log(2, 'returning len(btree .keys())', count)622 count = len(btree) 623 assert log(2, 'returning len(btree)', count) 603 624 return count 604 625 el
