"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/tools/gfind_missing_files/gfid_to_path.py" (16 Sep 2020, 4569 Bytes) of package /linux/misc/glusterfs-8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "gfid_to_path.py" see the Fossies "Dox" file reference documentation.

    1 #!/usr/bin/python3
    2 
    3 # Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com/>
    4 # This file is part of GlusterFS.
    5 #
    6 # This file is licensed to you under your choice of the GNU Lesser
    7 # General Public License, version 3 or any later version (LGPLv3 or
    8 # later), or the GNU General Public License, version 2 (GPLv2), in all
    9 # cases as published by the Free Software Foundation.
   10 
   11 import sys
   12 import os
   13 import xattr
   14 import uuid
   15 import re
   16 import errno
   17 
   18 CHANGELOG_SEARCH_MAX_TRY = 31
   19 DEC_CTIME_START = 5
   20 ROOT_GFID = "00000000-0000-0000-0000-000000000001"
   21 MAX_NUM_CHANGELOGS_TRY = 2
   22 
   23 
   24 def output_not_found(gfid):
   25     # Write GFID to stderr
   26     sys.stderr.write("%s\n" % gfid)
   27 
   28 
   29 def output_success(path):
   30     # Write converted Path to Stdout
   31     sys.stdout.write("%s\n" % path)
   32 
   33 
   34 def full_dir_path(gfid):
   35     out_path = ""
   36     while True:
   37         path = os.path.join(".glusterfs", gfid[0:2], gfid[2:4], gfid)
   38         path_readlink = os.readlink(path)
   39         pgfid = os.path.dirname(path_readlink)
   40         out_path = os.path.join(os.path.basename(path_readlink), out_path)
   41         if pgfid == "../../00/00/%s" % ROOT_GFID:
   42             out_path = os.path.join("./", out_path)
   43             break
   44         gfid = os.path.basename(pgfid)
   45     return out_path
   46 
   47 
   48 def find_path_from_changelog(fd, gfid):
   49     """
   50     In given Changelog File, finds using following pattern
   51     <T><GFID>\x00<TYPE>\x00<MODE>\x00<UID>\x00<GID>\x00<PARGFID>/<BASENAME>
   52     Pattern search finds PARGFID and BASENAME, Convert PARGFID to Path
   53     Using readlink and add basename to form Full path.
   54     """
   55     content = fd.read()
   56 
   57     pattern = "E%s" % gfid
   58     pattern += "\x00(3|23)\x00\d+\x00\d+\x00\d+\x00([^\x00]+)/([^\x00]+)"
   59     pat = re.compile(pattern)
   60     match = pat.search(content)
   61 
   62     if match:
   63         pgfid = match.group(2)
   64         basename = match.group(3)
   65         if pgfid == ROOT_GFID:
   66             return os.path.join("./", basename)
   67         else:
   68             full_path_parent = full_dir_path(pgfid)
   69             if full_path_parent:
   70                 return os.path.join(full_path_parent, basename)
   71 
   72     return None
   73 
   74 
   75 def gfid_to_path(gfid):
   76     """
   77     Try readlink, if it is directory it succeeds.
   78     Get ctime of the GFID file, Decrement by 5 sec
   79     Search for Changelog filename, Since Changelog file generated
   80     every 15 sec, Search and get immediate next Changelog after the file
   81     Creation. Get the Path by searching in Changelog file.
   82     Get the resultant file's GFID and Compare with the input, If these
   83     GFIDs are different then Some thing is changed(May be Rename)
   84     """
   85     gfid = gfid.strip()
   86     gpath = os.path.join(".glusterfs", gfid[0:2], gfid[2:4], gfid)
   87     try:
   88         output_success(full_dir_path(gfid))
   89         return
   90     except OSError:
   91         # Not an SymLink
   92         pass
   93 
   94     try:
   95         ctime = int(os.stat(gpath).st_ctime)
   96         ctime -= DEC_CTIME_START
   97     except (OSError, IOError):
   98         output_not_found(gfid)
   99         return
  100 
  101     path = None
  102     found_changelog = False
  103     changelog_parse_try = 0
  104     for i in range(CHANGELOG_SEARCH_MAX_TRY):
  105         cl = os.path.join(".glusterfs/changelogs", "CHANGELOG.%s" % ctime)
  106 
  107         try:
  108             with open(cl, "rb") as f:
  109                 changelog_parse_try += 1
  110                 found_changelog = True
  111                 path = find_path_from_changelog(f, gfid)
  112                 if not path and changelog_parse_try < MAX_NUM_CHANGELOGS_TRY:
  113                     ctime += 1
  114                     continue
  115             break
  116         except (IOError, OSError) as e:
  117             if e.errno == errno.ENOENT:
  118                 ctime += 1
  119             else:
  120                 break
  121 
  122     if not found_changelog:
  123         output_not_found(gfid)
  124         return
  125 
  126     if not path:
  127         output_not_found(gfid)
  128         return
  129     gfid1 = str(uuid.UUID(bytes=xattr.get(path, "trusted.gfid")))
  130     if gfid != gfid1:
  131         output_not_found(gfid)
  132         return
  133 
  134     output_success(path)
  135 
  136 
  137 def main():
  138     num_arguments = 3
  139     if not sys.stdin.isatty():
  140         num_arguments = 2
  141 
  142     if len(sys.argv) != num_arguments:
  143         sys.stderr.write("Invalid arguments\nUsage: "
  144                          "%s <BRICK_PATH> <GFID_FILE>\n" % sys.argv[0])
  145         sys.exit(1)
  146 
  147     path = sys.argv[1]
  148 
  149     if sys.stdin.isatty():
  150         gfid_list = os.path.abspath(sys.argv[2])
  151         os.chdir(path)
  152         with open(gfid_list) as f:
  153             for gfid in f:
  154                 gfid_to_path(gfid)
  155     else:
  156         os.chdir(path)
  157         for gfid in sys.stdin:
  158             gfid_to_path(gfid)
  159 
  160 
  161 if __name__ == "__main__":
  162     main()