##// END OF EJS Templates
rust-index: support cache clearing...
Raphaël Gomès -
r52090:4e6620b7 default
parent child Browse files
Show More
@@ -1,5 +1,6 b''
1 use std::fmt::Debug;
1 use std::fmt::Debug;
2 use std::ops::Deref;
2 use std::ops::Deref;
3 use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
3
4
4 use byteorder::{BigEndian, ByteOrder};
5 use byteorder::{BigEndian, ByteOrder};
5 use bytes_cast::{unaligned, BytesCast};
6 use bytes_cast::{unaligned, BytesCast};
@@ -225,8 +226,9 b' pub struct Index {'
225 bytes: IndexData,
226 bytes: IndexData,
226 /// Offsets of starts of index blocks.
227 /// Offsets of starts of index blocks.
227 /// Only needed when the index is interleaved with data.
228 /// Only needed when the index is interleaved with data.
228 offsets: Option<Vec<usize>>,
229 offsets: RwLock<Option<Vec<usize>>>,
229 uses_generaldelta: bool,
230 uses_generaldelta: bool,
231 is_inline: bool,
230 }
232 }
231
233
232 impl Debug for Index {
234 impl Debug for Index {
@@ -294,8 +296,9 b' impl Index {'
294 if offset == bytes.len() {
296 if offset == bytes.len() {
295 Ok(Self {
297 Ok(Self {
296 bytes: IndexData::new(bytes),
298 bytes: IndexData::new(bytes),
297 offsets: Some(offsets),
299 offsets: RwLock::new(Some(offsets)),
298 uses_generaldelta,
300 uses_generaldelta,
301 is_inline: true,
299 })
302 })
300 } else {
303 } else {
301 Err(HgError::corrupted("unexpected inline revlog length"))
304 Err(HgError::corrupted("unexpected inline revlog length"))
@@ -303,8 +306,9 b' impl Index {'
303 } else {
306 } else {
304 Ok(Self {
307 Ok(Self {
305 bytes: IndexData::new(bytes),
308 bytes: IndexData::new(bytes),
306 offsets: None,
309 offsets: RwLock::new(None),
307 uses_generaldelta,
310 uses_generaldelta,
311 is_inline: false,
308 })
312 })
309 }
313 }
310 }
314 }
@@ -315,7 +319,7 b' impl Index {'
315
319
316 /// Value of the inline flag.
320 /// Value of the inline flag.
317 pub fn is_inline(&self) -> bool {
321 pub fn is_inline(&self) -> bool {
318 self.offsets.is_some()
322 self.is_inline
319 }
323 }
320
324
321 /// Return a slice of bytes if `revlog` is inline. Panic if not.
325 /// Return a slice of bytes if `revlog` is inline. Panic if not.
@@ -328,13 +332,35 b' impl Index {'
328
332
329 /// Return number of entries of the revlog index.
333 /// Return number of entries of the revlog index.
330 pub fn len(&self) -> usize {
334 pub fn len(&self) -> usize {
331 if let Some(offsets) = &self.offsets {
335 if let Some(offsets) = &*self.get_offsets() {
332 offsets.len()
336 offsets.len()
333 } else {
337 } else {
334 self.bytes.len() / INDEX_ENTRY_SIZE
338 self.bytes.len() / INDEX_ENTRY_SIZE
335 }
339 }
336 }
340 }
337
341
342 pub fn get_offsets(&self) -> RwLockReadGuard<Option<Vec<usize>>> {
343 if self.is_inline() {
344 {
345 // Wrap in a block to drop the read guard
346 // TODO perf?
347 let mut offsets = self.offsets.write().unwrap();
348 if offsets.is_none() {
349 offsets.replace(inline_scan(&self.bytes.bytes).1);
350 }
351 }
352 }
353 self.offsets.read().unwrap()
354 }
355
356 pub fn get_offsets_mut(&mut self) -> RwLockWriteGuard<Option<Vec<usize>>> {
357 let mut offsets = self.offsets.write().unwrap();
358 if self.is_inline() && offsets.is_none() {
359 offsets.replace(inline_scan(&self.bytes.bytes).1);
360 }
361 offsets
362 }
363
338 /// Returns `true` if the `Index` has zero `entries`.
364 /// Returns `true` if the `Index` has zero `entries`.
339 pub fn is_empty(&self) -> bool {
365 pub fn is_empty(&self) -> bool {
340 self.len() == 0
366 self.len() == 0
@@ -346,8 +372,8 b' impl Index {'
346 if rev == NULL_REVISION {
372 if rev == NULL_REVISION {
347 return None;
373 return None;
348 }
374 }
349 Some(if let Some(offsets) = &self.offsets {
375 Some(if let Some(offsets) = &*self.get_offsets() {
350 self.get_entry_inline(rev, offsets)
376 self.get_entry_inline(rev, offsets.as_ref())
351 } else {
377 } else {
352 self.get_entry_separated(rev)
378 self.get_entry_separated(rev)
353 })
379 })
@@ -393,7 +419,7 b' impl Index {'
393 ) -> Result<(), RevlogError> {
419 ) -> Result<(), RevlogError> {
394 revision_data.validate()?;
420 revision_data.validate()?;
395 let new_offset = self.bytes.len();
421 let new_offset = self.bytes.len();
396 if let Some(offsets) = self.offsets.as_mut() {
422 if let Some(offsets) = &mut *self.get_offsets_mut() {
397 offsets.push(new_offset)
423 offsets.push(new_offset)
398 }
424 }
399 self.bytes.added.extend(revision_data.into_v1().as_bytes());
425 self.bytes.added.extend(revision_data.into_v1().as_bytes());
@@ -401,12 +427,37 b' impl Index {'
401 }
427 }
402
428
403 pub fn remove(&mut self, rev: Revision) -> Result<(), RevlogError> {
429 pub fn remove(&mut self, rev: Revision) -> Result<(), RevlogError> {
404 self.bytes.remove(rev, self.offsets.as_deref())?;
430 let offsets = self.get_offsets().clone();
405 if let Some(offsets) = self.offsets.as_mut() {
431 self.bytes.remove(rev, offsets.as_deref())?;
432 if let Some(offsets) = &mut *self.get_offsets_mut() {
406 offsets.truncate(rev.0 as usize)
433 offsets.truncate(rev.0 as usize)
407 }
434 }
408 Ok(())
435 Ok(())
409 }
436 }
437
438 pub fn clear_caches(&mut self) {
439 // We need to get the 'inline' value from Python at init and use this
440 // instead of offsets to determine whether we're inline since we might
441 // clear caches. This implies re-populating the offsets on-demand.
442 self.offsets = RwLock::new(None);
443 }
444 }
445
446 fn inline_scan(bytes: &[u8]) -> (usize, Vec<usize>) {
447 let mut offset: usize = 0;
448 let mut offsets = Vec::new();
449
450 while offset + INDEX_ENTRY_SIZE <= bytes.len() {
451 offsets.push(offset);
452 let end = offset + INDEX_ENTRY_SIZE;
453 let entry = IndexEntry {
454 bytes: &bytes[offset..end],
455 offset_override: None,
456 };
457
458 offset += INDEX_ENTRY_SIZE + entry.compressed_len() as usize;
459 }
460 (offset, offsets)
410 }
461 }
411
462
412 impl super::RevlogIndex for Index {
463 impl super::RevlogIndex for Index {
@@ -205,6 +205,7 b' py_class!(pub class MixedIndex |py| {'
205 self.nt(py).borrow_mut().take();
205 self.nt(py).borrow_mut().take();
206 self.docket(py).borrow_mut().take();
206 self.docket(py).borrow_mut().take();
207 self.nodemap_mmap(py).borrow_mut().take();
207 self.nodemap_mmap(py).borrow_mut().take();
208 self.index(py).borrow_mut().clear_caches();
208 self.call_cindex(py, "clearcaches", args, kw)
209 self.call_cindex(py, "clearcaches", args, kw)
209 }
210 }
210
211
General Comments 0
You need to be logged in to leave comments. Login now