packfile.c

来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 575 行 · 第 1/2 页

C
575
字号
                          rt_child_node_ptr->used_slots*slot_sz);                /* copy what was the parents last used slot as right childs                 * m/2 slot, at this time there is still no child node pointer                 * for this slot */                memcpy(((char *)&rt_child_slot_ptr->keyno)                            + (right_used_slots-1) * slot_sz,                          &tmp_slot_ptr->keyno,                          slot_sz - sizeof(F_ADDR));                /* copy left child's lower half to right childs first half, note                 * that this opperation adds the child node pointer to the m/2                 * slot which was added above */                memcpy(rt_child_slot_ptr,                           ((char*)lf_child_slot_ptr)+(left_used_slots+1)*slot_sz,                          (right_used_slots - 1) * slot_sz + sizeof(F_ADDR));                /* update right child's used slot counter */                rt_child_node_ptr->used_slots += (short) right_used_slots;            }        }    }    if (status == S_OKAY)    {        psp_fileSeek(pk->pkf, (off_t)(pk->next_node * node_sz));        /* flush out node in lvls */        for (lvl = LEAF_LVL; lvl < pk->root_lvl && status == S_OKAY; ++lvl)        {            if (!pk->lvls[lvl].node_ptr->used_slots)                continue;            node_ptr = pk->lvls[lvl].node_ptr;            time(&node_ptr->last_chgd);            next_node_ptr = (F_ADDR *) (node_ptr->slots +                                                  node_ptr->used_slots * slot_sz);            if (lvl == LEAF_LVL)                tmp = NULL_NODE;            else                tmp = pk->next_node - 1;            memcpy(next_node_ptr, &tmp, sizeof(F_ADDR));            if ( psp_fileWrite(pk->pkf, (char *) node_ptr, node_sz) != node_sz )                status = S_BADWRITE;            pk->lvls[lvl].last_node = pk->next_node++;        }    }    if (status == S_OKAY)    {        /* update and write root node */        node_ptr = pk->lvls[pk->root_lvl].node_ptr;        next_node_ptr = (F_ADDR *) (node_ptr->slots +                                              node_ptr->used_slots * slot_sz);        /* then next node for the root node will be the last node written out */        if (lvl == LEAF_LVL)            tmp = NULL_NODE;        else            tmp = pk->next_node - 1;        memcpy(next_node_ptr, &tmp, sizeof(F_ADDR));        time(&node_ptr->last_chgd);        psp_fileSeek(pk->pkf, (off_t)node_sz);        if ( psp_fileWrite(pk->pkf, (char *) node_ptr, node_sz) != node_sz )            status = S_BADWRITE;        if (status == S_OKAY)        {            /* write page zero */            pz.dchain = NULL_NODE;            pz.next = pk->next_node;            pz.timestamp = 0L;            pz.bdate = 0L;            time(&pz.cdate);            d_dbver(DB_TEXT("%V"), pz.vdb_id, 48);            psp_fileSeek(pk->pkf, 0);            if (psp_fileWrite(pk->pkf, (char *) &pz,                    sizeof(struct page_zero)) != sizeof(struct page_zero) )                status = S_BADWRITE;            psp_fileClose(pk->pkf);        }    }    if (status == S_OKAY)    {        status = packcheck(fno, out_file, pk->buff, pk->buff_size,                                 popts, pstats, task);    }    /* free allocated memory */    if (pk)    {        if (pk->lvls)        {            if (lf_child_node_ptr)            {                if (tmp_slot_ptr)                {                    if (pk->buff)                        psp_freeMemory((char *) pk->buff, 0);                    psp_freeMemory((char *) tmp_slot_ptr, 0);                }                psp_freeMemory((char *) lf_child_node_ptr, 0);            }            for (lvl = 0; lvl < max_lvls; ++lvl)            {                if (pk->lvls[lvl].node_ptr)                    psp_freeMemory((char *) pk->lvls[lvl].node_ptr, 0);            }            psp_freeMemory((char *) pk->lvls, 0);        }        psp_freeMemory(pk, 0);    }    if (status != S_OKAY)        dberr(status);    return (status);}/* =====================================================================    Add slot to key file node*/static int add_slot(    int lvl,    KEY_SLOT *slot_ptr,    PACKFILE_DATA *pk,    DB_TASK *task){    int status;    int node_sz;    int slot_sz;    NODE *curr_node_ptr;    KEY_SLOT *buff_slot_ptr;    F_ADDR *child_node_ptr;    F_ADDR *next_node_ptr;    F_ADDR tmp;                   /* needed for memcpy() */    curr_node_ptr = pk->lvls[lvl].node_ptr;    slot_sz = task->file_table[pk->fno].ft_slsize;    node_sz = task->file_table[pk->fno].ft_pgsize;    /* 1st use of new lvls will have last_chgd == 0 */    if (!curr_node_ptr->last_chgd)    {        /* mark new root level */        pk->root_lvl = (short) lvl;        /* make update time non-zero (the time will go in later) */        curr_node_ptr->last_chgd = pk->next_node;    }    /* In an db.* B-Tree, the child node ptr will also serve as       the next node ptr in the first unused slot.  Here we are initializing       both the child node ptr and the next node pointer    */    next_node_ptr = child_node_ptr =             (F_ADDR *) (curr_node_ptr->slots +            curr_node_ptr->used_slots * slot_sz);    /* check and, if full, output node */    if (curr_node_ptr->used_slots == pk->max_slots)    {        /* new slot goes into the next higher level (the parent node) */        if ((status = add_slot(lvl + 1, slot_ptr, pk, task)) != S_OKAY)            return (status);        time(&curr_node_ptr->last_chgd);        /* update next node (the current node is the next node) */        if (lvl == LEAF_LVL)            tmp = NULL_NODE;        else            tmp = pk->next_node + 1;        memcpy(next_node_ptr, &tmp, sizeof(F_ADDR));        if (pk->buff_max_nodes > 0)        {            if (pk->buff_curr_node < pk->buff_max_nodes)            {                /* copy filled node into output buffer */                memcpy(pk->buff + pk->buff_curr_node * node_sz,                    curr_node_ptr, node_sz);                ++(pk->buff_curr_node);            }            else            {                /* buffer is full - write to disk */                if ( psp_fileWrite(pk->pkf, pk->buff, pk->buff_curr_node * node_sz) !=                      pk->buff_curr_node*node_sz )                    status = S_BADWRITE;                if (status != S_OKAY)                    return (status);                memcpy(pk->buff, curr_node_ptr, node_sz);                pk->buff_curr_node = 1;            }        }        else if ((psp_fileWrite(pk->pkf, (char *)curr_node_ptr, node_sz)) != node_sz)            return (S_BADWRITE);                pk->lvls[lvl].last_node = pk->next_node++;        curr_node_ptr->used_slots = 0;    }    else /* node is not full */    {        /* copy slot */        buff_slot_ptr = (KEY_SLOT *) (curr_node_ptr->slots +            curr_node_ptr->used_slots * slot_sz);        memcpy(buff_slot_ptr, slot_ptr, slot_sz);        /* update child node */        if (lvl == LEAF_LVL)            tmp = NULL_NODE;        else            tmp = pk->next_node;        memcpy(child_node_ptr, &tmp, sizeof(F_ADDR));        ++curr_node_ptr->used_slots;    }    return (S_OKAY);}/* ======================================================================    Display packing results*/static int packcheck(    FILE_NO fno,    DB_TCHAR *out_file,    char *buff,    size_t buff_sz,    KEYPACK_OPTS *popts,    KEYPACK_STATS *pstats,    DB_TASK *task){    DB_TCHAR backfile[FILENMLEN];    int page_sz;    page_sz = task->file_table[fno].ft_pgsize;    pstats->or_size = psp_fileLength(task->file_table[fno].ft_name);    pstats->pk_size = psp_fileLength(out_file);    pstats->or_total += pstats->or_size;    pstats->pk_total += pstats->pk_size;    vtprintf(DB_TEXT("  reduced %4.1f%%"),                (1 - (double) pstats->pk_size / pstats->or_size) * 100);    if (popts->backup)    {        vstprintf(backfile, DB_TEXT("%s%s"), popts->backpath, task->file_table[fno].ft_name);        vtprintf(DB_TEXT("  backing up..."));        if (psp_fileCopy(task->file_table[fno].ft_name, backfile) != PSP_OKAY)        {            vftprintf(stderr, DB_TEXT("unable to copy file %s to %s\n"),                         task->file_table[fno].ft_name, backfile);        }    }    if (!popts->keep)    {        dio_close(fno, task);        psp_fileRemove(task->file_table[fno].ft_name);        vtprintf(DB_TEXT("  replacing..."));        if (psp_fileMove(out_file, task->file_table[fno].ft_name) != PSP_OKAY)        {            vftprintf(stderr, DB_TEXT("unable to move file %s to %s\n"),                         out_file, task->file_table[fno].ft_name);            return(-1);        }    }    vtprintf(DB_TEXT("\nDone\n"));    return(0);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?