mmfcp

Torak 27.06.03 08:23

Memory-mapped file copy

 Tekstiversio  Arvo: 1 (2 ääntä)  Äänestä: +  -
#include <stdio.h>
#include <windows.h>

BOOL FileCopy(LPCTSTR lpExistingFileName,  LPCTSTR lpNewFileName);

#ifdef DEBUG
#define Debug() fprintf(stderr, "Debug() line: %d GetLastError: %lu\n", \
    __LINE__, GetLastError());
#else
    #define Debug() (NULL)
#endif

int main(int argc, char *argv[])
{
    DWORD start;
    if(argc != 3)
    {
        printf( "Copy file to another location"
                "Usage: mmfcp file1 file2");
        return 0;
    }
    start = GetTickCount();
    FileCopy(argv[1], argv[2]);
    printf("test1: %d\n", GetTickCount() - start);
/*
    start = GetTickCount();
    CopyFile(argv[1], argv[2], FALSE);
    printf("test2: %d\n", GetTickCount() - start);
*/

    return 0;
}

BOOL FileCopy(LPCTSTR lpExistingFileName,  LPCTSTR lpNewFileName)
{
    HANDLE hInFile;
    HANDLE hOutFile;
    HANDLE hInMap;
    HANDLE hOutMap;
    const void *pIn;
    void *pOut;
    LARGE_INTEGER FileSize;
    LARGE_INTEGER MapOffset = { 0, 0 };
    DWORD MapSize;
    BOOL bRet = FALSE;

    // Opening source file
    hInFile = CreateFile(lpExistingFileName, GENERIC_READ, FILE_SHARE_READ,
        NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
    if(hInFile == INVALID_HANDLE_VALUE)
    {
        Debug();
        return FALSE;
    }

    // Getting file size
    FileSize.LowPart  = GetFileSize(hInFile, &FileSize.HighPart);
    if(FileSize.LowPart == 0xFFFFFFFF)
    {
        Debug();
        goto CleanUp;
    }

    // Don't allow copy zero byte files. Becose CreateFileMapping fails.
    if(FileSize.QuadPart == 0)
    {
        Debug();
        goto CleanUp;
    }

    // Mapping source file
    hInMap=CreateFileMapping(hInFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if(hInMap ==NULL)
    {
        Debug();
        goto CleanUp;
    }

    // Creating destination file
    hOutFile=CreateFile(lpNewFileName, GENERIC_WRITE | GENERIC_READ, 0,
        NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
    if(hOutFile==INVALID_HANDLE_VALUE)
    {
        Debug();
        goto CleanUp;
    }

    // Mapping output file
    hOutMap=CreateFileMapping(hOutFile, NULL, PAGE_READWRITE,
       FileSize.HighPart, FileSize.LowPart, NULL);
    if(hOutMap==NULL)
    {
        Debug();
        goto CleanUp;
    }

    while (0 != FileSize.QuadPart)
    {
        if(FileSize.HighPart)
            MapSize = 4294967295;
        else
            MapSize = FileSize.LowPart;

        // Creating view of input file
        pIn=MapViewOfFile(hInMap, FILE_MAP_READ,
            MapOffset.HighPart,MapOffset.LowPart, MapSize);
        if(pIn == NULL)
        {
            Debug();
            goto CleanUp;
        }

        // Createte view of output file
        pOut=MapViewOfFile(hOutMap, FILE_MAP_WRITE,
            MapOffset.HighPart,MapOffset.LowPart, MapSize);
        if(pOut==NULL)
        {
            Debug();
            goto CleanUp;
        }
        CopyMemory(pOut, pIn, MapSize);

        FileSize.QuadPart  -= MapSize;
        MapOffset.QuadPart += MapSize;
    }

    bRet = TRUE;

CleanUp:
    if(pIn != NULL) UnmapViewOfFile (pIn);
    if(pOut != NULL) UnmapViewOfFile (pOut);
    if(hInMap != NULL) CloseHandle (hInMap);
    if(hOutMap != NULL) CloseHandle (hOutMap);
    if(hInFile != INVALID_HANDLE_VALUE) CloseHandle (hInFile);
    if(hOutFile != INVALID_HANDLE_VALUE) CloseHandle (hOutFile);
    if(bRet == FALSE) DeleteFile(lpNewFileName);

    return bRet;
}

Torak 08:26 27.6.03 
Ajattelin kopioida oman tiedosto kopiointi rutiinin jos se olisi nopeampi kuin CopyFile() kun tuli luettua jostain webbi sivulta että MMF on nopsa kun käytetään NTFS:ssää. No pienen testauksen jälkeen tuli kuitenkin huomattua että yllä oleva pätkä on hitaampi :(
thefox 20:29 27.6.03 
Ok esimerkki memorymapped-filuista... tosiaan, yksinkertaisemmat tavat lienevät hieman nopeampia kun on kyseessä pelkkä tiedoston kopiointi :-) Jos tuota nyt oikeasti meinaisi käyttää niin ainakin jonkinlainen wildcard-systeemi olisi kätevä.
weicco 20:55 28.6.03 
Hyvin demostroitu memory-mapping asioita ja tiedostonkäsittelyä Windowsissa. Ehkä memory-mappi ei kuitenkaan ole paras mahdollinen vaihtoehto tähän tarkoitukseen.
Snpr 17:29 23.7.03 
Mjooh, tota vois tarvita vaikkapa global hookeissa jos täytyy pitää esim. joku tietty notifikaatio hWnd muistissa.