summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2009-11-29 16:29:03 +0100
committerTomas Bzatek <tbzatek@users.sourceforge.net>2009-11-29 16:29:03 +0100
commit959269c4432632e9228a5fa148eed2255e508554 (patch)
tree090517465da49e84c7b3ec117f88d52ccd903107
parent9883e3b4eec8e457b49cb70ca006f5f7601332da (diff)
downloadtuxcmd-959269c4432632e9228a5fa148eed2255e508554.tar.xz
Introduce copy operation start/stop callsv0.6.73
This is the first step for a rapid extraction speed increase as we don't need to open&seek for every file. Sorting by inode is still need to be written but most archives work fine as they are. TODO: writing into the archive needs special care (see TODO in zip plugin)
-rw-r--r--UConfig.pas4
-rw-r--r--UCoreWorkers.pas89
-rw-r--r--vfs/UVFSCore.pas91
-rw-r--r--vfs/uVFSprototypes.pas4
4 files changed, 126 insertions, 62 deletions
diff --git a/UConfig.pas b/UConfig.pas
index a4a9978..a8dc5b6 100644
--- a/UConfig.pas
+++ b/UConfig.pas
@@ -25,8 +25,8 @@ uses Classes, ULocale;
resourcestring
ConstAppTitle = 'Tux Commander';
- ConstAboutVersion = '0.6.72-dev';
- ConstAboutBuildDate = '2009-11-28';
+ ConstAboutVersion = '0.6.73-dev';
+ ConstAboutBuildDate = '2009-11-29';
{$IFDEF FPC}
{$INCLUDE fpcver.inc}
diff --git a/UCoreWorkers.pas b/UCoreWorkers.pas
index b2b6479..2b5c4d5 100644
--- a/UCoreWorkers.pas
+++ b/UCoreWorkers.pas
@@ -996,16 +996,14 @@ var DefResponse: integer; // Global variables for this function
if (SrcEngine is TLocalTreeEngine) and (DestEngine is TVFSEngine) then
begin
AEngine := DestEngine;
- Result := (DestEngine as TVFSEngine).CopyFileInEx(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ErrorFunc, Append,
- @vfs_ask_question_callback, @vfs_ask_password_callback, @vfs_progress_callback, SenderThread);
+ Result := (DestEngine as TVFSEngine).CopyFileInEx(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ErrorFunc, Append);
end else
// from VFS engine to local (most common use)
if (SrcEngine is TVFSEngine) and (DestEngine is TLocalTreeEngine) then
begin
AEngine := SrcEngine;
- Result := (SrcEngine as TVFSEngine).CopyFileOutEx(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ErrorFunc, Append,
- @vfs_ask_question_callback, @vfs_ask_password_callback, @vfs_progress_callback, SenderThread);
+ Result := (SrcEngine as TVFSEngine).CopyFileOutEx(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ErrorFunc, Append);
end
// VFS to VFS (not supported yet)
@@ -1322,6 +1320,7 @@ var i: longint;
List: TList;
CurrPath, SaveDestPath, SaveSrcPath, s: string;
MaxSize: Int64;
+ StartPassed: boolean;
begin
List := TList.Create;
List.Clear;
@@ -1395,45 +1394,59 @@ begin
ParamBool2 := False;
if MaxSize < 2 then ParamFloat1 := 1 else ParamFloat1 := 100 / (MaxSize - 1);
- if List.Count > 0 then
- for i := 0 to List.Count - 1 do begin
- if Assigned(PDataItemSL(List[i])^.ADestination)
- then s := string(PDataItemSL(List[i])^.ADestination)
- else
- begin
- s := ProcessPattern(DestEngine, ParamString1, CurrPath, Copy(PDataItemSL(List[i])^.DataItem^.FName, Length(CurrPath) + 1, Length(PDataItemSL(List[i])^.DataItem^.FName) - Length(CurrPath)),
- PDataItemSL(List[i])^.DataItem^.IsDir and (not PDataItemSL(List[i])^.DataItem^.IsLnk));
-// DebugMsg(['s2 = ', Copy(PDataItemSL(List[i])^.AName, Length(CurrPath) + 1, Length(PDataItemSL(List[i])^.AName) - Length(CurrPath)), ', s = ', s]);
- end;
+ if List.Count > 0 then begin
+ StartPassed := True;
+ if (SrcEngine is TVFSEngine) and (SrcEngine as TVFSEngine).ArchiveMode then
+ StartPassed := StartPassed and (SrcEngine as TVFSEngine).StartCopyOperation(SenderThread, @CopyFilesWorker_ErrorFunc, @vfs_ask_question_callback, @vfs_ask_password_callback, @vfs_progress_callback, SenderThread);
+ if (DestEngine is TVFSEngine) and (DestEngine as TVFSEngine).ArchiveMode then
+ StartPassed := StartPassed and (DestEngine as TVFSEngine).StartCopyOperation(SenderThread, @CopyFilesWorker_ErrorFunc, @vfs_ask_question_callback, @vfs_ask_password_callback, @vfs_progress_callback, SenderThread);
+
+ if StartPassed then
+ for i := 0 to List.Count - 1 do begin
+ if Assigned(PDataItemSL(List[i])^.ADestination)
+ then s := string(PDataItemSL(List[i])^.ADestination)
+ else
+ begin
+ s := ProcessPattern(DestEngine, ParamString1, CurrPath, Copy(PDataItemSL(List[i])^.DataItem^.FName, Length(CurrPath) + 1, Length(PDataItemSL(List[i])^.DataItem^.FName) - Length(CurrPath)),
+ PDataItemSL(List[i])^.DataItem^.IsDir and (not PDataItemSL(List[i])^.DataItem^.IsLnk));
+ // DebugMsg(['s2 = ', Copy(PDataItemSL(List[i])^.AName, Length(CurrPath) + 1, Length(PDataItemSL(List[i])^.AName) - Length(CurrPath)), ', s = ', s]);
+ end;
- if not (SrcEngine is TVFSEngine) then UpdateCaption1(Format(LANGFromS, [string(PDataItemSL(List[i])^.DataItem^.FDisplayName)])) else
- if (SrcEngine as TVFSEngine).ArchiveMode then UpdateCaption1(Format(LANGFromS, [Format(ConstFullPathFormatStr, [(SrcEngine as TVFSEngine).ArchivePath, string(PDataItemSL(List[i])^.DataItem^.FDisplayName)])]))
- else UpdateCaption1(Format(LANGFromS, [GetURIPrefix((SrcEngine as TVFSEngine).GetPathURI) + StrToUTF8(string(PDataItemSL(List[i])^.DataItem^.FDisplayName))]));
- if not (DestEngine is TVFSEngine) then UpdateCaption2(Format(LANGToS, [StrToUTF8(s)])) else
- if (DestEngine as TVFSEngine).ArchiveMode then UpdateCaption2(Format(LANGToS, [Format(ConstFullPathFormatStr, [(DestEngine as TVFSEngine).ArchivePath, StrToUTF8(s)])]))
- else UpdateCaption2(Format(LANGToS, [GetURIPrefix((DestEngine as TVFSEngine).GetPathURI) + StrToUTF8(s)]));
- CommitGUIUpdate;
- if TwoSameFiles(s, string(PDataItemSL(List[i])^.DataItem^.FName), ParamBool3) and (not PDataItemSL(List[i])^.DataItem^.IsDir) then begin
- FCancelMessage := LANGCannotCopyFileToItself;
- FShowCancelMessage := True;
- ErrorHappened := True;
- Break;
- end;
-// * FIXME: why the hell we had something like this here??
-// if s <> string(PDataItemSL(List[i])^.DataItem^.FName) then
- if not HandleCopy(List[i], s) then begin
+ if not (SrcEngine is TVFSEngine) then UpdateCaption1(Format(LANGFromS, [string(PDataItemSL(List[i])^.DataItem^.FDisplayName)])) else
+ if (SrcEngine as TVFSEngine).ArchiveMode then UpdateCaption1(Format(LANGFromS, [Format(ConstFullPathFormatStr, [(SrcEngine as TVFSEngine).ArchivePath, string(PDataItemSL(List[i])^.DataItem^.FDisplayName)])]))
+ else UpdateCaption1(Format(LANGFromS, [GetURIPrefix((SrcEngine as TVFSEngine).GetPathURI) + StrToUTF8(string(PDataItemSL(List[i])^.DataItem^.FDisplayName))]));
+ if not (DestEngine is TVFSEngine) then UpdateCaption2(Format(LANGToS, [StrToUTF8(s)])) else
+ if (DestEngine as TVFSEngine).ArchiveMode then UpdateCaption2(Format(LANGToS, [Format(ConstFullPathFormatStr, [(DestEngine as TVFSEngine).ArchivePath, StrToUTF8(s)])]))
+ else UpdateCaption2(Format(LANGToS, [GetURIPrefix((DestEngine as TVFSEngine).GetPathURI) + StrToUTF8(s)]));
+ CommitGUIUpdate;
+ if TwoSameFiles(s, string(PDataItemSL(List[i])^.DataItem^.FName), ParamBool3) and (not PDataItemSL(List[i])^.DataItem^.IsDir) then begin
+ FCancelMessage := LANGCannotCopyFileToItself;
+ FShowCancelMessage := True;
+ ErrorHappened := True;
+ Break;
+ end;
+ // * FIXME: why the hell we had something like this here??
+ // if s <> string(PDataItemSL(List[i])^.DataItem^.FName) then
+ if not HandleCopy(List[i], s) then begin
+ ErrorHappened := True;
+ Break;
+ end;
+ if (not PDataItemSL(List[i])^.DataItem^.IsDir) and (not PDataItemSL(List[i])^.DataItem^.IsLnk)
+ then Inc(ParamInt64, PDataItemSL(List[i])^.DataItem^.Size);
+ if Cancelled then begin
+ FCancelMessage := LANGUserCancelled;
+ FShowCancelMessage := True;
ErrorHappened := True;
Break;
end;
- if (not PDataItemSL(List[i])^.DataItem^.IsDir) and (not PDataItemSL(List[i])^.DataItem^.IsLnk)
- then Inc(ParamInt64, PDataItemSL(List[i])^.DataItem^.Size);
- if Cancelled then begin
- FCancelMessage := LANGUserCancelled;
- FShowCancelMessage := True;
- ErrorHappened := True;
- Break;
end;
- end;
+
+ // We need to ensure these to be called in case of error
+ if (SrcEngine is TVFSEngine) and (SrcEngine as TVFSEngine).ArchiveMode then
+ (SrcEngine as TVFSEngine).StopCopyOperation(SenderThread, @CopyFilesWorker_ErrorFunc);
+ if (DestEngine is TVFSEngine) and (DestEngine as TVFSEngine).ArchiveMode then
+ (DestEngine as TVFSEngine).StopCopyOperation(SenderThread, @CopyFilesWorker_ErrorFunc);
+ end;
// Free the objects
if List.Count > 0 then
diff --git a/vfs/UVFSCore.pas b/vfs/UVFSCore.pas
index 2bccea7..ff5445d 100644
--- a/vfs/UVFSCore.pas
+++ b/vfs/UVFSCore.pas
@@ -66,6 +66,8 @@ type
FVFSGetPasswordRequired: TVFSGetPasswordRequired;
FVFSSetCallbacks: TVFSSetCallbacks;
FVFSResetPassword: TVFSResetPassword;
+ FVFSStartCopyOperation: TVFSStartCopyOperation;
+ FVFSStopCopyOperation: TVFSStopCopyOperation;
function GetHandlesArchives: boolean;
function GetHandlesNetwork: boolean;
public
@@ -152,11 +154,11 @@ type
function GetPasswordRequired: boolean;
procedure ResetPassword;
- // the callbacks here are used for next volume prompts, password prompts (encrypted archives) - as long as this is specific to each file
- function CopyFileInEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean;
- AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
- function CopyFileOutEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean;
- AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
+ // callbacks here are used for next volume prompts, password prompts (encrypted archives)
+ function StartCopyOperation(Sender: Pointer; ErrorFunc: TEngineErrorFunc; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
+ function StopCopyOperation(Sender: Pointer; ErrorFunc: TEngineErrorFunc): boolean;
+ function CopyFileInEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
+ function CopyFileOutEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
published
property Path: string read GetPath write SetPath;
property BlockSize: Cardinal read GetBlockSize write SetBlockSize;
@@ -242,6 +244,8 @@ begin
@FVFSGetPasswordRequired := dlsym(ModuleHandle, 'VFSGetPasswordRequired');
@FVFSSetCallbacks := dlsym(ModuleHandle, 'VFSSetCallbacks');
@FVFSResetPassword := dlsym(ModuleHandle, 'VFSResetPassword');
+ @FVFSStartCopyOperation := dlsym(ModuleHandle, 'VFSStartCopyOperation');
+ @FVFSStopCopyOperation := dlsym(ModuleHandle, 'VFSStopCopyOperation');
// Initialize the extensions list
SetLength(Extensions, 0);
@@ -766,37 +770,34 @@ end;
(********************************************************************************************************************************)
function TVFSEngine.CopyFileIn(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
begin
- Result := CopyFileInEx(Sender, SourceFile, DestFile, ErrorFunc, Append, nil, nil, nil, nil);
+ Result := StartCopyOperation(Sender, ErrorFunc, nil, nil, nil, nil);
+ Result := Result and CopyFileInEx(Sender, SourceFile, DestFile, ErrorFunc, Append);
+ Result := Result and StopCopyOperation(Sender, ErrorFunc);
end;
function TVFSEngine.CopyFileOut(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
begin
- Result := CopyFileInEx(Sender, SourceFile, DestFile, ErrorFunc, Append, nil, nil, nil, nil);
+ Result := StartCopyOperation(Sender, ErrorFunc, nil, nil, nil, nil);
+ Result := Result and CopyFileInEx(Sender, SourceFile, DestFile, ErrorFunc, Append);
+ Result := Result and StopCopyOperation(Sender, ErrorFunc);
end;
-function TVFSEngine.CopyFileOutEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean;
- AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
+function TVFSEngine.CopyFileOutEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
var Res: TVFSResult;
begin
Result := False;
try
if @FSourcePlugin.FVFSCopyToLocal <> nil then begin
-// DebugMsg(['0 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']);
-// DebugMsg([' Pointer(FGlobs) = 0x', IntToHex(Int64(FGlobs), 16), ', Pointer(@NewVFSCopyCallBackFunc) = 0x', IntToHex(Int64(@NewVFSCopyCallBackFunc), 16), ', Pointer(Self) = 0x', IntToHex(Int64(Self), 16)]);
try
- if @FSourcePlugin.FVFSSetCallbacks <> nil then
- FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData);
Res := FSourcePlugin.FVFSCopyToLocal(FGlobs, PChar(SourceFile), PChar(DestFile), Append);
- if @FSourcePlugin.FVFSSetCallbacks <> nil then
- FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil);
except
on E: Exception do begin
DebugMsg(['*** Exception raised in TVFSEngine.CopyFileOut(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
Res := cVFS_WriteErr;
end;
end;
-// DebugMsg(['1 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']);
Result := Res = cVFS_OK;
+ // * TODO: Port to GError
if (Res <> cVFS_OK) and Assigned(ErrorFunc) then
case Res of
cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, SourceFile);
@@ -810,19 +811,14 @@ begin
end;
end;
-function TVFSEngine.CopyFileInEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc;
- Append: boolean; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
+function TVFSEngine.CopyFileInEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
var Res: TVFSResult;
begin
Result := False;
try
if @FSourcePlugin.FVFSCopyFromLocal <> nil then begin
try
- if @FSourcePlugin.FVFSSetCallbacks <> nil then
- FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData);
Res := FSourcePlugin.FVFSCopyFromLocal(FGlobs, PChar(SourceFile), PChar(DestFile), Append);
- if @FSourcePlugin.FVFSSetCallbacks <> nil then
- FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil);
except
on E: Exception do begin
DebugMsg(['*** Exception raised in TVFSEngine.CopyFileIn(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
@@ -830,6 +826,7 @@ begin
end;
end;
Result := Res = cVFS_OK;
+ // * TODO: Port to GError
if (Res <> cVFS_OK) and Assigned(ErrorFunc) then
case Res of
cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, SourceFile);
@@ -843,6 +840,56 @@ begin
end;
end;
+function TVFSEngine.StartCopyOperation(Sender: Pointer; ErrorFunc: TEngineErrorFunc; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
+var Res: TVFSResult;
+begin
+ Result := False;
+ try
+ if @FSourcePlugin.FVFSSetCallbacks <> nil then
+ FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData);
+ if @FSourcePlugin.FVFSStartCopyOperation <> nil then begin
+ Res := FSourcePlugin.FVFSStartCopyOperation(FGlobs);
+ Result := Res = cVFS_OK;
+ // * TODO: Port to GError
+ if (Res <> cVFS_OK) and Assigned(ErrorFunc) then
+ case Res of
+ cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, 'StartCopyOperation');
+ cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, 'StartCopyOperation');
+ cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, 'StartCopyOperation');
+ cVFS_Cancelled: ErrorFunc(Sender, 0, 0, 'StartCopyOperation');
+ end;
+ end else
+ ErrorFunc(Sender, 2, 0, 'StartCopyOperation not supported');
+ except
+ on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.StartCopyOperation(Sender=', QWord(Sender), '): (', E.ClassName, '): ', E.Message]);
+ end;
+end;
+
+function TVFSEngine.StopCopyOperation(Sender: Pointer; ErrorFunc: TEngineErrorFunc): boolean;
+var Res: TVFSResult;
+begin
+ Result := False;
+ try
+ if @FSourcePlugin.FVFSSetCallbacks <> nil then
+ FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil);
+ if @FSourcePlugin.FVFSStopCopyOperation <> nil then begin
+ Res := FSourcePlugin.FVFSStopCopyOperation(FGlobs);
+ Result := Res = cVFS_OK;
+ // * TODO: Port to GError
+ if (Res <> cVFS_OK) and Assigned(ErrorFunc) then
+ case Res of
+ cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, 'StopCopyOperation');
+ cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, 'StopCopyOperation');
+ cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, 'StopCopyOperation');
+ cVFS_Cancelled: ErrorFunc(Sender, 0, 0, 'StopCopyOperation');
+ end;
+ end else
+ ErrorFunc(Sender, 5, 0, 'StopCopyOperation not supported');
+ except
+ on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.StopCopyOperation(Sender=', QWord(Sender), '): (', E.ClassName, '): ', E.Message]);
+ end;
+end;
+
(********************************************************************************************************************************)
(********************************************************************************************************************************)
diff --git a/vfs/uVFSprototypes.pas b/vfs/uVFSprototypes.pas
index bef0246..bd33726 100644
--- a/vfs/uVFSprototypes.pas
+++ b/vfs/uVFSprototypes.pas
@@ -238,6 +238,10 @@ type
TVFSCopyToLocal = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Append: gboolean): TVFSResult; cdecl;
// Performs the copy process from local filesystem into the module
TVFSCopyFromLocal = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Append: gboolean): TVFSResult; cdecl;
+ // Start the copy operation - open the archive and prepare internal structures
+ TVFSStartCopyOperation = function (g:TVFSGlobs): TVFSResult; cdecl;
+ // Stop the copy operation - close the archive and free memory
+ TVFSStopCopyOperation = function (g:TVFSGlobs): TVFSResult; cdecl;
// TODO: Prototype function for packing new files into archive