Whamcloud - gitweb
EX-8130 lipe: Add func for working with paths
authorVitaliy Kuznetsov <vkuznetsov@ddn.com>
Mon, 19 Feb 2024 19:02:44 +0000 (20:02 +0100)
committerAndreas Dilger <adilger@whamcloud.com>
Sat, 9 Mar 2024 07:42:43 +0000 (07:42 +0000)
This patсh adds directory path processing helper functions
that will be used later to collect directory size statistics.

These functions set the stage for working on increasing the
size counters for each directory, along the entire chain in
the file or directory path.

Test-Parameters: trivial
Signed-off-by: Vitaliy Kuznetsov <vkuznetsov@ddn.com>
Change-Id: I6e7302e9771dce2933c6730a1117fec3bc2b0fda
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/53961
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Alexandre Ioffe <aioffe@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lipe/src/lipe_scan3/ls3_dir_stats.c

index 000f001..9725b1a 100644 (file)
@@ -321,6 +321,129 @@ static void ls3_stats_init_first_dir(char *path)
        free(tmp_path);
 }
 
+/* ls3_get_trimmed_path_and_depth - Trims the desired path.
+ * For example, when we have a “path” filter, it contains a path,
+ * but this does not mean that the resulting path from the attribute
+ * will not contain this path, so we need to trim the path from the
+ * filter and leave only the final path.
+ *
+ * ex: (/path/from/filter/dir1/dir11/dir111/file -> dir1/dir11/dir111/file)
+ */
+static void
+       ls3_stats_get_trimmed_path_and_depth(struct ls3_object_attrs *loa_all,
+                                            char *path, char **trimmed_path,
+                                            int *depth)
+{
+       char *sub_path = NULL;
+       const char *original_sub_path;
+       const char *last_slash;
+       const char *last_sub_path_slash = NULL;
+       size_t offset_from_start;
+       int count = 0;
+
+       if (!path || !dir_stats->lsdg_start_path)
+               LS3_FATAL("path name or start path is NULL\n");
+
+       /* Find the last slash in dir_stats->lsdg_start_path */
+       last_slash = strrchr(dir_stats->lsdg_start_path, '/');
+
+       /* if there is no slash, then simply cut it off to the beginning
+        * of dir_stats->lsdg_start_path
+        */
+       if (!last_slash) {
+               sub_path = path;
+       } else {
+               offset_from_start = last_slash - dir_stats->lsdg_start_path + 1;
+               sub_path = path + offset_from_start;
+       }
+
+       original_sub_path = sub_path;
+
+       /* Calculate the depth and at the same time look
+        * for the last slash in sub_path (for subsequent cutting)
+        */
+       while (*sub_path) {
+               if (*sub_path == '/') {
+                       count++;
+                       last_sub_path_slash = sub_path;
+               }
+               sub_path++;
+       }
+
+       if ((loa_all->loa_mode & S_IFDIR) &&
+           (last_sub_path_slash != sub_path + strlen(sub_path) - 1))
+               count++;
+       else if (last_sub_path_slash == sub_path + strlen(sub_path) - 1)
+               count--;
+
+       *depth = (count == 0) ? 0 : count;
+
+       /* Trim the path to the last slash, if it exists */
+       if (loa_all->loa_mode & S_IFDIR)
+               *trimmed_path = xstrdup(original_sub_path);
+       else if (last_sub_path_slash)
+               *trimmed_path = xstrndup(original_sub_path,
+                                        last_sub_path_slash -
+                                        original_sub_path);
+       else
+               *trimmed_path = xstrdup(original_sub_path);
+}
+
+/* ls3_stats_dir_split_path - Splits a path into an array of names.
+ * Ex: dir1/dir11/dir111/dir1111/file -> ["dir1", "dir11", "dir111"]
+ * This is necessary in order to track the entire chain of pointers
+ * and increase the size counters in the future, but not more than
+ * the maximum specified depth.
+ */
+static char** ls3_stats_dir_split_path(const char *path, int *count)
+{
+       const char *tmp_patch = path;
+       int max_depth = dir_stats->lsdg_max_depth;
+       int dir_count = 0;
+       char **result;
+       int i;
+
+       *count = 0;
+       if (!path || max_depth <= 0)
+               return NULL;
+
+       if (strlen(path) == 0)
+               return NULL;
+
+
+       while (*tmp_patch) {
+               if (*tmp_patch == '/')
+                       dir_count++;
+
+               tmp_patch++;
+       }
+
+       tmp_patch = path;       /* pointer reset */
+       dir_count++;
+
+       if (dir_count < max_depth)
+               max_depth = dir_count;
+
+       result = (char**)xcalloc(max_depth, sizeof(char*));
+       for (i = 0; i < max_depth; i++) {
+               const char *next_slash = strchr(tmp_patch, '/');
+               size_t length = next_slash ? (next_slash - tmp_patch) :
+                                            (path + strlen(path) - tmp_patch);
+
+               result[i] = (char*) xcalloc(length + 1, sizeof(char));
+               strncpy(result[i], tmp_patch, length);
+               result[i][length] = '\0';
+
+               if (!next_slash)
+                       break;
+
+               tmp_patch = next_slash + 1;
+       }
+
+       *count = max_depth;
+       return result;
+}
+
 void ls3_stats_dir_init(void)
 {
        int rc;