Slik oppretter en Pre-Caching System

Denne artikkelen beskriver hvordan du kan overvåke en stasjon, og pre-cache små filer. . Dette er spesielt nyttig med programmer som sakte transportstrømmer, som mp3-spillere eller p2p programmer
Dette eksemplet viser to ting: For det første: hvordan å overvåke en stasjon ved hjelp ReadDirectoryChangesW. Dette vil la vinduer tilbakeringings applikasjonen når en endring i en fil eller attributter er gjort. Dernest
et lite eksempel på en tråd som utfører pre-cache. Opprett stringlists før du ringer monitordrive eller starte tråden. Overvåke en kjøretur med MonitorDrive (Sti)
typen TTrackInfo = posten H: Integer; O: TOverLapped; B: TFNIBuf; D: String; ende; TPreCache = klasse (TThread) prosedyre Execute; styre; end;
funksjonen Track (I: Integer {TrackIndex}): LongBool;
implementering Var Extensions: array [0..0] av String = ('mp3'); Var Tracks: Array of TTrackInfo; FFilesOpened, FFilesHistory: TStringList; FHasNewFileToCache: Boolean = false; FPrecached: Integer; FTotPrecached: Int64 = 0; FPreCachedFile: String; CS, css: TCriticalSection; //Tilbakeringing rutine: prosedyre {VOID WinAPI} FileIOCompletionRoutine (dwErrorCode: Dword; //ferdigstillelse kode dwNumberOfBytesTransfered: DWORD; //antall byte overført lpOverlapped: Pointer //peker til strukturere med I /O informasjon); STDCALL; Var S, M, V: String; POverLapped: ^ TOverLapped; i, l: Integer; begynne //Return POverLapped: = lpOverLapped;
//hvisOverLapped = POverlapped deretter logger ('ie'); l: = - 1; for i: = 0 til høye (Tracks) gjøre hvisTracks [i] .O = lpOverlapped deretter //funnet tilsvarende indeks begynne l: = i; gå i stykker; ende; hvis l < 0 da //Help, finnes ikke! begynne //Log ('spor indeksen ikke funnet'); exit; end;
gjenta hvis sanne {Tracks [l] .B.Action < > 0} deretter //ignorere gjentatte skriver etc begynne S: = Tracks [l] .B.FileName; //Dette fungerer fordi Filename = array of WChar! SetLength (S, Tracks [l] .B.FileNameLength div 2); S: = Tracks [L] .D + S; //Gjør det hele banen {tilfelle Tracks [l] .B.Action av FILE_ACTION_ADDED: M: = '. Filen ble lagt til katalogen'; FILE_ACTION_REMOVED: M: = 'Filen ble fjernet fra katalogen.'; FILE_ACTION_MODIFIED: M: = 'Filen ble endret. Dette kan være en forandring i tidsstempel eller attributter. '; FILE_ACTION_RENAMED_OLD_NAME: M: = '. Filen ble omdøpt, og dette er det gamle navnet'; FILE_ACTION_RENAMED_NEW_NAME: M: = 'Filen ble omdøpt og dette er det nye navnet.'; end;}
//Log ('Jeempie' + S + '' + M); //Visual system aktivitet: {//Ikke !! Å Computing OMFATTENDE hvis frmMain.lbxActiveFiles.Items.IndexOf (S + '' + M) < 0 da begynne frmMain.lbxActiveFiles.Items.Add (S + '' + M); hvis frmMain.lbxActiveFiles.Items.Count > 8 da frmMain.lbxActiveFiles.Items.Delete (0); ende; } //V: = små bokstaver (extractfileext (S)); //For i: = lav (Extensions) til høy (Extensions) trenger //if (Extensions [i] = V) da begynne //Legg til i kø hvis FFilesHistory.IndexOf (S) < 0 da begynne hvis FFilesHistory.Count > 2000 da FFilesHistory.Clear; FFilesHistory.Add (S); CS.Enter; //Filesize getfileattr FFilesOpened.Add (S); FHasNewFileToCache: = true; CS.Leave; ende; // Gå i stykker; //Isfileopen slutten; end;
hvis Tracks [l] .B.NextEntryOf > 0 deretter flytte (Tracks [l] .B.RawData [Tracks [l] .B.NextEntryOf], Tracks [l] .B.RawData [0], sizeof (Tracks [l] .B) Sporl [l]. B.NextEntryOf); inntil Tracks [l] .B.NextEntryOf = 0;
//Vi kaller Track igjen: Track (l); end;
funksjonen Track (I: Integer {TrackIndex}): LongBool; begynne //Hvis vi Resultat: = ReadDirectoryChangesW (Tracks [I] .h,Tracks [i] .B, DWORD (sizeof (Tracks [i] .B)), LongBool (1), DWORD (FILE_NOTIFY_CHANGE_FILE_NAME eller FILE_NOTIFY_CHANGE_DIR_NAME eller FILE_NOTIFY_CHANGE_ATTRIBUTES eller FILE_NOTIFY_CHANGE_SIZE eller FILE_NOTIFY_CHANGE_LAST_WRITE eller FILE_NOTIFY_CHANGE_LAST_ACCESS eller FILE_NOTIFY_CHANGE_CREATION eller FILE_NOTIFY_CHANGE_CREATION eller FILE_NOTIFY_CHANGE_SECURITY), nil, //@ NrBytes,Tracks [i] .O,FileIOCompletionRoutine); end;
prosedyre MonitorDrive (Sti: String); //Vi vil sette opp en ReadDirectoryChangesW (), treet aktivert //å overvåke alle fil I /O. Var i: LongBool; j, l: Integer; //Buffer innholdet:
HB: DWORD; LB: LongBool; NrBytes: integer; begynne LB: = true; //Ja, rekursiv :))) //for j: = 32 downto 0 gjøre SetLength (Spor, høy (Tracks) +2); l: = høy (Tracks); Tracks [l] .D: = bane; begynne HB: = sizeof (Tracks [l] .B); Tracks [l] .H {Hdir}: = Create (PChar (bane), //peker til filnavnet $ 1, //FILE_READ_DATA, FILE_LIST_DIRECTORY, FILE_SHARE_READ eller FILE_SHARE_DELETE, //aksje modus 0, //sikkerhetsbeskrivelse OPEN_EXISTING, //hvordan du oppretter FILE_FLAG_BACKUP_SEMANTICS eller FILE_FLAG_OVERLAPPED, //filattributter 0 //fil med attributter for å kopiere); jeg: = ReadDirectoryChangesW (Tracks [l] .H {Hdir}Tracks [l] .B {BUF}, HB, LongBool (1), DWORD (FILE_NOTIFY_CHANGE_FILE_NAME eller FILE_NOTIFY_CHANGE_DIR_NAME eller FILE_NOTIFY_CHANGE_ATTRIBUTES eller FILE_NOTIFY_CHANGE_SIZE eller FILE_NOTIFY_CHANGE_LAST_WRITE eller FILE_NOTIFY_CHANGE_LAST_ACCESS eller FILE_NOTIFY_CHANGE_CREATION eller FILE_NOTIFY_CHANGE_SECURITY ), nil, //@ NrBytes,Tracks [l] .O {verlapped}FileIOCompletionRoutine); //CloseHandle (Hdir); La oss holde håndtaket, ikke sant? hvis jeg da begynne //Log ('Track lyktes' + IntToStr (Tracks [l] .H)) end annet; //Log ('Track Feilet' + IntToStr (Tracks [l] .H {Hdir})); enden, product: {HANDLE hDirectory, //håndtere til katalogen for å bli sett LPVOID lpBuffer, //peker til buffer for å motta leseresultater DWORD nBufferLength, //lengde lpBuffer BOOL bWatchSubtree, //flagg for overvåking katalog eller katalogtreet DWORD dwNotifyFilter, //filter forhold å se etter LPDWORD lpBytesReturned, //antall byte returnert LPOVERLAPPED lpOverlapped, //peker til strukturen som trengs for overlappet I /O LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine //peker til ferdigstillelse rutine} ende;
prosedyre TPreCache.Execute; Var F: TFileStream; s, fn: String; begynne SetLength (s, 262 144); //side blokkstørrelse = 256 K F: = null; mens ikke Avsluttet ikke begynne søvn (2); hvis FHasNewFileToCache deretter begynne CS.Enter; hvis FFilesOpened.Count > 0 da begynne fn: = FFilesOpened [0]; FFilesOpened.Delete (0); ende annet begynne fn: = ''; FHasNewFileToCache: = False; ende; CS.Leave; ende; if (fn < > '') og ikke (DirectoryExists (fn)) og FileExists (Fn) da begynne prøve F: = TFileStream.Create (fn, fmOpenRead eller fmShareDenyNone); hvis F.Size < 12 * 1024 * 1024 da //12MB max størrelse begynne mens F.Position < F.Size gjør begynne F.Read (S [1], Lengde (S)); søvn (32); //< 2MB /s end; inc (FTotPrecached, F.Size); FPrecached: = F.Size; FreeAndNil (F); css.Enter; FPrecachedFile: = fn; css.Leave; ende; bortsett //sannsynligvis filen ikke klarte å åpne, bare ignorere slutten; fn: = ''; prøve hvis Assigned (F) da FreeAndNil (F); bortsett fra slutten,
slutten; ende; end;
Det er en viktig ting å gjøre. For å motta tilbakeringing meldingen, må tråden være i alertable tilstand. Dette eksempelet er løp fra hovedtråden, så vi bruker en tidtaker for at:
prosedyre TForm1.tmrAlertableStateTimer (Sender: TObject); begynne SleepEx (2, sann); enden,
Hvis du ikke kaller sleepex () -funksjonen, vil tilbakeringing rutinen ikke får ringt. Sett timeren intervall rimelig lav (200ms eller så). Selvfølgelig ville det være bedre å kjøre dette i en tråd, ville denne tråden bare å sløyfe sleepex hele tiden
vi starte hele ting med dette:
prosedyren TForm1.FormCreate (Sender: TObject.); skriver TDrives = 'C' .. 'Z'; Var d: TDrives; dt: Integer; p: TPreCache; begynne FFilesOpened: = TStringList.Create; FFilesHistory: = TStringList.Create; FFilesHistory.Sorted: = true; CS: = TCriticalSection.Create; css: = TCriticalSection.Create; //stasjonsspor: for d: = lav (TDrives) til høy (TDrives) gjør begynne dt: = GetDriveType (PChar (d + ': \\')); if (dt = DRIVE_FIXED) eller (dt = DRIVE_REMOTE) så MonitorDrive (D + ': \\'); ende; p: = TPreCache.Create (usann); end;
Bare kommentere inn og ut de delene som du vil
.



Previous:
Next Page: