Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Для опытного глаза


Страницы:   1 2 3 4

Dennis I. Komarov ©   (2007-10-16 10:11:00) 

код модуля потока предназначенного для транспорта пакетов с диска в и-нет(FTP)
Еще неизвестно как будет хранится база клиентов и не ведуться логи

Просьба посмотреть данный код на корректность, в смысле поведения при нестабильном конекте (ну и вообще :) )


unit u_send;

interface

uses
 Classes, Windows, SysUtils, StrUtils, DateUtils,
 IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdFTP, IniFiles;

type
 TThreadSend = class(TThread)
 private
   { Private declarations }
 protected
   procedure Execute; override;
 end;

var
 FTP: TIdFTP;

implementation

uses
 Main;

{ Important: Methods and properties of objects in visual components can only be
 used in a method called using Synchronize, for example,

     Synchronize(UpdateCaption);

 and UpdateCaption could look like,

   procedure TThreadSend.UpdateCaption;
   begin
     Form1.Caption := 'Updated in a thread';
   end; }

{ TThreadSend }

procedure TThreadSend.Execute;

var
 SearchRec: TSearchRec;
 FindResult: Integer;

 ClientCode: string;
 FTPLogin: string;

 HomeDir: string;

begin
 { Place thread code here }

 FTP:=TIdFTP.Create(nil);
 try
   FTP.Host:='**.**.**.***';
   FTP.Username:='********';
   FTP.Password:='********';
   FTP.Passive:=true;
   while not Terminated do begin
     {для каждого клиента делать } begin
       FindResult := FindFirst(BCDir + '\MAILBOX\' + ClientCode + '\POSTIN\*.*', faAnyFile, SearchRec);
       while FindResult = 0 do  begin
         with SearchRec do
           begin
             if (Name <> '.') and (Name <> '..') then
               if not (Attr and faDirectory <> 0)
                 then begin
                   if not(FTP.Connected) then
                     try
                       FTP.Connect;
                       HomeDir:=FTP.RetrieveCurrentDir;
                     except
                       FTP.Disconnect;
                     end;
                   if FTP.Connected then
                     try
                       FTP.ChangeDir(HomeDir + '/' + FTPLogin + '/MBOX/RT');
                       FTP.Put(BCDir + '\MAILBOX\' + ClientCode + '\POSTIN\' + Name, Name);
                       if FTP.Size(Name) = Size then begin
                         FTP.Rename(Name, '../R/' + Name);
                         DeleteFile(BCDir + '\MAILBOX\' + ClientCode + '\POSTIN\' + Name);
                       end;
                     except
                       FTP.Disconnect;
                     end;
                 end;
             FindResult:= FindNext(SearchRec);
           end;
       end;
       FindClose(SearchRec);
     end;
     FTP.Disconnect;
     Sleep(15000);
   end;
 finally
   FTP.Disconnect;
   FTP.Free;
 end;
end;
end.


Dennis I. Komarov   (2007-10-30 16:47:00) [21]

Почему
> lpNumberOfBytesTansferred^

?

GetOverLappedResult(hDir, lpOverlapped^, lpNumberOfBytesTansferred, true)
третьим параметром указатель кушать не хочет, хотя в справке LPDWORD

В функции хочет Cardinal а на Pointer ругается.


> От балды ты поставил, а не "из-за щедрости")


Неее, балда подумала, что этого более чем хватит!

A array [0..4095] of ... почему низя сделать? Получим такойже объем (64*1024 = SizeOf(TFileNotifyInformation)*4096). По идее все должно оказаться в массиве. С ним же удобнее работать. Ну и пусть памяти быдет выделено немного больше (65Kb Не так страшно)


Сергей М.   (2007-10-30 16:11:00) [22]


> Дабы если false, то пытался поставить запрос заново


Малацца, что тут сказать)

А почему false - тебе по барабану.

Жди бесконечного цикла)


> А 1000 поставил из-за щедрости


От балды ты поставил, а не "из-за щедрости")

Программа, реализованная от балды, работать как положено никогда не будет.

У тебя есть lpNumberOfBytesTansferred^, у тебя есть связный список в lpBuf^, вот пробегись по этому списку и выдели памяти под врем.буфер ровно столько, сколько нужно, но не более  lpNumberOfBytesTansferred^


Dennis I. Komarov   (2007-10-30 15:50:00) [23]

> Накой ляд тут этот цикл ?

Дабы если false, то пытался поставить запрос заново :)


> Как кореллирует sizeof(TTFileNotifyInformationArray) c 64*1024
> и lpNumberOfBytesTansferred^ ?

Откровенно говоря никак, но он веди не меньше получится. Я так понимаю, что остальные элементы массива просто пустыми остануться. А 1000 поставил из-за щедрости :)

Ок, понял. Меняем packed record на просто record

array [0..4095] of ....


Сергей М.   (2007-10-30 15:33:00) [24]

Действительно безобразие)


> while not ReadDirectoryChangesW(hDir, lpBuf, SizeOf(lpBuf),
>  true, FILE_NOTIFY_CHANGE_FILE_NAME, nil, lpOverlapped,
> nil) do;


Накой ляд тут этот цикл ?


>    tBuf:=TTFileNotifyInformationArray(lpBuf^);


А это что такое ?

Как кореллирует sizeof(TTFileNotifyInformationArray) c 64*1024 и lpNumberOfBytesTansferred^ ?


Dennis I. Komarov   (2007-10-30 15:23:00) [25]


unit u_send;

interface

uses
 Classes, Windows, SysUtils, StrUtils, DateUtils,
 IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdFTP, IniFiles;

type

 TThreadSend = class(TThread)
 private
   { Private declarations }

 protected
   procedure Execute; override;

 end;

implementation

uses
 Main;

{ TThreadSend }
type
 PFileNotifyInformation = ^TFileNotifyInformation;
 TFileNotifyInformation = packed record
   NextEntryOffset: DWORD;
   Action: DWORD;
   FileNameLength:DWORD;
   FileName: WideChar;
 end;

 TTFileNotifyInformationArray = array[0..1000] of TFileNotifyInformation;

procedure TThreadSend.Execute;

var
 i: Integer;
 tBuf: TTFileNotifyInformationArray;
 hDir, hDirChangeEvent: THandle;

 lpBuf: Pointer;
 lpOverlapped: POverlapped;

 lpNumberOfBytesTansferred: Cardinal;
begin
 { Place thread code here }
 FreeOnTerminate:=false;
 hDirChangeEvent:=CreateEvent(nil, false, false, PChar('OnChangeDirecory'));
 hDir := CreateFile ( 'c:\test', GENERIC_READ, FILE_SHARE_READ, nil,
         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED, 0);
 if hDir <> INVALID_HANDLE_VALUE then begin
   GetMem(lpBuf, 64*1024);
   GetMem(lpOverlapped, SizeOf(lpOverlapped^));
   try
     ZeroMemory(lpBuf, 64*1024);
     lpOverlapped^.hEvent:=hDirChangeEvent;
     if ReadDirectoryChangesW(hDir, lpBuf, SizeOf(lpBuf), true, FILE_NOTIFY_CHANGE_FILE_NAME, nil, lpOverlapped, nil) then
       while not Terminated do begin
         if (WaitForSingleObject(hDirChangeEvent, 1000) = WAIT_OBJECT_0) and
            (GetOverLappedResult(hDir, lpOverlapped^, lpNumberOfBytesTansferred, true)) then begin
           //Копируем результаты в резервный буфер
           tBuf:=TTFileNotifyInformationArray(lpBuf^);
           while not ReadDirectoryChangesW(hDir, lpBuf, SizeOf(lpBuf), true, FILE_NOTIFY_CHANGE_FILE_NAME, nil, lpOverlapped, nil) do;
           i:=0;
           repeat

{
             Разбераем tBuf[i]
             Если появился новый => шмаляем, исли гуд то в архив
{}

             Inc(i);
           until tBuf[i].NextEntryOffset > 0
         end;
       end;
   finally
     FreeMem(lpBuf);
     FreeMem(lpOverlapped);
     CloseHandle(hDirChangeEvent);
     CloseHandle(hDir);
   end;
 end;
end;

end.


Вот такой "безобразие". Как оно?


Сергей М.   (2007-10-30 08:18:00) [26]


> Как быть?


Ну как ?...
Конечно же скопировать содержимое lpBuf^ во временный буфер и разбирать уже этот временнный буфер, а не lpBuf^. Неужели это не очевидно ?


Dennis I. Komarov   (2007-10-29 17:10:00) [27]

> [47] Сергей М. ©   (26.10.07 16:51)

> if WaitFor...... and GetOverlappedResult(..) then
>  begin
>    if ReadDir...
>    //далее разбираем lpBuf
Если получаем информацию, о появлении нового файла, то отправляем на FTP, исли он отправился успешно, то удаляем его => получаем очередное изменение, а значит lpBuf изменен, т.е. все остальные информацонные записи - утеряны :(  
    Как быть?
>  end;


Сергей М.   (2007-10-29 13:59:00) [28]


> как положено разбирать lpBuf?


В точном соответствии с офиц.описанием структуры FILE_NOTIFY_INFORMATION.


> Ведь там может храниться несколько записей типа


И что ?


Dennis I. Komarov   (2007-10-29 13:52:00) [29]

А как положеноразбирать lpBuf? Ведь там может храниться несколько записей типа TFileNotifyInformation.


Сергей М.   (2007-10-26 16:51:00) [30]

if WaitFor...... and GetOverlappedResult(..)then
  begin
    if ReadDir...
    //далее разбираем lpBuf
  end;


Dennis I. Komarov   (2007-10-26 16:35:00) [31]

Как понимаю, lpBuff заполняется пакетамя типа TFileNotifyInformation, в котором NextEntryOffset отвечает за существование следующего пакета. Отсюда и возник вопрос, нужен ли pNumberOfBytesTranferred вообще.

И как лучше сделать:
1.

...
 if WaitFor...... do
   begin
     if ReadDir...
     //далее разбираем lpBuf
   end;

2.
 if WaitFor...... do
   begin
     //тут разбираем lpBuf
     if ReadDir...
   end;


Сергей М.   (2007-10-26 15:51:00) [32]


> Dennis I. Komarov ©   (26.10.07 15:47) [44]


А, ты вон про что ..

Ну да, в дельфийской декларации этот параметр объявлен для передачи по ссылке, т.е. как var-параметр.


> Мой скромный перевод - это скока надо читать ин-фы из lpBuf.
>  (разумеется не переменная)


Правильно перевел.


Dennis I. Komarov   (2007-10-26 15:47:00) [33]

> Это Points to a 32-bit variable that receives the number
> of bytes that were actually transferred by a read or write
> operation

Я F1 умею жать :) только не понял почему Point s
Мой скромный перевод - это скока надо читать ин-фы из lpBuf. (разумеется не переменная)


Сергей М.   (2007-10-26 14:40:00) [34]


> Ибо обновление по F5 получаем


А у меня Explorer самотслеживает изменения в показываемой им в тек.момент директории.

Что я делаю не так ?


> А первоначальную информацию он как читает?


А по барабану как он ее читает. Мы же об отслеживании изменений речь ведем)


> это VAR ?


Это Points to a 32-bit variable that receives the number of bytes that were actually transferred by a read or write operation


> Он вообще имеет значение


А нафига он тогда фигурирует в структуре, если он якобы не нужен ?


Dennis I. Komarov   (2007-10-26 13:34:00) [35]

> С чего ты так уверен ?

Ибо обновление по F5 получаем. Я сомниваюсь, что все это время Explorer хранит эти изменения, и отображает их по команде.

А первоначальную информацию он как читает?

----------

lpNumberOfBytesTranferred - это VAR ? Он вообще имеет значение, ведь читаль lpBuf будем.


Сергей М.   (2007-10-26 12:32:00) [36]


> Dennis I. Komarov ©   (26.10.07 12:26) [40]


> Но ведь не асинхронный.


С чего ты так уверен ?
Да и какая разница, синхронный или асинхронный ?
Режим не имеет значения с т.з. твоих волнений насчет "потерь" .


Dennis I. Komarov   (2007-10-26 12:26:00) [37]

> [39] Сергей М. ©   (26.10.07 11:44)

Но ведь не асинхронный.


Сергей М.   (2007-10-26 11:44:00) [38]


> "сканить" диск всетаки надежнее


С чего бы ?

Explorer, заметь, использует именно ReadDirectoryChangesW


Сергей М.   (2007-10-26 11:23:00) [39]


> чего она сюда хочет?


hDir твой она хочет.


Dennis I. Komarov   (2007-10-26 09:57:00) [40]

> Нет. Поэтому следует как можно быстрей после сигнала ивента
> принять решение о постановке очередного запроса и лишь потом
> разбирать результаты текущего выполненного.

Гм... Но для этого все равно понадобится какое то время, т.е.
Получили сигнал события, далее по идее запроса в очереди нет, следует отправить его еще раз, отправлять с тем же указателем на буфер низя - можем потерять его, следовательно, предварительно надо сохранить данные, это потребует некоторого времени, за которое могут произойти изменения, начинаю подумывать о том, что "сканить" диск всетаки надежнее


> Мало ли что могло произойти во время исполнения запроса
> !
> Ф-ция как раз и покажет, успешно ли выполнен запрос.
> А сигнал ивента лишь фиксирует факт завершения (успешного
> или неуспешного) асинхронной операции.


hFile - чего она сюда хочет?


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо