Logo Search packages:      
Sourcecode: tardy version File versions  Download package

progress.cc

//
//    tardy - a tar post-processor
//    Copyright (C) 2002 Peter Miller;
//    All rights reserved.
//
//    This program is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
//
// MANIFEST: functions to manipulate progresss
//

#pragma implementation "filenamelist_filter_progress"

#include <ac/stdio.h>
#include <ac/stddef.h>
#include <ac/unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <filenamelist/filter/progress.h>


00034 filenamelist_filter_progress::~filenamelist_filter_progress()
{
}


00039 filenamelist_filter_progress::filenamelist_filter_progress(filenamelist *arg) :
      filenamelist_filter(arg),
      state(state_begin),
      position(0),
      start_time(0),
      next_time(0),
      size_total(0),
      size_position(0),
      spinner_state(0),
      show(isatty(2))
{
}


static char *
format_size(long long x)
{
      static char buffer[10];
      if (x < 10000)
      {
            snprintf(buffer, sizeof(buffer), "%4d ", (int)x);
            return buffer;
      }
      x >>= 10;
      if (x < 10000)
      {
            snprintf(buffer, sizeof(buffer), "%4dK", (int)x);
            return buffer;
      }
      x >>= 10;
      if (x < 10000)
      {
            snprintf(buffer, sizeof(buffer), "%4dM", (int)x);
            return buffer;
      }
      x >>= 10;
      if (x < 10000)
      {
            snprintf(buffer, sizeof(buffer), "%4dG", (int)x);
            return buffer;
      }
      x >>= 10;
      if (x < 10000)
      {
            snprintf(buffer, sizeof(buffer), "%4dT", (int)x);
            return buffer;
      }
      x >>= 10;
      if (x < 10000)
      {
            snprintf(buffer, sizeof(buffer), "%4dP", (int)x);
            return buffer;
      }
      x >>= 10;
      snprintf(buffer, sizeof(buffer), "%4ldE", (long)x);
      return buffer;
}


char
00099 filenamelist_filter_progress::spinner()
{
      return ("|/-\\"[spinner_state++ & 3]);
}


void
00106 filenamelist_filter_progress::show_start_status()
{
      if (!show)
            return;
      time_t now;
      time(&now);
      if (now < next_time)
            return;
      next_time = now + 1;

      char buffer[80];
      strcpy(buffer, "\rReading file list: ");
      char *bp = buffer + strlen(buffer);
      snprintf(bp, buffer + sizeof(buffer) - bp, "%s files, ",
            format_size(list.size()));
      bp += strlen(bp);
      snprintf(bp, buffer + sizeof(buffer) - bp, "%sB ",
            format_size(size_total));
      bp += strlen(bp);
      snprintf(bp, buffer + sizeof(buffer) - bp, "%c ", spinner());
      ::write(2, buffer, strlen(buffer));
}


static char *
format_time(long x)
{
      static char buffer[20];
      if (x < 60 * 60)
      {
            snprintf(buffer, sizeof(buffer), "%2dm%02ds",
                  (int)(x / 60), (int)(x % 60));
            return buffer;
      }
      x = (x + 30) / 60;
      if (x < 24 * 60)
      {
            snprintf(buffer, sizeof(buffer), "%2dh%02dm",
                  (int)(x / 60), (int)(x % 60));
            return buffer;
      }
      x = (x + 30) / 60;
      if (x < 100 * 24)
      {
            snprintf(buffer, sizeof(buffer), "%2dd%02dh",
                  (int)(x / 24), (int)(x % 24));
            return buffer;
      }
      return "forever";
}


void
00159 filenamelist_filter_progress::show_middle_status()
{
      if (!show)
            return;
      time_t now;
      time(&now);
      if (now < next_time)
            return;
      next_time = now + 1;

      char buffer[80];
      char *bp = buffer;
      *bp++ = '\r';

      snprintf(bp, buffer + sizeof(buffer) - bp, "%s of ",
            format_size(position));
      bp += strlen(bp);
      snprintf(bp, buffer + sizeof(buffer) - bp, "%s files, ",
            format_size(list.size()));
      bp += strlen(bp);

      snprintf(bp, buffer + sizeof(buffer) - bp, "%sB of ",
            format_size(size_position));
      bp += strlen(bp);
      snprintf(bp, buffer + sizeof(buffer) - bp, "%sB, ",
            format_size(size_total));
      bp += strlen(bp);

      time_t elapsed = now - start_time;
      if (elapsed > 5 && size_total)
      {
          long long rate = size_position / elapsed;
          snprintf(bp, buffer + sizeof(buffer) - bp, "%sB/sec, ",
            format_size(rate));
          bp += strlen(bp);

          double frac = (double)size_position / (double)size_total;
          time_t total_time = time_t(elapsed / frac);
          time_t remaining_time = total_time - elapsed;
          snprintf(bp, buffer + sizeof(buffer) - bp, "ETA %s ",
            format_time(remaining_time));
          bp += strlen(bp);
      }

      snprintf(bp, buffer + sizeof(buffer) - bp, "%c ", spinner());
      ::write(2, buffer, strlen(buffer));
}


void
00209 filenamelist_filter_progress::show_end_status()
{
      if (!show)
            return;
      time_t now;
      time(&now);

      char buffer[80];
      char *bp = buffer;
      *bp++ = '\r';

      snprintf(bp, buffer + sizeof(buffer) - bp, "%s files, ",
            format_size(list.size()));
      bp += strlen(bp);

      snprintf(bp, buffer + sizeof(buffer) - bp, "%sB, ",
            format_size(size_total));
      bp += strlen(bp);

      time_t elapsed = now - start_time;
      if (elapsed < 1)
            elapsed = 1;
      long long rate = size_position / elapsed;
      snprintf(bp, buffer + sizeof(buffer) - bp, "%sB/sec, ",
          format_size(rate));
      bp += strlen(bp);

      snprintf(bp, buffer + sizeof(buffer) - bp, "%s     ",
          format_time(elapsed));
      bp += strlen(bp);
      while (bp < buffer + sizeof(buffer) - 1)
          *bp++ = ' ';
      *bp++ = '\n';

      ::write(2, buffer, sizeof(buffer));
}


bool
00248 filenamelist_filter_progress::read_one_line(rcstring &result)
{
      switch (state)
      {
      case state_begin:
            {
                rcstring temp;
                while (read_one_deeper(temp))
                {
                  show_start_status();
                  struct stat st;
                  if (lstat(temp.to_c_string(), &st))
                        memset(&st, 0, sizeof(st));
                  long size = S_ISREG(st.st_mode) ? st.st_size : 0;
                  // round up
                  size = ((size + 511) & ~511) + 512;
                  list.push_back(item_t(temp, size));
                  size_total += size;
                }
                state = state_middle;
                time(&start_time);
            }
            // fall through...
      
      case state_middle:
            if (position < list.size())
            {
                  show_middle_status();
                  item_t item = list[position++];
                  result = item.name;
                  size_position += item.size;
                  return true;
            }
            show_end_status();
            state = state_end;
            // fall through...

      case state_end:
            break;
      }
      return false;
}

Generated by  Doxygen 1.6.0   Back to index