Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

Combine.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Mon May 23 22:34:26 EDT 2005 by ken@xorian.net        
00020 //      modified on Sun Jul 28 12:01:59 EDT 2002 by lken@remote.xorian.net
00021 //      modified on Fri Feb 27 18:29:21 PST 1998 by heydon
00022 
00023 #include <Basics.H>
00024 #include <FS.H>
00025 #include <VestaLog.H>
00026 #include <Recovery.H>
00027 #include <FP.H>
00028 #include <BitVector.H>
00029 
00030 #include "IntIntTblLR.H"
00031 #include "Combine.H"
00032 
00033 using std::ostream;
00034 using std::istream;
00035 using std::endl;
00036 
00037 // Combine::XorTag ------------------------------------------------------------
00038 
00039 static Combine::XorTag& NamesXOR(const FP::List& fps, const BitVector& bv,
00040   /*OUT*/ Combine::XorTag& res, const IntIntTblLR *imap = NULL) throw ()
00041 /* Set "res" to the combined fingerprint of the words "fps[imap(i)].w"
00042    for those bits "i" such that "bv.Read(i)", and return the result. The
00043    fingerprints are combined by computing the exclusive OR of their words.
00044    If "imap == NULL", the identity map is used. */
00045 {
00046     int i;
00047     FP::Tag *fp;
00048 
00049     // initialize result
00050     res.w = 0UL;
00051 
00052     if (bv.Size() > 0) {
00053         // compute XOR
00054         BVIter iter(bv);
00055         while (iter.Next(/*OUT*/ i)) {
00056             short mapRes;
00057             if (imap == (IntIntTblLR *)NULL)
00058                 mapRes = i;
00059             else {
00060                 bool inMap = imap->Get(i, /*OUT*/ mapRes);
00061                 assert(inMap);
00062             }
00063             res ^= fps.fp[mapRes];
00064         }
00065     }
00066     return res;
00067 }
00068 
00069 Combine::XorTag::XorTag(const FP::List& pkFPs, BitVector& bv,
00070   const IntIntTblLR *imap) throw ()
00071 {
00072     (void)NamesXOR(pkFPs, bv, *this, imap);
00073 }
00074 
00075 void Combine::XorTag::Debug(ostream &os) const throw ()
00076 {
00077     char buff[17];
00078     int printLen = sprintf(buff, "%016" FORMAT_LENGTH_INT_64 "x", this->w);
00079     assert(printLen == 16);
00080     os << buff;
00081 }
00082 
00083 // Combine::FPTag -------------------------------------------------------------
00084 
00085 struct AvailBuff {
00086   char *buff;
00087   int len;
00088   AvailBuff *next;
00089 };
00090 
00091 static Basics::mutex availMu;
00092 static AvailBuff *head;
00093 
00094 static AvailBuff *NextAvail(int size) throw ()
00095 /* Return an "AvailBuff" contain a buffer of length at least "size". */
00096 {
00097     AvailBuff *res;
00098     availMu.lock();
00099     if (head == (AvailBuff *)NULL) {
00100       res = NEW(AvailBuff);
00101       res->buff = NEW_PTRFREE_ARRAY(char, size);
00102       res->len = size;
00103       availMu.unlock();
00104     } else {
00105         res = head;
00106         head = head->next;
00107         availMu.unlock();
00108         if (res->len < size) {
00109             delete[] res->buff;
00110             res->buff = NEW_PTRFREE_ARRAY(char, size);
00111         }
00112     }
00113     return res;
00114 }
00115 
00116 static void ReturnAvail(AvailBuff *avail) throw ()
00117 /* Return "avail" to the list of available buffers. */
00118 {
00119     availMu.lock();
00120     avail->next = head;
00121     head = avail;
00122     availMu.unlock();
00123 }
00124 
00125 static FP::Tag& NamesFP(const FP::List& fps, const BitVector& bv,
00126   /*OUT*/ FP::Tag& res, const IntIntTblLR *imap = NULL) throw ()
00127 /* Set "res" to the combined fingerprint of the words "fps[imap(i)].w"
00128    for those bits "i" such that "bv.Read(i)", and return the result. The
00129    fingerprints are combined in increasing index order (in "bv") by
00130    computing the fingerprint tag of the concatenation of their words.
00131    If "imap == NULL", the identity map is used. */
00132 {
00133     AvailBuff *avail = (AvailBuff *)NULL;
00134     char *fpBuff;
00135     int buffLen = 0;
00136 
00137     if (bv.Size() > 0) {
00138         // fill a buffer with the bytes of the relevant fingerprints
00139         int i;
00140         BVIter iter(bv);
00141         // the following is a conservative upper-bound on space required
00142         avail = NextAvail(bv.Size() * FP::ByteCnt);
00143         fpBuff = avail->buff;
00144         while (iter.Next(/*OUT*/ i)) {
00145             short mapRes;
00146             if (imap == (IntIntTblLR *)NULL)
00147                 mapRes = i;
00148             else {
00149                 bool inMap = imap->Get(i, /*OUT*/ mapRes);
00150                 assert(inMap);
00151             }
00152             Word *words = fps.fp[mapRes].Words();
00153             memcpy(fpBuff + buffLen, (char *)words, FP::ByteCnt);
00154             buffLen += FP::ByteCnt;
00155         }
00156     }
00157 
00158     // create a new fingerprint on those bytes
00159     res = FP::Tag(fpBuff, buffLen);
00160 
00161     // clean up and return
00162     if (avail != (AvailBuff *)NULL) ReturnAvail(avail);
00163     return res;
00164 }
00165 
00166 Combine::FPTag::FPTag(const FP::List& fps, const BitVector& bv,
00167   const IntIntTblLR *imap) throw ()
00168 {
00169     (void)NamesFP(fps, bv, *this, imap);
00170 }
00171 
00172 // Combine::XorFPTag ----------------------------------------------------------
00173 
00174 void Combine::XorFPTag::Init(const FP::List& fps, const BitVector& bv,
00175   const IntIntTblLR *imap) throw ()
00176 {
00177     (void)NamesXOR(fps, bv, /*OUT*/ this->xort, imap);
00178     this->xort.w &= ~LSB;
00179 }
00180 
00181 FP::Tag& Combine::XorFPTag::FPVal(const FP::List &fps,
00182   const BitVector &bv, const IntIntTblLR *imap) throw ()
00183 {
00184     if (!(this->xort.w & LSB)) {
00185         (void)NamesFP(fps, bv, /*OUT*/ this->fp, imap);
00186         this->xort.w |= LSB;
00187     }
00188     return this->fp;
00189 }
00190 
00191 void Combine::XorFPTag::Log(VestaLog &log) const
00192   throw (VestaLog::Error)
00193 {
00194     xort.Log(log);
00195     if (this->xort.w & LSB) fp.Log(log);
00196 }
00197 
00198 void Combine::XorFPTag::Recover(RecoveryReader &rd)
00199   throw (VestaLog::Error, VestaLog::Eof)
00200 {
00201     this->xort.Recover(rd);
00202     if (this->xort.w & LSB) this->fp.Recover(rd);
00203 }
00204 
00205 void Combine::XorFPTag::Write(ostream &ofs) const
00206   throw (FS::Failure)
00207 {
00208     this->xort.Write(ofs);
00209     if (this->xort.w & LSB) this->fp.Write(ofs);
00210 }
00211 
00212 void Combine::XorFPTag::Read(istream &ifs)
00213   throw (FS::EndOfFile, FS::Failure)
00214 {
00215     this->xort.Read(ifs);
00216     if (this->xort.w & LSB) this->fp.Read(ifs);
00217 }
00218 
00219 inline void Indent(ostream &os, int indent) throw ()
00220 {
00221     for (int i = 0; i < indent; i++) os << " ";
00222 }
00223 
00224 void Combine::XorFPTag::Debug(ostream &os, int indent) const throw ()
00225 {
00226     Indent(os, indent); os << "xor = "; this->xort.Debug(os); os << endl;
00227     Indent(os, indent); os << "fp  = ";
00228     if (this->xort.w & LSB) os << this->fp; else os << "<lazy>";
00229 }

Generated on Mon May 8 00:48:34 2006 for Vesta by  doxygen 1.4.2