rucbase 任务一

void DiskManager::write_page(int fd, page_id_t page_no, const char *offset, int num_bytes) {
    // Todo:
    // 1.lseek()定位到文件头,通过(fd,page_no)可以定位指定页面及其在磁盘文件中的偏移量
    // 2.调用write()函数
    // 注意处理异常
    //off_t 文件偏移量 long 类型
    off_t offset = static_cast<off_t>(page_no) * PAGE_SIZE;
    if (lseek(fd, offset, SEEK_SET) == -1) {
        throw UnixError();
    }
    int num = write(fd, offset, num_bytes);
    if (num != num_bytes) {
        throw UnixError();
    }

off_t类型用于指示文件的偏移量,常就是long类型,其默认为一个32位的整数,在gcc编译中会被编译为long int类型,在64位的Linux系统中则会被编译为long long int,这是一个64位的整数,其定义在unistd.h头文件中可以查看。

fseek(FILE *stream, long offset, int whence);
1.offset表示文件指针的偏移量

SEEK_SET:基准位置为文件开头,即offset表示距离文件开头的偏移量。

SEEK_CUR:基准位置为文件当前位置,即offset表示距离文件当前位置的偏移量。

SEEK_END:基准位置为文件末尾,即offset表示距离文件末尾的偏移量。
2.whence表示偏移量的基准位置

当whence为SEEK_SET时,offset表示距离文件开头的偏移量;

当whence为SEEK_CUR时,offset表示距离文件当前位置的偏移量;

当whence为SEEK_END时,offset表示距离文件末尾的偏移量。

void DiskManager::read_page(int fd, page_id_t page_no, char *offset, int num_bytes) {
    // Todo:
    // 1.lseek()定位到文件头,通过(fd,page_no)可以定位指定页面及其在磁盘文件中的偏移量
    // 2.调用read()函数
    // 注意处理异常
    off_t offset_in_file = static_cast<off_t>(page_no) * PAGE_SIZE;
    if (lseek(fd, offset_in_file, SEEK_SET) == -1) {
        throw UnixError();
    }
    if (read(fd, offset, num_bytes) == -1) {
        throw UnixError();
    }

page_id_t DiskManager::AllocatePage(int fd) {
    // Todo:
    // 简单的自增分配策略,指定文件的页面编号加1
    fd2pageno_[fd]++;
    return fd2pageno_[fd] - 1;
}
bool DiskManager::is_file(const std::string &path) {
    // Todo:
    // 用struct stat获取文件信息
    struct stat st;
    return stat(path.c_str(), &st) == 0;
}

c_strstring类的一个函数,可以把string类型变量转换成char*变量
open()要求的是一个char*字符串

void DiskManager::destroy_file(const std::string &path) {
    // Todo:
    // 调用unlink()函数
    // 注意不能删除未关闭的文件,不存在的文件也不能删
    if (!is_file(path)) {
            throw FileNotFoundError(path);
    }
    if (path2fd_.count(path)) {
            throw FileNotClosedError(path);
    }
    unlink(path.c_str())
    

首先判断文件是否被创建,如果路径不存在抛出异常再判断文件是否已经打开,不能删除未关闭的文件,然后用unlink()函数关闭文件

int DiskManager::open_file(const std::string &path) {
    // Todo:
    // 调用open()函数,使用O_RDWR模式
    // 注意不能重复打开相同文件,并且需要更新文件打开列表
    if (path2fd_.count(path)) 
        return -1;
    int fd = open(path.c_str(), O_RDWR);
    path2fd_.emplace(path,fd);
    fd2path_.emplace(fd,path);

    return fd;
}

首先判断文件是否打开,然后打开文件,更新打开文件的列表

c.emplace(p,t)在迭代器p所指向的元素之前创建一个值为t的元素,返回指定新添加元素的迭代器

O_RDWR:以读写方式打开文件

void DiskManager::close_file(int fd) {
    // Todo:
    // 调用close()函数
    // 注意不能关闭未打开的文件,并且需要更新文件打开列表

    if (!fd2path_.count(fd)) {
            throw FileNotOpenError(fd);
    } 
    close(fd)
    auto it = fd2path_.find(fd);
    path2fd_.erase(it->first);
    fd2path_.erase(fd);
}

bool LRUReplacer::Victim(frame_id_t *frame_id) {
    // C++17 std::scoped_lock
    // 它能够避免死锁发生,其构造函数能够自动进行上锁操作,析构函数会对互斥量进行解锁操作,保证线程安全。
    std::scoped_lock lock{latch_};

    // Todo:
    //  利用lru_replacer中的LRUlist_,LRUHash_实现LRU策略
    //  选择合适的frame指定为淘汰页面,赋值给*frame_id

    *frame_id = LRUlist_.back();
    LRUlist_.pop_back();
    LRUhash_.erase(*frame_id);
    return true;
}

bool LRUReplacer::Victim(frame_id_t *frame_id) {
    // C++17 std::scoped_lock
    // 它能够避免死锁发生,其构造函数能够自动进行上锁操作,析构函数会对互斥量进行解锁操作,保证线程安全。
    std::scoped_lock lock{latch_};

    // Todo:
    //  利用lru_replacer中的LRUlist_,LRUHash_实现LRU策略
    //  选择合适的frame指定为淘汰页面,赋值给*frame_id
    *frame_id = LRUlist_.back();
    LRUlist_.pop_back();
    LRUhash_.erase(*frame_id);
    return true;
}

/**
 * @brief 固定一个frame, 表明它不应该成为victim(即在replacer中移除该frame_id)
 * @param frame_id the id of the frame to pin
 */
void LRUReplacer::Pin(frame_id_t frame_id) {
    std::scoped_lock lock{latch_};
    // Todo:
    // 固定指定id的frame
    // 在数据结构中移除该frame

    auto it = LRUhash_.find(frame_id);
    LRUlist_.erase(it);
    LRUhash_.erase(it);
    }
}

/**
 * 取消固定一个frame, 表明它可以成为victim(即将该frame_id添加到replacer)
 * @param frame_id the id of the frame to unpin
 */
void LRUReplacer::Unpin(frame_id_t frame_id) {
    // Todo:
    //  支持并发锁
    //  选择一个frame取消固定
    std::scoped_lock lock{latch_};
    LRUlist_.push_front(frame_id);
    LRUhash_[frame_id] = LRUlist_.begin();
}

/** @return replacer中能够victim的数量 */
size_t LRUReplacer::Size() {
    // Todo:
    // 改写return size

    std::scoped_lock lock{latch_};
    return LRUlist_.size();
}

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值