mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
ADD: Use connections in TWfxPluginFileSource
This commit is contained in:
parent
a7534d3d7e
commit
c23b3efae4
6 changed files with 307 additions and 19 deletions
|
|
@ -127,6 +127,10 @@ const FS_STATUS_START=0;
|
|||
|
||||
FS_STATUS_OP_SYNC_DELETE=18;
|
||||
|
||||
FS_STATUS_OP_GET_MULTI_THREAD=19;
|
||||
|
||||
FS_STATUS_OP_PUT_MULTI_THREAD=20;
|
||||
|
||||
{Flags for FsExtractCustomIcon}
|
||||
|
||||
const FS_ICONFLAG_SMALL=1;
|
||||
|
|
@ -167,6 +171,14 @@ const FS_BITMAP_NONE=0;
|
|||
|
||||
FS_CRYPTOPT_MASTERPASS_SET=1; {The user already has a master password defined}
|
||||
|
||||
{Flags for FsGetBackgroundFlags}
|
||||
|
||||
BG_DOWNLOAD=1; { Plugin supports downloads in background }
|
||||
|
||||
BG_UPLOAD=2; { Plugin supports uploads in background }
|
||||
|
||||
BG_ASK_USER=4; { Plugin requires separate connection for background transfers -> ask user first }
|
||||
|
||||
type
|
||||
{ Unsigned integer with pointer size }
|
||||
THandle = {$IFDEF CPU64}QWord{$ELSE}LongWord{$ENDIF};
|
||||
|
|
@ -543,6 +555,8 @@ function FsContentGetDefaultViewW(ViewContents,ViewHeaders,ViewWidths,
|
|||
|
||||
ViewOptions:pwidechar;maxlen:integer):bool; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
|
||||
|
||||
function FsGetBackgroundFlags:integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
|
||||
|
||||
*)
|
||||
|
||||
implementation
|
||||
|
|
|
|||
|
|
@ -95,12 +95,16 @@ begin
|
|||
with FWfxPluginFileSource do
|
||||
FCallbackDataClass:= TCallbackDataClass(WfxOperationList.Objects[PluginNumber]);
|
||||
|
||||
if theSourceFiles.Count > 1 then
|
||||
inherited Create(aSourceFileSource, aTargetFileSource, theSourceFiles, aTargetPath);
|
||||
|
||||
FNeedsConnection:= (FWfxPluginFileSource.WfxModule.BackgroundFlags and BG_UPLOAD = 0);
|
||||
|
||||
if (FNeedsConnection = False) then
|
||||
FInfoOperation:= FS_STATUS_OP_PUT_MULTI_THREAD
|
||||
else if (theSourceFiles.Count > 1) then
|
||||
FInfoOperation:= FS_STATUS_OP_PUT_MULTI
|
||||
else
|
||||
FInfoOperation:= FS_STATUS_OP_PUT_SINGLE;
|
||||
|
||||
inherited Create(aSourceFileSource, aTargetFileSource, theSourceFiles, aTargetPath);
|
||||
end;
|
||||
|
||||
destructor TWfxPluginCopyInOperation.Destroy;
|
||||
|
|
|
|||
|
|
@ -94,12 +94,16 @@ begin
|
|||
with FWfxPluginFileSource do
|
||||
FCallbackDataClass:= TCallbackDataClass(WfxOperationList.Objects[PluginNumber]);
|
||||
|
||||
if theSourceFiles.Count > 1 then
|
||||
inherited Create(aSourceFileSource, aTargetFileSource, theSourceFiles, aTargetPath);
|
||||
|
||||
FNeedsConnection:= (FWfxPluginFileSource.WfxModule.BackgroundFlags and BG_DOWNLOAD = 0);
|
||||
|
||||
if (FNeedsConnection = False) then
|
||||
FInfoOperation:= FS_STATUS_OP_GET_MULTI_THREAD
|
||||
else if (theSourceFiles.Count > 1) then
|
||||
FInfoOperation:= FS_STATUS_OP_GET_MULTI
|
||||
else
|
||||
FInfoOperation:= FS_STATUS_OP_GET_SINGLE;
|
||||
|
||||
inherited Create(aSourceFileSource, aTargetFileSource, theSourceFiles, aTargetPath);
|
||||
end;
|
||||
|
||||
destructor TWfxPluginCopyOutOperation.Destroy;
|
||||
|
|
|
|||
|
|
@ -61,9 +61,27 @@ type
|
|||
|
||||
function GetPluginNumber: LongInt;
|
||||
function GetWfxModule: TWfxModule;
|
||||
|
||||
function CreateConnection: TFileSourceConnection;
|
||||
procedure CreateConnections;
|
||||
|
||||
procedure AddToConnectionQueue(Operation: TFileSourceOperation);
|
||||
procedure RemoveFromConnectionQueue(Operation: TFileSourceOperation);
|
||||
procedure AddConnection(Connection: TFileSourceConnection);
|
||||
procedure RemoveConnection(Connection: TFileSourceConnection);
|
||||
|
||||
{en
|
||||
Searches connections list for a connection assigned to operation.
|
||||
}
|
||||
function FindConnectionByOperation(operation: TFileSourceOperation): TFileSourceConnection; virtual;
|
||||
|
||||
procedure NotifyNextWaitingOperation(allowedOps: TFileSourceOperationTypes);
|
||||
|
||||
procedure ClearCurrentOperation(Operation: TFileSourceOperation);
|
||||
protected
|
||||
function GetSupportedFileProperties: TFilePropertiesTypes; override;
|
||||
function GetCurrentAddress: String; override;
|
||||
procedure OperationFinished(Operation: TFileSourceOperation); override;
|
||||
public
|
||||
procedure FillAndCount(Files: TFiles; CountDirs: Boolean; ExcludeRootDir: Boolean;
|
||||
out NewFiles: TFiles; out FilesCount: Int64; out FilesSize: Int64);
|
||||
|
|
@ -104,11 +122,26 @@ type
|
|||
|
||||
class function CreateByRootName(aRootName: String): IWfxPluginFileSource;
|
||||
|
||||
function GetConnection(Operation: TFileSourceOperation): TFileSourceConnection; override;
|
||||
procedure RemoveOperationFromQueue(Operation: TFileSourceOperation); override;
|
||||
|
||||
property PluginNumber: LongInt read FPluginNumber;
|
||||
property WfxModule: TWfxModule read FWfxModule;
|
||||
|
||||
end;
|
||||
|
||||
{ TWfxPluginFileSourceConnection }
|
||||
|
||||
TWfxPluginFileSourceConnection = class(TFileSourceConnection)
|
||||
private
|
||||
FWfxModule: TWfxModule;
|
||||
|
||||
public
|
||||
constructor Create(aWfxModule: TWfxModule); reintroduce;
|
||||
|
||||
property WfxModule: TWfxModule read FWfxModule;
|
||||
end;
|
||||
|
||||
var
|
||||
// Used in callback functions
|
||||
WfxOperationList: TStringList = nil;
|
||||
|
|
@ -117,11 +150,23 @@ implementation
|
|||
|
||||
uses
|
||||
LCLProc, FileUtil, StrUtils, {} LCLType, uShowMsg, {} uGlobs, uDCUtils, uLog,
|
||||
uDebug, uLng, uCryptProc, uFileAttributes, uConnectionManager,
|
||||
uDebug, uLng, uCryptProc, uFileAttributes, uConnectionManager, contnrs, syncobjs,
|
||||
uWfxPluginCopyInOperation, uWfxPluginCopyOutOperation, uWfxPluginMoveOperation,
|
||||
uWfxPluginExecuteOperation, uWfxPluginListOperation, uWfxPluginCreateDirectoryOperation,
|
||||
uWfxPluginDeleteOperation, uWfxPluginSetFilePropertyOperation, uWfxPluginCopyOperation;
|
||||
|
||||
const
|
||||
connCopyIn = 0;
|
||||
connCopyOut = 1;
|
||||
connDelete = 2;
|
||||
|
||||
var
|
||||
// Always use appropriate lock to access these lists.
|
||||
WfxConnections: TObjectList; // store connections created by Wcx file sources
|
||||
WfxOperationsQueue: TObjectList; // store queued operations, use only under FOperationsQueueLock
|
||||
WfxConnectionsLock: TCriticalSection; // used to synchronize access to connections
|
||||
WfxOperationsQueueLock: TCriticalSection; // used to synchronize access to operations queue
|
||||
|
||||
{ CallBack functions }
|
||||
|
||||
function MainProgressProc(PluginNr: Integer; SourceName, TargetName: UTF8String; PercentDone: Integer): Integer;
|
||||
|
|
@ -441,6 +486,8 @@ begin
|
|||
FOperationsClasses[fsoCreateDirectory] := TWfxPluginCreateDirectoryOperation.GetOperationClass;
|
||||
FOperationsClasses[fsoSetFileProperty] := TWfxPluginSetFilePropertyOperation.GetOperationClass;
|
||||
FOperationsClasses[fsoExecute] := TWfxPluginExecuteOperation.GetOperationClass;
|
||||
|
||||
CreateConnections;
|
||||
end;
|
||||
|
||||
destructor TWfxPluginFileSource.Destroy;
|
||||
|
|
@ -530,10 +577,10 @@ end;
|
|||
|
||||
function TWfxPluginFileSource.GetProperties: TFileSourceProperties;
|
||||
begin
|
||||
Result := [];
|
||||
Result := [fspUsesConnections];
|
||||
with FWfxModule do
|
||||
if Assigned(FsLinksToLocalFiles) and FsLinksToLocalFiles() then
|
||||
Result:= [fspLinksToLocalFiles];
|
||||
Result:= Result + [fspLinksToLocalFiles];
|
||||
end;
|
||||
|
||||
function TWfxPluginFileSource.GetSupportedFileProperties: TFilePropertiesTypes;
|
||||
|
|
@ -777,6 +824,201 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TWfxPluginFileSource.AddToConnectionQueue(Operation: TFileSourceOperation);
|
||||
begin
|
||||
WfxOperationsQueueLock.Acquire;
|
||||
try
|
||||
if WfxOperationsQueue.IndexOf(Operation) < 0 then
|
||||
WfxOperationsQueue.Add(Operation);
|
||||
finally
|
||||
WfxOperationsQueueLock.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWfxPluginFileSource.RemoveFromConnectionQueue(Operation: TFileSourceOperation);
|
||||
begin
|
||||
WfxOperationsQueueLock.Acquire;
|
||||
try
|
||||
WfxOperationsQueue.Remove(Operation);
|
||||
finally
|
||||
WfxOperationsQueueLock.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWfxPluginFileSource.AddConnection(Connection: TFileSourceConnection);
|
||||
begin
|
||||
WfxConnectionsLock.Acquire;
|
||||
try
|
||||
if WfxConnections.IndexOf(Connection) < 0 then
|
||||
WfxConnections.Add(Connection);
|
||||
finally
|
||||
WfxConnectionsLock.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWfxPluginFileSource.RemoveConnection(Connection: TFileSourceConnection);
|
||||
begin
|
||||
WfxConnectionsLock.Acquire;
|
||||
try
|
||||
WfxConnections.Remove(Connection);
|
||||
finally
|
||||
WfxConnectionsLock.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TWfxPluginFileSource.GetConnection(Operation: TFileSourceOperation): TFileSourceConnection;
|
||||
begin
|
||||
Result := nil;
|
||||
case Operation.ID of
|
||||
fsoCopyIn:
|
||||
Result := WfxConnections[connCopyIn] as TFileSourceConnection;
|
||||
fsoCopyOut:
|
||||
Result := WfxConnections[connCopyOut] as TFileSourceConnection;
|
||||
fsoDelete:
|
||||
Result := WfxConnections[connDelete] as TFileSourceConnection;
|
||||
else
|
||||
begin
|
||||
Result := CreateConnection;
|
||||
if Assigned(Result) then
|
||||
AddConnection(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
if Assigned(Result) then
|
||||
Result := TryAcquireConnection(Result, Operation);
|
||||
|
||||
// No available connection - wait.
|
||||
if not Assigned(Result) then
|
||||
AddToConnectionQueue(Operation)
|
||||
else
|
||||
// Connection acquired.
|
||||
// The operation may have been waiting in the queue
|
||||
// for the connection, so remove it from the queue.
|
||||
RemoveFromConnectionQueue(Operation);
|
||||
end;
|
||||
|
||||
procedure TWfxPluginFileSource.RemoveOperationFromQueue(Operation: TFileSourceOperation);
|
||||
begin
|
||||
RemoveFromConnectionQueue(Operation);
|
||||
end;
|
||||
|
||||
function TWfxPluginFileSource.CreateConnection: TFileSourceConnection;
|
||||
begin
|
||||
Result := TWfxPluginFileSourceConnection.Create(FWfxModule);
|
||||
end;
|
||||
|
||||
procedure TWfxPluginFileSource.CreateConnections;
|
||||
begin
|
||||
WfxConnectionsLock.Acquire;
|
||||
try
|
||||
if WfxConnections.Count = 0 then
|
||||
begin
|
||||
// Reserve some connections (only once).
|
||||
WfxConnections.Add(CreateConnection); // connCopyIn
|
||||
WfxConnections.Add(CreateConnection); // connCopyOut
|
||||
WfxConnections.Add(CreateConnection); // connDelete
|
||||
end;
|
||||
finally
|
||||
WfxConnectionsLock.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TWfxPluginFileSource.FindConnectionByOperation(operation: TFileSourceOperation): TFileSourceConnection;
|
||||
var
|
||||
i: Integer;
|
||||
connection: TFileSourceConnection;
|
||||
begin
|
||||
Result := nil;
|
||||
WfxConnectionsLock.Acquire;
|
||||
try
|
||||
for i := 0 to WfxConnections.Count - 1 do
|
||||
begin
|
||||
connection := WfxConnections[i] as TFileSourceConnection;
|
||||
if connection.AssignedOperation = operation then
|
||||
Exit(connection);
|
||||
end;
|
||||
finally
|
||||
WfxConnectionsLock.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWfxPluginFileSource.OperationFinished(Operation: TFileSourceOperation);
|
||||
var
|
||||
allowedIDs: TFileSourceOperationTypes = [];
|
||||
connection: TFileSourceConnection;
|
||||
begin
|
||||
ClearCurrentOperation(Operation);
|
||||
|
||||
connection := FindConnectionByOperation(Operation);
|
||||
if Assigned(connection) then
|
||||
begin
|
||||
connection.Release; // unassign operation
|
||||
|
||||
WfxConnectionsLock.Acquire;
|
||||
try
|
||||
// If there are operations waiting, take the first one and notify
|
||||
// that a connection is available.
|
||||
// Only check operation types for which there are reserved connections.
|
||||
if Operation.ID in [fsoCopyIn, fsoCopyOut, fsoDelete, fsoTestArchive] then
|
||||
begin
|
||||
Include(allowedIDs, Operation.ID);
|
||||
NotifyNextWaitingOperation(allowedIDs);
|
||||
end
|
||||
else
|
||||
begin
|
||||
WfxConnections.Remove(connection);
|
||||
end;
|
||||
|
||||
finally
|
||||
WfxConnectionsLock.Release;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWfxPluginFileSource.NotifyNextWaitingOperation(allowedOps: TFileSourceOperationTypes);
|
||||
var
|
||||
i: Integer;
|
||||
operation: TFileSourceOperation;
|
||||
begin
|
||||
WfxOperationsQueueLock.Acquire;
|
||||
try
|
||||
for i := 0 to WfxOperationsQueue.Count - 1 do
|
||||
begin
|
||||
operation := WfxOperationsQueue.Items[i] as TFileSourceOperation;
|
||||
if (operation.State = fsosWaitingForConnection) and
|
||||
(operation.ID in allowedOps) then
|
||||
begin
|
||||
operation.ConnectionAvailableNotify;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
WfxOperationsQueueLock.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWfxPluginFileSource.ClearCurrentOperation(Operation: TFileSourceOperation);
|
||||
begin
|
||||
{
|
||||
case Operation.ID of
|
||||
fsoCopyIn:
|
||||
TWfxPluginCopyInOperation.ClearCurrentOperation;
|
||||
fsoCopyOut:
|
||||
TWfxPluginCopyOutOperation.ClearCurrentOperation;
|
||||
fsoDelete:
|
||||
TWfxPluginDeleteOperation.ClearCurrentOperation;
|
||||
end;
|
||||
}
|
||||
end;
|
||||
|
||||
{ TWfxPluginFileSourceConnection }
|
||||
|
||||
constructor TWfxPluginFileSourceConnection.Create(aWfxModule: TWfxModule);
|
||||
begin
|
||||
FWfxModule := aWfxModule;
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
{ TCallbackDataClass }
|
||||
|
||||
constructor TCallbackDataClass.Create(aFileSource: TWfxPluginFileSource);
|
||||
|
|
@ -788,8 +1030,16 @@ end;
|
|||
|
||||
initialization
|
||||
WfxOperationList:= TStringList.Create;
|
||||
WfxConnections := TObjectList.Create(True); // True = destroy objects when destroying list
|
||||
WfxConnectionsLock := TCriticalSection.Create;
|
||||
WfxOperationsQueue := TObjectList.Create(False); // False = don't destroy operations (only store references)
|
||||
WfxOperationsQueueLock := TCriticalSection.Create;
|
||||
|
||||
finalization
|
||||
if Assigned(WfxOperationList) then
|
||||
FreeAndNil(WfxOperationList);
|
||||
FreeThenNil(WfxOperationList);
|
||||
FreeThenNil(WfxConnections);
|
||||
FreeThenNil(WfxConnectionsLock);
|
||||
FreeThenNil(WfxOperationsQueue);
|
||||
FreeThenNil(WfxOperationsQueueLock);
|
||||
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ type
|
|||
private
|
||||
FModuleHandle: TLibHandle; // Handle to .DLL or .so
|
||||
FModuleFileName: UTF8String;
|
||||
FBackgroundFlags: Integer;
|
||||
public
|
||||
{ Mandatory }
|
||||
FsInit : TFsInit;
|
||||
|
|
@ -90,6 +91,8 @@ type
|
|||
FsLinksToLocalFiles:TFsLinksToLocalFiles;
|
||||
FsGetLocalName:TFsGetLocalName;
|
||||
//---------------------
|
||||
FsGetBackgroundFlags: TFsGetBackgroundFlags;
|
||||
//---------------------
|
||||
FsContentGetDetectString:TFsContentGetDetectString;
|
||||
FsContentGetSupportedField:TFsContentGetSupportedField;
|
||||
FsContentGetValue:TFsContentGetValue;
|
||||
|
|
@ -155,6 +158,8 @@ type
|
|||
function VFSRootName: UTF8String;
|
||||
|
||||
function IsLoaded: Boolean;
|
||||
|
||||
property BackgroundFlags: Integer read FBackgroundFlags write FBackgroundFlags;
|
||||
end;
|
||||
|
||||
{ TWFXModuleList }
|
||||
|
|
@ -510,6 +515,8 @@ begin
|
|||
FsLinksToLocalFiles := TFsLinksToLocalFiles (GetProcAddress(FModuleHandle,'FsLinksToLocalFiles'));
|
||||
FsGetLocalName := TFsGetLocalName (GetProcAddress(FModuleHandle,'FsGetLocalName'));
|
||||
//---------------------
|
||||
FsGetBackgroundFlags := TFsGetBackgroundFlags (GetProcAddress(FModuleHandle,'FsGetBackgroundFlags'));
|
||||
//---------------------
|
||||
FsContentGetDetectString := TFsContentGetDetectString (GetProcAddress(FModuleHandle,'FsContentGetDetectString'));
|
||||
FsContentGetSupportedField := TFsContentGetSupportedField (GetProcAddress(FModuleHandle,'FsContentGetSupportedField'));
|
||||
FsContentGetValue := TFsContentGetValue (GetProcAddress(FModuleHandle,'FsContentGetValue'));
|
||||
|
|
@ -576,6 +583,8 @@ begin
|
|||
FsLinksToLocalFiles := nil;
|
||||
FsGetLocalName := nil;
|
||||
//---------------------
|
||||
FsGetBackgroundFlags := nil;
|
||||
//---------------------
|
||||
FsContentGetDetectString := nil;
|
||||
FsContentGetSupportedField := nil;
|
||||
FsContentGetValue := nil;
|
||||
|
|
@ -615,14 +624,19 @@ var
|
|||
dps: tFsDefaultParamStruct;
|
||||
StartupInfo: TExtensionStartupInfo;
|
||||
begin
|
||||
if Assigned(FsSetDefaultParams) then
|
||||
begin
|
||||
dps.DefaultIniName := mbFileNameToSysEnc(gpCfgDir + WfxIniFileName);
|
||||
dps.PluginInterfaceVersionHi:= 2;
|
||||
dps.PluginInterfaceVersionLow:= 0;
|
||||
dps.Size:= SizeOf(dps);
|
||||
FsSetDefaultParams(@dps);
|
||||
end;
|
||||
if Assigned(FsSetDefaultParams) then
|
||||
begin
|
||||
dps.DefaultIniName := mbFileNameToSysEnc(gpCfgDir + WfxIniFileName);
|
||||
dps.PluginInterfaceVersionHi:= 2;
|
||||
dps.PluginInterfaceVersionLow:= 0;
|
||||
dps.Size:= SizeOf(dps);
|
||||
FsSetDefaultParams(@dps);
|
||||
end;
|
||||
|
||||
if not Assigned(FsGetBackgroundFlags) then
|
||||
FBackgroundFlags:= 0
|
||||
else
|
||||
FBackgroundFlags:= FsGetBackgroundFlags();
|
||||
|
||||
// Extension API
|
||||
if Assigned(ExtensionInitialize) then
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ type
|
|||
{U} TFsGetPreviewBitmap = function ( RemoteName:pchar; width,height:integer; ReturnedBitmap:HBITMAP):integer;
|
||||
{R} TFsLinksToLocalFiles = function:boolean;
|
||||
{R} TFsGetLocalName = function (RemoteName:pchar;maxlen:integer):boolean;
|
||||
//------------------------------------------------------
|
||||
TFsGetBackgroundFlags = function: integer;
|
||||
//------------------------------------------------------
|
||||
{R} TFsContentPluginUnloading = procedure;
|
||||
{U} TFsContentGetDetectString = procedure (DetectString:pchar;maxlen:integer);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue