Changeset 73


Ignore:
Timestamp:
Mar 4, 2006, 7:10:07 PM (15 years ago)
Author:
Jari Häkkinen
Message:

Divided Gnuplot class into a basic gnuplot communication class
and a front end class specialized for svnstat.
Added option to plot stats against time or revision.
Removed gnuplot usage of temporary files.

Location:
trunk
Files:
2 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/ChangeLog

    r2 r73  
    11$Id$
    22
     3version 0.2:
     4  - Removed usage of temporary files.
     5  - Added option to plot changes against time or revision.
     6
    37version 0.1:
     8  - First release.
  • trunk/bin/Parameter.cc

    r66 r73  
    1111
    1212  Parameter::Parameter(const int argc,const char *argv[])
    13     : force_(false), root_("."), targetdir_("svnstat_output"), verbose_(false)
    1413  {
    15  
     14    defaults();
    1615    for (int i=1; i<argc; i++) {
    1716      bool ok=false;
     
    3029          ok=true;
    3130        }
     31      }
     32      else if (myargv=="-rev" || myargv=="--revisions") {
     33          revisions_=true;
     34          ok=true;
    3235      }
    3336      else if (myargv=="-t" || myargv=="--target"){
     
    6164
    6265
     66  void Parameter::defaults(void)
     67  {
     68    force_=false;
     69    revisions_=false;
     70    root_=".";
     71    targetdir_="svnstat_output";
     72    verbose_=false;
     73  }
     74
     75
    6376  void Parameter::help(void)
    6477  {
     
    8093              << "  -r [--root] arg : svn controlled directory to perform\n"
    8194              << "                    statistics calculation on [.]\n"
     95              << "  -rev [--revisions]: Use revision numbers as time scale\n"
     96              << "                      instead of dates [dates].\n"
    8297              << "  -t [--target] arg : output directory [svnstat_output]\n"
    8398              << "  -v [--verbose] : explain what is being done\n"
  • trunk/bin/Parameter.h

    r49 r73  
    1414    Parameter(const int argc,const char *argv[]);
    1515    inline bool force(void) const { return force_; }
     16    inline bool revisions(void) const { return revisions_; }
    1617    inline const std::string& root(void) const { return root_; }
    1718    inline const std::string& targetdir(void) const { return targetdir_; }
     
    2021  private:
    2122    void analyse(void);
     23    void defaults(void);
    2224    void help(void);
    2325    void version(void);
    2426
    2527    bool force_;
     28    bool revisions_;
    2629    std::string root_;
    2730    std::string targetdir_;
    2831    bool verbose_;
    29 
    3032  };
    3133
  • trunk/bin/svnstat.cc

    r63 r73  
    44#include "CommitStat.h"
    55#include "Directory.h"
    6 #include "Gnuplot.h"
     6#include "GnuplotFE.h"
    77#include "rmdirhier.h"
    88
     
    3535  }
    3636
    37   if (option.verbose())
    38     std::cout << "Parsing the log." << std::endl;
    39   CommitStat cs;
    40   cs.parse(option.root());
    41   assert(cs.date()[0].size());
    42   Stats::gnuplot_pipe_.set_dates(cs.date());
     37  if (!option.revisions()) {
     38    if (option.verbose())
     39      std::cout << "Parsing the log." << std::endl;
     40    CommitStat cs;
     41    cs.parse(option.root());
     42    GnuplotFE::instance()->set_dates(cs.date());
     43  }
    4344 
    4445  string prefix("svnstat_");
     
    4748  tree.parse(option.verbose());
    4849
    49   Stats::gnuplot_pipe_.command(string("cd '")+option.targetdir()+"'");
     50  GnuplotFE::instance()->command(string("cd '")+option.targetdir()+"'");
    5051  chdir(option.targetdir().c_str());
    5152  try {
  • trunk/lib/CommitStat.cc

    r65 r73  
    1 
    2 //$Id$
     1// $Id$
    32
    43#include "CommitStat.h"
     
    6867    is.close();
    6968
     69    assert(date_.size());
     70    assert(date_[0].size());
    7071    return system_return;
    7172  }
  • trunk/lib/CommitStat.h

    r63 r73  
    3030    int parse(const std::string& path);
    3131
    32     inline const std::vector<std::string> date(void) const { return date_; }
     32    inline const std::vector<std::string>& date(void) const { return date_; }
    3333
    3434  private:
  • trunk/lib/Directory.cc

    r72 r73  
    9292
    9393    // print daughter nodes, i.e, this function is recursive
    94     for_each(daughters_.begin(), daughters_.end(),
    95              std::bind1st(std::mem_fun(&Node::print), verbose));
    96 
     94    for (std::list<Node*>::const_iterator i=daughters_.begin();
     95         i!=daughters_.end(); i++)
     96      (*i)->print(verbose);
    9797  }
    9898
  • trunk/lib/Gnuplot.cc

    r71 r73  
    66#include <string>
    77#include <unistd.h>
     8
     9#include <iostream>
    810
    911
     
    2931    if (pclose(pipe_) == -1)
    3032      throw GnuplotException("Problem closing communication to gnuplot");
    31     for (std::list<std::string>::iterator i=tempfiles_.begin();
    32          i!=tempfiles_.end(); i++)
    33       remove(i->c_str());
    3433  }
    3534
     
    5756
    5857 
    59   void Gnuplot::date_plot(const std::vector<double>& y,
    60                           const std::string& format)
    61   {
    62     command(std::string("set xdata time"));
    63     command("set timefmt '" + date_input_format_ + "'");
    64     command("set format x '" + format + "'");
    65     plot(y,date_,"plot");
    66   }
    67 
    68 
    69   void Gnuplot::date_replot(const std::vector<double>& y,
    70                             const std::string& format)
    71   {
    72     plot(y,date_,"replot");
    73   }
    74 
    75 
    7658  void Gnuplot::tokenizer(const std::string& in,
    7759                          std::list<std::string>& tokens,
     
    8870
    8971
    90   void Gnuplot::command(std::string cmdstr)
     72  void Gnuplot::command(const std::string& cmdstr)
    9173  {
     74    fputs(cmdstr.c_str(),pipe_);
    9275    if (*(cmdstr.rbegin())!='\n')
    93       cmdstr+='\n';
    94     fputs(cmdstr.c_str(),pipe_);
     76      fputc('\n',pipe_);
    9577    fflush(pipe_);
    9678  }
  • trunk/lib/Gnuplot.h

    r70 r73  
    66#include <cassert>
    77#include <cstdio>
    8 #include <fstream>
    98#include <list>
    109#include <stdexcept>
     10#include <sstream>
    1111#include <string>
    1212#include <vector>
     
    2525  ///
    2626  /// The Gnuplot class creates a pipe to 'gnuplot' and facilitates
    27   /// communication with the binary.
    28   ///
    29   /// Temporary files are created in directory /tmp. These temporary
    30   /// files are removed on a normal program exit.
     27  /// communication with the gnuplot binary.
    3128  ///
    3229  class Gnuplot
     
    4542
    4643    ///
    47     /// The destructor deletes all temporary files created in the
    48     /// calls to plot_xy and plot_x. If the program execution fails to
    49     /// reach this destructor the temporary files will not be removed
    50     /// from the storage area.
     44    /// The destructor, closes the pipe to the gnuplot binary.
    5145    ///
    52     ~Gnuplot(void);
     46    virtual ~Gnuplot(void);
    5347
    5448    ///
    5549    /// Send arbitrary commands to Gnuplot.
    5650    ///
    57     void command(std::string);
    58 
    59     ///
    60     /// @return input format for date
    61     ///
    62     // Peter, obsolete ?
    63     const std::string& date_input_format(void) { return date_input_format_; }
    64 
    65     ///
    66     ///
    67     ///
    68     void date_plot(const std::vector<double>& y,
    69                    const std::string& format="%y-%b-%d");
    70     ///
    71     ///
    72     ///
    73     void date_replot(const std::vector<double>& y,
    74                      const std::string& format="%y-%b-%d");
     51    void command(const std::string&);
    7552
    7653    ///
     
    9572    /// Gnuplot usage.
    9673    ///
    97     // Peter, do we have to set xdata for replot
    98     inline void
    99     plot(const std::vector<double>& y,
    100          const std::vector<double>& x=std::vector<double>())
    101     { command("set xdata"); plot(y,x,"plot"); }
     74    template <class T1, class T2>
     75    void plot(const std::vector<T1>& y, const std::vector<T2>& x)
     76    { plot(y,x,"plot"); }
     77
     78    template <class T1>
     79    void plot(const std::vector<T1>& y,
     80              const std::vector<T1>& x=std::vector<T1>())
     81    { plot(y,x,"plot"); }
    10282
    10383    ///
     
    10686    /// Gnuplot usage.
    10787    ///
    108     inline void
    109     replot(const std::vector<double>& y,
    110            const std::vector<double>& x=std::vector<double>())
    111     { command("set xdata"); plot(y,x,"replot"); }
     88    template <class T1, class T2>
     89    void replot(const std::vector<T1>& y, const std::vector<T2>& x)
     90    { plot(y,x,"replot"); }
    11291
    113     ///
    114     /// sets format of date output
    115     ///
    116     inline void set_date_format(const std::string& format)
    117     { date_output_format_ = format;}
    118 
    119     ///
    120     /// Function setting the dates. \a format must comply with strings
    121     /// in date
    122     ///
    123     inline void set_dates(const std::vector<std::string>& date,
    124                           const std::string& format="%Y-%m-%d")
    125     { date_=date; date_input_format_=format; }
     92    template <class T1>
     93    void replot(const std::vector<T1>& y,
     94              const std::vector<T1>& x=std::vector<T1>())
     95    { plot(y,x,"replot"); }
    12696
    12797  private:
     
    142112      assert(x.size()==y.size() || x.empty());
    143113      assert(plotcmd=="plot" || plotcmd=="replot");
    144       char name[]="/tmp/svnstatXXXXXX";
    145       int fd=mkstemp(name); // mkstemp return a file descriptor
    146       if (fd == -1)
    147         throw GnuplotException(std::string("Failed to get unique filename: ") +
    148                                name);
    149       // Jari would like to do something like 'std::ofstream tmp(fd);'
    150       // but has to settle for (which is stupid since the file is
    151       // already open for writing.
    152       std::ofstream tmp(name);
    153       for (size_t i = 0; i<y.size() && (i<x.size() || x.empty()); ++i )
    154         if (x.empty())
    155           tmp << y[i] << '\n';
     114
     115      std::ostringstream cmdstring;
     116      cmdstring << plotcmd << " '-' u 1:2 title '" << linetitle_ << "' with "
     117                << linestyle_ << '\n';
     118      for (size_t i=0; i<y.size(); ++i) {
     119        if (!x.empty())
     120          cmdstring << x[i] << '\t';
    156121        else
    157           tmp << x[i] << '\t' << y[i] << '\n';
    158       // Jari, here the stupidity goes beyond everything - the
    159       // ofstream must be closed as well as the file descriptor. If
    160       // not the program will exhaust the availabe number of
    161       // simultaneous open files.
    162       tmp.close();
    163       close(fd);
     122          cmdstring << i << '\t';
     123        cmdstring << y[i] << '\n';
     124      }
     125      cmdstring << "e\n";
    164126
    165       std::string cmdstring(plotcmd + " '" + name + "' u 1:2 title '" +
    166                               linetitle_ + "' with " + linestyle_ + "\n");
    167       if (x.empty())
    168         cmdstring = plotcmd + " '" + name + "' u 1 title '" +
    169           linetitle_ + "' with " + linestyle_ + "\n";
    170        
    171       command(cmdstring);
    172       // need to keep track of created files since the gnuplot command
    173       // is not executed until pclose on MacOSX, shouldn't the fflush
    174       // fix this in the command() member function?
    175       tempfiles_.push_back(name);
     127      command(cmdstring.str());
    176128    }
    177129
     
    179131                   const std::string& delimiters = ":");
    180132
    181     // need to keep track of created files since the gnuplot command
    182     // is not executed until pclose on MacOSX, shouldn't the fflush
    183     // fix this in the command() member function?
    184     std::list<std::string> tempfiles_;
    185     std::vector<std::string> date_;
    186     std::string date_input_format_;
    187     std::string date_output_format_;
    188133    std::string gnuplot_binary_;
    189134    std::string linestyle_;
  • trunk/lib/Makefile.am

    r60 r73  
    44
    55noinst_LIBRARIES = libsvnstat.a
    6 libsvnstat_a_SOURCES = \
    7   CommitStat.cc Directory.cc File.cc Gnuplot.cc Node.cc Stats.cc utility.cc
     6libsvnstat_a_SOURCES = CommitStat.cc Directory.cc File.cc Gnuplot.cc  \
     7  GnuplotFE.cc Node.cc Stats.cc utility.cc
  • trunk/lib/Stats.cc

    r72 r73  
    22
    33#include "Stats.h"
    4 #include "Gnuplot.h"
     4#include "GnuplotFE.h"
    55#include "utility.h"
    66
     
    88#include <cassert>
    99#include <cstdlib>
     10#include <fstream>
    1011#include <iostream>
    1112#include <map>
     
    2122namespace svnstat{
    2223
    23   Gnuplot Stats::gnuplot_pipe_;
    2424  u_int Stats::latest_revision_=0;
    2525
     
    104104  {
    105105    std::string cmd=std::string("set term png; set output '")+name+"'";
    106     gnuplot_pipe_.command(cmd);
    107     gnuplot_pipe_.command("set key left Left reverse");
     106    GnuplotFE* gp=GnuplotFE::instance();
     107    gp->command(cmd);
     108    gp->command("set key default");
     109    gp->command("set key left Left reverse");
     110    gp->command("set multiplot");
    108111    std::vector<double> x=accumulated();   
    109112    std::stringstream sa;
    110113    sa << x.back() << " total";
    111     gnuplot_pipe_.linetitle(sa.str());
    112     gnuplot_pipe_.date_plot(x);
     114    gp->linetitle(sa.str());
     115    gp->linestyle("steps 1");
     116    gp->plot(x);
     117    size_t plotno=2;
    113118    for (MapConstIter_ i= map_.begin(); i != map_.end(); i++) {
     119      std::stringstream s0;
     120      s0 << "set key height " << plotno;
     121      gp->command(s0.str());
    114122      x=accumulated(i->first);
    115123      std::stringstream s;
    116124      s << x.back() << " " << i->first;
    117       gnuplot_pipe_.linetitle(s.str());
    118       gnuplot_pipe_.date_replot(x);
     125      gp->linetitle(s.str());
     126      // Jari, reuse the stream above
     127      std::stringstream s2;
     128      s2 << "steps " << plotno++;
     129      gp->linestyle(s2.str());
     130      gp->plot(x);
    119131    }
     132    gp->command("unset multiplot");
    120133
    121     // Jari, must rewrite output once since the replots above are not
    122     // added to the plot. Rather, the plot only contains the result
    123     // from the first 'plot' call.
    124     gnuplot_pipe_.command(cmd);
    125     gnuplot_pipe_.command("replot");
    126134    return name;
    127135  }
  • trunk/lib/Stats.h

    r72 r73  
    1212namespace theplu{
    1313namespace svnstat{
    14 
    15   class Gnuplot;
    1614
    1715  ///
     
    4745    Stats& operator+=(const Stats&);
    4846
    49     ///
    50     /// Jari, this is public. Naughty!
    51     ///
    52     /// @todo Make this non-public. The issues that gnuplot is started
    53     /// in cwd, but the main program makes a 'chdir' to another, and
    54     /// we cannot get gnuplot to change directory if it is
    55     /// private. Some redesign is needed.
    56     ///
    57     static Gnuplot gnuplot_pipe_;
    58 
    5947  private:
    6048    ///
     
    8068    std::string plot(const std::string&) const;
    8169
    82     static u_int latest_revision_; // latest rev. for whole project
     70    static u_int latest_revision_; // latest revision for whole project
    8371
    8472    // Peter, if the vector is sparse make it a map
Note: See TracChangeset for help on using the changeset viewer.