Exemple #1
0
/*
 * the idea id to print each context description at most once but provide enough
 * info for deducing the current execution stack
 */
static void
ctx_print(void)
{
    /* lock so _db_print will not call us recursively */
    Ctx_Lock++;
    /* ok, user saw [0,Ctx_Reported_Level] descriptions */
    /* first inform about entries popped since user saw them */
    if (Ctx_Valid_Level < Ctx_Reported_Level) {
	if (Ctx_Reported_Level != Ctx_Valid_Level + 1)
	    _db_print("ctx: exit levels from %2d down to %2d\n",
		Ctx_Reported_Level, Ctx_Valid_Level + 1);
	else
	    _db_print("ctx: exit level %2d\n", Ctx_Reported_Level);
	Ctx_Reported_Level = Ctx_Valid_Level;
    }
    /* report new contexts that were pushed since last report */
    while (Ctx_Reported_Level < Ctx_Current_Level) {
	Ctx_Reported_Level++;
	Ctx_Valid_Level++;
	_db_print("ctx: enter level %2d: '%s'\n", Ctx_Reported_Level,
	    ctx_get_descr(Ctx_Reported_Level));
    }
    /* unlock */
    Ctx_Lock--;
}
/*********************************
    新增虚拟文件
入参:
    dbHandle     库句柄
出参:
    pVfile       虚文件控制结构指针。
返回值:
    _DB_SUCCESS             新增成功。
    _DB_E_MEM_NO_PAGE       内存池页面不够,虚文件创建失败。
    _DB_ERROR               其他错误,创建失败。
************************************/
_DB_RET _db_vfile_create(_db_t_database_handle dbHandle, _db_t_vfile *pVfile)
{
    _db_t_mem_head *pMemHead;
    DWORD rootPage;
    DWORD pageNo;
    VOID *pAddr;
    _DB_RET ret;

    /* 初始化文件控制结构 */
    pVfile->dirLevel = 0;
    pVfile->rootPage = _DB_PAGE_INVALID;
    pVfile->pageNum = 0;
    pVfile->fileSize = 0;
    pVfile->currentOffset = 0;

    pMemHead = (_db_t_mem_head *)_DB_GET_MEM_HEAD(dbHandle);

    /* 生成一级目录页面 */
    ret = _db_mem_page_new(dbHandle, &rootPage);
    if (ret != _DB_SUCCESS)
    {
        _db_print(LOG_ERROR, "File %s, line %d: vfile create error!\n", __FILE__, __LINE__);
        return ret;
    }
    pAddr = _db_mem_get_page_addr(dbHandle, rootPage);
    if (NULL == pAddr)
    {
        _db_print(LOG_ERROR, "File %s, line %d: vfile create error!\n", __FILE__, __LINE__);
        _db_mem_page_release(dbHandle, rootPage);
        return _DB_ERROR;
    }
    memset(pAddr, 0xff, pMemHead->pageSize);

    /* 为文件添加第一个页面 */
    ret = _db_mem_page_new(dbHandle, &pageNo);
    if (ret != _DB_SUCCESS)
    {
        _db_mem_page_release(dbHandle, rootPage);
        return ret;
    }

    *(DWORD *)pAddr = pageNo;
    pVfile->rootPage = rootPage;
    pVfile->pageNum = 1;
    pVfile->dirLevel = 1;

    return _DB_SUCCESS;
}
/*********************************
    文件分配表扩容,增加一层
入参:
    dbHandle      库句柄。
    pVfile        虚文件控制结构
出参:
返回值:
    _DB_SUCCESS 扩容成功
    其它        扩容失败
说明:
************************************/
static _DB_RET _db_vfile_add_level(_db_t_database_handle dbHandle, _db_t_vfile *pVfile)
{
    _db_t_mem_head *pMemHead;
    VOID *pAddr;
    DWORD pageNo;
    _DB_RET ret;

    pMemHead = (_db_t_mem_head *)_DB_GET_MEM_HEAD(dbHandle);
    if (pVfile->dirLevel >= _DB_VFILE_MAX_LEVEL)
    {
        _db_print(LOG_ERROR, "File %s, line %d: vfile dir level overflow!\n", __FILE__, __LINE__);
        return _DB_ERROR;
    }

    /* 增加新的根目录页面 */
    ret = _db_mem_page_new(dbHandle, &pageNo);
    if (ret != _DB_SUCCESS)
    {
        _db_print(LOG_ERROR, "File %s, line %d: vfile create page error!\n", __FILE__, __LINE__);
        return ret;
    }
    pAddr = _db_mem_get_page_addr(dbHandle, pageNo);
    if (NULL == pAddr)
    {
        _db_print(LOG_ERROR, "File %s, line %d: vfile get page addr error!\n", __FILE__, __LINE__);
        _db_mem_page_release(dbHandle, pageNo);
        return _DB_ERROR;
    }
    memset(pAddr, 0xff, pMemHead->pageSize);

    /* 目录链接 */
    *(DWORD *)pAddr = pVfile->rootPage;
    pVfile->rootPage = pageNo;
    pVfile->dirLevel++;

    return _DB_SUCCESS;
}
Exemple #4
0
// the callback in the server called by a communication backend
// on each comm. protocol command
void handler (ULONG obj, int ncmd, int data, int threadNum)
{
    int  rc, l, len;
    char buf[256];

    switch(ncmd)
    {
    case F_CMD_GET_IHAB:
    {
        int iHAB = 1, inf[2];
        static int iClientId = 1;
        debug(0, 2)("Fs_ClientWork: F_CMD_GET_IHAB not yet full implemented\n");
        iClientId++;
        iHAB = session.hab_list.Add(iClientId ,threadNum);
        inf[0] = iHAB;
        inf[1] = iClientId;
        rc=  F_SendDataToClient(obj, inf , sizeof(inf));
    }
    break;
    case F_CMD_CLIENT_EXIT:
//todo: clear ihab = data
        debug(0, 2) ("Fs_ClientWork: F_CMD_CLIENT_EXIT %x ; not yet implemented\n", data);
        break;
    case F_CMD_WINPOSTMSG:
    {   SQMSG sqmsg;
        int rc1,ihabto;
        rc = F_RecvDataFromClient(obj, &sqmsg, &l, sizeof(SQMSG));
        debug(0, 2) ("Fs_ClientWork: F_CMD_WINPOSTMSG get %i bytes\n",l);
        if(rc == 0 && l == sizeof(SQMSG))
        {   rc1 = _WndList.QueryHab(sqmsg.qmsg.hwnd, ihabto);
            if(rc1 == 1)
            {   sqmsg.ihto = ihabto;
                rc  = session.hab_list.Queue.Add(&sqmsg);
            }
        }
    }
    break;
    case F_CMD_WINSENDMSG:
    {   SQMSG sqmsg;
        int rc1,ihabto;
        rc = F_RecvDataFromClient(obj, &sqmsg, &l, sizeof(SQMSG));
        debug(0, 2) ("Fs_ClientWork: F_CMD_WINPOSTMSG get %i bytes\n",l);
        if(rc == 0 && l == sizeof(SQMSG))
        {   rc1 = _WndList.QueryHab(sqmsg.qmsg.hwnd, ihabto);
            if(rc1 == 1)
            {   sqmsg.ihto = ihabto;
//todo: it is sendmsg == postmsg implementation
//it seems that we must wait in client via call to CMD_WINQUERYPOSTED or smth like it
                rc  = session.hab_list.Queue.Add(&sqmsg);
            }
        }
    }
    break;

    case F_CMD_WINQUERY_MSG: /* Query messages for ihab = data */
    {
        int nmsg=0;
        int ihabto;
        ihabto = data;
        nmsg = session.hab_list.Queue.QueryNmsg(ihabto);
        if (nmsg)
            debug(0, 2) ("Fs_ClientWork: F_CMD_WINQUERY_MSG, nmsg=%i\n",nmsg);
        rc = F_SendDataToClient(obj, &nmsg , sizeof(int));
    }
    break;
    case F_CMD_WINGET_MSG:  /* Get message for ihab = data */
    {
        SQMSG sqmsg;
        int rc, ihabto;
        int nmsg=0;
        ihabto = data;
        rc = session.hab_list.Queue.GetForIhab(&sqmsg, ihabto);
        if (rc == 0) nmsg = 1;

        if (nmsg == 1)
            debug(0, 2) ("Fs_ClientWork: F_CMD_WINGET_MSG for %i, msg=%x\n", ihabto, sqmsg.qmsg.msg);
        else
            debug(0, 2) ("Fs_ClientWork: F_CMD_WINGET_MSG, No msg  for %i\n", ihabto);

        rc = F_SendDataToClient(obj, &nmsg , sizeof(int));

        if(nmsg)
            rc = F_SendDataToClient(obj, &sqmsg.qmsg , sizeof(QMSG));
    }
    break;

    case F_CMD_WINCREATE_HWND:
    {   HWND hwnd;
        int iHab;
        iHab = data;
        hwnd = _WndList.Add(iHab);
//todo: set _WndList with thread info and cleanup at thread(client exit) end
        rc=  F_SendDataToClient(obj, &hwnd , sizeof(HWND));
    }

    break;
    case F_CMD_WINSET_PARENT_HWND:
    {   HWND hwnd, hwndParent;
        hwnd = data;
        rc = F_RecvDataFromClient(obj, (void *)&hwndParent, &len, sizeof(HWND));
        rc = _WndList.SetParent(hwnd, hwndParent);
    }
    break;

    case F_CMD_GET_HPS:
    {   HWND hwnd;
        HPS hps;
        hwnd = data;
        hps = _WndList.GetHPS(hwnd);
        rc=  F_SendDataToClient(obj, &hps, sizeof(HPS));
    }
    break;
    case F_CMD_RELEASE_HPS:
    {
        HPS hps;
        int rc1;
        hps = data;
        rc1 = _WndList.ReleaseHPS(hps);
        rc=  F_SendDataToClient(obj, &rc1, sizeof(int));
    }
    break;
    case F_CMD_WIN_SET_WND_SIZE:
    {   HWND hwnd = data;
        int par[2],rc1;
        rc = F_RecvDataFromClient(obj, (void *)&par[0], &len, sizeof(int)*2);
        rc1 = 0;
        //todo
        rc=  F_SendDataToClient(obj, &rc1, sizeof(int));
    }
    break;

    case F_CMD_WIN_SET_WND_POS:
    {   HWND hwnd = data;
        int par[2],rc1;
        rc = F_RecvDataFromClient(obj, (void *)&par[0], &len, sizeof(int)*2);
        rc1 = 0;
        //todo
        rc=  F_SendDataToClient(obj, &rc1, sizeof(int));
    }
    break;

    case F_CMD_WIN_GET_WND_SWP:
    {   HWND hwnd = data;
        SWP swp;
        //todo
        rc=  F_SendDataToClient(obj, &swp, sizeof(SWP));
    }
    break;

    case F_CMD_WIN_SHOW:
    {   HWND hwnd = data;
        int par,rc1;
        rc = F_RecvDataFromClient(obj, (void *)&par, &len, sizeof(int));
        rc1 = 0;
        //todo
        rc=  F_SendDataToClient(obj, &rc1, sizeof(int));
    }
    break;

    case F_CMD_GPI_SET_COLOR:
    {   HPS hps;
        int color, len, rc1=FALSE;
        hps = data;
        rc = F_RecvDataFromClient(obj, (void *)&color, &len, sizeof(int));
        debug(0, 0) ("F_CMD_GPI_SET_COLOR: get hps=%x, color=%x, len=%i\n",hps,color,len);
        if(hps >= 0 && hps < _WndList.numPS)
        {   if(_WndList.pPS[hps].used)
                /* rc1 = F_GpiSetColor(&_WndList.pPS[hps], color); */
                rc1 = F_PS_GpiSetColor(&_WndList.pPS[hps], color);
        }
        rc=  F_SendDataToClient(obj, &rc1, sizeof(int));
    }
    break;
    case F_CMD_GPI_MOVE:
    {   HPS hps;
        int rc1=FALSE;
        POINTL Point;
        hps = data;
        rc = F_RecvDataFromClient(obj, (void *)&Point, &len, sizeof(POINTL));
        debug(0, 0) ("F_CMD_GPI_MOVE: get hps=%x,len=%i\n",hps,len);

        if(hps >= 0 && hps < _WndList.numPS)
        {   if(_WndList.pPS[hps].used)
                rc1 = F_PS_GpiMove(&_WndList.pPS[hps], &Point);
        }
        rc=  F_SendDataToClient(obj, &rc1, sizeof(int));
    }
    break;
    case F_CMD_GPI_LINE:
    {   HPS hps;
        int rc1=FALSE;
        POINTL Point;
        hps = data;
        rc = F_RecvDataFromClient(obj, (void *)&Point, &len, sizeof(POINTL));

        if(hps >= 0 && hps < _WndList.numPS)
        {   if(_WndList.pPS[hps].used)
                rc1 = F_PS_GpiLine(&_WndList.pPS[hps], &Point);
        }
        rc=  F_SendDataToClient(obj, &rc1, sizeof(int));
    }
    break;
    case F_CMD_GPI_DRAW_LINE:
//TODO
        break;
    case F_CMD_GPI_DRAW_RECT:
//TODO
        break;
    case F_CMD_DB_PRINT:
    {
        F_RecvDataFromClient(obj, (char *)buf, &len, sizeof(buf));
        _db_print(buf);
    }
    break;
    case F_CMD_FATAL_COMMON:
        F_RecvDataFromClient(obj, (char *)buf, &len, sizeof(buf));
        _fatal_common(buf);
        break;

#define POKA 0
#if POKA
    case 1:
        debug(0, 2) ("Fs_ClientWork: Get ncmd %x %x\n", ncmd, data);
        rc=F_SendCmdToServer(obj, ncmd, data);
        switch(data)
        {
        case S_SHUTDOWN:
//                 squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
//            debug(0, 0) ("squid_signal:\n");
            DosSleep(100);
            rc = raise(SIGTERM);
//            debug(0, 0) ("raise: rc =%x %s\n",rc,xstdio_strerror());
            break;
        case S_RECONFIGURE:
//                       do_reconfigure = 1;
            break;
        case S_ROTATE:
//                       do_rotate = 1;
            break;
        case S_DEBUG:
            break;
        case S_KILL:
            debug(1, 1) ("Preparing for killing\n");
//               do_shutdown++;
//           SquidShutdown(NULL);
            break;
        }
        ncmd = 0;
        break;
#endif
    //POKA
    default:
        debug(0, 2) ("Fs_ClientWork:WARNING: Unimplemented cmd %x\n", ncmd);
        ncmd = 0;
        break;

    } //endof switch(ncmd)
}
/**********************************
    自当前偏移处,读虚拟文件。
入参:
    dbHandle        库句柄。
    pVfile          虚文件控制结构指针。
    dest            目的缓冲区。
    len             数据长度
出参:
返回值:
    _DB_SUCCESS                读文件成功。
    _DB_E_FILE_LEN             长度无效。
    _DB_ERROR                  其他读失败。
说明:
读成功,文件当前偏移 = 原偏移 + 读长度
***********************************/
_DB_RET _db_vfile_read(_db_t_database_handle dbHandle, _db_t_vfile *pVfile, VOID *dest, DWORD len)
{
    _db_t_mem_head *pMemHead;
    DWORD lgcPageNo;
    DWORD readed = 0;
    WORD pageOffset;
    WORD toRead;
    WORD pageSize;

    if ((0 == len) || (NULL == dest))
    {
        _db_print(LOG_ERROR, "File %s, line %d: Wrong input! Vfile read error!\n", __FILE__, __LINE__);
        return _DB_E_FILE_LEN;
    }
    if (pVfile->currentOffset + len > pVfile->fileSize)
    {
        _db_print(LOG_ERROR, "File %s, line %d: Wrong input! Vfile read error!\n", __FILE__, __LINE__);
        return _DB_E_FILE_LEN;
    }

    pMemHead = (_db_t_mem_head *)_DB_GET_MEM_HEAD(dbHandle);
    pageSize = pMemHead->pageSize;

    /* 定位逻辑页面 */
    lgcPageNo = pVfile->currentOffset >> pMemHead->pageShift;
    pageOffset = (WORD)(pVfile->currentOffset & pMemHead->pageMask);

    if (pageOffset > 0)
    {
        if (pageOffset + len <= pageSize)
        {
            /* 在文件已有页面完成数据的读 */
            if (_DB_SUCCESS != _db_vfile_page_read(dbHandle, pVfile, lgcPageNo, pageOffset, dest, (WORD)len))
            {
                _db_print(LOG_ERROR, "File %s, line %d: Vfile read error!\n", __FILE__, __LINE__);
                return _DB_ERROR;
            }
            pVfile->currentOffset += len;
            return _DB_SUCCESS;
        }

        toRead = pageSize - pageOffset;
        if (_DB_SUCCESS != _db_vfile_page_read(dbHandle, pVfile, lgcPageNo, pageOffset, dest, toRead))
        {
            _db_print(LOG_ERROR, "File %s, line %d: Vfile read error!\n", __FILE__, __LINE__);
            return _DB_ERROR;
        }
        readed += toRead;
        lgcPageNo++;
    }

    while (lgcPageNo < pVfile->pageNum)
    {
        if (readed + pageSize >= len)
        {
            /* 在文件已有页面完成数据的读入 */
            toRead = (WORD)(len - readed);
            if (_DB_SUCCESS != _db_vfile_page_read(dbHandle, pVfile, lgcPageNo, 0, (BYTE *)dest + readed, toRead))
            {
                _db_print(LOG_ERROR, "File %s, line %d: Vfile read error!\n", __FILE__, __LINE__);
                return _DB_ERROR;
            }
            pVfile->currentOffset += len;
            return _DB_SUCCESS;
        }

        toRead = pageSize;
        if (_DB_SUCCESS != _db_vfile_page_read(dbHandle, pVfile, lgcPageNo, 0, (BYTE *)dest + readed, toRead))
        {
            _db_print(LOG_ERROR, "File %s, line %d: Vfile read error!\n", __FILE__, __LINE__);
            return _DB_ERROR;
        }
        readed += toRead;
        lgcPageNo++;
    }

    _db_print(LOG_ERROR, "File %s, line %d: Vfile read error!\n", __FILE__, __LINE__);
    return _DB_ERROR;
}
/**********************************
    自当前偏移处,改写虚拟文件。
入参:
    dbHandle        库句柄。
    pVfile          虚文件控制结构指针。
    src             待写的数据内容。
    len             数据长度
出参:
返回值:
    _DB_SUCCESS                写文件成功。
    _DB_E_MEM_NO_PAGE          内存池页面不够,虚文件改写失败。
    _DB_ERROR                  其他错误,写失败。
说明:
改写成功,文件当前偏移 = 原偏移 + 改写长度
注意:文件的长度并非 = 页面数 * 页面大小
***********************************/
_DB_RET _db_vfile_write(_db_t_database_handle dbHandle, _db_t_vfile *pVfile, VOID *src, DWORD len)
{
    _db_t_mem_head *pMemHead;
    DWORD lgcPageNo;
    DWORD writed = 0;
    WORD pageOffset;
    WORD toWrite;
    WORD pageSize;
    _DB_RET ret;

    pMemHead = (_db_t_mem_head *)_DB_GET_MEM_HEAD(dbHandle);
    pageSize = pMemHead->pageSize;

    if ((0 == len) || (NULL == src))
    {
        _db_print(LOG_ERROR, "File %s, line %d: Wrong input! Vfile write error!\n", __FILE__, __LINE__);
        return _DB_ERROR;
    }

    /* 定位逻辑页面 */
    lgcPageNo = pVfile->currentOffset >> pMemHead->pageShift;
    pageOffset = (WORD)(pVfile->currentOffset & pMemHead->pageMask);

    if ((lgcPageNo < pVfile->pageNum) && (pageOffset > 0))
    {
        if (pageOffset + len <= pageSize)
        {
            /* 在文件已有页面完成数据的写入 */
            if (_DB_SUCCESS != _db_vfile_page_write(dbHandle, pVfile, lgcPageNo, pageOffset, src, (WORD)len))
            {
                _db_print(LOG_ERROR, "File %s, line %d:Vfile write error!\n", __FILE__, __LINE__);
                return _DB_ERROR;
            }
            pVfile->currentOffset += len;
            if (pVfile->currentOffset > pVfile->fileSize)
            {
                pVfile->fileSize = pVfile->currentOffset;
            }
            return _DB_SUCCESS;
        }

        toWrite = pageSize - pageOffset;
        if (_DB_SUCCESS != _db_vfile_page_write(dbHandle, pVfile, lgcPageNo, pageOffset, src, toWrite))
        {
            _db_print(LOG_ERROR, "File %s, line %d:Vfile write error!\n", __FILE__, __LINE__);
            return _DB_ERROR;
        }
        writed += toWrite;
        lgcPageNo++;
    }

    while (writed < len)
    {
        if (lgcPageNo >= pVfile->pageNum)
        {
            /* 文件页面数不够,申请新的页面 */
            ret = _db_vfile_add_page(dbHandle, pVfile);
            if (_DB_SUCCESS != ret)
            {
                _db_print(LOG_ERROR, "File %s, line %d:Vfile add page error!\n", __FILE__, __LINE__);
                return ret;
            }
        }
        if (writed + pageSize >= len)
        {
            /* 在文件已有页面完成数据的写入 */
            toWrite = (WORD)(len - writed);
            if (_DB_SUCCESS != _db_vfile_page_write(dbHandle, pVfile, lgcPageNo, 0, (BYTE *)src + writed, toWrite))
            {
                _db_print(LOG_ERROR, "File %s, line %d:Vfile write error!\n", __FILE__, __LINE__);
                return _DB_ERROR;
            }
            pVfile->currentOffset += len;
            if (pVfile->currentOffset > pVfile->fileSize)
            {
                pVfile->fileSize = pVfile->currentOffset;
            }
            return _DB_SUCCESS;
        }

        toWrite = pageSize;
        if (_DB_SUCCESS != _db_vfile_page_write(dbHandle, pVfile, lgcPageNo, 0, (BYTE *)src + writed, toWrite))
        {
            _db_print(LOG_ERROR, "File %s, line %d:Vfile write error!\n", __FILE__, __LINE__);
            return _DB_ERROR;
        }
        writed += toWrite;
        lgcPageNo++;
    }

    _db_print(LOG_ERROR, "File %s, line %d:Vfile write error!\n", __FILE__, __LINE__);
    return _DB_ERROR;
}
/*********************************
    删除虚拟文件
入参:
    dbHandle     库句柄
    pVfile       虚文件控制结构指针。
出参:
返回值:
    _DB_SUCCESS             删除成功。
    _DB_ERROR               失败。
************************************/
_DB_RET _db_vfile_remove(_db_t_database_handle dbHandle, _db_t_vfile *pVfile)
{
    _db_t_mem_head *pMemHead;
    DWORD *pAddr;
    DWORD deleted = 0;
    _db_t_vfile_node nodeStack[_DB_VFILE_MAX_LEVEL];
    BYTE stackNodeNum = 0;
    WORD itemNumPerPage;
    WORD itemInPage;
    DWORD brother;
    _db_t_vfile_node curNode;

    pMemHead = (_db_t_mem_head *)_DB_GET_MEM_HEAD(dbHandle);
    itemNumPerPage = pMemHead->pageSize >> 2;

    if (pVfile->dirLevel > _DB_VFILE_MAX_LEVEL)
    {
        _db_print(LOG_ERROR, "File %s, line %d: vfile dir level overflow!\n", __FILE__, __LINE__);
        return _DB_ERROR;
    }

    /* 使用堆栈,按深度对树进行遍历 */
    curNode.node = pVfile->rootPage;
    curNode.father = _DB_PAGE_INVALID;
    curNode.level = 1;       /* 根节点为第一层 */
    curNode.childOrder = 0;
    while (_DB_PAGE_INVALID != curNode.node)
    {
        if (_DB_PAGE_INVALID != curNode.father)
        {
            if (curNode.childOrder < itemNumPerPage)
            {
                pAddr = (DWORD *)_db_mem_get_page_addr(dbHandle, curNode.father);
                brother = *(pAddr + curNode.childOrder);
                if (_DB_PAGE_INVALID != brother)
                {
                    /* 当前节点的右兄弟非空,将其压入堆栈 */
                    if (stackNodeNum >= _DB_VFILE_MAX_LEVEL)
                    {
                        _db_print(LOG_ERROR, "File %s, line %d: Vfile dir destroyed! Delete error!\n", __FILE__, __LINE__);
                        return _DB_ERROR;
                    }
                    nodeStack[stackNodeNum].node = brother;
                    nodeStack[stackNodeNum].father = curNode.father;
                    nodeStack[stackNodeNum].childOrder = curNode.childOrder + 1;
                    nodeStack[stackNodeNum].level = curNode.level;
                    stackNodeNum++;
                }
                else
                {
                    /* 最后一个孩子,释放父节点 */
                    _db_mem_page_release(dbHandle, curNode.father);
                }
            }
            else
            {
                /* 最后一个孩子,释放父节点 */
                _db_mem_page_release(dbHandle, curNode.father);
            }
        }

        /* 对当前节点的处理 */
        if (curNode.level == pVfile->dirLevel)
        {
            /* 如果是叶子节点,那么直接释放叶子目录上的数据页面,并回收该节点 */
            pAddr = _db_mem_get_page_addr(dbHandle, curNode.node);
            if (NULL == pAddr)
            {
                return _DB_ERROR;
            }
            itemInPage = 0;
            while ((itemInPage < itemNumPerPage) && (_DB_PAGE_INVALID != *pAddr))
            {
                _db_mem_page_release(dbHandle, *pAddr);
                deleted++;
                pAddr++;
                itemInPage++;
            }
            _db_mem_page_release(dbHandle, curNode.node);

            if (stackNodeNum > 0)
            {
                /* 弹栈 */
                curNode = nodeStack[stackNodeNum - 1];
                stackNodeNum--;
            }
            else
            {
                /* 栈空,访问路径空,删除已完成,直接退出 */
                break;
            }
        }
        else
        {
            /* 非叶子节点,取第一个孩子为当前节点 */
            pAddr = (DWORD *)_db_mem_get_page_addr(dbHandle, curNode.node);
            if ((NULL == pAddr) || (_DB_PAGE_INVALID == *pAddr))
            {
                _db_print(LOG_ERROR, "File %s, line %d: Vfile dir error!\n", __FILE__, __LINE__);
                return _DB_ERROR;
            }
            curNode.father = curNode.node;
            curNode.level++;
            curNode.childOrder = 1;
            curNode.node = *pAddr;
        }
    }  /* end while */
    
    if (deleted != pVfile->pageNum)
    {
        _db_print(LOG_ERROR, "File %s, line %d: Vfile dir destroyed! Delete error!\n", __FILE__, __LINE__);
        return _DB_ERROR;
    }

    pVfile->dirLevel = 0;
    pVfile->rootPage = _DB_PAGE_INVALID;
    pVfile->pageNum = 0;
    pVfile->fileSize = 0;
    pVfile->currentOffset = 0;

    return _DB_SUCCESS;
}
/*********************************
    文件新增一个数据页面
入参:
    dbHandle      库句柄。
    pVfile        虚文件控制结构。
出参:
返回值:
    _DB_SUCCESS                页面申请成功。
    其它                       新增页面失败。
说明:
************************************/
static _DB_RET _db_vfile_add_page(_db_t_database_handle dbHandle, _db_t_vfile *pVfile)
{
    _db_t_mem_head *pMemHead;
    VOID *pAddr;
    DWORD *pPageItem;
    DWORD phyPageNo;
    DWORD lgcPageNo;
    DWORD pageNo;
    DWORD temp;
    WORD lgcItem[_DB_VFILE_MAX_LEVEL];
    WORD i;
    WORD itemNumPerPage;
    _DB_RET ret;

    pMemHead = (_db_t_mem_head *)_DB_GET_MEM_HEAD(dbHandle);

    /* 申请数据页面 */
    ret = _db_mem_page_new(dbHandle, &phyPageNo);
    if (ret != _DB_SUCCESS)
    {
        _db_print(LOG_ERROR, "File %s, line %d: vfile create data page error!\n", __FILE__, __LINE__);
        return ret;
    }

    lgcPageNo = pVfile->pageNum;
    itemNumPerPage = pMemHead->pageSize >> 2;

    /* 判断页面分配表是否满,如果满,则扩容一层 */
    temp = 1;
    for (i = 0; i < pVfile->dirLevel; i++)
    {
        temp *= itemNumPerPage;
    }
    if (lgcPageNo >= temp)
    {
        ret = _db_vfile_add_level(dbHandle, pVfile);
        if (_DB_SUCCESS != ret)
        {
            _db_print(LOG_ERROR, "File %s, line %d: vfile add dir level error!\n", __FILE__, __LINE__);
            _db_mem_page_release(dbHandle, phyPageNo);
            return ret;
        }
    }

    temp = lgcPageNo;
    /* 获取逻辑页面在每一级目录内部对应的目录项 */
    for (i = pVfile->dirLevel; i > 0; i--)
    {
        lgcItem[i - 1] = (WORD)(temp % itemNumPerPage);
        temp = temp / itemNumPerPage;
    }

    /* 访问非叶子节点,获取目录项 */
    temp = pVfile->rootPage;
    for (i = 0; i < pVfile->dirLevel - 1; i++)
    {
        /* 获取目录所在的物理页面 */
        pAddr = _db_mem_get_page_addr(dbHandle, temp);
        if (NULL == pAddr)
        {
            _db_print(LOG_ERROR, "File %s, line %d: vfile get dir info error!\n", __FILE__, __LINE__);
            _db_mem_page_release(dbHandle, phyPageNo);
            return ret;
        }
        pPageItem = (DWORD *)pAddr + lgcItem[i];
        if (_DB_PAGE_INVALID == *pPageItem)
        {
            /* 当前目录项为空,新建 */
            ret = _db_mem_page_new(dbHandle, &pageNo);
            if (ret != _DB_SUCCESS)
            {
                _db_print(LOG_ERROR, "File %s, line %d: vfile create dir page error!\n", __FILE__, __LINE__);
                _db_mem_page_release(dbHandle, phyPageNo);
                return ret;
            }
            pAddr = _db_mem_get_page_addr(dbHandle, pageNo);
            if (NULL == pAddr)
            {
                _db_print(LOG_ERROR, "File %s, line %d: get page addr error!\n", __FILE__, __LINE__);
                _db_mem_page_release(dbHandle, phyPageNo);
                _db_mem_page_release(dbHandle, pageNo);
                return ret;
            }
            memset(pAddr, 0xff, pMemHead->pageSize);

            *pPageItem = pageNo;
        }
        temp = *pPageItem;
    }

    /* 叶子节点目录页面 */
    pAddr = _db_mem_get_page_addr(dbHandle, temp);
    pPageItem = (DWORD *)pAddr + lgcItem[i];
    *pPageItem = phyPageNo;
    pVfile->pageNum++;

    return _DB_SUCCESS;
}