Skip to content

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

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`

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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