Skip to content

Commit

Permalink
feat: read chunks from cached files
Browse files Browse the repository at this point in the history
  • Loading branch information
JoanVicens committed Mar 20, 2024
1 parent 63792fa commit e6afb04
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 26 deletions.
5 changes: 4 additions & 1 deletion src/apps/fuse/FuseApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ export class FuseApp {
this.fuseContainer.offlineDriveContainer
);
const open = new OpenCallback(this.fuseContainer.virtualDriveContainer);
const read = new ReadCallback(this.fuseContainer.virtualDriveContainer);
const read = new ReadCallback(
this.fuseContainer.virtualDriveContainer,
this.fuseContainer.offlineDriveContainer
);
const renameOrMove = new RenameOrMoveCallback(
this.fuseContainer.virtualDriveContainer
);
Expand Down
4 changes: 2 additions & 2 deletions src/apps/fuse/callbacks/FuseErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export class FuseError extends Error {
}

export class FuseNoSuchFileOrDirectoryError extends FuseError {
constructor() {
super(FuseCodes.ENOENT, 'No such file or directory');
constructor(readonly path: string) {
super(FuseCodes.ENOENT, `No such file or directory <${path}>`);
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/apps/fuse/callbacks/GetAttributesCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ export class GetAttributesCallback extends FuseCallback<GetAttributesCallbackDat
}

protected left(
error: FuseError
error: FuseNoSuchFileOrDirectoryError
): Either<FuseError, GetAttributesCallbackData> {
// When the OS wants to check if a node exists will try to get the attributes of it
// so not founding them is not an error
Logger.info(`Attributes of ${this.name}:.`);
Logger.info(`No attributes found for ${error.path}`);
return left(error);
}

Expand Down Expand Up @@ -88,6 +88,6 @@ export class GetAttributesCallback extends FuseCallback<GetAttributesCallbackDat
});
}

return this.left(new FuseNoSuchFileOrDirectoryError());
return this.left(new FuseNoSuchFileOrDirectoryError(path));
}
}
2 changes: 1 addition & 1 deletion src/apps/fuse/callbacks/OpenCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class OpenCallback extends FuseCallback<number> {
const file = await this.container.filesSearcher.run({ path });

if (!file) {
return this.left(new FuseNoSuchFileOrDirectoryError());
return this.left(new FuseNoSuchFileOrDirectoryError(path));
}

try {
Expand Down
28 changes: 18 additions & 10 deletions src/apps/fuse/callbacks/ReadCallback.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
import Logger from 'electron-log';
import fs from 'fs/promises';
import { VirtualDriveDependencyContainer } from '../dependency-injection/virtual-drive/VirtualDriveDependencyContainer';
import { OfflineDriveDependencyContainer } from '../dependency-injection/offline/OfflineDriveDependencyContainer';

// eslint-disable-next-line @typescript-eslint/no-var-requires
const fuse = require('@gcas/fuse');

export class ReadCallback {
constructor(private readonly container: VirtualDriveDependencyContainer) {}
constructor(
private readonly virtualDrive: VirtualDriveDependencyContainer,
private readonly offlineDrive: OfflineDriveDependencyContainer
) {}

private async read(
filePath: string,
buffer: Buffer,
length: number,
position: number
): Promise<number> {
// Logger.debug('READING FILE FROM ', filePath, length, position);
Logger.debug('READING ', length, 'MB FROM ', filePath);

const data = await fs.readFile(filePath);
const readResult = await this.offlineDrive.contentsChunkReader.run(
filePath,
length,
position
);

if (position >= data.length) {
if (!readResult.isPresent()) {
Logger.debug('READ DONE');
return 0;
}

const part = data.slice(position, position + length);
part.copy(buffer); // write the result of the read to the result buffer
return part.length; // number of bytes read
const chunk = readResult.get();

chunk.copy(buffer); // write the result of the read to the result buffer
return chunk.length; // number of bytes read
}

async execute(
Expand All @@ -36,14 +44,14 @@ export class ReadCallback {
pos: number,
cb: (code: number, params?: any) => void
) {
const file = await this.container.filesSearcher.run({ path });
const file = await this.virtualDrive.filesSearcher.run({ path });

if (!file) {
cb(fuse.ENOENT);
return;
}

const filePath = this.container.relativePathToAbsoluteConverter.run(
const filePath = this.virtualDrive.relativePathToAbsoluteConverter.run(
file.contentsId
);

Expand Down
2 changes: 1 addition & 1 deletion src/apps/fuse/callbacks/RenameOrMoveCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ export class RenameOrMoveCallback extends NotifyFuseCallback {
return this.right();
}

return this.left(new FuseNoSuchFileOrDirectoryError());
return this.left(new FuseNoSuchFileOrDirectoryError(src));
}
}
2 changes: 1 addition & 1 deletion src/apps/fuse/callbacks/TrashFileCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class TrashFileCallback extends NotifyFuseCallback {
});

if (!file) {
return this.left(new FuseNoSuchFileOrDirectoryError());
return this.left(new FuseNoSuchFileOrDirectoryError(path));
}

try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ContentsChunkReader } from '../../../../../context/offline-drive/contents/application/ContentsChunkReader';
import { OfflineContentsAppender } from '../../../../../context/offline-drive/contents/application/OfflineContentsAppender';
import { OfflineContentsCreator } from '../../../../../context/offline-drive/contents/application/OfflineContentsCreator';
import { OfflineContentsUploader } from '../../../../../context/offline-drive/contents/application/OfflineContentsUploader';
Expand All @@ -6,4 +7,5 @@ export interface OfflineContentsDependencyContainer {
offlineContentsCreator: OfflineContentsCreator;
offlineContentsAppender: OfflineContentsAppender;
offlineContentsUploader: OfflineContentsUploader;
contentsChunkReader: ContentsChunkReader;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { ContentsChunkReader } from '../../../../../context/offline-drive/contents/application/ContentsChunkReader';
import { OfflineContentsAppender } from '../../../../../context/offline-drive/contents/application/OfflineContentsAppender';
import { OfflineContentsCreator } from '../../../../../context/offline-drive/contents/application/OfflineContentsCreator';
import { OfflineContentsUploader } from '../../../../../context/offline-drive/contents/application/OfflineContentsUploader';
import { EnvironmentOfflineContentsManagersFactory } from '../../../../../context/offline-drive/contents/infrastructure/EnvironmentRemoteFileContentsManagersFactory';
import { NodeFSOfflineContentsRepository } from '../../../../../context/offline-drive/contents/infrastructure/NodeFSOfflineContentsRepository';
import { CachedFSContentsRepository } from '../../../../../context/offline-drive/contents/infrastructure/cache/CachedFSContentsRepository';
import { MainProcessUploadProgressTracker } from '../../../../../context/shared/infrastructure/MainProcessUploadProgressTracker';
import { FuseAppDataLocalFileContentsDirectoryProvider } from '../../../../../context/virtual-drive/shared/infrastructure/LocalFileContentsDirectoryProviders/FuseAppDataLocalFileContentsDirectoryProvider';
import { DependencyInjectionEventBus } from '../../../../fuse/dependency-injection/common/eventBus';
Expand Down Expand Up @@ -50,9 +52,13 @@ export async function buildOfflineContentsContainer(

const offlineContentsCreator = new OfflineContentsCreator(repository);

const contentsRepository = new CachedFSContentsRepository();
const contentsChunkReader = new ContentsChunkReader(contentsRepository);

return {
offlineContentsCreator,
offlineContentsAppender,
offlineContentsUploader,
contentsChunkReader,
};
}
7 changes: 0 additions & 7 deletions src/apps/fuse/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,11 @@ import eventBus from '../main/event-bus';
import { FuseApp } from './FuseApp';
import path from 'path';
import { FuseDependencyContainerFactory } from './dependency-injection/FuseDependencyContainerFactory';
import { HydrationApi } from '../hydration-api/HydrationApi';
import { getRootVirtualDrive } from '../main/virtual-root-folder/service';

let fuseApp: FuseApp;

async function startFuseApp() {
const api = new HydrationApi();

await api.start({
debug: false,
});

const root = getRootVirtualDrive();

Logger.debug('ROOT FOLDER: ', root);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Optional } from '../../../../shared/types/Optional';
import { ContentsRepository } from '../domain/ContentsRepository';

export class ContentsChunkReader {
constructor(private readonly repository: ContentsRepository) {}

async run(
contentsPath: string,
length: number,
position: number
): Promise<Optional<Buffer>> {
const data = await this.repository.read(contentsPath);

if (position >= data.length) {
return Optional.empty();
}

const chunk = data.slice(position, position + length);

return Optional.of(chunk);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface ContentsRepository {
read(path: string): Promise<Buffer>;

forget(path: string): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ContentsRepository } from '../../domain/ContentsRepository';
import fs from 'fs/promises';

export class CachedFSContentsRepository implements ContentsRepository {
private buffers: Map<string, Buffer> = new Map();

async read(path: string): Promise<Buffer> {
const cached = this.buffers.get(path);

if (cached) {
return cached;
}

const read = await fs.readFile(path);
this.buffers.set(path, read);

return read;
}

forget(_path: string): void {
//
}
}
23 changes: 23 additions & 0 deletions src/shared/types/Optional.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export class Optional<T> {
private constructor(private readonly value: T | undefined) {}

static of<T>(value: T): Optional<T> {
return new Optional(value);
}

static empty<T>(): Optional<T> {
return new Optional<T>(undefined);
}

get(): T {
if (!this.value) {
throw new Error('Element not found');
}

return this.value;
}

isPresent(): boolean {
return this.value !== undefined;
}
}

0 comments on commit e6afb04

Please sign in to comment.