Chromium Code Reviews| Index: pkg/analysis_server/lib/src/services/index/store/split_store.dart |
| diff --git a/pkg/analysis_server/lib/src/services/index/store/split_store.dart b/pkg/analysis_server/lib/src/services/index/store/split_store.dart |
| index 8d94d740adb63dd3b424b6263a85224f644683d2..a66b2710c9d48c33e0042275759836c8fe3c8ed9 100644 |
| --- a/pkg/analysis_server/lib/src/services/index/store/split_store.dart |
| +++ b/pkg/analysis_server/lib/src/services/index/store/split_store.dart |
| @@ -22,6 +22,190 @@ import 'package:analyzer/src/generated/source.dart'; |
| import 'package:analyzer/src/generated/utilities_general.dart'; |
| /** |
| + * The implementation of [IndexObjectManager] for indexing |
| + * [CompilationUnitElement]s. |
| + */ |
| +class DartUnitIndexObjectManager extends IndexObjectManager { |
| + /** |
| + * The mapping of library [Source] to the [Source]s of part units. |
| + */ |
| + Map<AnalysisContext, Map<Source, Set<Source>>> _contextToLibraryToUnits = |
| + new HashMap<AnalysisContext, Map<Source, Set<Source>>>(); |
| + |
| + /** |
| + * The mapping of unit [Source] to the [Source]s of libraries it is used in. |
| + */ |
| + Map<AnalysisContext, Map<Source, Set<Source>>> _contextToUnitToLibraries = |
| + new HashMap<AnalysisContext, Map<Source, Set<Source>>>(); |
| + |
| + @override |
| + String aboutToIndex(AnalysisContext context, Object object) { |
| + // may be already disposed in other thread |
|
Brian Wilkerson
2015/09/22 19:22:37
nit: Minimally, the comment is out of date, given
|
| + if (context.isDisposed) { |
| + return null; |
| + } |
| + // validate object |
| + if (object is! CompilationUnitElement) { |
| + return null; |
| + } |
| + CompilationUnitElement unitElement = object; |
| + // validate unit |
| + if (unitElement == null) { |
| + return null; |
| + } |
| + LibraryElement libraryElement = unitElement.library; |
| + if (libraryElement == null) { |
| + return null; |
| + } |
| + CompilationUnitElement definingUnitElement = |
| + libraryElement.definingCompilationUnit; |
| + if (definingUnitElement == null) { |
| + return null; |
| + } |
| + // prepare sources |
| + Source library = definingUnitElement.source; |
| + Source unit = unitElement.source; |
| + // special handling for the defining library unit |
| + if (unit == library) { |
| + // prepare new parts |
| + HashSet<Source> newParts = new HashSet<Source>(); |
| + for (CompilationUnitElement part in libraryElement.parts) { |
| + newParts.add(part.source); |
| + } |
| + // prepare old parts |
| + Map<Source, Set<Source>> libraryToUnits = |
| + _contextToLibraryToUnits[context]; |
| + if (libraryToUnits == null) { |
| + libraryToUnits = new HashMap<Source, Set<Source>>(); |
| + _contextToLibraryToUnits[context] = libraryToUnits; |
| + } |
| + Set<Source> oldParts = libraryToUnits[library]; |
| + // check if some parts are not in the library now |
| + if (oldParts != null) { |
| + Set<Source> noParts = oldParts.difference(newParts); |
| + for (Source noPart in noParts) { |
| + String nodeName = _getNodeName(library, noPart); |
| + site.removeNodeByName(context, nodeName); |
| + site.removeSource(library); |
| + site.removeSource(noPart); |
| + } |
| + } |
| + // remember new parts |
| + libraryToUnits[library] = newParts; |
| + } |
| + // remember library/unit relations |
| + _recordUnitInLibrary(context, library, unit); |
| + _recordLibraryWithUnit(context, library, unit); |
| + site.addSource(library); |
| + site.addSource(unit); |
| + // prepare node |
| + String nodeName = _getNodeName(library, unit); |
| + return nodeName; |
| + } |
| + |
| + @override |
| + void removeContext(AnalysisContext context) { |
| + _contextToLibraryToUnits.remove(context); |
| + _contextToUnitToLibraries.remove(context); |
| + } |
| + |
| + @override |
| + void removeSource(AnalysisContext context, Source source) { |
| + // remove nodes for unit/library pairs |
| + Map<Source, Set<Source>> unitToLibraries = |
| + _contextToUnitToLibraries[context]; |
| + if (unitToLibraries != null) { |
| + Set<Source> libraries = unitToLibraries.remove(source); |
| + if (libraries != null) { |
| + for (Source library in libraries) { |
| + String nodeName = _getNodeName(library, source); |
| + site.removeNodeByName(context, nodeName); |
| + site.removeSource(library); |
| + site.removeSource(source); |
| + } |
| + } |
| + } |
| + // remove nodes for library/unit pairs |
| + Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context]; |
| + if (libraryToUnits != null) { |
| + Set<Source> units = libraryToUnits.remove(source); |
| + if (units != null) { |
| + for (Source unit in units) { |
| + String nodeName = _getNodeName(source, unit); |
| + site.removeNodeByName(context, nodeName); |
| + site.removeSource(source); |
| + site.removeSource(unit); |
| + } |
| + } |
| + } |
| + } |
| + |
| + @override |
| + void removeSources(AnalysisContext context, SourceContainer container) { |
| + // remove nodes for unit/library pairs |
| + Map<Source, Set<Source>> unitToLibraries = |
| + _contextToUnitToLibraries[context]; |
| + if (unitToLibraries != null) { |
| + List<Source> units = unitToLibraries.keys.toList(); |
| + for (Source source in units) { |
| + if (container == null || container.contains(source)) { |
| + removeSource(context, source); |
| + } |
| + } |
| + } |
| + // remove nodes for library/unit pairs |
| + Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context]; |
| + if (libraryToUnits != null) { |
| + List<Source> libraries = libraryToUnits.keys.toList(); |
| + for (Source source in libraries) { |
| + if (container == null || container.contains(source)) { |
| + removeSource(context, source); |
| + } |
| + } |
| + } |
| + } |
| + |
| + String _getNodeName(Source library, Source unit) { |
| + String libraryName = library != null ? library.fullName : null; |
| + String unitName = unit.fullName; |
| + int libraryNameIndex = site.encodeString(libraryName); |
| + int unitNameIndex = site.encodeString(unitName); |
| + return 'DartUnitElement_${libraryNameIndex}_${unitNameIndex}.index'; |
| + } |
| + |
| + void _recordLibraryWithUnit( |
| + AnalysisContext context, Source library, Source unit) { |
| + Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context]; |
| + if (libraryToUnits == null) { |
| + libraryToUnits = new HashMap<Source, Set<Source>>(); |
| + _contextToLibraryToUnits[context] = libraryToUnits; |
| + } |
| + Set<Source> units = libraryToUnits[library]; |
| + if (units == null) { |
| + units = new HashSet<Source>(); |
| + libraryToUnits[library] = units; |
| + } |
| + units.add(unit); |
| + } |
| + |
| + void _recordUnitInLibrary( |
| + AnalysisContext context, Source library, Source unit) { |
| + Map<Source, Set<Source>> unitToLibraries = |
| + _contextToUnitToLibraries[context]; |
| + if (unitToLibraries == null) { |
| + unitToLibraries = new HashMap<Source, Set<Source>>(); |
| + _contextToUnitToLibraries[context] = unitToLibraries; |
| + } |
| + Set<Source> libraries = unitToLibraries[unit]; |
| + if (libraries == null) { |
| + libraries = new HashSet<Source>(); |
| + unitToLibraries[unit] = libraries; |
| + } |
| + libraries.add(library); |
| + } |
| +} |
| + |
| +/** |
| * A manager for files content. |
| */ |
| abstract class FileManager { |
| @@ -341,6 +525,36 @@ class IndexNode { |
| } |
| } |
| +/** |
| + * [SplitIndexStore] uses instances of this class to manager index nodes. |
| + */ |
| +abstract class IndexObjectManager { |
| + SplitIndexStoreSite site; |
| + |
| + /** |
| + * Notifies the manager that the given [object] is to be indexed. |
| + * Returns the name of the index node to put information into. |
| + */ |
| + String aboutToIndex(AnalysisContext context, Object object); |
| + |
| + /** |
| + * Notifies the manager that the given [context] is disposed. |
| + */ |
| + void removeContext(AnalysisContext context); |
| + |
| + /** |
| + * Notifies the manager that the given [source] is no longer part of |
| + * the given [context]. |
| + */ |
| + void removeSource(AnalysisContext context, Source source); |
| + |
| + /** |
| + * Notifies the manager that the sources described by the given [container] |
| + * are no longer part of the given [context]. |
| + */ |
| + void removeSources(AnalysisContext context, SourceContainer container); |
| +} |
| + |
| class InspectLocation { |
| final String nodeName; |
| final RelationshipImpl relationship; |
| @@ -526,70 +740,62 @@ class RelationKeyData { |
| */ |
| class SplitIndexStore implements InternalIndexStore { |
| /** |
| - * The [ContextCodec] to encode/decode [AnalysisContext]s. |
| + * The [NodeManager] to get/put [IndexNode]s. |
| */ |
| - ContextCodec _contextCodec; |
| + final NodeManager _nodeManager; |
| + |
| + final List<IndexObjectManager> _objectManagers; |
| /** |
| - * Information about top-level elements. |
| - * We need to keep them together to avoid loading of all index nodes. |
| - * |
| - * Order of keys: contextId, nodeId. |
| + * The [ContextCodec] to encode/decode [AnalysisContext]s. |
| */ |
| - Map<int, Map<int, List<_TopElementData>>> _topDeclarations = |
| - new Map<int, Map<int, List<_TopElementData>>>(); |
| + final ContextCodec _contextCodec; |
| /** |
| - * The mapping of library [Source] to the [Source]s of part units. |
| + * The [ElementCodec] to encode/decode [Element]s. |
| */ |
| - Map<AnalysisContext, Map<Source, Set<Source>>> _contextToLibraryToUnits = |
| - new HashMap<AnalysisContext, Map<Source, Set<Source>>>(); |
| + final ElementCodec _elementCodec; |
| /** |
| - * The mapping of unit [Source] to the [Source]s of libraries it is used in. |
| + * The [StringCodec] to encode/decode [String]s. |
| */ |
| - Map<AnalysisContext, Map<Source, Set<Source>>> _contextToUnitToLibraries = |
| - new HashMap<AnalysisContext, Map<Source, Set<Source>>>(); |
| - |
| - int _currentContextId = 0; |
| - |
| - IndexNode _currentNode; |
| - |
| - String _currentNodeName; |
| - |
| - int _currentNodeNameId = 0; |
| + final StringCodec _stringCodec; |
| /** |
| - * The [ElementCodec] to encode/decode [Element]s. |
| + * Information about top-level elements. |
| + * We need to keep them together to avoid loading of all index nodes. |
| + * |
| + * Order of keys: contextId, nodeId. |
| */ |
| - ElementCodec _elementCodec; |
| + final Map<int, Map<int, List<_TopElementData>>> _topDeclarations = |
| + new Map<int, Map<int, List<_TopElementData>>>(); |
| + |
| + int _currentContextId; |
| + String _currentNodeName; |
| + int _currentNodeNameId; |
| + IndexNode _currentNode; |
| /** |
| * A table mapping element names to the node names that may have relations with elements with |
| * these names. |
| */ |
| - Map<RelationshipImpl, IntToIntSetMap> _relToNameMap = |
| + final Map<RelationshipImpl, IntToIntSetMap> _relToNameMap = |
| new HashMap<RelationshipImpl, IntToIntSetMap>(); |
| /** |
| - * The [NodeManager] to get/put [IndexNode]s. |
| - */ |
| - final NodeManager _nodeManager; |
| - |
| - /** |
| * The set of known [Source]s. |
| */ |
| - Set<Source> _sources = new HashSet<Source>(); |
| - |
| - /** |
| - * The [StringCodec] to encode/decode [String]s. |
| - */ |
| - StringCodec _stringCodec; |
| - |
| - SplitIndexStore(this._nodeManager) { |
| - this._contextCodec = _nodeManager.contextCodec; |
| - this._elementCodec = _nodeManager.elementCodec; |
| - this._stringCodec = _nodeManager.stringCodec; |
| + final Set<Source> _sources = new HashSet<Source>(); |
| + |
| + SplitIndexStore(NodeManager _nodeManager, this._objectManagers) |
| + : _nodeManager = _nodeManager, |
| + _contextCodec = _nodeManager.contextCodec, |
| + _elementCodec = _nodeManager.elementCodec, |
| + _stringCodec = _nodeManager.stringCodec { |
| + SplitIndexStoreSiteImpl site = new SplitIndexStoreSiteImpl(this); |
| + for (IndexObjectManager manager in _objectManagers) { |
| + manager.site = site; |
| + } |
| } |
| @override |
| @@ -608,64 +814,23 @@ class SplitIndexStore implements InternalIndexStore { |
| } |
| @override |
| - bool aboutToIndexDart( |
| - AnalysisContext context, CompilationUnitElement unitElement) { |
| + bool aboutToIndex(AnalysisContext context, Object object) { |
| // may be already disposed in other thread |
| if (context.isDisposed) { |
| return false; |
| } |
| - // validate unit |
| - if (unitElement == null) { |
| - return false; |
| + // try to find a node name |
| + _currentNodeName = null; |
| + for (IndexObjectManager manager in _objectManagers) { |
| + _currentNodeName = manager.aboutToIndex(context, object); |
| + if (_currentNodeName != null) { |
| + break; |
| + } |
| } |
| - LibraryElement libraryElement = unitElement.library; |
| - if (libraryElement == null) { |
| + if (_currentNodeName == null) { |
| return false; |
| } |
| - CompilationUnitElement definingUnitElement = |
| - libraryElement.definingCompilationUnit; |
| - if (definingUnitElement == null) { |
| - return false; |
| - } |
| - // prepare sources |
| - Source library = definingUnitElement.source; |
| - Source unit = unitElement.source; |
| - // special handling for the defining library unit |
| - if (unit == library) { |
| - // prepare new parts |
| - HashSet<Source> newParts = new HashSet<Source>(); |
| - for (CompilationUnitElement part in libraryElement.parts) { |
| - newParts.add(part.source); |
| - } |
| - // prepare old parts |
| - Map<Source, Set<Source>> libraryToUnits = |
| - _contextToLibraryToUnits[context]; |
| - if (libraryToUnits == null) { |
| - libraryToUnits = new HashMap<Source, Set<Source>>(); |
| - _contextToLibraryToUnits[context] = libraryToUnits; |
| - } |
| - Set<Source> oldParts = libraryToUnits[library]; |
| - // check if some parts are not in the library now |
| - if (oldParts != null) { |
| - Set<Source> noParts = oldParts.difference(newParts); |
| - for (Source noPart in noParts) { |
| - _removeLocations(context, library, noPart); |
| - } |
| - } |
| - // remember new parts |
| - libraryToUnits[library] = newParts; |
| - } |
| - // remember library/unit relations |
| - _recordUnitInLibrary(context, library, unit); |
| - _recordLibraryWithUnit(context, library, unit); |
| - _sources.add(library); |
| - _sources.add(unit); |
| // prepare node |
| - String libraryName = library.fullName; |
| - String unitName = unit.fullName; |
| - int libraryNameIndex = _stringCodec.encode(libraryName); |
| - int unitNameIndex = _stringCodec.encode(unitName); |
| - _currentNodeName = '${libraryNameIndex}_${unitNameIndex}.index'; |
| _currentNodeNameId = _stringCodec.encode(_currentNodeName); |
| _currentNode = _nodeManager.newNode(context); |
| _currentContextId = _contextCodec.encode(context); |
| @@ -678,27 +843,7 @@ class SplitIndexStore implements InternalIndexStore { |
| } |
| @override |
| - bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement) { |
| - // may be already disposed in other thread |
| - if (context.isDisposed) { |
| - return false; |
| - } |
| - // remove locations |
| - Source source = htmlElement.source; |
| - _removeLocations(context, null, source); |
| - // remember library/unit relations |
| - _recordUnitInLibrary(context, null, source); |
| - // prepare node |
| - String sourceName = source.fullName; |
| - int sourceNameIndex = _stringCodec.encode(sourceName); |
| - _currentNodeName = '${sourceNameIndex}.index'; |
| - _currentNodeNameId = _stringCodec.encode(_currentNodeName); |
| - _currentNode = _nodeManager.newNode(context); |
| - return true; |
| - } |
| - |
| - @override |
| - void cancelIndexDart() { |
| + void cancelIndex() { |
| if (_currentNode != null) { |
| // remove top-level information for the current node |
| for (Map<int, dynamic> nodeRelations in _topDeclarations.values) { |
| @@ -875,8 +1020,9 @@ class SplitIndexStore implements InternalIndexStore { |
| // remove sources |
| removeSources(context, null); |
| // remove context information |
| - _contextToLibraryToUnits.remove(context); |
| - _contextToUnitToLibraries.remove(context); |
| + for (IndexObjectManager manager in _objectManagers) { |
| + manager.removeContext(context); |
| + } |
| _topDeclarations.remove(_contextCodec.encode(context)); |
| // remove context from codec |
| _contextCodec.remove(context); |
| @@ -887,26 +1033,8 @@ class SplitIndexStore implements InternalIndexStore { |
| if (context == null) { |
| return; |
| } |
| - // remove nodes for unit/library pairs |
| - Map<Source, Set<Source>> unitToLibraries = |
| - _contextToUnitToLibraries[context]; |
| - if (unitToLibraries != null) { |
| - Set<Source> libraries = unitToLibraries.remove(source); |
| - if (libraries != null) { |
| - for (Source library in libraries) { |
| - _removeLocations(context, library, source); |
| - } |
| - } |
| - } |
| - // remove nodes for library/unit pairs |
| - Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context]; |
| - if (libraryToUnits != null) { |
| - Set<Source> units = libraryToUnits.remove(source); |
| - if (units != null) { |
| - for (Source unit in units) { |
| - _removeLocations(context, source, unit); |
| - } |
| - } |
| + for (IndexObjectManager manager in _objectManagers) { |
| + manager.removeSource(context, source); |
| } |
| } |
| @@ -915,44 +1043,11 @@ class SplitIndexStore implements InternalIndexStore { |
| if (context == null) { |
| return; |
| } |
| - // remove nodes for unit/library pairs |
| - Map<Source, Set<Source>> unitToLibraries = |
| - _contextToUnitToLibraries[context]; |
| - if (unitToLibraries != null) { |
| - List<Source> units = new List<Source>.from(unitToLibraries.keys); |
| - for (Source source in units) { |
| - if (container == null || container.contains(source)) { |
| - removeSource(context, source); |
| - } |
| - } |
| - } |
| - // remove nodes for library/unit pairs |
| - Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context]; |
| - if (libraryToUnits != null) { |
| - List<Source> libraries = new List<Source>.from(libraryToUnits.keys); |
| - for (Source source in libraries) { |
| - if (container == null || container.contains(source)) { |
| - removeSource(context, source); |
| - } |
| - } |
| + for (IndexObjectManager manager in _objectManagers) { |
| + manager.removeSources(context, container); |
| } |
| } |
| - void _recordLibraryWithUnit( |
| - AnalysisContext context, Source library, Source unit) { |
| - Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context]; |
| - if (libraryToUnits == null) { |
| - libraryToUnits = new HashMap<Source, Set<Source>>(); |
| - _contextToLibraryToUnits[context] = libraryToUnits; |
| - } |
| - Set<Source> units = libraryToUnits[library]; |
| - if (units == null) { |
| - units = new HashSet<Source>(); |
| - libraryToUnits[library] = units; |
| - } |
| - units.add(unit); |
| - } |
| - |
| void _recordNodeNameForElement( |
| IndexableObject indexable, RelationshipImpl relationship) { |
| IntToIntSetMap nameToNodeNames = _relToNameMap[relationship]; |
| @@ -964,37 +1059,9 @@ class SplitIndexStore implements InternalIndexStore { |
| nameToNodeNames.add(nameId, _currentNodeNameId); |
| } |
| - void _recordUnitInLibrary( |
| - AnalysisContext context, Source library, Source unit) { |
| - Map<Source, Set<Source>> unitToLibraries = |
| - _contextToUnitToLibraries[context]; |
| - if (unitToLibraries == null) { |
| - unitToLibraries = new HashMap<Source, Set<Source>>(); |
| - _contextToUnitToLibraries[context] = unitToLibraries; |
| - } |
| - Set<Source> libraries = unitToLibraries[unit]; |
| - if (libraries == null) { |
| - libraries = new HashSet<Source>(); |
| - unitToLibraries[unit] = libraries; |
| - } |
| - libraries.add(library); |
| - } |
| - |
| - /** |
| - * Removes locations recorded in the given library/unit pair. |
| - */ |
| - void _removeLocations(AnalysisContext context, Source library, Source unit) { |
| - // remove node |
| - String libraryName = library != null ? library.fullName : null; |
| - String unitName = unit.fullName; |
| - int libraryNameIndex = _stringCodec.encode(libraryName); |
| - int unitNameIndex = _stringCodec.encode(unitName); |
| - String nodeName = '${libraryNameIndex}_${unitNameIndex}.index'; |
| + void _removeNodeByName(AnalysisContext context, String nodeName) { |
| int nodeNameId = _stringCodec.encode(nodeName); |
| _nodeManager.removeNode(nodeName); |
| - // remove source |
| - _sources.remove(library); |
| - _sources.remove(unit); |
| // remove top-level relations |
| { |
| int contextId = _contextCodec.encode(context); |
| @@ -1006,6 +1073,45 @@ class SplitIndexStore implements InternalIndexStore { |
| } |
| } |
| +/** |
| + * Interface to [SplitIndexStore] for [IndexObjectManager] implementations. |
| + */ |
| +abstract class SplitIndexStoreSite { |
| + void addSource(Source source); |
| + int encodeString(String str); |
| + void removeNodeByName(AnalysisContext context, String nodeName); |
| + void removeSource(Source source); |
| +} |
| + |
| +/** |
| + * The implementaiton of [SplitIndexStoreSite]. |
| + */ |
| +class SplitIndexStoreSiteImpl implements SplitIndexStoreSite { |
| + final SplitIndexStore store; |
| + |
| + SplitIndexStoreSiteImpl(this.store); |
| + |
| + @override |
| + void addSource(Source source) { |
| + store._sources.add(source); |
| + } |
| + |
| + @override |
| + int encodeString(String str) { |
| + return store._stringCodec.encode(str); |
| + } |
| + |
| + @override |
| + void removeNodeByName(AnalysisContext context, String nodeName) { |
| + store._removeNodeByName(context, nodeName); |
| + } |
| + |
| + @override |
| + void removeSource(Source source) { |
| + store._sources.remove(source); |
| + } |
| +} |
| + |
| class _DataInputStream { |
| ByteData _byteData; |
| int _byteOffset = 0; |