Annotation of embedaddon/rsync/progress.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Routines to output progress information during a file transfer.
        !             3:  *
        !             4:  * Copyright (C) 1996-2000 Andrew Tridgell
        !             5:  * Copyright (C) 1996 Paul Mackerras
        !             6:  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
        !             7:  * Copyright (C) 2003-2009 Wayne Davison
        !             8:  *
        !             9:  * This program is free software; you can redistribute it and/or modify
        !            10:  * it under the terms of the GNU General Public License as published by
        !            11:  * the Free Software Foundation; either version 3 of the License, or
        !            12:  * (at your option) any later version.
        !            13:  *
        !            14:  * This program is distributed in the hope that it will be useful,
        !            15:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            17:  * GNU General Public License for more details.
        !            18:  *
        !            19:  * You should have received a copy of the GNU General Public License along
        !            20:  * with this program; if not, visit the http://fsf.org website.
        !            21:  */
        !            22: 
        !            23: #include "rsync.h"
        !            24: 
        !            25: extern int am_server;
        !            26: extern int need_unsorted_flist;
        !            27: extern struct stats stats;
        !            28: extern struct file_list *cur_flist;
        !            29: 
        !            30: #define PROGRESS_HISTORY_SECS 5
        !            31: 
        !            32: #ifdef GETPGRP_VOID
        !            33: #define GETPGRP_ARG
        !            34: #else
        !            35: #define GETPGRP_ARG 0
        !            36: #endif
        !            37: 
        !            38: struct progress_history {
        !            39:        struct timeval time;
        !            40:        OFF_T ofs;
        !            41: };
        !            42: 
        !            43: int progress_is_active = 0;
        !            44: 
        !            45: static struct progress_history ph_start;
        !            46: static struct progress_history ph_list[PROGRESS_HISTORY_SECS];
        !            47: static int newest_hpos, oldest_hpos;
        !            48: static int current_file_index;
        !            49: 
        !            50: static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
        !            51: {
        !            52:        return (t2->tv_sec - t1->tv_sec) * 1000L
        !            53:             + (t2->tv_usec - t1->tv_usec) / 1000;
        !            54: }
        !            55: 
        !            56: 
        !            57: /**
        !            58:  * @param ofs Current position in file
        !            59:  * @param size Total size of file
        !            60:  * @param is_last True if this is the last time progress will be
        !            61:  * printed for this file, so we should output a newline.  (Not
        !            62:  * necessarily the same as all bytes being received.)
        !            63:  **/
        !            64: static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
        !            65:                            int is_last)
        !            66: {
        !            67:        char rembuf[64], eol[128];
        !            68:        const char *units;
        !            69:        int pct = ofs == size ? 100 : (int) (100.0 * ofs / size);
        !            70:        unsigned long diff;
        !            71:        double rate, remain;
        !            72: 
        !            73:        if (is_last) {
        !            74:                /* Compute stats based on the starting info. */
        !            75:                if (!ph_start.time.tv_sec
        !            76:                    || !(diff = msdiff(&ph_start.time, now)))
        !            77:                        diff = 1;
        !            78:                rate = (double) (ofs - ph_start.ofs) * 1000.0 / diff / 1024.0;
        !            79:                /* Switch to total time taken for our last update. */
        !            80:                remain = (double) diff / 1000.0;
        !            81:        } else {
        !            82:                /* Compute stats based on recent progress. */
        !            83:                if (!(diff = msdiff(&ph_list[oldest_hpos].time, now)))
        !            84:                        diff = 1;
        !            85:                rate = (double) (ofs - ph_list[oldest_hpos].ofs) * 1000.0
        !            86:                     / diff / 1024.0;
        !            87:                remain = rate ? (double) (size - ofs) / rate / 1000.0 : 0.0;
        !            88:        }
        !            89: 
        !            90:        if (rate > 1024*1024) {
        !            91:                rate /= 1024.0 * 1024.0;
        !            92:                units = "GB/s";
        !            93:        } else if (rate > 1024) {
        !            94:                rate /= 1024.0;
        !            95:                units = "MB/s";
        !            96:        } else {
        !            97:                units = "kB/s";
        !            98:        }
        !            99: 
        !           100:        if (remain < 0)
        !           101:                strlcpy(rembuf, "  ??:??:??", sizeof rembuf);
        !           102:        else {
        !           103:                snprintf(rembuf, sizeof rembuf, "%4d:%02d:%02d",
        !           104:                         (int) (remain / 3600.0),
        !           105:                         (int) (remain / 60.0) % 60,
        !           106:                         (int) remain % 60);
        !           107:        }
        !           108: 
        !           109:        if (is_last) {
        !           110:                snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
        !           111:                        stats.num_transferred_files,
        !           112:                        stats.num_files - current_file_index - 1,
        !           113:                        stats.num_files);
        !           114:        } else
        !           115:                strlcpy(eol, "\r", sizeof eol);
        !           116:        progress_is_active = 0;
        !           117:        rprintf(FCLIENT, "%12s %3d%% %7.2f%s %s%s",
        !           118:                human_num(ofs), pct, rate, units, rembuf, eol);
        !           119:        if (!is_last)
        !           120:                progress_is_active = 1;
        !           121: }
        !           122: 
        !           123: void set_current_file_index(struct file_struct *file, int ndx)
        !           124: {
        !           125:        if (need_unsorted_flist)
        !           126:                current_file_index = flist_find(cur_flist, file) + cur_flist->ndx_start;
        !           127:        else
        !           128:                current_file_index = ndx;
        !           129:        current_file_index -= cur_flist->flist_num;
        !           130: }
        !           131: 
        !           132: void end_progress(OFF_T size)
        !           133: {
        !           134:        if (!am_server) {
        !           135:                struct timeval now;
        !           136:                gettimeofday(&now, NULL);
        !           137:                rprint_progress(size, size, &now, True);
        !           138:        }
        !           139:        memset(&ph_start, 0, sizeof ph_start);
        !           140: }
        !           141: 
        !           142: void show_progress(OFF_T ofs, OFF_T size)
        !           143: {
        !           144:        struct timeval now;
        !           145: #if defined HAVE_GETPGRP && defined HAVE_TCGETPGRP
        !           146:        static pid_t pgrp = -1;
        !           147:        pid_t tc_pgrp;
        !           148: #endif
        !           149: 
        !           150:        if (am_server)
        !           151:                return;
        !           152: 
        !           153: #if defined HAVE_GETPGRP && defined HAVE_TCGETPGRP
        !           154:        if (pgrp == -1)
        !           155:                pgrp = getpgrp(GETPGRP_ARG);
        !           156: #endif
        !           157: 
        !           158:        gettimeofday(&now, NULL);
        !           159: 
        !           160:        if (!ph_start.time.tv_sec) {
        !           161:                int i;
        !           162: 
        !           163:                /* Try to guess the real starting time when the sender started
        !           164:                 * to send us data by using the time we last received some data
        !           165:                 * in the last file (if it was recent enough). */
        !           166:                if (msdiff(&ph_list[newest_hpos].time, &now) <= 1500) {
        !           167:                        ph_start.time = ph_list[newest_hpos].time;
        !           168:                        ph_start.ofs = 0;
        !           169:                } else {
        !           170:                        ph_start.time.tv_sec = now.tv_sec;
        !           171:                        ph_start.time.tv_usec = now.tv_usec;
        !           172:                        ph_start.ofs = ofs;
        !           173:                }
        !           174: 
        !           175:                for (i = 0; i < PROGRESS_HISTORY_SECS; i++)
        !           176:                        ph_list[i] = ph_start;
        !           177:        }
        !           178:        else {
        !           179:                if (msdiff(&ph_list[newest_hpos].time, &now) < 1000)
        !           180:                        return;
        !           181: 
        !           182:                newest_hpos = oldest_hpos;
        !           183:                oldest_hpos = (oldest_hpos + 1) % PROGRESS_HISTORY_SECS;
        !           184:                ph_list[newest_hpos].time.tv_sec = now.tv_sec;
        !           185:                ph_list[newest_hpos].time.tv_usec = now.tv_usec;
        !           186:                ph_list[newest_hpos].ofs = ofs;
        !           187:        }
        !           188: 
        !           189: #if defined HAVE_GETPGRP && defined HAVE_TCGETPGRP
        !           190:        tc_pgrp = tcgetpgrp(STDOUT_FILENO);
        !           191:        if (tc_pgrp != pgrp && tc_pgrp != -1)
        !           192:                return;
        !           193: #endif
        !           194: 
        !           195:        rprint_progress(ofs, size, &now, False);
        !           196: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>