#!/usr/bin/env python3
################################################################################
#
# Copyright (c) 2020, 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: 2020/09/18 $
#
# = Description
#
# Collect information about workspaces and output them in csv format:
# name,owner,last_update_date,last_access_date,nb_synced_files
#
# = Usage
#
# clientStats.py a_checkpoint|a_checkpoint.gz > clientStats.out
# Example of queries:
# - list of clients sorted on last access date:
# sort -t"," -k 3 clientStats.out
# - list of clients sorted in reverse order on number of synced files:
# sort -t"," -k 5 -n -r clientStats.out
#
################################################################################
from __future__ import print_function
import re
import time
import sys
import gzip
import mimetypes
import os
import math
def cmdUsage():
sys.exit("Usage: clientStats.py a_checkpoint|a_checkpoint.gz")
def main():
if len(sys.argv) < 2:
cmdUsage()
clients = {}
filename = sys.argv[1]
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 @.*?@ @.*?@ @.*?@ @.*?@ @(.*?)@ ([0-9]*) ([0-9]*) [0-9]* @.*')
haveRE = re.compile(b'@pv@ [0-9]* @db.have@ @//(.*?)/.*')
stopRE = re.compile(b'.* @db.label@ .*')
print("Processing, it may take several hours...\n", end='', file=sys.stderr)
sys.stderr.flush()
for line in ckp:
match = clientSpecRE.search(line)
if match:
client = match.group(1)
if client not in clients:
clients[client] = {}
clients[client]["have"] = 0
clients[client]["owner"] = match.group(2)
clients[client]["update"] = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(float(match.group(3))))
clients[client]["access"] = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(float(match.group(4))))
else:
match = haveRE.search(line)
if match:
client = match.group(1)
if client not in clients:
clients[client] = {}
clients[client]["have"] = 0
clients[client]["owner"] = b"unknown"
clients[client]["update"] = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(0.0))
clients[client]["access"] = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(0.0))
clients[client]["have"] += 1
else:
if stopRE.search(line):
# stop, no need to look further
break
ckp.close()
# In order to output bytes to stdout, sys.stdout.buffer must be used in Python 3
# but this is not compatible with Python 2, so to make it compatible:
output = getattr(sys.stdout, 'buffer', sys.stdout)
for (key, value) in clients.items():
output.write(key + b"," + value["owner"] + b",")
sys.stdout.write(value["update"] + "," + value["access"] + "," + str(value["have"]) + "\n")
sys.stdout.flush()
if __name__ == '__main__':
main()