@@ -469,28 +469,47 @@ struct SQLiteWorkspaceDictionary: WorkspaceDictionary {
469469 for i in 0 ..< Storage . size {
470470 storage. lock ( i)
471471 defer { storage. unlock ( i) }
472- keys. formUnion (
473- storage. dictionaries [ i] . compactMap { ( key, value) -> String ? in
474- guard !( value is None ) else { return nil }
475- return key
476- } )
472+ for (key, value) in storage. dictionaries [ i] {
473+ // Remove it, it doesn't exist any more from disk.
474+ if value is None {
475+ keys. remove ( key)
476+ } else {
477+ keys. insert ( key)
478+ }
479+ }
477480 }
478481 return Array ( keys)
479482 }
480483
481484 func removeAll( ) {
485+ let namespace = storage. namespace
486+ let items = workspace. fetch ( for: DictItem . self) . where ( DictItem . namespace == namespace)
487+ var keys = [ [ String] ] ( repeating: [ ] , count: Storage . size)
488+ for key in items. lazy. map ( \. key) {
489+ var hasher = Hasher ( )
490+ key. hash ( into: & hasher)
491+ let hashValue = Int ( UInt ( bitPattern: hasher. finalize ( ) ) % UInt( Storage . size) )
492+ keys [ hashValue] . append ( key)
493+ }
482494 for i in 0 ..< Storage . size {
483495 storage. lock ( i)
484496 defer { storage. unlock ( i) }
497+ // Set existing ones in the dictionaries to be None.
485498 for key in storage. dictionaries [ i] . keys {
486499 storage. dictionaries [ i] [ key] = None . none
487500 }
501+ // Set the ones fetched from disk to be None.
502+ for key in keys [ i] {
503+ storage. dictionaries [ i] [ key] = None . none
504+ }
488505 }
489506 let workspace = self . workspace
490- let namespace = storage. namespace
491507 workspace. performChanges (
492508 [ DictItem . self] ,
493509 changesHandler: { txnContext in
510+ // Note that any insertions / updates after removeAll will be queued after this.
511+ // We need to fetch again because we may have pending writes that not available
512+ // when do the fetching in the beginning of removeAll.
494513 let items = workspace. fetch ( for: DictItem . self) . where ( DictItem . namespace == namespace)
495514 for item in items {
496515 if let deletionRequest = DictItemChangeRequest . deletionRequest ( item) {
0 commit comments