source: tags/1.2/disparm.cpp @ 5

Last change on this file since 5 was 5, checked in by willem, 11 years ago

willem

File size: 24.4 KB
Line 
1#include <iostream>
2#include <fstream>
3#include <libgen.h>
4#include <cstdlib>
5#include <string.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
9#include <unistd.h>
10
11#include "disparm.h"
12#include "tofromstring.h"
13#include "token.h"
14#include "shellenv.h"
15#include <errno.h>
16#include <dirent.h>
17
18const std::string disparm::keyname       = "DISPARM_KEY";
19const std::string disparm::committedname = "DISPARM_COMMITTED";
20const std::string disparm::valuename     = "DISPARM_VALUE";
21const std::string disparm::rcname        = "DISPARM_RC";
22const std::string disparm::linename      = "DISPARM_LINENO";
23
24const std::string disparm::defpath_pool   = "pool.disparm";
25const std::string disparm::definputfilename = "-";
26
27//
28//constructor disparm
29//
30disparm::disparm()
31{
32  char defpoolname_c[this->defpath_pool.length()+1];        // default path_pool
33  strcpy(defpoolname_c,this->defpath_pool.c_str());         
34  //
35  // A note about basename and dirname: they need as argument a char*
36  // NOT a const char*. Both functions may modify the argument,
37  // so, in general, do not use the same argument more than
38  // once.
39  //
40  char defpath_lockdir_c[this->defpath_lockdir.length()+1];  // default directory for the lockfile
41  strcpy(defpath_lockdir_c,this->defpath_lockdir.c_str());
42  this->setpath_pool(this->defpath_pool);
43  this->defpath_lockdir = std::string(dirname(defpoolname_c));
44  this->setpath_link("");
45  this->setpath_lock("");     // the name of the lock folder
46  this->setbaselinkfilename("");
47  this->setinputfilename(this->definputfilename);  // default input file name
48  this->setpath_lockdir(this->defpath_lockdir);      // default lock directory
49  this->setmaxiter(1);                             // default maximum times a string can be given out
50  this->pmarker="pp";                              // start of record with pointer to next string in pool
51  this->pmarkerlen = this->pmarker.length();
52  this->lockname="lock.disparm";
53
54  std::string shell = getenv("SHELL");
55  if (shell.find("csh") != std::string::npos) 
56    this->shelltype = SHELL_CSH;
57  else
58    this->shelltype = SHELL_SH;
59
60  //
61  // following items are returned on stdout as in:
62  // export DISPARM_KEY=1234
63  // See also above
64  //
65  this->key       = -1;     // key: pointer to next item in pool
66  this->status    = '0';
67  this->committed = 0;      // the number of times the string is given out
68  this->rc        = "OK";   // return code
69  this->value     = "";     // the string to give out
70  this->linenr    = 0;      // the line number in the pool
71
72  this->debug     = 0;
73
74  int rc = posix_memalign((void**)&buffer, 4096, 512);
75  if (rc != 0)
76    std::cerr << "Disparm: posix_memalign fails" << std::endl;
77}
78
79// destructor
80disparm::~disparm()
81{
82  free(this->buffer);
83}
84
85void disparm::removelock()
86{
87  unlink(this->path_link.c_str());
88  // wwvv not removing lock directory
89  // rmdir(this->path_lock.c_str());
90}
91
92void disparm::setpath_pool(std::string pool)
93{
94  this->path_pool = pool;
95}
96
97void disparm::setpath_link(std::string path_link)
98{
99  this->path_link = path_link;
100}
101
102void disparm::setpath_lock(std::string path_lock)
103{
104  this->path_lock = path_lock;
105}
106
107void disparm::setbaselinkfilename(std::string baselinkfilename)
108{
109  this->baselinkfilename = baselinkfilename;
110}
111
112int disparm::setpath_lockdir(std::string lockdir)
113{
114  this->path_lockdir = lockdir;
115  int rc = mkdir(path_lockdir.c_str(),0777);
116  if (rc ==0)
117    return 0;
118  else
119  {
120    if (errno == EEXIST)
121    {
122      struct stat buf;
123      stat(path_lockdir.c_str(),&buf);
124      if (S_ISDIR(buf.st_mode))
125        return 0;
126    }
127    else
128      return -1;
129  }
130  return 0;  // never reached
131}
132
133//
134// Create a name for the directory to be used as lock: this->path_lock
135// This directory will reside in this->path_lockdir
136// We try to generate a name for a linkfile that is unique.
137// In the name is also the creation time.
138// The link file will be placed in the lock directory
139//
140void disparm::createlinkfilename()
141{
142  if (this->debug)
143    this->debugger("Before createlinkfilename:");
144  char hostname[1025];
145  gethostname(hostname,1024);
146  char poolname_c[this->path_pool.length()+1];
147  strcpy(poolname_c,this->path_pool.c_str());
148  std::string poolnamebase = basename(poolname_c);
149  this->lockname=poolnamebase+".lock.disparm";
150  this->setpath_lock(this->path_lockdir + "/" + this->lockname);
151  std::string base = this->path_lock + "/" + poolnamebase + ".link.";
152  this->setbaselinkfilename(base);
153  this->setpath_link(   base
154                         + to_string(time(0))
155                         + "." 
156                         + hostname
157                         + "." 
158                         + to_string(getpid()));
159  if (this->debug)
160    this->debugger("After createlinkfilename:");
161}
162
163void disparm::setinputfilename(std::string inputfilename)
164{
165  this->inputfilename = inputfilename;
166}
167
168void disparm::setkey(std::streampos key)
169{
170  this->key = key;
171}
172
173std::streampos disparm::getkey(void)
174{
175  return this->key;
176}
177
178void disparm::setmaxiter(int maxiter)
179{
180  this->maxiter = maxiter;
181}
182
183//
184// Create poolfile from input file
185//
186// On return, s wil contain the output of createrc
187//
188int disparm::create(std::string &s)
189{
190  if (this->debug)
191    this->debugger("Before create:");
192  std::ifstream inp;
193  std::istream *pinp;
194  s = "";
195  //
196  // open inputfile, take care that stdin is also allowed
197  //
198  if (this->inputfilename == "-")
199    pinp = &std::cin;
200  else
201  {
202    inp.open(this->inputfilename.c_str());
203    if (!inp.is_open())
204    {
205      std::cerr<<"Cannot open '"<<inputfilename<<"'"<<std::endl;
206      this->rc = "FAIL";
207      s = this->createrc();
208      return 1;
209    }
210    pinp = &inp;
211  }
212  //
213  // open poolfile
214  //
215  std::string line;
216  std::fstream out;
217  out.open(this->path_pool.c_str(),std::fstream::in | std::fstream::out
218                               |  std::fstream::trunc);
219
220  //
221  // fill poolfile
222  //
223  token tok;
224  tok.setfile(out);
225  std::streampos p;
226  unsigned int linenr = 0;
227  while (getline(*pinp,line))
228  {
229    tok.setlinenr(++linenr);
230    tok.setcommitted(0);
231    tok.clearstatus();
232    tok.setvalue(line);
233    tok.writetoken(p);
234  }
235  tok.writelocpointer(0);
236
237  //
238  // close input file, only if it is not stdin
239  //
240  if (pinp == &inp)
241    inp.close();
242  out.close();
243
244  this->key = 0;
245  s = createrc();
246  if (this->debug)
247    this->debugger("After create:");
248
249  return 0;
250}
251
252//
253// get next string from pool
254//
255int disparm::next(std::string& s)
256{
257  if (this->debug)
258    this->debugger("Before next:");
259  int rc = this->realnext();
260  s = this->createrc();
261  if (this->debug)
262    this->debugger("After next:");
263  return rc;
264}
265
266//
267// create string to be eval'd by the shell
268//
269std::string disparm::createrc(void)
270{
271  std::string s = "";
272  s = s + shellenv(to_string(this->key),      this->keyname,      this->shelltype);
273  s = s + shellenv(to_string(this->committed),this->committedname,this->shelltype);
274  s = s + shellenv(to_string(this->value),    this->valuename,    this->shelltype);
275  s = s + shellenv(to_string(this->rc),       this->rcname,       this->shelltype);
276  s = s + shellenv(to_string(this->linenr),   this->linename,     this->shelltype);
277  return s;
278}
279
280//
281// get the next string from the pool
282//
283int disparm::realnext()
284{
285  std::fstream file;
286  bool good = 1;
287
288  this->key       = 0;
289  this->status    = '0';
290  this->committed = 0;
291  this->rc        = "OK";
292  this->linenr    = 0;
293  this->value     = "";
294
295  //
296  // get lock, return if that fails
297  //
298  if (this->getlock()!=0)
299  {
300    this->rc = "FAIL";
301    return 1;
302  }
303
304  //
305  // read next string from pool
306  // take care of ready records, maximum iterations
307  // allowed and some kinds of mishaps
308  //
309  // open first using O_DIRECT, to force a fresh cache.
310  int f = open(this->path_link.c_str(),O_DIRECT|O_RDONLY);
311  int bytesread = read(f,buffer,512);
312  if (bytesread <0)
313  {
314    std::cerr << "How strange: cannot read from poolfile." << std::endl;
315  }
316  close(f);
317  file.open (this->path_link.c_str(), std::fstream::in | std::fstream::out);
318  if (file.is_open())
319  {
320    token       tok;
321    std::string line;
322    tok.setfile(file);
323    std::streampos locpointer, posused, posnext;
324
325    //
326    // get pointer to next string
327    //
328    locpointer = tok.readlocpointer();
329    if (locpointer < 0)
330    {
331      std::cerr << "Corrupt parameterfile: cannot find locpointer\n" << std::endl;
332      this->rc = "FAIL";
333      good = 0;
334    }
335    //
336    // read next string from pool
337    //
338    if (good)
339    {
340      int rc = tok.readnext(locpointer,posused,posnext);
341      if (rc != 0)
342      {
343        std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
344        std::cerr << "Corrupt or empty parameterfile: cannot read next line\n" << std::endl;
345        this->rc = "FAIL";
346        good = 0;
347      }
348    }
349    //
350    // keep reading until a valid record is found
351    // take appropriate action if no such record exists
352    //
353    if (good)
354    {
355      std::streampos locpointerold = locpointer;
356      bool allready = 1;  // to learn if all records are
357                          // ready
358      while (1)
359      {
360        if (!tok.getready())
361        {
362          allready = 0;
363          if (tok.getcommitted() >= this->maxiter)
364          {
365            good = 0;
366            this->rc = "MAX_EXCEEDED";
367            break;
368          }
369          this->key = posused;
370          this->status = tok.getstatus();
371          this->committed = tok.getcommitted();
372          this->value = tok.getvalue();
373          this->linenr = tok.getlinenr();
374          tok.setcommitted(tok.getcommitted()+1);
375          tok.writetoken(posused);
376          tok.writelocpointer(posused);
377          break;
378        }
379        locpointer = posnext;
380        if (locpointer == locpointerold)
381        {
382          //
383          // so we are cycling, nothing to find, it seems
384          //
385          good = 0;
386          if (allready)
387            this->rc = "ALL_READY";
388          else
389            this->rc = "MAX_EXCEEDED";
390          break;
391        }
392        int rc = tok.readnext(locpointer,posused,posnext);
393        if (rc != 0)
394        {
395          std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
396          std::cerr << "Corrupt or empty parameterfile: cannot read next line\n" << std::endl;
397          this->rc = "FAIL";
398          good = 0;
399          break;
400        }
401      }
402    }
403  }
404  else
405  {
406    std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
407    std::cerr<< this->arg << ": Strange error: cannot open '"<<path_link<<"'"<<std::endl;
408    return 1;
409  }
410
411  file.close();
412  this->removelock();
413  return !good;
414}
415
416//
417// get a lock on the poolfile
418//
419// The normal methods don't work on an nfs file system.
420// Luckily, there is a method based on the creation
421// of a directory, which is an atomic operation.
422// If we can create the directory, we are sure that no
423// other instantiation of this program was also successful.
424// After successful creation of the lock directory, we create
425// a hard link to the poolfile, and use this link to read from and
426// write to. We do not use the poolfile itself to read and write,
427// we can never be sure in a nfs filesystem of the status of a
428// file. It appears that creating a new hard link suffices to
429// get an up to date version of the poolfile.
430//
431int disparm::getlock(void)
432{
433  struct stat buf;
434  int rc;
435  int sleeptime=2;
436
437  int iter = 0;
438  int ntryremovelock = 0;
439  while(1)
440  {
441    rc  = stat(this->path_pool.c_str(),&buf);
442    std::string er="";
443    switch (errno)
444    {
445      case (EACCES): er="Search permission is denied for one of the  directories  in  the path prefix of path.  (See also path_resolution(7).)";
446                     break;
447
448      case(EBADF):  er="fd is bad.";
449                    break;
450
451      case(EFAULT): er="Bad address.";
452                    break;
453
454      case(ELOOP):  er="Too many symbolic links encountered while traversing the path.";
455                    break;
456
457      case(ENAMETOOLONG):er="File name too long.";
458                         break;
459
460      case(ENOENT): er="A component of path does not exist, or path is an empty string.";
461                    break;
462
463      case(ENOMEM): er="Out of memory (i.e., kernel memory).";
464                    break;
465
466      case(ENOTDIR):
467              er="A component of the path prefix of path is not a directory.";
468              break;
469
470      case(EOVERFLOW):er="(stat())  path refers to a file whose size cannot be represented in the type off_t.  This can occur when an application  compiled on a 32-bit platform without -D_FILE_OFFSET_BITS=64 calls stat() on a file whose size exceeds (2<<31)-1 bits";
471                      break;
472
473    }
474    if (rc !=0 )
475    {
476      perror("Disparm: Error stat poolfile:");
477      std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
478      std::cerr<<er<<std::endl;
479      std::cerr<< this->arg << ": Cannot stat the pool file:'"<<this->path_pool.c_str()<<"'"<< std::endl;
480      return 1;
481    }
482    this->createlinkfilename();
483    //
484    // Try to create the lock directory
485    //
486    rc = mkdir(this->path_lock.c_str(), 0700);
487    // it seems that relying on the atomicity of
488    // mkdir does not work on the Lisa system.
489    // therefore, we skip the test and rely on the creation of
490    // links
491    rc = 0;
492    if (rc == 0)
493    {
494      // Creation of lock directory was successful, now create link
495      // to the poolfile
496      // As an extra check: check if the number of hard links to the
497      // poolfile equals 2.
498      //
499      // Strange: sometimes, when many threads are involved on one node,
500      // the poolfile seems to be gone, get error: "no such file or directory"
501      // I guess this is a race condition in the NFS filesystem
502      // so, I'll try 10 times, and then give up.
503      //
504      int tries = 0;
505      while (1)
506      {
507        tries++;
508        int rc = link(this->path_pool.c_str(),this->path_link.c_str());
509        if (rc < 0)
510        {
511          if (tries < 10)
512          {
513            sleep(1);
514          }
515          else
516          {
517            perror("Disparm: Error making link:");
518            std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
519            std::cerr<< this->arg << ": Cannot make link '"<<this->path_link<<"' to '"
520              <<this->path_pool<<"'"<<std::endl<<" Is poolname '"<<path_pool
521              <<"' correct?"<<std::endl;
522
523            this->removelock();
524            return 1;
525          }
526        }
527        else
528          break;
529      }
530      //
531      // check if number of hard links equals 2
532      //
533      struct stat linkbuf;
534      rc = stat(this->path_link.c_str(),&linkbuf);
535      if (rc !=0)
536      {
537        std::cerr << this->arg << ": Cannot stat just created link'"<<this->path_link<<"'"<<std::endl;
538        this->removelock();
539        return 1;
540      }
541      if (linkbuf.st_nlink == 2)
542      {
543        break;
544      }
545      else
546      {
547        rc = unlink(this->path_link.c_str());
548      }
549    }
550    //
551    // wait some time before trying again
552    //
553    iter++;
554#ifdef VERBOSE
555    std::cerr << iter <<": waiting for lock " << std::endl;
556#endif
557    sleep(sleeptime);
558    if (iter > 9)
559    {
560#ifdef VERBOSE
561      std::cerr << "Trying to remove locks" << std::endl;
562#endif
563      //
564      // remove stale link files
565      //
566      this->remove_lock_and_links();
567      ntryremovelock ++;
568      if (ntryremovelock > 100)
569      {
570        std::cerr << this->arg << ": Cannot get lock after many tries." << std::endl;
571        this->removelock();
572        return 1;
573      }
574      iter = 0;
575    }
576  }
577  return 0;
578}
579
580//
581// mark string as ready
582//
583int disparm::ready()
584{
585  if (this->getlock()!=0)
586  {
587    return 1;
588  }
589
590  //
591  // if no key given as parameter, read it from environment
592  //
593  if (this->key < 0)
594  {
595    char * s = getenv(this->keyname.c_str());
596    if (s == NULL || *s == 0)
597    {
598      this->removelock();
599      std::cerr << this->arg << ": No key given" << std::endl;
600      return 1;
601    }
602    else
603    {
604      this->key = from_string<long long>(std::string(s));
605    }
606  }
607
608  std::streampos locpointer = this->key;
609  std::fstream file;
610
611  // open first using O_DIRECT, to force a fresh cache.
612  int f = open(this->path_link.c_str(),O_DIRECT|O_RDONLY);
613  int bytesread = read(f,buffer,512);
614  if (bytesread <0)
615  {
616    std::cerr << this->arg << ": cannot read from poolfile." << std::endl;
617    return 1;
618  }
619  close(f);
620  file.open (this->path_link.c_str(), std::fstream::in | std::fstream::out);
621  if (file.is_open())
622  {
623    token tok;
624    std::string line;
625    tok.setfile(file);
626    std::streampos posused,posnext;
627    //
628    // read next record
629    //
630    int rc = tok.readnext(locpointer,posused,posnext);
631    if (rc != 0)
632    {
633      std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
634      std::cerr << this->arg << ": Corrupt or empty parameterfile: cannot read next line\n" << std::endl;
635      file.close();
636      this->removelock();
637      return 1;
638    }
639    //
640    // mark record as ready
641    //
642    tok.ready();
643    //
644    // write record back
645    //
646    tok.writetoken(locpointer);
647  }
648  else
649  {
650    std::cerr << this->arg << ": Cannot read " << this->path_link << std::endl;
651  }
652  file.close();
653  this->removelock();
654  return 0;
655}
656
657//
658// remove poolfile
659//
660int disparm::REMOVE()
661{
662  if (this->getlock()!=0)
663  {
664    return 1;
665  }
666  this->removelock();
667
668  int rc = unlink(this->path_pool.c_str());
669  if (rc)
670  {
671    std::cerr << this->arg << ": Cannot remove " << this->path_pool << std::endl;
672    return 1;
673  }
674  return 0;
675}
676
677//
678// return statistics about the pool
679// no wait for lock, so be careful interpretating the results
680//
681stats disparm::getstats()
682{
683  stats statistics;
684  token tok;
685  std::fstream file;
686  statistics.valid     =  0;
687  statistics.records   = -1;
688  statistics.committed = -1;
689  statistics.ready     = -1;
690  statistics.commax    = -1;
691
692
693  file.open (this->path_pool.c_str(), std::fstream::in | std::fstream::out);
694
695  if (file.is_open())
696  {
697    tok.setfile(file);
698    std::streampos pos = 0;
699    std::streampos posused;
700    std::streampos posnext;
701    statistics.valid     = 1;
702    statistics.records   = 0;
703    statistics.committed = 0;
704    statistics.ready     = 0;
705    statistics.commax    = 0;
706   
707    while(1)
708    {
709      tok.readnext(pos, posused,posnext);
710      if (pos != posused)
711        break;
712      if (tok.getready())
713        statistics.ready++;
714      if (tok.getcommitted()>0)
715        statistics.committed++;
716      if (tok.getcommitted() > statistics.commax)
717        statistics.commax = tok.getcommitted();
718      statistics.records++;
719      pos = posnext;
720    }
721    file.close();
722  }
723  else
724  {
725    std::cerr << this->arg << ": Cannot open poolfile '"<<this->path_pool<<"'"<<std::endl;
726  }
727
728  return statistics;
729}
730
731int disparm::echounhandled(void)
732{
733  token tok;
734  std::fstream file;
735
736  file.open (this->path_pool.c_str(), std::fstream::in | std::fstream::out);
737
738  if (file.is_open())
739  {
740    tok.setfile(file);
741    std::streampos pos = 0;
742    std::streampos posused;
743    std::streampos posnext;
744    std::cerr << "linenr:committed:value"<< std::endl;
745   
746    while(1)
747    {
748      tok.readnext(pos, posused,posnext);
749      if (pos != posused)
750        break;
751
752      if (!tok.getready()&&tok.getcommitted()>0)
753      {
754        std::cerr << tok.getlinenr() << ":"<<tok.getcommitted()<<":" << tok.getvalue() << std::endl;
755      }
756      pos = posnext;
757    }
758  }
759  else
760  {
761    std::cerr << this->arg << ": Cannot open pool file '"<<this->path_pool<<"'"<<std::endl;
762    return 1;
763  }
764
765  file.close();
766  return 0;
767}
768
769
770int disparm::remove_lock_and_links(const std::string path, const std::string dirl, const std::string path_lock, int timer)
771{
772  // removes lock and hard links in directory "dirl" to file "path"
773  // in directory "dir", if they are older than "time" seconds.
774  // Method:
775  // if lock is older than timer seconds, remove it.
776  // and:
777  // using readdir, examine all components of dirl and see
778  // if they have the same inode as "path". If so, remove, unless
779  // the realname is the same as the realname of "path"
780  //
781  DIR *pdir;
782  struct dirent *pent;
783  int rc;
784  struct stat buf;
785
786  pdir = opendir(dirl.c_str());
787  if (!pdir)
788  {
789    std::cerr << this->arg << ": Cannot read link directory '"<<dirl<<"'"<<std::endl;
790    return 1;
791  }
792  rc = stat(path.c_str(),&buf);
793  if (rc !=0)
794  {
795    std::cerr << this->arg << ": Cannot stat '"<<path<<"'"<<std::endl;
796    return 1;
797  }
798  ino_t inodenr = buf.st_ino;
799  char* rpathc = (char*)malloc(PATH_MAX+1);
800  rpathc = realpath(path.c_str(),rpathc);
801  std::string rpath = rpathc;
802  std::string rpath1;
803 
804  while ((pent=readdir(pdir)))
805  {
806    struct stat buf;
807    std::string name = pent->d_name;
808    if (name == ".") continue;
809    if (name == "..") continue;
810    rpathc = realpath((dirl+"/"+name).c_str(),rpathc);
811    rpath1 = rpathc;
812#ifdef VERBOSE
813    std::cerr<<"TD: looking at '"<<rpath1<<"'"<<std::endl;
814#endif
815    if (rpath != rpath1)
816    {
817      int rc = stat(rpath1.c_str(),&buf);
818      if (rc != 0)
819      {
820        std::cerr << this->arg << ": Cannot stat '"<<rpath1<<"'"<<" this cannot happen!" << std::endl;
821        free(rpathc);
822        return 1;
823      }
824      if (buf.st_ino == inodenr)
825      {
826#ifdef VERBOSE
827        std::cerr << "time: " << time(0) << " " << buf.st_mtime << " " << timer << std::endl;
828#endif
829        if (time(0) > buf.st_mtime + timer)
830        {
831          int rc = unlink(rpath1.c_str());
832          if (rc == 0)
833          {
834#ifdef VERBOSE
835            std::cerr<<"Unlinked '"<<rpath1<<"'"<<std::endl;
836#endif
837          }
838          else
839          {
840#ifdef VERBOSE
841            std::cerr<<"Could not unlink '"<<rpath1<<"'"<<std::endl;
842#endif
843          }
844        }
845        else
846        {
847#ifdef VERBOSE
848          std::cerr << "TD: not unlinking because time: '"<<rpath1<<"'"<<std::endl;
849#endif
850        }
851      }
852    }
853    else
854    {
855#ifdef VERBOSE
856      std::cerr<<"TD: not unlinking '"<<rpath1<<"'"<<std::endl;
857#endif
858    }
859  }
860  free(rpathc);
861  // look if lock can be removed, if yes: and make it so
862  rc = stat(path_lock.c_str(),&buf);
863  if (rc == 0)
864  {
865    if (time(0) > buf.st_mtime + timer)
866    {
867#ifdef VERBOSE
868      std::cerr << "Trying to remove '"<<path_lock<<"'"<<std::endl;
869#endif
870      // wwvv not removing lock directory
871      // rc = rmdir(path_lock.c_str());
872      // It could happen that rmdir failed, for example another process
873      // already deleted it, or path is invalid etc.
874      // We ignore this, relying on the fact that eventually
875      // getlock will time out.
876    }
877  }
878  return 0;
879}
880
881
882//
883// remove lock and links
884// method: do a glob on baselinkfilename and unlink
885// the files.
886//
887// Only remove if links are older than 60 seconds.
888//
889void disparm::remove_lock_and_links()
890{
891  if (this->debug)
892    this->debugger("Before remove_lock_and_links:");
893
894  remove_lock_and_links(this->path_pool,this->path_lockdir,this->path_lock,60);
895  if (this->debug)
896    this->debugger("Before remove_lock_and_links:");
897}
898
899void disparm::setdebug()
900{
901  this->debug = 1;
902}
903void disparm::debugger(const std::string s)
904{
905  std::cerr << s << std::endl;
906  std::cerr << "baselinkfilename: '" << this->baselinkfilename << "'" << std::endl;
907  std::cerr << "committed:        '" << this->committed << "'" << std::endl;
908  std::cerr << "committedname:    '" << this->committedname << "'" << std::endl;
909  std::cerr << "definputfilename: '" << this->definputfilename << "'" << std::endl;
910  std::cerr << "defpath_pool:     '" << this->defpath_pool << "'" << std::endl;
911  std::cerr << "defpath_lockdir:  '" << this->defpath_lockdir << "'" << std::endl;
912  std::cerr << "inputfilename:    '" << this->inputfilename << "'" << std::endl;
913  std::cerr << "key:              '" << this->key << "'" << std::endl;
914  std::cerr << "keyname:          '" << this->keyname << "'" << std::endl;
915  std::cerr << "linename:         '" << this->linename << "'" << std::endl;
916  std::cerr << "linenr:           '" << this->linenr << "'" << std::endl;
917  std::cerr << "lockname:         '" << this->lockname << "'" << std::endl;
918  std::cerr << "maxiter:          '" << this->maxiter << "'" << std::endl;
919  std::cerr << "path_link:        '" << this->path_link << "'" << std::endl;
920  std::cerr << "path_lock:        '" << this->path_lock << "'" << std::endl;
921  std::cerr << "path_lockdir:     '" << this->path_lockdir << "'" << std::endl;
922  std::cerr << "path_pool:        '" << this->path_pool << "'" << std::endl;
923  std::cerr << "pmarker:          '" << this->pmarker << "'" << std::endl;
924  std::cerr << "pmarkerlen:       '" << this->pmarkerlen << "'" << std::endl;
925  std::cerr << "pointerlen:       '" << this->pointerlen << "'" << std::endl;
926  std::cerr << "rc:               '" << this->rc << "'" << std::endl;
927  std::cerr << "rcname:           '" << this->rcname << "'" << std::endl;
928  std::cerr << "shelltype:        '" << this->shelltype << "'" << std::endl;
929  std::cerr << "status:           '" << this->status << "'" << std::endl;
930  std::cerr << "value:            '" << this->value << "'" << std::endl;
931  std::cerr << "valuename:        '" << this->valuename << "'" << std::endl;
932}
933
934void disparm::setarg(int argc, char*argv[])
935{
936  this->arg = argv[0];
937  for (int i=1; i<argc; i++)
938    this->arg += std::string(" ") + std::string(argv[i]);
939  this->arg += " pid:" + to_string(getpid());
940}
941
942//
943// Just to teach me again how to make an object
944// suitable for the << operator
945//
946std::ostream& operator <<(std::ostream &os,disparm &obj)
947{
948  stats sta;
949  sta = obj.getstats();
950  if ( sta.valid )
951  {
952    os << "Total:     " << sta.records   << "\n" 
953       << "Committed: " << sta.committed << "\n"
954       << "Ready:     " << sta.ready     << "\n"
955       << "Max:       " << sta.commax;
956  }
957  return os;
958}
959
Note: See TracBrowser for help on using the repository browser.