4.4 版本管理器——VM实现

news2024/12/27 11:21:58

VM层通过VersionManager,向上层提供api接口以及各种功能,对于VM上层的模块(是使用了VM层接口的上层模块),那么操作的都是Entry结构
而VM依赖于DM,所以VM视角里(在自我实现里面),操作的是DataItem

VersionManager定义

public interface VersionManager {
    byte[] read(long xid, long uid) throws Exception;
    long insert(long xid, byte[] data) throws Exception;
    boolean delete(long xid, long uid) throws Exception;

    long begin(int level);
    void commit(long xid) throws Exception;
    void abort(long xid);
}

同时,可以看到其中有一个CacheManager,说明也是实现了抽象缓存的,用到了模板方法设计模式,这个在介绍日志模块和数据管理器时也见到过。

VM 的实现类还被设计为 **Entry**** **的缓存,需要继承** AbstractCache<Entry>**。需要实现的获取到缓存和从缓存释放的方法很简单:

抽象缓存的实现

GetForCache
@verride
protected Entry getForCache(long uid) throws Exception {
    // 核心还是调用dm.read()方法
    Entry entry = Entry.loadEntry(this, uid);
    if (entry == null) {
        throw Error.NullEntryException;
    }
    return entry;
}



ReleaseForCache

释放缓存

@Override
protected void releaseForCache(Entry entry) {
    entry.remove();
}

开启事务Begin

在这里插入图片描述

//创建事务,将事务添加到活动事务的映射中,并返回新事务的ID
@Override
public long begin(int level) {
    lock.lock(); // 获取锁,防止并发问题
    try {
        long xid = tm.begin(); // 调用事务管理器的begin方法,开始一个新的事务,并获取事务ID
        Transaction t = Transaction.newTransaction(xid, level, activeTransaction); // 创建一个新的事务对象
        activeTransaction.put(xid, t); // 将新的事务对象添加到活动事务的映射中
        return xid; // 返回新的事务ID
    } finally {
        lock.unlock(); // 释放锁
    }
}

// 创建一个新的事务:设置事务的隔离级别、隔离级别是可重复读时创建快照
public static Transaction newTransaction(long xid, int level, Map<Long, Transaction> active) {
    Transaction t = new Transaction();
    // 设置事务ID
    t.xid = xid;
    // 设置事务隔离级别
    t.level = level;
    // 如果隔离级别不为0,创建快照
    if (level != 0) {
        t.snapshot = new HashMap<>();
        // 将活跃事务的ID添加到快照中
        for (Long x : active.keySet()) {
            t.snapshot.put(x, true);
        }
    }
    // 返回新创建的事务
    return t;
}

提交事务Commit

主要就是 free 掉相关的结构,并且释放持有的锁,并修改事务状态

在这里插入图片描述



// Commit 公开的commit方法,用于提交一个事务
@Override
public void commit(long xid) throws Exception {
    lock.lock(); // 获取锁,防止并发问题
    Transaction t = activeTransaction.get(xid); // 从活动事务中获取事务对象
    lock.unlock(); // 释放锁

    try {
        if (t.err != null) { // 如果事务已经出错,那么抛出错误
            throw t.err;
        }
    } catch (NullPointerException n) { // 如果事务对象为null,打印事务ID和活动事务的键集,然后抛出异常
        System.out.println(xid);
        System.out.println(activeTransaction.keySet());
        Panic.panic(n);
    }

    lock.lock(); // 获取锁,防止并发问题
    activeTransaction.remove(xid); // 1、从活动事务中移除这个事务
    lock.unlock(); // 释放锁

    lt.remove(xid); // 2、从锁表中移除这个事务的锁
    tm.commit(xid); // 3、调用事务管理器的commit方法,进行事务的提交操作
}



中止事务Abort

中止事务的方法则有两种,手动和自动。手动指的是调用 abort() 方法,而自动,则是在事务被检测出出现死锁时,会自动撤销回滚事务;或者出现版本跳跃时,也会自动回滚:

在这里插入图片描述

@Override
// 公开的abort方法,用于中止一个事务
public void abort(long xid) {
    // 调用内部的abort方法,autoAborted参数为false表示这不是一个自动中止的事务
    internAbort(xid, false);
}

// 内部的abort方法,处理事务的中止
private void internAbort(long xid, boolean autoAborted) {
    // 获取锁,防止并发问题
    lock.lock();
    // 从活动事务中获取事务对象
    Transaction t = activeTransaction.get(xid);
    // 如果这不是一个自动中止的事务,那么从活动事务中移除这个事务
    if (!autoAborted) {
        activeTransaction.remove(xid);
    }
    // 释放锁
    lock.unlock();

    // 如果事务已经被自动中止,那么直接返回,不做任何处理
    if (t.autoAborted) return;
    // 从锁表中移除这个事务的锁
    lt.remove(xid);
    // 调用事务管理器的abort方法,进行事务的中止操作
    tm.abort(xid);
}

读取数据Read

read() 方法读取一个 entry,需要注意判断可见性

在这里插入图片描述

//读取一个entry,注意判断可见性
@Override
public byte[] read(long xid, long uid) throws Exception {
    lock.lock(); // 获取锁,防止并发问题
    Transaction t = activeTransaction.get(xid); // 从活动事务中获取事务对象
    lock.unlock(); // 释放锁

    if (t.err != null) { // 如果事务已经出错,那么抛出错误
        throw t.err;
    }

    Entry entry = null;
    try {
        entry = super.get(uid); // 尝试获取数据项
    } catch (Exception e) {
        if (e == Error.NullEntryException) { // 如果数据项不存在,那么返回null
            return null;
        } else { // 如果出现其他错误,那么抛出错误
            throw e;
        }
    }
    try {
        // 在事务隔离级别中讲解了该方法
        if (Visibility.isVisible(tm, t, entry)) { // 如果数据项对当前事务可见,那么返回数据项的数据
            return entry.data();
        } else { // 如果数据项对当前事务不可见,那么返回null
            return null;
        }
    } finally {
        entry.release(); // 释放数据项
    }
}

插入数据Insert

将数据包裹成 Entry,然后交给 DM 插入即可

// Insert 将数据包裹成Entry,然后交给DM插入即可
@Override
public long insert(long xid, byte[] data) throws Exception {
    lock.lock(); // 获取锁,防止并发问题
    Transaction t = activeTransaction.get(xid); // 从活动事务中获取事务对象
    lock.unlock(); // 释放锁

    if (t.err != null) { // 如果事务已经出错,那么抛出错误
        throw t.err;
    }

    byte[] raw = Entry.wrapEntryRaw(xid, data); // 将事务ID和数据包装成一个新的数据项
    return dm.insert(xid, raw); // 调用数据管理器的insert方法,插入新的数据项,并返回数据项的唯一标识符
}

删除数据Delete

在这里插入图片描述

// Delete 删除一个数据项
@Override
// 删除一个数据项的方法
public boolean delete(long xid, long uid) throws Exception {
    // 获取锁,防止并发问题
    lock.lock();
    // 从活动事务中获取事务对象
    Transaction t = activeTransaction.get(xid);
    // 释放锁
    lock.unlock();

    // 如果事务已经出错,那么抛出错误
    if (t.err != null) {
        throw t.err;
    }
    Entry entry = null;
    try {
        // 尝试获取数据项
        entry = super.get(uid);
    } catch (Exception e) {
        // 如果数据项不存在,那么返回false
        if (e == Error.NullEntryException) {
            return false;
        } else {
            // 如果出现其他错误,那么抛出错误
            throw e;
        }
    }
    try {
        // 如果数据项对当前事务不可见,那么返回false
        if (!Visibility.isVisible(tm, t, entry)) {
            return false;
        }
        Lock l = null;
        try {
            // 尝试为数据项添加锁
            l = lt.add(xid, uid);
        } catch (Exception e) {
            // 如果出现并发更新的错误,那么中止事务,并抛出错误
            t.err = Error.ConcurrentUpdateException;
            internAbort(xid, true);
            t.autoAborted = true;
            throw t.err;
        }
        // 如果成功获取到锁,那么锁定并立即解锁
        if (l != null) {
            l.lock();
            l.unlock();
        }

        // 如果数据项已经被当前事务删除,那么返回false
        if (entry.getXmax() == xid) {
            return false;
        }

        // 如果数据项的版本被跳过,那么中止事务,并抛出错误
        if (Visibility.isVersionSkip(tm, t, entry)) {
            t.err = Error.ConcurrentUpdateException;
            internAbort(xid, true);
            t.autoAborted = true;
            throw t.err;
        }

        // 设置数据项的xmax为当前事务的ID,表示数据项被当前事务删除
        entry.setXmax(xid);
        // 返回true,表示删除操作成功
        return true;

    } finally {
        // 释放数据项
        entry.release();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2114130.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++数据结构重要知识点(5)(哈希表、unordered_map和unordered_set封装)

1.哈希思想和哈希表 &#xff08;1&#xff09;哈希思想和哈希表的区别 哈希&#xff08;散列、hash&#xff09;是一种映射思想&#xff0c;本质上是值和值建立映射关系&#xff0c;key-value就使用了这种思想。哈希表&#xff08;散列表&#xff0c;数据结构&#xff09;&a…

鸿蒙轻内核M核源码分析系列十五 CPU使用率CPUP

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 轻内核M核源码分析系列一 数据结构-双向循环链表 轻内核M核源码分析系列二 数据结构-任务就绪队列 鸿蒙轻内核M核源码分析系列三 数据结构-任务排序链表 轻…

三维布尔运算对不规范几何数据的兼容处理

1.前言 上一篇文章谈过八叉树布尔运算&#xff0c;对于规范几何数据的情况是没有问题的。 在实际情况中&#xff0c;由于几何数据来源不一&#xff0c;处理和生成方式不一&#xff0c;我们无法保证进行布尔运算的几何数据都是规范的&#xff0c;对于不规范情况有时候也有需求…

个股场外期权的行权时间是什么时候?

今天带你了解个股场外期权的行权时间是什么时候&#xff1f;场外个股期权的行权日并没有一个固定的日期&#xff0c;它主要取决于期权合约的具体条款和规定。 个股场外期权 个股场外期权是指在场外交易市场进行的、以单个股票为标的资产的期权合约。这种期权与在交易所交易的…

@Cacheable踩坑,服务停住,~lock

1、问题&#xff1a; 方法使用Cacheable注解&#xff0c;服务每次重启后&#xff0c;调到这个方法都服务停住了&#xff0c;日志也不打了。 2、原因&#xff1a; 服务停止住了&#xff0c;发现redis会生成key~lock的锁&#xff0c;永不过期&#xff0c;也没有删除。 例如以下…

【2025】公司仓库管理系统的设计与实现(公司仓库信息管理系统,仓库信息系统,管理系统,信息管理系统,货物仓管系统)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

【IEEE出版】2024博鳌新型电力系统国际论坛——电力系统与新能源技术创新论坛(NPSIF 2024,10月30-11月1)

2024博鳌新型电力系统国际论坛——电力系统与新能源技术创新论坛将于2024年10月30-11月1日于海南博鳌举办。 会议的历史悠久&#xff0c;致力于促进电力系统领域的研究和开发活动&#xff0c;同时也着眼于促进全球各地研究人员、开发人员、工程师、学生和从业人员之间的科学信息…

适合新手进阶,借助ChatGPT撰写学术论文全流程指南,附顶级提示词使用攻略

大家好,感谢关注。我是七哥,一个在高校里不务正业,折腾学术科研AI实操的学术人。关于使用ChatGPT等AI学术科研的相关问题可以和作者七哥(yida985)交流,多多交流,相互成就,共同进步,为大家带来最酷最有效的智能AI学术科研写作攻略。 学术论文的写作涉及深入研究、分析…

ECCV`24 | 蚂蚁集团开源风格控制新SOTA!StyleTokenizer:零样本精确控制图像生成

文章链接&#xff1a;https://arxiv.org/pdf/2409.02543 代码&数据集链接&#xff1a; https://github.com/alipay/style-tokenizer 亮点直击 介绍了一种名为StyleTokenizer的新方法&#xff0c;用于在扩散模型中进行风格控制。这种方法允许通过一个任意参考图像实现对生成…

元学习(meta learning)(一)

元学习从字面的意思就是“学习”的“学习”&#xff0c;也 就是学习如何学习。大部分的深度学习就是在不断的调整超参数&#xff0c;或者在决定网络架构&#xff0c;改变 学习率等等。实际上没有什么好方法来调这些超参&#xff0c;今天工业界最常拿来解决调整超参数的 方法是买…

dpdk——数据平面开发套件

数据平面开发工具包 &#xff08;DPDK&#xff09; 是一个 Linux Foundation 项目&#xff0c;它由多个库组成&#xff0c;用于加速在各种 CPU 架构上运行的数据包处理。 网络性能、吞吐量和延迟对于各种应用程序至关重要&#xff0c;包括无线和有线基础设施、路由器、负载均衡…

2024年【防爆电气】考试题库及防爆电气复审模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 防爆电气考试题库根据新防爆电气考试大纲要求&#xff0c;安全生产模拟考试一点通将防爆电气模拟考试试题进行汇编&#xff0c;组成一套防爆电气全真模拟考试试题&#xff0c;学员可通过防爆电气复审模拟考试全真模拟…

基于Java+SpringBoot+Vue+MySQL的高校大学生迎新管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于SpringBootVue的高校大学生迎新管理系统【附源码文档】…

828华为云征文 | Flexus X 实例服务器网络性能深度评测

引言 随着互联网应用的快速发展&#xff0c;网络带宽和性能对云服务器的表现至关重要。在不同的云服务平台上&#xff0c;即便配置相同的带宽&#xff0c;实际的网络表现也可能有所差异。因此&#xff0c;了解并测试服务器的网络性能变得尤为重要。本文将以华为云X实例服务器为…

【NumPy】基础知识

NumPy是Python的第三方库&#xff0c;要使用需要先导入。 import numpy as np 在pycharm中可以通过np.来查看numpy的可用函数。 np.函数名? 查看对应函数的详细信息。 生成NumPy数组 ndarray 多维数组对象 numpy封装了一个新的数据类型ndarray&#xff0c;是一个多维数组对…

图论篇--代码随想录算法训练营第五十三天打卡| 110. 字符串接龙,105.有向图的完全可达性,106. 岛屿的周长

110. 字符串接龙 题目链接&#xff1a;110. 字符串接龙 题目描述&#xff1a; 字典 strList 中从字符串 beginStr 和 endStr 的转换序列是一个按下述规格形成的序列&#xff1a; 序列中第一个字符串是 beginStr。序列中最后一个字符串是 endStr。 每次转换只能改变一个字符…

解决报错:java.lang.NumberFormatException: Cannot parse null string

最近在做javaweb项目&#xff0c;整了一整天&#xff0c;代码翻来覆去反复看&#xff0c;就是没看出问题&#xff0c;没承想问题是出在编码上&#xff0c;我服了&#xff01;我就知道我代码逻辑没问题。 把enctype"multipart/form-data"删掉&#xff0c;就好了... 这…

自然语言处理系列六十三》神经网络算法》LSTM长短期记忆神经网络算法

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 自然语言处理系列六十三神经网络算法》LSTM长短期记忆神经网络算…

【C++多线程编程】 线程安全与对象生命周期管理

目录 类的线程安全 实现线程安全 构造函数在多线程中的安全性 析构函数多线程环境的安全 智能指针实现多线程安全 shared_ptr 非完全线程安全 shared_ptr可能导致对象生命周期延长 const引用可以减少传递shared_ptr开销 shared_ptr 智能指针块模块的优点 析构所在线程…

前端核心基础知识总结

目录 前言 一、HTML模块 1. 标签结构 2. 语义化标签 3. 表单元素 二、CSS模块 1. 选择器 2. 盒模型 示例一&#xff1a;为一个div标签设置了宽度为 200 像素&#xff0c;高度为 100 像素的内容区。 示例二&#xff1a;内边距的存在可以使内容与边框之间有一定的间隔&…