Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kirawi committed Jan 20, 2023
1 parent 68d3936 commit 060c4d6
Showing 1 changed file with 46 additions and 23 deletions.
69 changes: 46 additions & 23 deletions helix-view/src/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ use std::{
};

use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use sha1_smol::Sha1;

// Needs to mimic borrowing rules.
// Allow multiple read-only references, and only one mutable reference w/ no read-only.
// Should not lock unless actively used. And should be unlocked automatically when all file handles are dropped.
pub struct Session {
path: PathBuf,
guard: Option<FileLock>,
lock: Option<FileLock>,
}

impl Session {
Expand All @@ -21,16 +23,30 @@ impl Session {
let bytes = sys::path_as_bytes(path.as_path());
let hash = Sha1::from(bytes).digest().to_string();
let path = helix_loader::cache_dir().join("sessions").join(hash);
Ok(Self { path, guard: None })
Ok(Self { path, lock: None })
}

// TODO: Return a FileLockGuard instead.
pub fn get(&mut self, filename: String) -> Result<File> {
if self.guard.is_none() {
let lock = FileLock::new(self.path.join(".helix.lock"))?;
if self.lock.is_none() {
let lock = FileLock::shared(self.path.join(".helix.lock"))?;
lock.lock()?;

self.lock = Some(lock);
}

OpenOptions::new()
.read(true)
.open(self.path.join(filename))
.context("failed to open file")
}

// TODO: Return a FileLockGuard instead.
pub fn get_mut(&mut self, filename: String) -> Result<File> {
if self.lock.is_none() {
let lock = FileLock::exclusive(self.path.join(".helix.lock"))?;
lock.lock()?;

self.guard = Some(lock);
self.lock = Some(lock);
}

OpenOptions::new()
Expand All @@ -44,21 +60,34 @@ impl Session {

pub struct FileLock {
file: File,
shared: bool,
}

impl FileLock {
pub fn new(path: PathBuf) -> Result<Self> {
pub fn exclusive(path: PathBuf) -> Result<Self> {
let file = Self::open_lock(path)?;
Ok(Self {
file,
shared: false,
})
}

pub fn shared(path: PathBuf) -> Result<Self> {
let file = Self::open_lock(path)?;
Ok(Self { file, shared: true })
}

pub fn lock(&self) -> Result<()> {
sys::lock(&self.file, self.shared)
}

fn open_lock(path: PathBuf) -> std::io::Result<File> {
if let Some(parent) = path.parent() {
if !parent.exists() {
std::fs::DirBuilder::new().recursive(true).create(parent)?;
}
}
let file = OpenOptions::new().write(true).create(true).open(path)?;
Ok(Self { file })
}

pub fn lock(&self) -> Result<()> {
sys::lock(&self.file)
OpenOptions::new().write(true).create(true).open(path)
}
}

Expand Down Expand Up @@ -145,17 +174,11 @@ mod sys {
}

/// Blocks until the lock is acquired.
pub(super) fn lock(file: &File) -> anyhow::Result<()> {
pub(super) fn lock(file: &File, shared: bool) -> anyhow::Result<()> {
let flag = if shared { 0 } else { LOCKFILE_EXCLUSIVE_LOCK };
unsafe {
let mut overlapped = std::mem::zeroed();
let ret = LockFileEx(
file.as_raw_handle(),
LOCKFILE_EXCLUSIVE_LOCK,
0,
!0,
!0,
&mut overlapped,
);
let ret = LockFileEx(file.as_raw_handle(), flag, 0, !0, !0, &mut overlapped);
if ret == 0 {
anyhow::bail!(Error::last_os_error())
} else {
Expand Down

0 comments on commit 060c4d6

Please sign in to comment.