storageIpc.ts ×22

Frontier kind: Code frontier

unlabeled · c_b189ce9e0b59

353 tests · 13577 LOC · 65 files · introduces 0 tests · 259 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
34 ranges259 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1870 ranges13577 lines · 65 files · Browse complete extent
All tests (intent)
353 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 259 introduced LOC across 34 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/storage/common/storageIpc.ts 150 introduced LOC · 22 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- storageIpc.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { Emitter, Event } from '../../../base/common/event.js';
7 > import { Disposable } from '../../../base/common/lifecycle.js';
8 > import { UriDto } from '../../../base/common/uri.js';
9 > import { IChannel } from '../../../base/parts/ipc/common/ipc.js';
10 > import { IStorageDatabase, IStorageItemsChangeEvent, IUpdateRequest } from '../../../base/parts/storage/common/storage.js';
11 > import { IUserDataProfile } from '../../userDataProfile/common/userDataProfile.js';
12 > import { ISerializedSingleFolderWorkspaceIdentifier, ISerializedWorkspaceIdentifier, IEmptyWorkspaceIdentifier, IAnyWorkspaceIdentifier } from '../../workspace/common/workspace.js';
13 >
14 > export type Key = string;
15 > export type Value = string;
16 > export type Item = [Key, Value];
17 >
18 > export interface IBaseSerializableStorageRequest {
19 >
20 > /**
21 > * Profile to correlate storage. Only used when no
22 > * workspace is provided. Can be undefined to denote
23 > * application scope.
24 > */
25 > readonly profile: UriDto<IUserDataProfile> | undefined;
26 >
27 > /**
28 > * Workspace to correlate storage. Can be undefined to
29 > * denote application or profile scope depending on profile.
30 > */
31 > readonly workspace: ISerializedWorkspaceIdentifier | ISerializedSingleFolderWorkspaceIdentifier | IEmptyWorkspaceIdentifier | undefined;
32 >
33 > /**
34 > * Whether this request targets the application shared storage
35 > * that is shared across VS Code and Sessions app.
36 > */
37 > readonly applicationShared?: boolean;
38 >
39 > /**
40 > * Additional payload for the request to perform.
41 > */
42 > readonly payload?: unknown;
43 > }
44 >
45 > export interface ISerializableUpdateRequest extends IBaseSerializableStorageRequest {
46 > insert?: Item[];
47 > delete?: Key[];
48 > }
49 >
50 > export interface ISerializableGetValueRequest extends IBaseSerializableStorageRequest {
51 > readonly key: Key;
52 > }
53 >
54 > export interface ISerializableCompareAndSwapRequest extends ISerializableGetValueRequest {
55 > readonly expectedValue: Value | undefined;
56 > readonly newValue: Value;
57 > }
58 >
59 > export interface ISerializableCompareAndSwapResult {
60 > readonly swapped: boolean;
61 > readonly currentValue: Value | undefined;
62 > }
63 >
64 > export interface ISerializableItemsChangeEvent {
65 > readonly changed?: Item[];
66 > readonly deleted?: Key[];
67 > }
68 >
69 > abstract class BaseStorageDatabaseClient extends Disposable implements IStorageDatabase {
70 >
71 > abstract readonly onDidChangeItemsExternal: Event<IStorageItemsChangeEvent>;
72 >
73 > protected get applicationShared(): boolean {
74 > return false;
75 > }
76 >
77 > constructor(
78 protected channel: IChannel,
79 protected profile: UriDto<IUserDataProfile> | undefined,
82 super();
83 }
85 > async getItems(): Promise<Map<string, string>> {
86 const serializableRequest: IBaseSerializableStorageRequest = { profile: this.profile, workspace: this.workspace, applicationShared: this.applicationShared };
87 const items: Item[] = await this.channel.call('getItems', serializableRequest);
89 return new Map(items);
90 }
92 > updateItems(request: IUpdateRequest): Promise<void> {
93 const serializableRequest: ISerializableUpdateRequest = { profile: this.profile, workspace: this.workspace, applicationShared: this.applicationShared };
94
103 return this.channel.call('updateItems', serializableRequest);
104 }
106 > optimize(): Promise<void> {
107 const serializableRequest: IBaseSerializableStorageRequest = { profile: this.profile, workspace: this.workspace, applicationShared: this.applicationShared };
108
109 return this.channel.call('optimize', serializableRequest);
110 }
112 > abstract close(): Promise<void>;
113 > }
114 >
115 > abstract class BaseProfileAwareStorageDatabaseClient extends BaseStorageDatabaseClient {
116 >
117 > private readonly _onDidChangeItemsExternal = this._register(new Emitter<IStorageItemsChangeEvent>());
118 > readonly onDidChangeItemsExternal = this._onDidChangeItemsExternal.event;
119 >
120 > constructor(channel: IChannel, profile: UriDto<IUserDataProfile> | undefined) {
121 super(channel, profile, undefined);
122
123 this.registerListeners();
124 }
126 > private registerListeners(): void {
127 this._register(this.channel.listen<ISerializableItemsChangeEvent>('onDidChangeStorage', { profile: this.profile, applicationShared: this.applicationShared })((e: ISerializableItemsChangeEvent) => this.onDidChangeStorage(e)));
128 }
130 > private onDidChangeStorage(e: ISerializableItemsChangeEvent): void {
131 if (Array.isArray(e.changed) || Array.isArray(e.deleted)) {
132 this._onDidChangeItemsExternal.fire({
136 }
137 }
138 > } storageIpc.ts
139 >
140 > export class ApplicationStorageDatabaseClient extends BaseProfileAwareStorageDatabaseClient {
141 >
142 > constructor(channel: IChannel) {
143 super(channel, undefined);
144 }
146 > async close(): Promise<void> {
147
148 // The application storage database is shared across all instances so
152 this.dispose();
153 }
154 > } storageIpc.ts
155 >
156 > export class ApplicationSharedStorageDatabaseClient extends BaseProfileAwareStorageDatabaseClient {
157 >
158 > constructor(channel: IChannel) {
159 super(channel, undefined);
160 }
162 > protected override get applicationShared(): boolean {
163 return true;
164 }
166 > async close(): Promise<void> {
167
168 // The application shared storage database is shared across all instances so
172 this.dispose();
173 }
174 > } storageIpc.ts
175 >
176 > export class ProfileStorageDatabaseClient extends BaseProfileAwareStorageDatabaseClient {
177 >
178 > async close(): Promise<void> {
179
180 // The profile storage database is shared across all instances of
185 this.dispose();
186 }
187 > } storageIpc.ts
188 >
189 > export class WorkspaceStorageDatabaseClient extends BaseStorageDatabaseClient implements IStorageDatabase {
190 >
191 > readonly onDidChangeItemsExternal = Event.None; // unsupported for workspace storage because we only ever write from one window
192 >
193 > constructor(channel: IChannel, workspace: IAnyWorkspaceIdentifier) {
194 super(channel, undefined, workspace);
195 }
197 > async close(): Promise<void> {
198
199 // The workspace storage database is only used in this instance
203 this.dispose();
204 }
205 > } storageIpc.ts
206 >
207 > export class StorageClient {
208 >
209 > constructor(private readonly channel: IChannel) { }
210 >
211 > isUsed(path: string): Promise<boolean> {
212 const serializableRequest: ISerializableUpdateRequest = { payload: path, profile: undefined, workspace: undefined };
213
214 return this.channel.call('isUsed', serializableRequest);
215 }
216 > } storageIpc.ts
217 >
218 > export class FallbackApplicationStorageDatabaseClient extends Disposable implements IStorageDatabase {
219 >
220 > onDidChangeItemsExternal = Event.None;
221 >
222 > constructor(private readonly channel: IChannel) {
223 super();
224 }
226 > async getItems(): Promise<Map<string, string>> {
227 const serializableRequest: IBaseSerializableStorageRequest = { profile: undefined, workspace: undefined, applicationShared: true };
228 const items: Item[] = await this.channel.call('getFallbackApplicationStorageItems', serializableRequest);
229 return new Map(items);
230 }
232 > updateItems(): Promise<void> {
233 throw new Error('Not supported');
234 }
236 > optimize(): Promise<void> {
237 throw new Error('Not supported');
238 }
240 > close(): Promise<void> {
241 throw new Error('Not supported');
242 }
243 > } storageIpc.ts
src/vs/platform/userDataProfile/common/userDataProfileStorageService.ts 109 introduced LOC · 12 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- userDataProfileStorageService.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { Disposable, DisposableMap, MutableDisposable, isDisposable, toDisposable } from '../../../base/common/lifecycle.js';
7 > import { IStorage, IStorageDatabase, Storage } from '../../../base/parts/storage/common/storage.js';
8 > import { createDecorator } from '../../instantiation/common/instantiation.js';
9 > import { AbstractStorageService, IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget, isProfileUsingDefaultStorage } from '../../storage/common/storage.js';
10 > import { Emitter, Event } from '../../../base/common/event.js';
11 > import { IRemoteService } from '../../ipc/common/services.js';
12 > import { ILogService } from '../../log/common/log.js';
13 > import { ApplicationStorageDatabaseClient, ProfileStorageDatabaseClient } from '../../storage/common/storageIpc.js';
14 > import { IUserDataProfile, IUserDataProfilesService, reviveProfile } from './userDataProfile.js';
15 >
16 > export interface IProfileStorageValueChanges {
17 > readonly profile: IUserDataProfile;
18 > readonly changes: IStorageValueChangeEvent[];
19 > }
20 >
21 > export interface IProfileStorageChanges {
22 > readonly targetChanges: IUserDataProfile[];
23 > readonly valueChanges: IProfileStorageValueChanges[];
24 > }
25 >
26 > export interface IStorageValue {
27 > readonly value: string | undefined;
28 > readonly target: StorageTarget;
29 > readonly scope?: StorageScope;
30 > }
31 >
32 > export const IUserDataProfileStorageService = createDecorator<IUserDataProfileStorageService>('IUserDataProfileStorageService');
33 > export interface IUserDataProfileStorageService {
34 > readonly _serviceBrand: undefined;
35 >
36 > /**
37 > * Emitted whenever data is updated or deleted in a profile storage or target of a profile storage entry changes
38 > */
39 > readonly onDidChange: Event<IProfileStorageChanges>;
40 >
41 > /**
42 > * Return the requested profile storage data
43 > * @param profile The profile from which the data has to be read from
44 > */
45 > readStorageData(profile: IUserDataProfile): Promise<Map<string, IStorageValue>>;
46 >
47 > /**
48 > * Update the given profile storage data in the profile storage
49 > * @param profile The profile to which the data has to be written to
50 > * @param data Data that has to be updated
51 > * @param target Storage target of the data
52 > * @param scope Storage scope of the data (defaults to PROFILE)
53 > */
54 > updateStorageData(profile: IUserDataProfile, data: Map<string, string | undefined | null>, target: StorageTarget, scope?: StorageScope): Promise<void>;
55 >
56 > /**
57 > * Calls a function with a storage service scoped to given profile.
58 > */
59 > withProfileScopedStorageService<T>(profile: IUserDataProfile, fn: (storageService: IStorageService) => Promise<T>): Promise<T>;
60 > }
61 >
62 > export abstract class AbstractUserDataProfileStorageService extends Disposable implements IUserDataProfileStorageService {
63 >
64 > _serviceBrand: undefined;
65 >
66 > readonly abstract onDidChange: Event<IProfileStorageChanges>;
67 >
68 > private readonly storageServicesMap: DisposableMap<string, StorageService> | undefined;
69 >
70 > constructor(
71 persistStorages: boolean,
72 @IStorageService protected readonly storageService: IStorageService
77 }
78 }
80 > async readStorageData(profile: IUserDataProfile): Promise<Map<string, IStorageValue>> {
81 return this.withProfileScopedStorageService(profile, async storageService => this.getItems(storageService, profile));
82 }
84 > async updateStorageData(profile: IUserDataProfile, data: Map<string, string | undefined | null>, target: StorageTarget, scope = StorageScope.PROFILE): Promise<void> {
85 return this.withProfileScopedStorageService(profile, async storageService => this.writeItems(storageService, data, target, scope));
86 }
88 > async withProfileScopedStorageService<T>(profile: IUserDataProfile, fn: (storageService: IStorageService) => Promise<T>): Promise<T> {
89 if (this.storageService.hasScope(profile)) {
90 return fn(this.storageService);
117 }
118 }
120 > private getItems(storageService: IStorageService, profile: IUserDataProfile): Map<string, IStorageValue> {
121 const result = new Map<string, IStorageValue>();
122 const populate = (scope: StorageScope, target: StorageTarget) => {
133 return result;
134 }
136 > private writeItems(storageService: IStorageService, items: Map<string, string | undefined | null>, target: StorageTarget, scope = StorageScope.PROFILE): void {
137 storageService.storeAll(Array.from(items.entries()).map(([key, value]) => ({ key, value, scope, target })), true);
138 }
140 > protected abstract createStorageDatabase(profile: IUserDataProfile): Promise<IStorageDatabase>;
141 > }
142 >
143 > export class RemoteUserDataProfileStorageService extends AbstractUserDataProfileStorageService implements IUserDataProfileStorageService {
144 >
145 > private readonly _onDidChange: Emitter<IProfileStorageChanges>;
146 > readonly onDidChange: Event<IProfileStorageChanges>;
147 >
148 > constructor(
149 persistStorages: boolean,
150 private readonly remoteService: IRemoteService,
173 this.onDidChange = this._onDidChange.event;
174 }
176 > protected async createStorageDatabase(profile: IUserDataProfile): Promise<IStorageDatabase> {
177 const storageChannel = this.remoteService.getChannel('storage');
178 return isProfileUsingDefaultStorage(profile) ? new ApplicationStorageDatabaseClient(storageChannel) : new ProfileStorageDatabaseClient(storageChannel, profile);
179 }
181 >
182 > class StorageService extends AbstractStorageService {
183 >
184 > private profileStorage: IStorage | undefined;
185 >
186 > constructor(private readonly profileStorageDatabase: Promise<IStorageDatabase>) {
187 super({ flushInterval: 100 });
188 }
190 > protected async doInitialize(): Promise<void> {
191 const profileStorageDatabase = await this.profileStorageDatabase;
192 const profileStorage = new Storage(profileStorageDatabase);
204 return this.profileStorage.init();
205 }
207 > protected getStorage(scope: StorageScope): IStorage | undefined {
208 return scope === StorageScope.PROFILE ? this.profileStorage : undefined;
209 }
211 > protected getLogDetails(): string | undefined { return undefined; }
212 > protected async switchToProfile(): Promise<void> { }
213 > protected async switchToWorkspace(): Promise<void> { }
214 > hasScope() { return false; }
215 > }