VirtualBox

Changeset 2339 in kBuild for trunk/src


Ignore:
Timestamp:
Apr 14, 2009 7:21:15 PM (16 years ago)
Author:
bird
Message:

More hacking.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kdepdb.c

    r2337 r2339  
    4848#endif
    4949
    50 #ifdef WINDOWS32
    51 # include <io.h>
    52 # include <process.h>
     50#if K_OS == K_WINDOWS
    5351# include <Windows.h>
    54 # define PARSE_IN_WORKER
    55 #endif
     52#else
     53# include <unistd.h>
     54# include <sys/mman.h>
     55#endif
     56
    5657
    5758/*******************************************************************************
     
    353354    /** The string table file. */
    354355    KDEPDBSTRTAB   *pStrTab;
     356    /** The handle of the string table file. */
     357    KDEPDBFH        hStrTab;
    355358    /** The end of the allocated string table indexes (i.e. when to grow the
    356359     * file). */
    357360    KU32            iStringAlloced;
    358     /** The handle of the string table file. */
    359     KDEPDBFH        hStrTab;
    360361} KDEPDBINTSTRTAB;
    361362
     
    412413static void *kDepDbAlloc(KSIZE cb);
    413414static void kDepDbFree(void *pv);
    414 static int  kDepDbFHOpen(KDEPDBFH *pFH, const char *pszFilename);
     415static void kDepDbFHInit(KDEPDBFH *pFH);
     416static int  kDepDbFHUpdateSize(KDEPDBFH *pFH);
     417static int  kDepDbFHOpen(KDEPDBFH *pFH, const char *pszFilename, KBOOL fCreate, KBOOL *pfNew);
    415418static int  kDepDbFHClose(KDEPDBFH *pFH);
    416419static int  kDepDbFHWriteAt(KDEPDBFH *pFH, KU32 off, void const *pvBuf, KSIZE cbBuf);
     
    427430}
    428431
    429 
    430432/** free wrapper. */
    431433static void kDepDbFree(void *pv)
     
    435437}
    436438
     439
     440/**
     441 * Initializes the file handle structure so closing it without first opening it
     442 * will work smoothly.
     443 *
     444 * @param   pFH         The file handle structure.
     445 */
     446static void kDepDbFHInit(KDEPDBFH *pFH)
     447{
     448#if K_OS == K_OS_WINDOWS
     449    pFH->hFile   = INVALID_HANDLE_VALUE;
     450    pFH->hMapObj = INVALID_HANDLE_VALUE;
     451#else
     452    pFH->fd = -1;
     453#endif
     454    pFH->cb = 0;
     455}
     456
     457/**
     458 * Updates the file size.
     459 *
     460 * @returns 0 on success. Some non-zero native error code on failure.
     461 * @param   pFH             The file handle structure.
     462 */
     463static int  kDepDbFHUpdateSize(KDEPDBFH *pFH)
     464{
     465#if K_OS == K_OS_WINDOWS
     466    DWORD   rc;
     467    DWORD   dwHigh;
     468    DWORD   dwLow;
     469
     470    SetLastError(0);
     471    dwLow = GetFileSize(File, &High);
     472    rc = GetLastError();
     473    if (rc)
     474    {
     475        pFH->cb = 0;
     476        return (int)rc;
     477    }
     478    if (High)
     479        pFH->cb = KU32_MAX;
     480    else
     481        pFH->cb = dwLow;
     482#else
     483    off_t cb;
     484
     485    cb = lseek(pFH->fd, 0, SEEK_END);
     486    if (cb == -1)
     487    {
     488        pFH->cb = 0;
     489        return errno;
     490    }
     491    pFH->cb = cb;
     492    if ((off_t)pFH->cb != cb)
     493        pFH->cb = KU32_MAX;
     494#endif
     495    return 0;
     496}
     497
     498/**
     499 * Opens an existing file or creates a new one.
     500 *
     501 * @returns 0 on success. Some non-zero native error code on failure.
     502 *
     503 * @param   pFH             The file handle structure.
     504 * @param   pszFilename     The name of the file.
     505 * @param   fCreate         Whether we should create the file or not.
     506 * @param   pfCreated       Where to return whether we created it or not.
     507 */
     508static int  kDepDbFHOpen(KDEPDBFH *pFH, const char *pszFilename, KBOOL fCreate, KBOOL *pfCreated)
     509{
     510    int                 rc;
     511#if K_OS == K_OS_WINDOWS
     512    SECURITY_ATTRIBUTES SecAttr;
     513
     514    SecAttr.bInheritHandle = FALSE;
     515    SecAttr.lpSecurityDescriptor = NULL;
     516    SecAttr.nLength = 0;
     517    pFH->cb = 0;
     518    SetLastError(0);
     519    pFH->hFile = CreateFile(pszFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &SecAttr,
     520                            fCreate ? OPEN_ALWAYS : OPEN_EXISTING, 0, NULL);
     521    if (pFH->hFile == INVALID_HANDLE_VALUE)
     522        return GetLastError();
     523    *pfCreated = GetLastError() == 0;
     524
     525#else
     526    int fFlags = O_RDWR;
     527# ifdef O_BINARY
     528    fFlags |= O_BINARY;
     529# endif
     530    pFH->cb = 0;
     531    pFH->fd = open(pszFilename, fFlags, 0);
     532    if (pFH->fd >= 0)
     533        *pfCreated = K_FALSE;
     534    else if (!fCreate)
     535        return errno;
     536    else
     537    {
     538        pFH->fd = open(pszFilename, fFlags | O_EXCL | O_CREATE, 0666);
     539        if (pFH->fd < 0)
     540            return errno;
     541        *pfCreated = K_TRUE;
     542    }
     543    fcntl(pFH->fd, F_SETFD, FD_CLOEXEC);
     544#endif
     545
     546    /* update the size */
     547    rc = kDepDbFHUpdateSize(pFH);
     548    if (rc)
     549        kDepDbFHClose(pFH);
     550    return rc;
     551}
     552
     553/**
     554 * Closes an open file.
     555 *
     556 * @returns 0 on success. Some non-zero native error code on failure.
     557 *
     558 * @param   pFH         The file handle structure.
     559 */
     560static int  kDepDbFHClose(KDEPDBFH *pFH)
     561{
     562#if K_OS == K_OS_WINDOWS
     563    if (pFH->hFile != INVALID_HANDLE_VALUE)
     564    {
     565        if (!CloseHandle(pFH->hFile))
     566            return GetLastError();
     567        pFH->hFile = INVALID_HANDLE_VALUE;
     568    }
     569
     570#else
     571    if (pFH->fd >= 0)
     572    {
     573        if (close(pFH->fd) != 0)
     574            return errno;
     575        pFH->fd = -1;
     576    }
     577#endif
     578    pFH->cb = 0;
     579    return 0;
     580}
     581
     582/**
     583 * Writes to a file.
     584 *
     585 * @returns 0 on success. Some non-zero native error code on failure.
     586 *
     587 * @param   pFH         The file handle structure.
     588 * @param   off         The offset into the file to start writing at.
     589 * @param   pvBuf       What to write.
     590 * @param   cbBuf       How much to write.
     591 */
     592static int  kDepDbFHWriteAt(KDEPDBFH *pFH, KU32 off, void const *pvBuf, KSIZE cbBuf)
     593{
     594#if K_OS == K_OS_WINDOWS
     595    ULONG cbWritten;
     596
     597    if (SetFilePointer(pFH->hFile, off, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
     598        return GetLastError();
     599
     600    if (!WriteFile(pFH->hFile, pvBuf, cbBuf, &cbWritten, NULL))
     601        return GetLastError();
     602    if (cbWritten != cbBuf)
     603        return -1;
     604
     605#else
     606    ssize_t cbWritten;
     607    if (lseek(pFH->fd, off, SEEK_SET) == -1)
     608        return errno;
     609    errno = 0;
     610    cbWritten = write(pFH->fd, pvBuf, cbBuf);
     611    if ((size_t)cbWritten != cbBuf)
     612        return errno ? errno : EIO;
     613#endif
     614    return kDepDbFHUpdateSize(pFH);
     615}
     616
     617
     618/**
     619 * Creates a memory mapping of the file.
     620 *
     621 * @returns 0 on success. Some non-zero native error code on failure.
     622 *
     623 * @param   pFH         The file handle structure.
     624 * @param   ppvMap      Where to return the map address.
     625 */
     626static int  kDepDbFHMap(KDEPDBFH *pFH, void **ppvMap)
     627{
     628#if K_OS == K_OS_WINDOWS
     629    *ppvMap = NULL;
     630    return -1;
     631#else
     632    *ppvMap = mmap(NULL, pFH->cb, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pFH->fd, 0);
     633    if (*ppvMap == (void *)-1)
     634    {
     635        *ppvMap = NULL;
     636        return errno;
     637    }
     638#endif
     639    return 0;
     640}
     641
     642
     643/**
     644 * Flushes and destroys a memory of the file.
     645 *
     646 * @returns 0 on success. Some non-zero native error code on failure.
     647 *
     648 * @param   pFH         The file handle structure.
     649 * @param   ppvMap      The pointer to the mapping pointer. This will be set to
     650 *                      NULL on success.
     651 */
     652static int  kDepDbFHUnmap(KDEPDBFH *pFH, void **ppvMap)
     653{
     654#if K_OS == K_OS_WINDOWS
     655    return -1;
     656#else
     657    if (msync(*ppvMap, pFH->cb, MS_SYNC) == -1)
     658        return errno;
     659    if (munmap(*ppvMap, pFH->cb) == -1)
     660        return errno;
     661    *ppvMap = NULL;
     662#endif
     663    return 0;
     664}
     665
     666
     667/**
     668 * Grows the memory mapping of the file.
     669 *
     670 * The content of the new space is undefined.
     671 *
     672 * @returns 0 on success. Some non-zero native error code on failure.
     673 *
     674 * @param   pFH         The file handle structure.
     675 * @param   cbNew       The new mapping size.
     676 * @param   ppvMap      The pointer to the mapping pointer. This may change and
     677 *                      may be set to NULL on failure.
     678 */
     679static int  kDepDbFHGrow(KDEPDBFH *pFH, KSIZE cbNew, void **ppvMap)
     680{
     681#if K_OS == K_OS_WINDOWS
     682    return -1;
     683#else
     684    if ((KU32)cbNew != cbNew)
     685        return ERANGE;
     686    if (cbNew <= pFH->cb)
     687        return 0;
     688
     689    if (munmap(*ppvMap, pFH->cb) == -1)
     690        return errno;
     691    *ppvMap = NULL;
     692
     693    pFH->cb = cbNew;
     694    return kDepDbFHMap(pFH, ppvMap);
     695#endif
     696}
     697
     698
     699/** Macro for reading an potentially unaligned 16-bit word from a string. */
     700# if K_ARCH == K_ARCH_AMD64 \
     701  || K_ARCH == K_ARCH_X86_32 \
     702  || K_ARCH == K_ARCH_X86_16
     703#  define kDepDbHashString_get_unaligned_16bits(ptr)   ( *((const KU16 *)(ptr)) )
     704# elif K_ENDIAN == K_ENDIAN_LITTLE
     705#  define kDepDbHashString_get_unaligned_16bits(ptr)   (  (((const KU8 *)(ptr))[0]) \
     706                                                        | (((const KU8 *)(ptr))[1] << 8) )
     707# else
     708#  define kDepDbHashString_get_unaligned_16bits(ptr)   (  (((const KU8 *)(ptr))[0] << 8) \
     709                                                        | (((const KU8 *)(ptr))[1]) )
     710# endif
     711
     712
     713/**
     714 * Hash a string.
     715 *
     716 * @returns Hash value.
     717 *
     718 * @param   pszString       The string to hash.
     719 * @param   cchString       How much to hash.
     720 */
     721static KU32 kDepDbHashString(const char *pszString, size_t cchString)
     722{
     723    /*
     724     * Paul Hsieh hash SuperFast function:
     725     * http://www.azillionmonkeys.com/qed/hash.html
     726     */
     727    /** @todo A path for well aligned data should be added to speed up execution on
     728     *        alignment sensitive systems. */
     729    unsigned int uRem;
     730    KU32 uHash;
     731    KU32 uTmp;
     732
     733    assert(sizeof(KU8) == sizeof(char));
     734
     735    /* main loop, walking on 2 x KU16 */
     736    uHash = cchString;
     737    uRem  = cchString & 3;
     738    cchString >>= 2;
     739    while (cchString > 0)
     740    {
     741        uHash      += kDepDbHashString_get_unaligned_16bits(pszString);
     742        uTmp        = (kDepDbHashString_get_unaligned_16bits(pszString + 2) << 11) ^ uHash;
     743        uHash       = (uHash << 16) ^ uTmp;
     744        pszString  += 2 * sizeof(KU16);
     745        uHash      += uHash >> 11;
     746        cchString--;
     747    }
     748
     749    /* the remainder */
     750    switch (uRem)
     751    {
     752        case 3:
     753            uHash += kDepDbHashString_get_unaligned_16bits(pszString);
     754            uHash ^= uHash << 16;
     755            uHash ^= pszString[sizeof(KU16)] << 18;
     756            uHash += uHash >> 11;
     757            break;
     758        case 2:
     759            uHash += kDepDbHashString_get_unaligned_16bits(pszString);
     760            uHash ^= uHash << 11;
     761            uHash += uHash >> 17;
     762            break;
     763        case 1:
     764            uHash += *pszString;
     765            uHash ^= uHash << 10;
     766            uHash += uHash >> 1;
     767            break;
     768    }
     769
     770    /* force "avalanching" of final 127 bits. */
     771    uHash ^= uHash << 3;
     772    uHash += uHash >> 5;
     773    uHash ^= uHash << 4;
     774    uHash += uHash >> 17;
     775    uHash ^= uHash << 25;
     776    uHash += uHash >> 6;
     777
     778    return uHash;
     779}
    437780
    438781
     
    454797    KDEPDBHASH const   *pHash      = pStrTab->pHash;
    455798    KDEPDBSTRING const *paStrings  = &pStrTab->pStrTab->aStrings[0];
    456     KU32 const          iStringEnd = pStrTab->pStrTab->iStringEnd;
     799    KU32 const          iStringEnd = K_LE2H_U32(pStrTab->pStrTab->iStringEnd);
    457800    KU32                iHash;
    458801
     
    467810    for (;;)
    468811    {
    469         KU32 iString = pHash->auEntries[iHash];
     812        KU32 iString = K_LE2H_U32(pHash->auEntries[iHash]);
    470813        if (iString < iStringEnd)
    471814        {
    472815            KDEPDBSTRING const *pString = &paStrings[iString];
    473             if (    pString->uHash     == uHash
    474                 &&  pString->cchString == cchString
     816            if (    K_LE2H_U32(pString->uHash)     == uHash
     817                &&  K_LE2H_U32(pString->cchString) == cchString
    475818                &&  !memcmp(pString->szString, pszString, cchString))
    476819                return iString;
     
    492835 * @returns 0 on success, -1 on failure.
    493836 * @param   pStrTab         The string table.
     837 * @todo    Rebuild from string table, we'll be accessing it anyways.
    494838 */
    495839static int kDepDbStrTabReHash(KDEPDBINTSTRTAB *pStrTab)
    496840{
    497841    KDEPDBSTRING const *paStrings   = &pStrTab->pStrTab->aStrings[0];
    498     KU32 const          iStringEnd  = pStrTab->pStrTab->iStringEnd;
     842    KU32 const          iStringEnd  = K_LE2H_U32(pStrTab->pStrTab->iStringEnd);
    499843    KDEPDBHASH         *pHash       = pStrTab->pHash;
    500844    KDEPDBHASH          HashHdr     = *pHash;
     
    525869     * Popuplate the new table.
    526870     */
    527     HashHdr.cEntries     = cEntriesNew;
     871    HashHdr.cEntries     = K_LE2H_U32(cEntriesNew);
    528872    HashHdr.cCollisions  = 0;
    529873    HashHdr.cUsedEntries = 0;
     
    531875    while (i-- > 0)
    532876    {
    533         KU32 iString = pHash->auEntries[i];
     877        KU32 iString = K_LE2H_U32(pHash->auEntries[i]);
    534878        if (iString < iStringEnd)
    535879        {
    536880            KU32 iHash = (paStrings[iString].uHash % cEntriesNew);
    537             if (pauNew[iHash] != KDEPDBHASH_UNUSED)
     881            if (pauNew[iHash] != K_H2LE_U32(KDEPDBHASH_UNUSED))
    538882            {
    539883                do
     
    541885                    iHash = (iHash + 1) % cEntriesNew;
    542886                    HashHdr.cCollisions++;
    543                 } while (pauNew[iHash] != KDEPDBHASH_UNUSED);
     887                } while (pauNew[iHash] != K_H2LE_U32(KDEPDBHASH_UNUSED));
    544888            }
    545889            pauNew[iHash] = iString;
    546             HashHdr.cEntries++;
     890            HashHdr.cUsedEntries++;
    547891        }
    548892        else if (   iString != KDEPDBHASH_UNUSED
    549893                 && iString != KDEPDBHASH_DELETED)
    550894        {
    551             /* ignore any invalid entires for now */;
     895            kDepDbFree(pauNew);
     896            return -1;
    552897        }
    553898    }
     899    HashHdr.cCollisions  = K_H2LE_U32(HashHdr.cCollisions);
     900    HashHdr.cUsedEntries = K_H2LE_U32(HashHdr.cUsedEntries);
    554901
    555902    /*
     
    593940    KDEPDBHASH         *pHash       = pStrTab->pHash;
    594941    KDEPDBSTRING       *paStrings   = &pStrTab->pStrTab->aStrings[0];
    595     KU32 const          iStringEnd  = pStrTab->pStrTab->iStringEnd;
     942    KU32 const          iStringEnd  = K_LE2H_U32(pStrTab->pStrTab->iStringEnd);
    596943    KU32                iInsertAt   = KDEPDBHASH_UNUSED;
    597944    KU32                cCollisions = 0;
     
    606953
    607954    /*
    608      * Hash lookup of the string.
     955     * Hash lookup of the string, finding either an existing copy or where to
     956     * insert the new string at in the hash table.
    609957     */
    610958    iHash = uHash % pHash->cEntries;
    611959    for (;;)
    612960    {
    613         iString = pHash->auEntries[iHash];
     961        iString = K_LE2H_U32(pHash->auEntries[iHash]);
    614962        if (iString < iStringEnd)
    615963        {
    616964            KDEPDBSTRING const *pString = &paStrings[iString];
    617             if (    pString->uHash     == uHash
    618                 &&  pString->cchString == cchString
     965            if (    K_LE2H_U32(pString->uHash)     == uHash
     966                &&  K_LE2H_U32(pString->cchString) == cchString
    619967                &&  !memcmp(pString->szString, pszString, cchString))
    620968                return iString;
     
    644992    if (iStringEnd + cEntries > pStrTab->iStringAlloced)
    645993    {
    646         KSIZE   cbNewSize = K_ALIGN_Z((iStringEnd + cEntries) * sizeof(KDEPDBSTRING) + 64*1024, 256*1024);
     994        KSIZE cbNewSize      = K_ALIGN_Z((iStringEnd + cEntries) * sizeof(KDEPDBSTRING) + 64*1024, 256*1024);
     995        KU32  iStringAlloced = (pStrTab->hStrTab.cb - K_OFFSETOF(KDEPDBSTRTAB, aStrings)) / sizeof(KDEPDBSTRING);
     996        if (    iStringAlloced <= pStrTab->iStringAlloced
     997            ||  iStringAlloced >= KDEPDBG_STRTAB_IDX_END
     998            ||  iStringAlloced >= KDEPDBHASH_END)
     999            return KDEPDBG_STRTAB_IDX_ERROR;
    6471000        if (kDepDbFHGrow(&pStrTab->hStrTab, cbNewSize, (void **)&pStrTab->pStrTab) != 0)
    6481001            return KDEPDBG_STRTAB_IDX_ERROR;
    649 
    650         pStrTab->iStringAlloced = (cbNewSize - K_OFFSETOF(KDEPDBSTRTAB, aStrings)) / sizeof(KDEPDBSTRING);
     1002        pStrTab->iStringAlloced = iStringAlloced;
    6511003        paStrings = &pStrTab->pStrTab->aStrings[0];
    6521004    }
     1005
    6531006    pNewString = &paStrings[iStringEnd];
    654     pNewString->uHash     = uHash;
    655     pNewString->cchString = cchString;
     1007    pNewString->uHash     = K_H2LE_U32(uHash);
     1008    pNewString->cchString = K_H2LE_U32(cchString);
    6561009    memcpy(&pNewString->szString, pszString, cchString);
    6571010    pNewString->szString[cchString] = '\0';
    6581011
    659     pStrTab->pStrTab->iStringEnd = iStringEnd + cEntries;
     1012    pStrTab->pStrTab->iStringEnd = K_H2LE_U32(iStringEnd + cEntries);
    6601013
    6611014    /*
    6621015     * Insert hash table entry, rehash it if necessary.
    6631016     */
    664     pHash->auEntries[iInsertAt] = iStringEnd;
    665     pHash->cUsedEntries++;
    666     pHash->cCollisions += cCollisions;
    667     if (    pHash->cUsedEntries > pHash->cEntries / 3 * 2
     1017    pHash->auEntries[iInsertAt] = K_H2LE_U32(iStringEnd);
     1018    pHash->cUsedEntries = K_H2LE_U32(K_LE2H_U32(pHash->cUsedEntries) + 1);
     1019    pHash->cCollisions  = K_H2LE_U32(K_LE2H_U32(pHash->cCollisions)  + cCollisions);
     1020    if (    K_LE2H_U32(pHash->cUsedEntries) > K_LE2H_U32(pHash->cEntries) / 3 * 2
    6681021        &&  kDepDbStrTabReHash(pStrTab) != 0)
    6691022        return KDEPDBG_STRTAB_IDX_ERROR;
     
    7011054
    7021055
    703 
     1056/**
     1057 * Opens the string table files, creating them if necessary.
     1058 */
     1059static int kDepDbStrTabInit(KDEPDBINTSTRTAB *pStrTab, const char *pszFilenameBase)
     1060{
     1061    size_t  cchFilenameBase = strlen(pszFilenameBase);
     1062    char    szPath[4096];
     1063    int     rc;
     1064
     1065    /* Basic member init, so kDepDbStrTabTerm always works. */
     1066    pStrTab->pHash = NULL;
     1067    kDepDbFHInit(&pStrTab->hHash);
     1068    pStrTab->pStrTab = NULL;
     1069    kDepDbFHInit(&pStrTab->hStrTab);
     1070    pStrTab->iStringAlloced = 0;
     1071
     1072    /* check the length. */
     1073    if (cchFilenameBase + sizeof(".strtab.hash") > sizeof(szPath))
     1074        return -1;
     1075
     1076    /*
     1077     * Open the string table first.
     1078     */
     1079    memcpy(szPath, pszFilenameBase, cchFilenameBase);
     1080    memcpy(&szPath[cchFilenameBase], ".strtab", sizeof(".strtab"));
     1081    rc = kDepDbFHOpen(&pStrTab->hStrTab, szPath, &fNew);
     1082
     1083
     1084}
     1085
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette