summaryrefslogtreecommitdiffstats
path: root/plzip.h
blob: b12bbbd840fafb58ff286c5cffdd4b7a4ea3d691 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*  Plzip - A parallel compressor compatible with lzip
    Copyright (C) 2009 Laszlo Ersek.
    Copyright (C) 2009, 2010, 2011, 2012 Antonio Diaz Diaz.

    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 3 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, see <http://www.gnu.org/licenses/>.
*/

class Pretty_print
  {
  const char * const stdin_name;
  unsigned int longest_name;
  std::string name_;
  mutable bool first_post;

public:
  explicit Pretty_print( const std::vector< std::string > & filenames )
    : stdin_name( "(stdin)" ), longest_name( 0 ), first_post( false )
    {
    const unsigned int stdin_name_len = std::strlen( stdin_name );
    for( unsigned int i = 0; i < filenames.size(); ++i )
      {
      const std::string & s = filenames[i];
      const unsigned int len = ( ( s == "-" ) ? stdin_name_len : s.size() );
      if( len > longest_name ) longest_name = len;
      }
    if( longest_name == 0 ) longest_name = stdin_name_len;
    }

  void set_name( const std::string & filename )
    {
    if( filename.size() && filename != "-" ) name_ = filename;
    else name_ = stdin_name;
    first_post = true;
    }

  void reset() const throw() { if( name_.size() ) first_post = true; }
  const char * name() const throw() { return name_.c_str(); }
  void operator()( const char * const msg = 0 ) const throw();
  };


/*--------------------- Defined in compress.cc ---------------------*/

void xinit( pthread_mutex_t * const mutex );
void xinit( pthread_cond_t * const cond );
void xdestroy( pthread_mutex_t * const mutex );
void xdestroy( pthread_cond_t * const cond );
void xlock( pthread_mutex_t * const mutex );
void xunlock( pthread_mutex_t * const mutex );
void xwait( pthread_cond_t * const cond, pthread_mutex_t * const mutex );
void xsignal( pthread_cond_t * const cond );
void xbroadcast( pthread_cond_t * const cond );


class Slot_tally
  {
public:
  unsigned long check_counter;
  unsigned long wait_counter;
private:
  const int num_slots;			// total slots
  int num_free;				// remaining free slots
  pthread_mutex_t mutex;
  pthread_cond_t slot_av;		// free slot available

  Slot_tally( const Slot_tally & );	// declared as private
  void operator=( const Slot_tally & );	// declared as private

public:
  explicit Slot_tally( const int slots )
    : check_counter( 0 ), wait_counter( 0 ),
      num_slots( slots ), num_free( slots )
    { xinit( &mutex ); xinit( &slot_av ); }

  ~Slot_tally() { xdestroy( &slot_av ); xdestroy( &mutex ); }

  bool all_free() { return ( num_free == num_slots ); }

  void get_slot()			// wait for a free slot
    {
    xlock( &mutex );
    ++check_counter;
    while( num_free <= 0 )
      { ++wait_counter; xwait( &slot_av, &mutex ); ++check_counter; }
    --num_free;
    xunlock( &mutex );
    }

  void leave_slot()			// return a slot to the tally
    {
    xlock( &mutex );
    if( ++num_free == 1 ) xsignal( &slot_av );
    xunlock( &mutex );
    }
  };


int compress( const int data_size, const int dictionary_size,
              const int match_len_limit, const int num_workers,
              const int infd, const int outfd,
              const Pretty_print & pp, const int debug_level );


/*-------------------- Defined in decompress.cc --------------------*/

int decompress( const int num_workers, const int infd, const int outfd,
                const Pretty_print & pp, const int debug_level,
                const bool testing );


/*----------------------- Defined in main.cc -----------------------*/

extern int verbosity;

void fatal();		// terminate the program

void show_error( const char * const msg, const int errcode = 0, const bool help = false ) throw();
void internal_error( const char * const msg ) throw();
int readblock( const int fd, uint8_t * const buf, const int size ) throw();
int writeblock( const int fd, const uint8_t * const buf, const int size ) throw();