orphanedMetadataDetection.py #1

  • //
  • guest/
  • perforce_software/
  • admin_toolkit/
  • orphanedMetadataDetection.py
  • View
  • Commits
  • Open Download .zip Download (6 KB)
#!/usr/bin/env python3

################################################################################
#
# Copyright (c) 2019, Perforce Software, Inc.  All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# = Date
#   
#   $Date: 2019/10/14 $
#
# = Description
#
#   Parse a checkpoint for database records without a corresponding
#   db.domain record
#   Orphaned records are written in journal patch which can be replay
#   on the Helix server to remove this unnecessary data.
#
# = Usage
# 
#   orphanedMetadataDetection.py a_checkpoint|a_checkpoint.gz
#
################################################################################

from __future__ import print_function
import re
import sys
import os
import gzip
import mimetypes

def cmdUsage():
    sys.exit("Usage: orphanedMetadataDetection.py a_checkpoint|a_checkpoint.gz")

def main():
    if len(sys.argv) < 2:
       cmdUsage()
    clients = []
    labels = []
    lastTable = ""
    filename = sys.argv[1]
    # for Python 2 compatibility purpose:
    stderr = getattr(sys.stderr, 'buffer', sys.stderr)
    if mimetypes.guess_type(filename)[1] == 'gzip':
       ckp = gzip.open(filename, "rb")
    else:
       ckp = open(filename, "rb")
    clientSpecRE = re.compile(b'@pv@ [0-9]* @db.domain@ @(.*?)@ 99 @.*')
    haveRE = re.compile(b'@pv@ [0-9]* @db.have.*?@ @//(.*?)/.*')
    haverpRE = re.compile(b'@pv@ [0-9]* @db.have.rp@ @//(.*?)/.*')
    workingRE = re.compile(b'@pv@ [0-9]* @db.working@ @//(.*?)/.*')
    locksRE = re.compile(b'@pv@ [0-9]* @db.locks@ @//.*?@ @(.*?)@ .*')
    labelSpecRE = re.compile(b'@pv@ [0-9]* @db.domain@ @(.*?)@ .*')
    labelRE = re.compile(b'@pv@ [0-9]* @db.label@ @(.*?)@.*')
    tableRE = re.compile(b'@pv@ [0-9]* @(.*?)@ .*')
    jnlPatchName = str.encode(os.getcwd()) + b"/jnl.patch.gz"
    if os.path.isfile(jnlPatchName):
       os.remove(jnlPatchName)
    jnlPatch = None
    for line in ckp:
        match = tableRE.search(line)
        if match:
           table = match.group(1)
           if table == b"db.change":
              # stop, no need to look further
              break
           if not table == lastTable:
              stderr.write(b"Processing " + table + b"...\n")
              stderr.flush()
              lastTable = table
        match = clientSpecRE.search(line)
        if match:
           client = match.group(1)
           if client not in clients:
              clients.append(client)
        else:
          match = haveRE.search(line)
          if match:
             client = match.group(1)
             if client not in clients:
                if not jnlPatch:
                   jnlPatch = gzip.open(jnlPatchName, "wb")
                jnlPatch.write(line.replace(b"^@pv@", b"@dv@"))
          else:
            match = haverpRE.search(line)
            if match:
               client = match.group(1)
               if client not in clients:
                  if not jnlPatch:
                     jnlPatch = gzip.open(jnlPatchName, "wb")
                  jnlPatch.write(line.replace(b"^@pv@", b"@dv@"))
            else:
              match = workingRE.search(line)
              if match:
                 client = match.group(1)
                 if client not in clients:
                    if not jnlPatch:
                       jnlPatch = gzip.open(jnlPatchName, "wb")
                    jnlPatch.write(line.replace(b"^@pv@", b"@dv@"))
              else:
                match = locksRE.search(line)
                if match:
                   client = match.group(1)
                   if client not in clients:
                      if not jnlPatch:
                         jnlPatch = gzip.open(jnlPatchName, "wb")
                      jnlPatch.write(line.replace(b"^@pv@", b"@dv@"))
                else:
                  match = labelSpecRE.search(line)
                  if match:
                     label = match.group(1)
                     if label not in labels:
                        labels.append(label)
                  else:
                     match = labelRE.search(line)
                     if match:
                        label = match.group(1)
                        if label not in labels:
                           if not jnlPatch:
                              jnlPatch = gzip.open(jnlPatchName, "wb")
                           jnlPatch.write(line.replace(b"^@pv@", b"@dv@"))
    ckp.close()
    if jnlPatch:
       jnlPatch.close()
       stderr.write(b"Found some database records without a corresponding db.domain record\n")
       stderr.write(b"Check and replay " + jnlPatchName + b" to remove these records\n")
    else:
       stderr.write(b"All the database records have a corresponding db.domain record\n")

if __name__ == '__main__':
   main()
# Change User Description Committed
#1 26123 Pascal Soccard New script to detect database records without a corresponding
db.domain record