next up previous contents index
Next: Makefile Up: The Sources Previous: FileStat.h

Main.cc

 
// Main.cc
// Copyright (C) 1997, 98 Mori Tetsuya
// 12/23/97
// 1/20/98 SortableFixedString, SimpleTree

#include "PersistentStorage.h"
#include <iostream.h>
#include <fstream.h>
#include <new.h>
#include <Regex.h>
#include <stdlib.h>
#include <time.h>

#define RAND(m) (rand() / (RAND_MAX / m))

//#define SILENT 1

// pseudo main()

#define STRSIZE 256

enum OID { OID_SampleObject, OID_SimpleTree };

class SampleObject: public PersistentObject {
  PersistentPointer next;
  char str[10];
public:
  SampleObject(PersistentPointer &p, 
               const char *s = 0) : 
    PersistentObject(OID_SampleObject), next(p) {
    if (s != 0) {
      strcpy(str, s);
    } else {
      strcpy(str, "abc");
    }
  }
  PersistentPointer &Next() {
    return next;
  }
  char *Str() {
    return str;
  }
};

template<int size>
class SortableFixedString {
protected:
  char     str[size];
public:
  SortableFixedString(char *s = 0) {
    if (s == 0) {
      str[0] = '\0';
    } else {
      strncpy(str, s, size);
      str[size - 1] = '\0';
    }
  }
  ~SortableFixedString() {}
  inline char *getValue() { return str; }
  inline ComparisonType compare(char *s) {
    return s != 0 ? strcmp(str, s) : GreaterThan;
  }
  inline ComparisonType compare(SortableFixedString &s) {
    return strcmp(str, s.str);
  }
  inline SortableFixedString &operator = (char *s) {
    if (s == 0) {
      str[0] = '\0';
    } else {
      strncpy(str, s, size);
      str[size - 1] = '\0';
    }
    return *this;
  }
};

template<int size>
ostream &operator<<(ostream &os, SortableFixedString<size> &obj) {
  return os << obj.getValue();
}

const EntryID SimpleTreeTopEID = 1;

class SimpleTree;

ostream &operator<<(ostream &os, SimpleTree &obj);

template <class Element, class Value, ObjectID oid>
class SimpleTree : public PersistentObject {
  friend ostream &operator<<(ostream &os, SimpleTree &obj);
protected:
  PersistentPointer left;
  PersistentPointer right;
  Element           object;
public:
  SimpleTree(Value value, 
             PersistentPointer l = PersistentPointer(),
             PersistentPointer r = PersistentPointer()) : 
    PersistentObject(oid), 
    left(l), right(r), object(value) {
  }
  ~SimpleTree() {}
  inline PersistentPointer &Left() { return left; }
  inline PersistentPointer &Right() { return right; }
  inline Value getValue() { return object.getValue(); }
  PersistentPointer insert(Value v, PersistentPointer This) {
    ComparisonType cmp = object.compare(v);
    if (cmp == 0) {
      return This;
    } else if (cmp < 0) {
      if (Right() == 0) {
        PointerPair pp = ps->allocate(sizeof(*this));
        pp.grab();
        if (P(pp) == 0)
          return PersistentPointer();
        new(pp) SimpleTree(v);
        pp.release();
        Right() = pp;
        return pp;
      } else {
        PointerPair pp = Right();
        pp.grabReadOnly();
        PersistentPointer p;
        if (P(pp) != 0 && P(pp)->getID() == oid)
          p = ((SimpleTree *)P(pp))->insert(v, Right());
        pp.releaseReadOnly();
        return p;
      }
    } else {
      if (Left() == 0) {
        PointerPair pp = ps->allocate(sizeof(*this));
        pp.grab();
        if (P(pp) == 0)
          return PersistentPointer();
        new(pp) SimpleTree(v);
        pp.release();
        Left() = pp;
        return pp;
      } else {
        PointerPair pp = Left();
        pp.grabReadOnly();
        PersistentPointer p;
        if (P(pp) != 0 && P(pp)->getID() == oid)
          p = ((SimpleTree *)P(pp))->insert(v, Left());
        pp.releaseReadOnly();
        return p;
      }
    }
  }

  PersistentPointer search(Value v, PersistentPointer This) {
    ComparisonType cmp = object.compare(v);
    if (cmp == 0) {
      return This;
    } else if (cmp < 0) {
      if (Right() == 0) {
        return PersistentPointer();
      } else {
        PointerPair pp = Right();
        pp.grabReadOnly();
        PersistentPointer p;
        if (P(pp) != 0 && P(pp)->getID() == oid)
          p = ((SimpleTree *)P(pp))->search(v, Right());
        pp.releaseReadOnly();
        return p;
      }
    } else {
      if (Left() == 0) {
        return PersistentPointer();
      } else {
        PointerPair pp = Left();
        pp.grabReadOnly();
        PersistentPointer p;
        if (P(pp) != 0 && P(pp)->getID() == oid)
          p = ((SimpleTree *)P(pp))->search(v, Left());
        pp.releaseReadOnly();
        return p;
      }
    }
  }

  PersistentPointer match(Value lower, Value upper) {
    PointerPair pp = ps->allocate(sizeof(*this));
    pp.grab();
    new (pp) SimpleTree("");
    doMatch(lower, upper, pp);
    pp.release();
    return pp;
  }

  PointerPair &doMatch(Value lower, Value upper, 
                       PointerPair &top) {
    ComparisonType cmpLower = object.compare(lower);
    ComparisonType cmpUpper = object.compare(upper);
    ComparisonType cmp;
    if (cmpLower < 0) {
      cmp = LessThan;
    } else if (cmpUpper > 0) {
      cmp = GreaterThan;
    } else {
      cmp = EqualTo;
    }
    if (cmp == 0) {
      ((SimpleTree *)P(top))->insert(object.getValue(), top);
    }
    if (cmp >= 0 && Left() != 0) {
      PointerPair L = Left();
      L.grabReadOnly();
      if (P(L) != 0 && ((SimpleTree *)P(L))->getID() == oid) 
        ((SimpleTree *)P(L))->doMatch(lower, upper, top);
      L.releaseReadOnly();
    }
    if (cmp <= 0 && Right() != 0) {
      PointerPair R = Right();
      R.grabReadOnly();
      if (P(R) != 0 && ((SimpleTree *)P(R))->getID() == oid) 
        ((SimpleTree *)P(R))->doMatch(lower, upper, top);
      R.releaseReadOnly();
    }
    return top;
  }

  void traverse(ostream &os) {
    if (Left() != 0) {
      PointerPair pp = Left();
      pp.grabReadOnly();
      if (P(pp) != 0 && P(pp)->getID() == oid)
        ((SimpleTree *)P(pp))->traverse(os);
      pp.releaseReadOnly();
    }
#ifndef SILENT
    os << object << endl;
#endif
    if (Right() != 0) {
      PointerPair pp = Right();
      pp.grabReadOnly();
      if (P(pp) != 0 && P(pp)->getID() == oid)
        ((SimpleTree *)P(pp))->traverse(os);
      pp.releaseReadOnly();
    }
  }

  inline isLeaf() { return Left() == 0 && Right() == 0; }

  BoolType destroy() {
#ifndef SILENT
    cout << "destroy " << object << endl;
#endif
    BoolType successR;
    BoolType successL;
    if (Left() != 0) {
      PointerPair L = Left();
      L.grab();
      if (P(L) != 0 && P(L)->getID() == oid) {
        successL = ((SimpleTree *)P(L))->destroy();
        if (successL && ((SimpleTree *)P(L))->isLeaf()) {
          successL = ps->destroy(L);
          if (!successL)
            successL = False;
          else 
            Left() = 0;
        } else {
          successL = False;
        }
        if (!successL)
          successL = L.release();
      } else {
        successL = False;
      }
    } else {
      successL = True;
    }
    if (Right() != 0) {
      PointerPair R = Right();
      R.grab();
      if (P(R) != 0 && P(R)->getID() == oid) {
        successR = ((SimpleTree *)P(R))->destroy();
        if (successR && ((SimpleTree *)P(R))->isLeaf()) {
          successR = ps->destroy(R);
          if (!successR)
            successR = False;
          else 
            Right() = 0;
        } else {
          successR = False;
        }
        if (!successR)
          successR = R.release();
      } else {
        successR = False;
      }
    } else {
      successR = True;
    }
    return successR && successL;
  }
}; // SimpleTree

typedef SimpleTree<SortableFixedString<STRSIZE>, char *, OID_SimpleTree> ST;
typedef ST *PST;

int main(int argc, char *argv[]) {
  new PersistentStorage(".");
  char line[STRSIZE];
  char *lower, *upper;
  BoolType verbose = True;

  ifstream fin;
  istream *is;
  if (argc >= 4) {
    fin.open(argv[1]);
    lower = argv[2];
    upper = argv[3];
    is = &fin;
  } else if (argc == 3) {
    verbose = False;
    lower = argv[1];
    upper = argv[2];
    is = &cin;
  } else {
    cout << "Usage " << argv[0] << " [file] lower upper" << endl;
    exit(1);
  }

  PointerPair pp = ps->getEntryPoint(SimpleTreeTopEID);
  if (pp == 0) {
    pp = ps->allocate(sizeof(ST));
    new(pp.grab()) ST("");
    ps->setEntryPoint(SimpleTreeTopEID, pp);
  } else {
    pp.grab();
  }

  if (P(pp)->getID() != OID_SimpleTree) {
    cout << "ObjectID is not OID_SimpleTree" << endl;
    exit(1);
  }

  do {
    is->getline(line, STRSIZE);
    PST(P(pp))->insert(line, pp);
#ifndef SILENT
    if (verbose)
      cout << "inserting " << line << endl;
#endif
  } while (is->gcount() > 0);

  if (verbose) {
    fin.close();
    fin.open(argv[1]);
    is = &fin;
    PointerPair p;
    do {
      is->getline(line, STRSIZE);
      p = PST(P(pp))->search(line, pp);
#ifndef SILENT
      if (p != 0) {
        p.grabReadOnly();
        if (P(p) != 0 && P(p)->getID() == OID_SimpleTree) {
          cout << "found     " << PST(P(p))->getValue() << endl;
        }
        p.releaseReadOnly();
      } else {
        cout << "not found " << line << endl;
      }
#endif
    } while (is->gcount() > 0);
  }  
  
  if (verbose) 
    PST(P(pp))->traverse(cout);

  if (argc >= 3) {
    PointerPair matched;
    matched = PST(P(pp))->match(lower, upper);

    matched.grab();
    if (P(matched) != 0 && P(matched)->getID() == OID_SimpleTree) {
      cout << "#matched" << endl;
      PST(P(matched))->traverse(cout);
      cout << "#end matched" << endl;
      PST(P(matched))->destroy();
    }
    if (matched.isGrabbed() != 0)
      ps->destroy(matched);
  }

  pp.release();

#if 0
  PointerPair p;
  PersistentPointer plast;
  PersistentPointer pnext;
  SizeType index;
  SizeType s;

  for (index = 0; index < 100000; index++) {
    plast = p;

    p = ps->allocate(s = sizeof(SampleObject) + RAND(1024) +
                      (RAND(100) == 0) * RAND(10000));
    if (p.isNull()) {
      cout << "\nallocate failed " << index << " " << s << endl; 
      break;
    }
    if (p.grab() != 0) {
      new(p) SampleObject(plast);
    } else {
      cout << "\ngrab failed " << index << " " << s << endl;
      break;
    }
    memset(((SampleObject *)P(p))->Str(), (index % (127 - 32)) + 32, 10);
    (((SampleObject *)P(p))->Str())[9] = '\0';
    if (!p.release()) {
      cout << "release failed" << endl;
      break;
    }
#ifndef SILENT
    cout << index << "\r" << flush;
#endif
  }
#ifndef SILENT
  cout << "\nallocation " << index << endl;
#endif
  plast = p;
  index = 0;
  while (!p.isNull()) {
    p.grabReadOnly();
#ifndef SILENT
    cout << index << "\r" << flush;
#endif
    if (P(p) == 0)
      break;
    pnext = ((SampleObject *)P(p))->Next();
    p.releaseReadOnly();
    p = pnext;
    index++;
  }
#ifndef SILENT
  cout << "\ngrabReadOnly " << index << endl;
#endif

  srand(time(0));

  p = plast;
  index = 0;
  while (!p.isNull()) {
    p.grab();
    if (P(p) == 0) {
#ifndef SILENT
      cout << "\ngrab failed" << index << endl;
#endif
      break;
    }
    pnext = ((SampleObject *)P(p))->Next();
    if (RAND(10) == 0) {
      if (ps->destroy(p)) {
#ifndef SILENT
        cout << "d" << index << "\r" << flush;
#endif
      } else {
#ifndef SILENT
        cout << "\ndestroy failed " << index << endl;
#endif
      }
    } else {
      if (p.release()) {
#ifndef SILENT
        cout << "r" << index << "\r" << flush;
#endif
      } else {
#ifndef SILENT
        cout << "\nrelease failed " << index << endl;
#endif
      }
    }
    p = pnext;
    index++;
  }

  cout << "\ndestroy or release " << index << endl;

#endif

  cout << "synchronization" << endl;
  delete ps;
#ifndef SILENT
  //  ps->printStatus();
#endif
  cout << "sizeof(SampleObject) " << sizeof(SampleObject) << endl;
  cout << "sizeof(SimpleTree) " << sizeof(ST) << endl;
  cout << "sizeof(PersistentObject) " << sizeof(PersistentObject) << endl;
  exit(1);
}



Mori Tetsuya / t2y3141592@gmail.com