########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Server/Commands/Log/View.py,v 1.7 2004/02/01 03:09:25 jkloth Exp $
"""
4ss_manager log view command

Copyright 2003 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

__doc__ = """View the logs"""


def Run(options, args):
    import time, sys, os
    from Ft.Server.Server.Commands.CommandUtil import GetRepository

    bytes = None
    if options.has_key('bytes'):
        bytes = int(options['bytes'])

    lines = None
    if options.has_key('lines'):
        lines = int(options['lines'])

    if bytes is None and lines is None:
        # default is 10 lines
        lines = 10

    interval = float(options.get('sleep-interval', 1.0))

    username, password, properties, repo = \
              GetRepository(options, '4ss_manager.log.view')
    repo.txRollback()

    f = open(properties['LogFile'], 'r')
    fd = f.fileno()
    filesize = os.fstat(fd)[6]

    if bytes is not None:
        # Display the last N bytes
        try:
            f.seek(filesize - bytes)
        except IOError:
            filesize = 0
        else:
            sys.stdout.write(f.read(bytes))
    else:
        # Display the last N lines
        avg_chars_per_line = 75
        while 1:
            pos = filesize - (avg_chars_per_line * lines)
            try:
                f.seek(pos)
            except IOError:
                filesize = 0
                break

            buffer = f.read()
            if buffer.count('\n') >= lines:
                split = buffer.split('\n')
                sys.stdout.write('\n'.join(split[-lines:]))
                break

            # The lines are bigger than we thought.  Increase line length
            # and try again.
            avg_chars_per_line *= 1.3

    # Tail file forever, or until killed.
    try:
        while 1:
            st_size = os.fstat(fd)[6]
            if st_size == filesize:
                time.sleep(interval)
                continue

            if st_size < filesize:
                sys.stderr.write("file truncated\n")
                f.seek(st_size)
            else:
                sys.stdout.write(f.read(st_size - filesize))

            filesize = st_size
    except KeyboardInterrupt:
        f.close()

    return


def Register():
    from Ft.Lib.CommandLine import Options, Command, Arguments

    options = [
        Options.Option('c', 'bytes=N',
                       'output the last N bytes'),
        Options.Option('n', 'lines=N',
                       'output the last N lines, instead of the last 10'),
        Options.Option('s', 'sleep-interval=S',
                       'sleep for approximately S seconds (default 1.0)'
                       ' between iterations'),
        ]

    cmd = Command.Command('view',
                          'View a 4SS Log',
                          '',
                          __doc__,
                          function = Run,
                          options = Options.Options(options),
                          fileName = __file__,
                          )
    return cmd


