source: trunk/disparm.cpp

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

willem

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