|
1 | 1 | #![allow(dead_code)]
|
| 2 | +use std::sync::Arc; |
| 3 | + |
2 | 4 | use crate::{
|
3 | 5 | error::{DirectoryError, DocumentError, LanguageServerError},
|
4 | 6 | utils::document,
|
@@ -109,30 +111,6 @@ impl TextDocument {
|
109 | 111 | }
|
110 | 112 | }
|
111 | 113 |
|
112 |
| -/// Marks the specified file as "dirty" by creating a corresponding flag file. |
113 |
| -/// |
114 |
| -/// This function ensures the necessary directory structure exists before creating the flag file. |
115 |
| -pub fn mark_file_as_dirty(uri: &Url) -> Result<(), LanguageServerError> { |
116 |
| - let path = document::get_path_from_url(uri)?; |
117 |
| - Ok(PidFileLocking::lsp(path) |
118 |
| - .lock() |
119 |
| - .map_err(|e| DirectoryError::LspLocksDirFailed(e.to_string()))?) |
120 |
| -} |
121 |
| - |
122 |
| -/// Removes the corresponding flag file for the specified Url. |
123 |
| -/// |
124 |
| -/// If the flag file does not exist, this function will do nothing. |
125 |
| -pub fn remove_dirty_flag(uri: &Url) -> Result<(), LanguageServerError> { |
126 |
| - let path = document::get_path_from_url(uri)?; |
127 |
| - let uri = uri.clone(); |
128 |
| - Ok(PidFileLocking::lsp(path) |
129 |
| - .release() |
130 |
| - .map_err(|err| DocumentError::UnableToRemoveFile { |
131 |
| - path: uri.path().to_string(), |
132 |
| - err: err.to_string(), |
133 |
| - })?) |
134 |
| -} |
135 |
| - |
136 | 114 | #[derive(Debug)]
|
137 | 115 | struct EditText<'text> {
|
138 | 116 | start_index: usize,
|
@@ -242,6 +220,57 @@ impl std::ops::Deref for Documents {
|
242 | 220 | }
|
243 | 221 | }
|
244 | 222 |
|
| 223 | +/// Manages process-based file locking for multiple files. |
| 224 | +pub struct PidLockedFiles { |
| 225 | + locks: DashMap<Url, Arc<PidFileLocking>>, |
| 226 | +} |
| 227 | + |
| 228 | +impl Default for PidLockedFiles { |
| 229 | + fn default() -> Self { |
| 230 | + Self::new() |
| 231 | + } |
| 232 | +} |
| 233 | + |
| 234 | +impl PidLockedFiles { |
| 235 | + pub fn new() -> Self { |
| 236 | + Self { |
| 237 | + locks: DashMap::new(), |
| 238 | + } |
| 239 | + } |
| 240 | + |
| 241 | + /// Marks the specified file as "dirty" by creating a corresponding flag file. |
| 242 | + /// |
| 243 | + /// This function ensures the necessary directory structure exists before creating the flag file. |
| 244 | + /// If the file is already locked, this function will do nothing. This is to reduce the number of |
| 245 | + /// unnecessary file IO operations. |
| 246 | + pub fn mark_file_as_dirty(&self, uri: &Url) -> Result<(), LanguageServerError> { |
| 247 | + if !self.locks.contains_key(uri) { |
| 248 | + let path = document::get_path_from_url(uri)?; |
| 249 | + let file_lock = Arc::new(PidFileLocking::lsp(path)); |
| 250 | + file_lock |
| 251 | + .lock() |
| 252 | + .map_err(|e| DirectoryError::LspLocksDirFailed(e.to_string()))?; |
| 253 | + self.locks.insert(uri.clone(), file_lock); |
| 254 | + } |
| 255 | + Ok(()) |
| 256 | + } |
| 257 | + |
| 258 | + /// Removes the corresponding flag file for the specified Url. |
| 259 | + /// |
| 260 | + /// If the flag file does not exist, this function will do nothing. |
| 261 | + pub fn remove_dirty_flag(&self, uri: &Url) -> Result<(), LanguageServerError> { |
| 262 | + if let Some((uri, file_lock)) = self.locks.remove(uri) { |
| 263 | + file_lock |
| 264 | + .release() |
| 265 | + .map_err(|err| DocumentError::UnableToRemoveFile { |
| 266 | + path: uri.path().to_string(), |
| 267 | + err: err.to_string(), |
| 268 | + })?; |
| 269 | + } |
| 270 | + Ok(()) |
| 271 | + } |
| 272 | +} |
| 273 | + |
245 | 274 | #[cfg(test)]
|
246 | 275 | mod tests {
|
247 | 276 | use super::*;
|
|
0 commit comments