Skip to content

db.del未能正确删除数据 #5

@huajiqaq

Description

@huajiqaq

当调用db.del时似乎是伪删除 each函数会报错
Runtime error: db.lua:909: not enough memory for buffer allocation
stack traceback:
[C]: in method 'read'
db.lua:909: in for iterator 'for iterator'

以下是我尝试修改的del函数 但修改失败了 但实现了对于db文件和map文件部分清理 而且修改后each函数无法使用 可是本人太菜导致并未成功修复--- 删除成员
`---@param k any|LUADB_ID|LUADB_ADDR 成员key
---@return LuaDB
function db:del(k)
-- 申明变量
local F = self.F
local fw, fm = self.fw, self.fm
-- 得到成员属性
local po, addr, size, _, ck, level = self:check_key(k)
-- key转换类型,用于判断是否碰撞
k = tostring(k)

-- 读取原本存储的数据类型和长度
fw:seek('set', addr + 8 + size)
local tp = unpack(F.B, fw:read(1))
local n = self:packsize(tp)

-- 计算数据总长度
local total_len = 8 + size + 1 + n

-- 从文件中删除数据
-- 先备份数据后面的部分
local backup = fw:read(fw:seek('end') - (addr + total_len))

-- 如果备份为空,确保它是一个空字符串
backup = backup or ''

-- 清空要删除的数据
fw:seek('set', addr)
fw:write(string.rep('\0', total_len))

-- 将备份的数据写回到文件中
fw:seek('end')
fw:write(backup)

-- 更新索引,移除该键值对的记录
local block_size = self.block_size
local addr_size = self.addr_size
local hash_code = (hash(k) % block_size) + 1 -- 获取hash值
k = tostring(k) -- key转字符串
if self.can_each then
    block_size = block_size * 2
    hash_code = hash_code * 2
end
-- 计算实际占用空间
block_size = block_size * addr_size
-- 计算指针实际位置
hash_code = hash_code * addr_size
while true do
    local po1 = (level * block_size) + hash_code
    fm:seek('set', po1)
    local addr1 = fm:read(addr_size)
    if addr1 then
        addr1 = unpack(F.A, addr1)
    else
        addr1 = 0
    end
    local po2 = ((level - 1) * block_size) + hash_code
    fm:seek('set', po2)
    fm:write((pack(F.A, addr1)))
    if addr1 == 0 then
        break
    end
    level = level + 1 -- 下降深度
end

-- 如果删除的是文件末尾的数据,重新写入文件
if addr + total_len == fw:seek('end') then
    -- 创建临时文件
    local temp_file = io.open(self.path .. '.tmp', 'wb')
    local pos = 0
    while pos < addr do
        pos = pos + 1024
        fw:seek('set', pos - 1024)
        temp_file:write(fw:read(1024))
    end
    temp_file:close()

    -- 替换原始文件
    os.remove(self.path)
    os.rename(self.path .. '.tmp', self.path)
end

-- 更新成员指针链表中的指针
self:update_pointers_after_delete(k, addr)

-- 清理成员指针链表
self:cleanup_pointers()

return self

end

--- 更新成员指针链表中的指针
---@param k string 成员key
---@param addr number 被删除成员的地址
function db:update_pointers_after_delete(k, addr)
-- 更新成员指针链表中的指针
local block_size = self.block_size
local addr_size = self.addr_size
local hash_code = (hash(k) % block_size) + 1 -- 获取hash值
if self.can_each then
block_size = block_size * 2
hash_code = hash_code * 2
end
-- 计算实际占用空间
block_size = block_size * addr_size
-- 计算指针实际位置
hash_code = hash_code * addr_size

local level = 0
while true do
    local po = (level * block_size) + hash_code
    local fm = self.fm
    fm:seek('set', po)
    local addr1 = fm:read(addr_size)
    if addr1 then
        addr1 = unpack(self.F.A, addr1)
    else
        addr1 = 0
    end
    if addr1 == addr then
        -- 如果当前地址是要删除的地址
        -- 获取下一个有效地址
        local next_addr = self:get_next_addr(addr)
        -- 更新指针
        fm:seek('set', po)
        fm:write((pack(self.F.A, next_addr)))
    elseif addr1 == 0 then
        break
    end
    level = level + 1 -- 下降深度
end

end

--- 清理成员指针链表
---@return LuaDB
function db:cleanup_pointers()
-- 遍历成员指针链表,清理无效的指针
local block_size = self.block_size
local addr_size = self.addr_size
local hash_code = (hash(k) % block_size) + 1 -- 获取hash值
if self.can_each then
block_size = block_size * 2
hash_code = hash_code * 2
end
-- 计算实际占用空间
block_size = block_size * addr_size
-- 计算指针实际位置
hash_code = hash_code * addr_size

local level = 0
while true do
    local po = (level * block_size) + hash_code
    local fm = self.fm
    fm:seek('set', po)
    local addr1 = fm:read(addr_size)
    if addr1 then
        addr1 = unpack(self.F.A, addr1)
    else
        addr1 = 0
    end
    if addr1 == 0 then
        break
    end
    local next_addr = self:get_next_addr(addr1)
    if next_addr == 0 then
        -- 如果下一个地址无效,则将当前地址设置为0
        fm:seek('set', po)
        fm:write((pack(self.F.A, 0)))
    else
        -- 否则,更新当前地址的下一个地址
        fm:seek('set', po + addr_size)
        fm:write((pack(self.F.A, next_addr)))
    end
    level = level + 1 -- 下降深度
end

end

--- 获取下一个有效地址
---@param addr number 当前地址
---@return number 下一个有效地址
function db:get_next_addr(addr)
local fw = self.fw
fw:seek('set', addr + 8)
local next_addr = unpack(self.F.A, fw:read(self.addr_size))
return next_addr
end`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions