提交 34ce3941 编写于 作者: B Benjamin Pasero

fix fdatasync working properly

上级 c7da35f1
......@@ -356,14 +356,13 @@ function doWriteFileStreamAndFlush(path: string, reader: NodeJS.ReadableStream,
}
};
// create writer to target
const writer = fs.createWriteStream(path, options);
// create writer to target. we set autoClose: false because we want to use the streams
// file descriptor to call fs.fdatasync to ensure the data is flushed to disk
const writer = fs.createWriteStream(path, { mode: options.mode, flags: options.flag, autoClose: false });
// handle errors properly
reader.once('error', error => finish(error));
writer.once('error', error => finish(error));
// save the fd for later use
// Event: 'open'
// Purpose: save the fd for later use
// Notes: will not be called when there is an error opening the file descriptor!
let fd: number;
let isOpen: boolean;
writer.once('open', descriptor => {
......@@ -371,11 +370,16 @@ function doWriteFileStreamAndFlush(path: string, reader: NodeJS.ReadableStream,
isOpen = true;
});
// we are done (underlying fd has been closed)
writer.once('close', () => finish());
// Event: 'error'
// Purpose: to return the error to the outside and to close the write stream (does not happen automatically)
reader.once('error', error => finish(error));
writer.once('error', error => finish(error));
// handle end event because we are in charge
reader.once('end', () => {
// Event: 'finish'
// Purpose: use fs.fdatasync to flush the contents to disk
// Notes: event is called when the writer has finished writing to the underlying resource. we must call writer.close()
// because we have created the WriteStream with autoClose: false
writer.once('finish', () => {
// flush to disk
if (canFlush && isOpen) {
......@@ -388,18 +392,20 @@ function doWriteFileStreamAndFlush(path: string, reader: NodeJS.ReadableStream,
canFlush = false;
}
writer.end();
writer.close();
});
}
// do not flush
else {
writer.end();
} else {
writer.close();
}
});
// end: false means we are in charge of ending the streams properly
reader.pipe(writer, { end: false });
// Event: 'close'
// Purpose: signal we are done to the outside
// Notes: event is called when the writer's filedescriptor is closed
writer.once('close', () => finish());
// start data piping
reader.pipe(writer);
}
// Calls fs.writeFile() followed by a fs.sync() call to flush the changes to disk
......
......@@ -10,8 +10,7 @@ import fs = require('fs');
import os = require('os');
import crypto = require('crypto');
import assert = require('assert');
import { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IFileStat, IStreamContent, FileOperationError, FileOperationResult, IUpdateContentOptions, FileChangeType, IImportResult, FileChangesEvent, ICreateFileOptions, IContentData, ITextSnapshot, snapshotToString } from 'vs/platform/files/common/files';
import { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IFileStat, IStreamContent, FileOperationError, FileOperationResult, IUpdateContentOptions, FileChangeType, IImportResult, FileChangesEvent, ICreateFileOptions, IContentData, ITextSnapshot } from 'vs/platform/files/common/files';
import { MAX_FILE_SIZE } from 'vs/platform/files/node/files';
import { isEqualOrParent } from 'vs/base/common/paths';
import { ResourceMap } from 'vs/base/common/map';
......@@ -508,8 +507,7 @@ export class FileService implements IFileService {
public updateContent(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise<IFileStat> {
if (this.options.elevationSupport && options.writeElevated) {
// We can currently only write strings elevated, so we need to convert snapshots properly
return this.doUpdateContentElevated(resource, typeof value === 'string' ? value : snapshotToString(value), options);
return this.doUpdateContentElevated(resource, value, options);
}
return this.doUpdateContent(resource, value, options);
......@@ -635,7 +633,7 @@ export class FileService implements IFileService {
});
}
private doUpdateContentElevated(resource: uri, value: string, options: IUpdateContentOptions = Object.create(null)): TPromise<IFileStat> {
private doUpdateContentElevated(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise<IFileStat> {
const absolutePath = this.toAbsolutePath(resource);
// 1.) check file
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册