This is an automated email from the ASF dual-hosted git repository.
JosiahWI pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 0847dc6f85 Move some directory helpers to `Directory` (#13245)
0847dc6f85 is described below
commit 0847dc6f853a045b2dc7335fec052e748a5645a3
Author: JosiahWI <[email protected]>
AuthorDate: Tue Jun 9 06:56:28 2026 -0500
Move some directory helpers to `Directory` (#13245)
* Move `dir_init_segment` to `Directory`
* Move `dir_init_segment` to `Directory`
* Move `dir_bucket_loop_fix` to `Directory`
* Move `unlink_from_freelist` to `Directory`
* Move `dir_delete_entry` to `Directory`
Co-authored-by: Copilot Autofix powered by AI
<[email protected]>
---
src/iocore/cache/CacheDir.cc | 97 +++++++++++--------------------------------
src/iocore/cache/CacheVC.cc | 5 +--
src/iocore/cache/P_CacheDir.h | 85 +++++++++++++++++++++++++++++++------
3 files changed, 97 insertions(+), 90 deletions(-)
diff --git a/src/iocore/cache/CacheDir.cc b/src/iocore/cache/CacheDir.cc
index ee14d521ff..7997c50108 100644
--- a/src/iocore/cache/CacheDir.cc
+++ b/src/iocore/cache/CacheDir.cc
@@ -210,16 +210,16 @@ dir_bucket_loop_check(Dir *start_dir, Dir *seg)
// adds all the directory entries
// in a segment to the segment freelist
void
-dir_init_segment(int s, Directory *directory)
+Directory::init_segment(int s)
{
- directory->header->freelist[s] = 0;
- Dir *seg = directory->get_segment(s);
+ this->header->freelist[s] = 0;
+ Dir *seg = this->get_segment(s);
int l, b;
- memset(static_cast<void *>(seg), 0, SIZEOF_DIR * DIR_DEPTH *
directory->buckets);
+ memset(static_cast<void *>(seg), 0, SIZEOF_DIR * DIR_DEPTH * this->buckets);
for (l = 1; l < DIR_DEPTH; l++) {
- for (b = 0; b < directory->buckets; b++) {
+ for (b = 0; b < this->buckets; b++) {
Dir *bucket = dir_bucket(b, seg);
- directory->free_entry(dir_bucket_row(bucket, l), s);
+ this->free_entry(dir_bucket_row(bucket, l), s);
}
}
}
@@ -227,11 +227,11 @@ dir_init_segment(int s, Directory *directory)
// break the infinite loop in directory entries
// Note : abuse of the token bit in dir entries
int
-dir_bucket_loop_fix(Dir *start_dir, int s, Directory *directory)
+Directory::bucket_loop_fix(Dir *start_dir, int s)
{
- if (!dir_bucket_loop_check(start_dir, directory->get_segment(s))) {
+ if (!dir_bucket_loop_check(start_dir, this->get_segment(s))) {
Warning("Dir loop exists, clearing segment %d", s);
- dir_init_segment(s, directory);
+ this->init_segment(s);
return 1;
}
return 0;
@@ -243,7 +243,7 @@ Directory::freelist_length(int s)
int free = 0;
Dir *seg = this->get_segment(s);
Dir *e = dir_from_offset(this->header->freelist[s], seg);
- if (dir_bucket_loop_fix(e, s, this)) {
+ if (this->bucket_loop_fix(e, s)) {
return (DIR_DEPTH - 1) * this->buckets;
}
while (e) {
@@ -260,7 +260,7 @@ Directory::bucket_length(Dir *b, int s)
int i = 0;
Dir *seg = this->get_segment(s);
#ifdef LOOP_CHECK_MODE
- if (dir_bucket_loop_fix(b, s, this))
+ if (this->bucket_loop_fix(b, s))
return 1;
#endif
while (e) {
@@ -296,55 +296,6 @@ Directory::check()
return 1;
}
-inline void
-unlink_from_freelist(Dir *e, int s, Directory *directory)
-{
- Dir *seg = directory->get_segment(s);
- Dir *p = dir_from_offset(dir_prev(e), seg);
- if (p) {
- dir_set_next(p, dir_next(e));
- } else {
- directory->header->freelist[s] = dir_next(e);
- }
- Dir *n = dir_from_offset(dir_next(e), seg);
- if (n) {
- dir_set_prev(n, dir_prev(e));
- }
-}
-
-inline Dir *
-dir_delete_entry(Dir *e, Dir *p, int s, Directory *directory)
-{
- Dir *seg = directory->get_segment(s);
- int no = dir_next(e);
- directory->header->dirty = 1;
- if (p) {
- unsigned int fo = directory->header->freelist[s];
- unsigned int eo = dir_to_offset(e, seg);
- dir_clear(e);
- dir_set_next(p, no);
- dir_set_next(e, fo);
- if (fo) {
- dir_set_prev(dir_from_offset(fo, seg), eo);
- }
- directory->header->freelist[s] = eo;
- } else {
- Dir *n = next_dir(e, seg);
- if (n) {
- // "Shuffle" here means that we're copying the second entry's data to
the head entry's location, and removing the second entry
- // - because the head entry can't be moved.
- ATS_PROBE3(cache_dir_shuffle, s, dir_to_offset(e, seg), dir_to_offset(n,
seg));
- dir_assign(e, n);
- dir_delete_entry(n, e, s, directory);
- return e;
- } else {
- dir_clear(e);
- return nullptr;
- }
- }
- return dir_from_offset(no, seg);
-}
-
inline void
dir_clean_bucket(Dir *b, int s, StripeSM *stripe)
{
@@ -357,7 +308,7 @@ dir_clean_bucket(Dir *b, int s, StripeSM *stripe)
#ifdef LOOP_CHECK_MODE
loop_count++;
if (loop_count > DIR_LOOP_THRESHOLD) {
- if (dir_bucket_loop_fix(b, s, vol->directory))
+ if (vol->directory.bucket_loop_fix(b, s))
return;
}
#endif
@@ -372,7 +323,7 @@ dir_clean_bucket(Dir *b, int s, StripeSM *stripe)
}
// Match cache_dir_remove arguments
ATS_PROBE7(cache_dir_remove_clean_bucket, stripe->fd, s,
dir_to_offset(e, seg), dir_offset(e), dir_approx_size(e), 0, 0);
- e = dir_delete_entry(e, p, s, &stripe->directory);
+ e = stripe->directory.delete_entry(e, p, s);
continue;
}
p = e;
@@ -462,7 +413,7 @@ freelist_pop(int s, StripeSM *stripe)
stripe->directory.header->freelist[s] = dir_next(e);
// if the freelist if bad, punt.
if (dir_offset(e)) {
- dir_init_segment(s, &stripe->directory);
+ stripe->directory.init_segment(s);
return nullptr;
}
Dir *h = dir_from_offset(stripe->directory.header->freelist[s], seg);
@@ -495,7 +446,7 @@ Directory::probe(const CacheKey *key, StripeSM *stripe, Dir
*result, Dir **last_
Dir *e = nullptr, *p = nullptr, *collision = *last_collision;
CHECK_DIR(d);
#ifdef LOOP_CHECK_MODE
- if (dir_bucket_loop_fix(dir_bucket(b, seg), s, this))
+ if (this->bucket_loop_fix(dir_bucket(b, seg), s))
return 0;
#endif
Lagain:
@@ -506,7 +457,7 @@ Lagain:
ink_assert(dir_offset(e));
// Bug: 51680. Need to check collision before checking
// dir_valid(). In case of a collision, if !dir_valid(), we
- // don't want to call dir_delete_entry.
+ // don't want to call Directory::delete_entry.
if (collision) {
if (collision == e) {
collision = nullptr;
@@ -533,7 +484,7 @@ Lagain:
ts::Metrics::Gauge::decrement(stripe->cache_vol->vol_rsb.direntries_used);
ATS_PROBE7(cache_dir_remove_invalid, stripe->fd, s, dir_to_offset(e,
seg), dir_offset(e), dir_approx_size(e),
key->slice64(0), key->slice64(1));
- e = dir_delete_entry(e, p, s, this);
+ e = this->delete_entry(e, p, s);
continue;
}
} else {
@@ -585,7 +536,7 @@ Lagain:
for (l = 1; l < DIR_DEPTH; l++) {
e = dir_bucket_row(b, l);
if (dir_is_empty(e)) {
- unlink_from_freelist(e, s, this);
+ this->unlink_from_freelist(e, s);
goto Llink;
}
}
@@ -653,7 +604,7 @@ Lagain:
#ifdef LOOP_CHECK_MODE
loop_count++;
if (loop_count > DIR_LOOP_THRESHOLD && loop_possible) {
- if (dir_bucket_loop_fix(b, s, this)) {
+ if (this->bucket_loop_fix(b, s)) {
loop_possible = false;
goto Lagain;
}
@@ -679,7 +630,7 @@ Lagain:
for (l = 1; l < DIR_DEPTH; l++) {
e = dir_bucket_row(b, l);
if (dir_is_empty(e)) {
- unlink_from_freelist(e, s, this);
+ this->unlink_from_freelist(e, s);
goto Llink;
}
}
@@ -733,7 +684,7 @@ Directory::remove(const CacheKey *key, StripeSM *stripe,
Dir *del)
#ifdef LOOP_CHECK_MODE
loop_count++;
if (loop_count > DIR_LOOP_THRESHOLD) {
- if (dir_bucket_loop_fix(dir_bucket(b, seg), s, this))
+ if (this->bucket_loop_fix(dir_bucket(b, seg), s))
return 0;
}
#endif
@@ -743,7 +694,7 @@ Directory::remove(const CacheKey *key, StripeSM *stripe,
Dir *del)
ts::Metrics::Gauge::decrement(stripe->cache_vol->vol_rsb.direntries_used);
ATS_PROBE7(cache_dir_remove, stripe->fd, s, dir_to_offset(e, seg),
offset, dir_approx_size(e), key->slice64(0),
key->slice64(1));
- dir_delete_entry(e, p, s, this);
+ this->delete_entry(e, p, s);
CHECK_DIR(d);
return 1;
}
@@ -939,7 +890,7 @@ Directory::entries_used()
sfull = 0;
for (int b = 0; b < this->buckets; b++) {
Dir *e = dir_bucket(b, seg);
- if (dir_bucket_loop_fix(e, s, this)) {
+ if (this->bucket_loop_fix(e, s)) {
sfull = 0;
break;
}
@@ -1068,7 +1019,7 @@ Lrestart:
/* Don't sync the directory to disk if its not dirty. Syncing the
clean directory to disk is also the cause of INKqa07151. Increasing
the serial number causes the cache to recover more data than
necessary.
- The dirty bit it set in dir_insert, overwrite and dir_delete_entry
+ The dirty bit is set in dir_insert, overwrite and
Directory::delete_entry
*/
if (!stripe->directory.header->dirty) {
Dbg(dbg_ctl_cache_dir_sync, "Dir %s not dirty",
stripe->hash_text.get());
diff --git a/src/iocore/cache/CacheVC.cc b/src/iocore/cache/CacheVC.cc
index 54a7abc739..821dce534a 100644
--- a/src/iocore/cache/CacheVC.cc
+++ b/src/iocore/cache/CacheVC.cc
@@ -111,9 +111,6 @@ next_in_map(Stripe *stripe, char *vol_map, off_t offset)
return new_off + start_offset;
}
-// Function in CacheDir.cc that we need for make_vol_map().
-int dir_bucket_loop_fix(Dir *start_dir, int s, Directory *directory);
-
// TODO: If we used a bit vector, we could make a smaller map structure.
// TODO: If we saved a high water mark we could have a smaller buf, and avoid
searching it
// when we are asked about the highest interesting offset.
@@ -137,7 +134,7 @@ make_vol_map(Stripe *stripe)
Dir *seg = stripe->directory.get_segment(s);
for (int b = 0; b < stripe->directory.buckets; b++) {
Dir *e = dir_bucket(b, seg);
- if (dir_bucket_loop_fix(e, s, &stripe->directory)) {
+ if (stripe->directory.bucket_loop_fix(e, s)) {
break;
}
while (e) {
diff --git a/src/iocore/cache/P_CacheDir.h b/src/iocore/cache/P_CacheDir.h
index fbd2f0b25b..0a9150f483 100644
--- a/src/iocore/cache/P_CacheDir.h
+++ b/src/iocore/cache/P_CacheDir.h
@@ -30,6 +30,8 @@
#include "tscore/Version.h"
#include "tscore/hugepages.h"
+#include <ts/ats_probe.h>
+
#include <cstdint>
#include <ctime>
@@ -286,7 +288,9 @@ struct StripeHeaderFooter {
uint16_t freelist[1];
};
-struct Directory {
+class Directory
+{
+public:
char *raw_dir{nullptr};
Dir *dir{};
StripeHeaderFooter *header{};
@@ -316,19 +320,13 @@ struct Directory {
int bucket_length(Dir *b, int s);
int freelist_length(int s);
void clean_segment(int s, StripeSM *stripe);
-};
-
-inline int
-Directory::entries() const
-{
- return this->buckets * DIR_DEPTH * this->segments;
-}
+ void init_segment(int s);
+ int bucket_loop_fix(Dir *start_dir, int s);
+ Dir *delete_entry(Dir *e, Dir *p, int s);
-inline Dir *
-Directory::get_segment(int s) const
-{
- return reinterpret_cast<Dir *>((reinterpret_cast<char *>(this->dir)) + (s *
this->buckets) * DIR_DEPTH * SIZEOF_DIR);
-}
+private:
+ void unlink_from_freelist(Dir *e, int s);
+};
// Global Functions
@@ -394,3 +392,64 @@ dir_bucket_row(Dir *b, int64_t i)
{
return dir_in_seg(b, i);
}
+
+inline int
+Directory::entries() const
+{
+ return this->buckets * DIR_DEPTH * this->segments;
+}
+
+inline Dir *
+Directory::get_segment(int s) const
+{
+ return reinterpret_cast<Dir *>((reinterpret_cast<char *>(this->dir)) + (s *
this->buckets) * DIR_DEPTH * SIZEOF_DIR);
+}
+
+inline void
+Directory::unlink_from_freelist(Dir *e, int s)
+{
+ Dir *seg = this->get_segment(s);
+ Dir *p = dir_from_offset(dir_prev(e), seg);
+ if (p) {
+ dir_set_next(p, dir_next(e));
+ } else {
+ this->header->freelist[s] = dir_next(e);
+ }
+ Dir *n = dir_from_offset(dir_next(e), seg);
+ if (n) {
+ dir_set_prev(n, dir_prev(e));
+ }
+}
+
+inline Dir *
+Directory::delete_entry(Dir *e, Dir *p, int s)
+{
+ Dir *seg = this->get_segment(s);
+ int no = dir_next(e);
+ this->header->dirty = 1;
+ if (p) {
+ unsigned int fo = this->header->freelist[s];
+ unsigned int eo = dir_to_offset(e, seg);
+ dir_clear(e);
+ dir_set_next(p, no);
+ dir_set_next(e, fo);
+ if (fo) {
+ dir_set_prev(dir_from_offset(fo, seg), eo);
+ }
+ this->header->freelist[s] = eo;
+ } else {
+ Dir *n = next_dir(e, seg);
+ if (n) {
+ // "Shuffle" here means that we're copying the second entry's data to
the head entry's location, and removing the second entry
+ // - because the head entry can't be moved.
+ ATS_PROBE3(cache_dir_shuffle, s, dir_to_offset(e, seg), dir_to_offset(n,
seg));
+ dir_assign(e, n);
+ this->delete_entry(n, e, s);
+ return e;
+ } else {
+ dir_clear(e);
+ return nullptr;
+ }
+ }
+ return dir_from_offset(no, seg);
+}