00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "Files.H"
00022 #include "EvalBasics.H"
00023 #include "ModelState.H"
00024 #include "Err.H"
00025 #include <ReposUI.H>
00026 #include <Replicator.H>
00027
00028 using std::fstream;
00029 using std::cout;
00030 using std::cerr;
00031 using std::endl;
00032
00033 extern "C" {void *opendir(const char *);}
00034 extern "C" {int closedir(void *);}
00035
00036 const char UnixDelimiter = '/';
00037
00038 bool IsDelimiter(const char c) {
00039 return (c == '/' || c == '\\');
00040 }
00041
00042 Text Canonical(const Text& path) {
00043
00044
00045
00046 int len = path.Length();
00047 const char *p = path.cchars();
00048 char *s = NEW_PTRFREE_ARRAY(char, len+1);
00049 int i;
00050
00051 for (i = 0; i < len; i++) {
00052 if (IsDelimiter(p[i])) s[i] = UnixDelimiter;
00053 else s[i] = p[i];
00054 }
00055 s[i] = 0;
00056 return Text(s);
00057 }
00058
00059 Text setSuffix(const Text& s, const Text& suff) {
00060 bool sf = false;
00061
00062 if (s == "/dev/null") return s;
00063 for (int i = 0; i < s.Length(); i++) {
00064 if (s[i] == '.') sf = true;
00065 else if (IsDelimiter(s[i])) sf = false;
00066 }
00067 return (sf) ? s : s + suff;
00068 }
00069
00070 bool IsAbsolutePath(const Text& path) {
00071 return !path.Empty() && IsDelimiter(path[0]);
00072 }
00073
00074 void SplitPath(const Text& path, Text& prefix, Text& name) {
00075 int n = path.Length() - 1;
00076 while (n >= 0 && !IsDelimiter(path[n])) n--;
00077 prefix = path.Sub(0, n+1);
00078 name = path.Sub(n+1);
00079 return;
00080 }
00081
00082 VestaSource::errorCode LookupPath(const Text& path, VestaSource *mRoot,
00083 VestaSource*& newRoot) {
00084 Text relPath;
00085 VestaSource *tempRoot;
00086 VestaSource::errorCode code = VestaSource::ok;
00087
00088 if (IsAbsolutePath(path)) {
00089 int i = 1;
00090 while (!IsDelimiter(path[i]) && i < path.Length()) i++;
00091 relPath = path.Sub(i+1);
00092 tempRoot = rRoot;
00093 }
00094 else {
00095 relPath = path;
00096 tempRoot = mRoot;
00097 }
00098 if (relPath.Empty())
00099 newRoot = tempRoot;
00100 else {
00101 code = tempRoot->lookupPathname(relPath.cchars(), newRoot);
00102 if((code == VestaSource::notFound) && autoRepl) {
00103 if(ReplicateMissing(tempRoot, relPath, newRoot))
00104 code = VestaSource::ok;
00105 }
00106 }
00107 return code;
00108 }
00109
00110
00111
00112 TextSeq SplitDefaultMains(const Text& defaultmain) throw()
00113 {
00114 TextSeq l_result;
00115
00116 unsigned int l_i = 0;
00117 while(l_i < defaultmain.Length())
00118 {
00119
00120 unsigned int l_start = l_i;
00121
00122
00123 while(!isspace(defaultmain[l_i]) &&
00124 (l_i < defaultmain.Length()))
00125 {
00126 l_i++;
00127 }
00128
00129 if(l_i > l_start)
00130 {
00131 l_result.addhi(defaultmain.Sub(l_start, (l_i - l_start)));
00132 }
00133
00134 while(isspace(defaultmain[l_i]) &&
00135 (l_i < defaultmain.Length()))
00136 {
00137 l_i++;
00138 }
00139 }
00140
00141 return l_result;
00142 }
00143
00144
00145
00146 Text FindExistingModel(const TextSeq &p_defaults, const Text& p_dir = "")
00147 {
00148 Text l_result;
00149
00150 for(unsigned int l_i = 0; l_i < p_defaults.size(); l_i++)
00151 {
00152 l_result = p_dir + p_defaults.get(l_i);
00153
00154 if(FS::Exists(l_result))
00155 {
00156 break;
00157 }
00158 }
00159 return l_result;
00160 }
00161
00162 Text MainModel(const Text& filename, const Text& defaultmain) {
00163 Text modelname(Canonical(filename));
00164 TextSeq l_defaults = SplitDefaultMains(defaultmain);
00165 if(modelname.Length() == 0)
00166 {
00167
00168
00169 modelname = FindExistingModel(l_defaults);
00170 }
00171 else
00172 {
00173 char c = modelname[modelname.Length()-1];
00174 if (IsDelimiter(c))
00175 {
00176
00177
00178 modelname = FindExistingModel(l_defaults, modelname);
00179 }
00180 else
00181 {
00182
00183 void *d = opendir(modelname.cchars());
00184 if (d == NULL)
00185 {
00186
00187
00188 modelname = setSuffix(modelname, ".ves");
00189 }
00190 else
00191 {
00192 (void)closedir(d);
00193
00194
00195 modelname = FindExistingModel(l_defaults,
00196 modelname + PathnameSep);
00197 }
00198 }
00199 }
00200 return modelname;
00201 }
00202
00203 bool IsDirectory(VestaSource *mRoot, Text& path, VestaSource*& vSource,
00204 VestaSource::errorCode& vSourceErr) {
00205 vSourceErr = LookupPath(path, mRoot, vSource);
00206 return (vSourceErr == VestaSource::ok &&
00207 vSource->type != VestaSource::immutableFile &&
00208 vSource->type != VestaSource::mutableFile);
00209 }
00210
00211 bool OpenSource(VestaSource *mRoot, const Text& fname, SrcLoc *loc,
00212 fstream*& iFile, VestaSource*& newRoot, ShortId& shortId,
00213 VestaSource*& vSource) {
00214 Text prefix, tail;
00215 VestaSource::errorCode err;
00216
00217 shortId = NullShortId;
00218 SplitPath(fname, prefix, tail);
00219 err = LookupPath(prefix, mRoot, newRoot);
00220 if(err != VestaSource::ok) {
00221 outputMu.lock();
00222 Error(VestaSourceErrorMsg(err) + " opening directory `" + prefix + "'.\n",
00223 loc);
00224 outputMu.unlock();
00225 return false;
00226 }
00227 err = newRoot->lookup(tail.cchars(), vSource);
00228 if (err != VestaSource::ok) {
00229 outputMu.lock();
00230 Error(VestaSourceErrorMsg(err) + " opening `" + fname + "'.\n", loc);
00231 outputMu.unlock();
00232 return false;
00233 }
00234 iFile = NULL;
00235 shortId = vSource->shortId();
00236 return true;
00237 }
00238
00239 bool ReplicateMissing(VestaSource* root, const Text& name,
00240 VestaSource*& vSource)
00241 {
00242 assert(autoRepl);
00243 if(!RootLongId.isAncestorOf(root->longid))
00244 return false;
00245 try {
00246 Text path = ReposUI::vsToFilename(root) + "/" + name;
00247 const int vlen = 7;
00248
00249 outputMu.lock();
00250 cout << "Trying to find a copy of " << path << endl;
00251 outputMu.unlock();
00252
00253 Text defhints;
00254 (void) VestaConfig::get("UserInterface", "DefaultHints", defhints);
00255 VestaSource* real_source = ReposUI::filenameToRealVS(path, defhints);
00256
00257 outputMu.lock();
00258 cout << "Replicating " << path << " from "
00259 << real_source->host() << ":" << real_source->port() << endl;
00260 outputMu.unlock();
00261
00262 Replicator repl(real_source->host(), real_source->port(),
00263 rRoot->host(), rRoot->port());
00264 Replicator::Directive d('+', path.Sub(vlen));
00265 Replicator::DirectiveSeq direcs;
00266 direcs.addhi(d);
00267 Replicator::Flags flags = (Replicator::Flags)
00268 (Replicator::attrNew | Replicator::attrOld | Replicator::attrAccess |
00269 Replicator::revive | Replicator::inclStubs | Replicator::latest);
00270 repl.replicate(&direcs, flags);
00271 vSource = ReposUI::filenameToVS(path, rRoot->host(), rRoot->port());
00272 delete real_source;
00273 return true;
00274 }
00275 catch(ReposUI::failure f){
00276 outputMu.lock();
00277 cerr << "ReposUI failure during replication of " << name << ": "
00278 << f.msg << endl;
00279 outputMu.unlock();
00280 return false;
00281 }
00282 catch(VestaConfig::failure f){
00283 outputMu.lock();
00284 cerr << "VestaConfig failure during replication of " << name << ": "
00285 << f.msg << endl;
00286 outputMu.unlock();
00287 return false;
00288 }
00289 catch(SRPC::failure f){
00290 outputMu.lock();
00291 cerr << "SRPC failure during replication of " << name << ": "
00292 << f.msg << " (" << f.r << ")" << endl;
00293 outputMu.unlock();
00294 return false;
00295 }
00296 catch(Replicator::Failure f){
00297 if(f.code == (VestaSource::errorCode) -1) {
00298 outputMu.lock();
00299 cerr << "Failure during replication of " << name << ": " << f.msg << endl;
00300 outputMu.unlock();
00301 }
00302 else {
00303 outputMu.lock();
00304 cerr << "Failure during replication of " << name << ": "
00305 << ReposUI::errorCodeText(f.code) << ", " << f.msg << endl;
00306 outputMu.unlock();
00307 }
00308 return false;
00309 }
00310 }