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

ReposRoots.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 // Created on Wed Mar 12 20:42:15 PST 1997 by heydon
00020 
00021 // Last modified on Sat Apr 30 16:39:24 EDT 2005 by ken@xorian.net  
00022 //      modified on Wed Jul 12 16:27:28 PDT 2000 by mann  
00023 //      modified on Tue Jul  7 16:28:05 PDT 1998 by heydon
00024 
00025 #include <sys/types.h>
00026 #if defined(__linux__) && !defined(__GNUC__)
00027 // For some reason, the Linux sys/types.h only defines int64_t under
00028 // the GNU compilers.  We need it for subsequent system includes.
00029 typedef long int int64_t;
00030 #endif
00031 #include <string.h>
00032 #include <dirent.h>
00033 #include <Basics.H>
00034 #include <Table.H>
00035 #include <SourceOrDerived.H>
00036 #include <VestaSource.H>
00037 #include <ReadConfig.H>
00038 #include <Debug.H>
00039 #include "PkgBuild.H"
00040 #include "Pathname.H"
00041 #include "CommonErrors.H"
00042 #include "ReposRoots.H"
00043 
00044 using std::cout;
00045 using std::endl;
00046 
00047 // character constants
00048 static const char Slash = '/';         // pathname separator
00049 static const char Null = '\0';         // end-of-string character
00050 
00051 // forward reference
00052 static void ReposRoots_SearchRepos(VestaSource *reposDir, Pathname::T pathT,
00053   /*INOUT*/ PkgTbl *pkgTbl) throw (SRPC::failure, ReposError);
00054 
00055 static bool ReposRoots_ValidFilename(Arc arc) throw ()
00056 /* Return "true" iff "arc" names a file ending with a ".ves" extension. */
00057 {
00058     static const char *ext = ".ves";       // magic extension
00059     static const int extLen = strlen(ext); // and its length
00060 
00061     int len = strlen(arc);
00062     if (len <= extLen) return false;
00063     return (strncmp(arc + (len - extLen), ext, extLen) == 0);
00064 }
00065 
00066 struct CallbackArgs {
00067     VestaSource *parent;
00068     Pathname::T parentPath;
00069     PkgTbl *pkgTbl;
00070 };
00071 
00072 static bool ReposRoots_DirCallback(void *closure, VestaSource::typeTag type,
00073   Arc arc, unsigned int index, /*UNUSED*/ Bit32 pseudoInode, 
00074   ShortId filesid, /*UNUSED*/ bool master)
00075   throw (SRPC::failure, ReposError)
00076 {
00077     CallbackArgs *args = (CallbackArgs *)closure;
00078     VestaSource::errorCode errCode;
00079 
00080     // handle directory and file cases differently
00081     switch (type) {
00082       case VestaSource::immutableFile:
00083         // skip this file if the parent dir type or the file name are wrong
00084         if (args->parent->type == VestaSource::immutableDirectory
00085             && ReposRoots_ValidFilename(arc)) {
00086             // form the PkgBuild and Pathname::T
00087             PkgBuild pkgBuild(args->parent->fptag, filesid);
00088             Pathname::T newPathT = Pathname::New(args->parentPath, arc);
00089 
00090             // add to the table
00091             (void) args->pkgTbl->Put(pkgBuild, newPathT);
00092         }
00093         break;
00094       case VestaSource::appendableDirectory:
00095       case VestaSource::immutableDirectory:
00096         // get this directory
00097         VestaSource *dir;
00098         errCode = args->parent->lookupIndex(index, /*OUT*/ dir);
00099         if (errCode != VestaSource::ok) {
00100             throw ReposError(errCode, "VestaSource::lookupIndex");
00101         }
00102 
00103         // form new Pathname::T
00104         Pathname::T newPathT = Pathname::New(args->parentPath, arc);
00105         
00106         // make recursive call
00107         ReposRoots_SearchRepos(dir, newPathT, /*INOUT*/ args->pkgTbl);
00108         break;
00109     }
00110     return true;
00111 } // ReposRoots_DirCallback
00112 
00113 static void ReposRoots_SearchRepos(VestaSource *reposDir, Pathname::T pathT,
00114   /*INOUT*/ PkgTbl *pkgTbl) throw (SRPC::failure, ReposError)
00115 /* Recursively search the subtree rooted at "reposDir", which is required to
00116    be an appendable or immutable directory. "pathT" is the "Pathname::T"
00117    corresponding to "path". For each file in an immutable directory with
00118    extension ".ves", add a mapping to "pkgTbl" for the file's complete
00119    pathname. Also add a mapping to "pkgTbl" for each immutable directory; the
00120    latter uses "NullShortId" for the shortid of the corresponding model. */
00121 {
00122     // add a mapping to "pkgTbl" if "reposDir" is immutable
00123     if (reposDir->type == VestaSource::immutableDirectory) {
00124         PkgBuild pkgBuild(reposDir->fptag, NullShortId);
00125         (void) pkgTbl->Put(pkgBuild, pathT);
00126     } else {
00127         assert(reposDir->type == VestaSource::appendableDirectory);
00128     }
00129 
00130     // fill in closure args
00131     CallbackArgs args;
00132     args.parent = reposDir;
00133     args.parentPath = pathT;
00134     args.pkgTbl = pkgTbl;
00135 
00136     VestaSource::errorCode errCode;
00137     errCode = reposDir->list(/*firstIndex=*/ 0,
00138       ReposRoots_DirCallback, (void *)(&args));
00139     if (errCode != VestaSource::ok) {
00140         throw ReposError(errCode, "VestaSource::list");
00141     }
00142 } // ReposRoots_SearchRepos
00143 
00144 PkgTbl *ReposRoots::Scan(bool debug) throw (SRPC::failure, ReposError)
00145 {
00146     // pre debugging
00147     if (debug) {
00148         cout << Debug::Timestamp() << "Starting repository scan" << endl;
00149         cout << endl;
00150     }
00151 
00152     // allocate result
00153     PkgTbl *res = NEW_CONSTR(PkgTbl, (/*sizeHint=*/ 2000, /*useGC=*/ true));
00154 
00155     // get repository appendable root
00156     VestaSource *reposRoot = VestaSource::repositoryRoot();
00157     assert(reposRoot->type == VestaSource::appendableDirectory);
00158 
00159     // read appendable root name from config file
00160     Text rootName(ReadConfig::TextVal("UserInterface", "AppendableRootName"));
00161     int rootNameLen = rootName.Length();
00162     Pathname::T rootPathT = Pathname::New(-1, rootName.chars());
00163 
00164     // recursively search subtree rooted at "path"
00165     ReposRoots_SearchRepos(reposRoot, rootPathT, /*INOUT*/ res);
00166 
00167     // post debugging
00168     if (debug) {
00169         cout << Debug::Timestamp() << "Finished repository scan" << endl;
00170         cout << "  total models found = " << res->Size() << endl;
00171         cout << endl;
00172     }
00173     return res;
00174 } // ReposRoots::Scan

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