|
@@ -716,8 +716,8 @@ IDFSFile *lookupDFSFile(const char *logicalName, unsigned timeoutSecs, unsigned
|
|
|
throw makeStringException(-1, "Could not find any DFS services in the target HPCC configuration.");
|
|
|
}
|
|
|
}
|
|
|
- serviceUrl.append(dfsServiceUrls[currentDfsServiceUrl++].c_str());
|
|
|
- logicalName = remoteLogicalFileName;
|
|
|
+ serviceUrl.append(dfsServiceUrls[currentDfsServiceUrl].c_str());
|
|
|
+ currentDfsServiceUrl = (currentDfsServiceUrl+1 == dfsServiceUrls.size()) ? 0 : currentDfsServiceUrl+1;
|
|
|
remoteName.clear(); // local
|
|
|
#endif
|
|
|
}
|
|
@@ -797,6 +797,312 @@ IDistributedFile *lookupLegacyDFSFile(const char *logicalName, unsigned timeoutS
|
|
|
return createLegacyDFSFile(dfsFile);
|
|
|
}
|
|
|
|
|
|
+IDistributedFile *lookup(CDfsLogicalFileName &lfn, IUserDescriptor *user, bool write, bool hold, bool lockSuperOwner, IDistributedFileTransaction *transaction, bool priviledged, unsigned timeout)
|
|
|
+{
|
|
|
+ bool viaDali = false;
|
|
|
+
|
|
|
+ // DFS service currently only supports remote files
|
|
|
+ if (write)
|
|
|
+ viaDali = true;
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // switch to Dali if non-remote file, unless "dfsesp-localfiles" enabled (and non-external)
|
|
|
+ if (!lfn.isRemote())
|
|
|
+ {
|
|
|
+ if (lfn.isExternal() || (!getComponentConfigSP()->getPropBool("dfsesp-localfiles")))
|
|
|
+ viaDali = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (viaDali)
|
|
|
+ return queryDistributedFileDirectory().lookup(lfn, user, write, hold, lockSuperOwner, transaction, priviledged, timeout);
|
|
|
+
|
|
|
+ return wsdfs::lookupLegacyDFSFile(lfn.get(), timeout, wsdfs::keepAliveExpiryFrequency, user);
|
|
|
+}
|
|
|
+
|
|
|
+IDistributedFile *lookup(const char *logicalFilename, IUserDescriptor *user, bool write, bool hold, bool lockSuperOwner, IDistributedFileTransaction *transaction, bool priviledged, unsigned timeout)
|
|
|
+{
|
|
|
+ CDfsLogicalFileName lfn;
|
|
|
+ lfn.set(logicalFilename);
|
|
|
+ return lookup(lfn, user, write, hold, lockSuperOwner, transaction, priviledged, timeout);
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
} // namespace wsdfs
|
|
|
|
|
|
+
|
|
|
+class CLocalOrDistributedFile: implements ILocalOrDistributedFile, public CInterface
|
|
|
+{
|
|
|
+ bool fileExists;
|
|
|
+ Owned<IDistributedFile> dfile;
|
|
|
+ CDfsLogicalFileName lfn; // set if localpath but prob not useful
|
|
|
+ StringAttr localpath;
|
|
|
+ StringAttr fileDescPath;
|
|
|
+public:
|
|
|
+ IMPLEMENT_IINTERFACE;
|
|
|
+ CLocalOrDistributedFile()
|
|
|
+ {
|
|
|
+ fileExists = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual const char *queryLogicalName() override
|
|
|
+ {
|
|
|
+ return lfn.get();
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual IDistributedFile * queryDistributedFile() override
|
|
|
+ {
|
|
|
+ return dfile.get();
|
|
|
+ }
|
|
|
+
|
|
|
+ bool init(const char *fname,IUserDescriptor *user,bool onlylocal,bool onlydfs, bool write, bool isPrivilegedUser, const StringArray *clusters)
|
|
|
+ {
|
|
|
+ fileExists = false;
|
|
|
+ if (!onlydfs)
|
|
|
+ lfn.allowOsPath(true);
|
|
|
+ if (!lfn.setValidate(fname))
|
|
|
+ return false;
|
|
|
+ if (!onlydfs)
|
|
|
+ {
|
|
|
+ bool gotlocal = true;
|
|
|
+ if (isAbsolutePath(fname)||(stdIoHandle(fname)>=0))
|
|
|
+ localpath.set(fname);
|
|
|
+ else if (!strstr(fname,"::"))
|
|
|
+ {
|
|
|
+ // treat it as a relative file
|
|
|
+ StringBuffer fn;
|
|
|
+ localpath.set(makeAbsolutePath(fname,fn).str());
|
|
|
+ }
|
|
|
+ else if (!lfn.isExternal())
|
|
|
+ gotlocal = false;
|
|
|
+ if (gotlocal)
|
|
|
+ {
|
|
|
+ if (!write && !onlylocal) // MORE - this means the dali access checks not happening... maybe that's ok?
|
|
|
+ dfile.setown(wsdfs::lookup(lfn, user, write, false, false, nullptr, isPrivilegedUser, INFINITE));
|
|
|
+ Owned<IFile> file = getPartFile(0,0);
|
|
|
+ if (file.get())
|
|
|
+ {
|
|
|
+ fileExists = file->exists();
|
|
|
+ return fileExists || write;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!onlylocal)
|
|
|
+ {
|
|
|
+ if (lfn.isExternal() && !lfn.isRemote())
|
|
|
+ {
|
|
|
+ Owned<IFileDescriptor> fDesc = createExternalFileDescriptor(lfn.get());
|
|
|
+ dfile.setown(queryDistributedFileDirectory().createExternal(fDesc, lfn.get()));
|
|
|
+ Owned<IFile> file = getPartFile(0,0);
|
|
|
+ if (file.get())
|
|
|
+ fileExists = file->exists();
|
|
|
+ if (write && lfn.isExternal()&&(dfile->numParts()==1)) // if it is writing to an external file then don't return distributed
|
|
|
+ dfile.clear();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ dfile.setown(wsdfs::lookup(lfn, user, write, false, false, nullptr, isPrivilegedUser, INFINITE));
|
|
|
+ if (dfile.get())
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ StringBuffer dir;
|
|
|
+ unsigned stripeNum = 0;
|
|
|
+#ifdef _CONTAINERIZED
|
|
|
+ StringBuffer cluster;
|
|
|
+ if (clusters)
|
|
|
+ {
|
|
|
+ if (clusters->ordinality()>1)
|
|
|
+ throw makeStringExceptionV(0, "Container mode does not yet support output to multiple clusters while writing file %s)", fname);
|
|
|
+ cluster.append(clusters->item(0));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ getDefaultStoragePlane(cluster);
|
|
|
+ Owned<IStoragePlane> plane = getDataStoragePlane(cluster, true);
|
|
|
+ dir.append(plane->queryPrefix());
|
|
|
+ unsigned numStripedDevices = plane->numDevices();
|
|
|
+ stripeNum = calcStripeNumber(0, lfn.get(), numStripedDevices);
|
|
|
+#endif
|
|
|
+ StringBuffer descPath;
|
|
|
+ makePhysicalDirectory(descPath, lfn.get(), 0, DFD_OSdefault, dir);
|
|
|
+ fileDescPath.set(descPath);
|
|
|
+
|
|
|
+ // MORE - should we create the IDistributedFile here ready for publishing (and/or to make sure it's locked while we write)?
|
|
|
+ StringBuffer physicalPath;
|
|
|
+ makePhysicalPartName(lfn.get(), 1, 1, physicalPath, 0, DFD_OSdefault, dir, false, stripeNum); // more - may need to override path for roxie
|
|
|
+ localpath.set(physicalPath);
|
|
|
+ fileExists = (dfile != NULL);
|
|
|
+ return write;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual IFileDescriptor *getFileDescriptor() override
|
|
|
+ {
|
|
|
+ if (dfile.get())
|
|
|
+ return dfile->getFileDescriptor();
|
|
|
+ Owned<IFileDescriptor> fileDesc = createFileDescriptor();
|
|
|
+ fileDesc->setTraceName(lfn.get());
|
|
|
+ StringBuffer dir;
|
|
|
+ if (localpath.isEmpty()) { // e.g. external file
|
|
|
+ StringBuffer tail;
|
|
|
+ IException *e=NULL;
|
|
|
+ bool iswin=
|
|
|
+#ifdef _WIN32
|
|
|
+ true;
|
|
|
+#else
|
|
|
+ false;
|
|
|
+#endif
|
|
|
+ if (!lfn.getExternalPath(dir,tail,iswin,&e)) {
|
|
|
+ if (e)
|
|
|
+ throw e;
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ splitDirTail(fileDescPath,dir);
|
|
|
+ fileDesc->setDefaultDir(dir.str());
|
|
|
+ RemoteFilename rfn;
|
|
|
+ getPartFilename(rfn,0,0);
|
|
|
+ fileDesc->setPart(0,rfn);
|
|
|
+ fileDesc->queryPartDiskMapping(0).defaultCopies = DFD_DefaultCopies;
|
|
|
+ return fileDesc.getClear();
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual bool getModificationTime(CDateTime &dt) override
|
|
|
+ {
|
|
|
+ if (dfile.get())
|
|
|
+ return dfile->getModificationTime(dt);
|
|
|
+ Owned<IFile> file = getPartFile(0,0);
|
|
|
+ if (file.get()) {
|
|
|
+ CDateTime dt;
|
|
|
+ return file->getTime(NULL,&dt,NULL);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual unsigned numParts() override
|
|
|
+ {
|
|
|
+ if (dfile.get())
|
|
|
+ return dfile->numParts();
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual unsigned numPartCopies(unsigned partnum) override
|
|
|
+ {
|
|
|
+ if (dfile.get())
|
|
|
+ return dfile->queryPart(partnum).numCopies();
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual IFile *getPartFile(unsigned partnum,unsigned copy) override
|
|
|
+ {
|
|
|
+ RemoteFilename rfn;
|
|
|
+ if ((partnum==0)&&(copy==0))
|
|
|
+ return createIFile(getPartFilename(rfn,partnum,copy));
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual void getDirAndFilename(StringBuffer &dir, StringBuffer &filename) override
|
|
|
+ {
|
|
|
+ if (dfile.get())
|
|
|
+ {
|
|
|
+ dir.append(dfile->queryDefaultDir());
|
|
|
+ splitFilename(localpath, nullptr, nullptr, &filename, &filename);
|
|
|
+ }
|
|
|
+ else if (localpath.isEmpty())
|
|
|
+ {
|
|
|
+ RemoteFilename rfn;
|
|
|
+ lfn.getExternalFilename(rfn);
|
|
|
+ StringBuffer fullPath;
|
|
|
+ rfn.getLocalPath(fullPath);
|
|
|
+ splitFilename(localpath, nullptr, &dir, &filename, &filename);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ dir.append(fileDescPath);
|
|
|
+ splitFilename(localpath, nullptr, nullptr, &filename, &filename);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual RemoteFilename &getPartFilename(RemoteFilename &rfn, unsigned partnum,unsigned copy) override
|
|
|
+ {
|
|
|
+ if (dfile.get())
|
|
|
+ dfile->queryPart(partnum).getFilename(rfn,copy);
|
|
|
+ else if (localpath.isEmpty())
|
|
|
+ lfn.getExternalFilename(rfn);
|
|
|
+ else
|
|
|
+ rfn.setRemotePath(localpath);
|
|
|
+ return rfn;
|
|
|
+ }
|
|
|
+
|
|
|
+ StringBuffer &getPartFilename(StringBuffer &path, unsigned partnum,unsigned copy)
|
|
|
+ {
|
|
|
+ RemoteFilename rfn;
|
|
|
+ if (dfile.get())
|
|
|
+ dfile->queryPart(partnum).getFilename(rfn,copy);
|
|
|
+ else if (localpath.isEmpty())
|
|
|
+ lfn.getExternalFilename(rfn);
|
|
|
+ else
|
|
|
+ path.append(localpath);
|
|
|
+ if (rfn.isLocal())
|
|
|
+ rfn.getLocalPath(path);
|
|
|
+ else
|
|
|
+ rfn.getRemotePath(path);
|
|
|
+ return path;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual bool getPartCrc(unsigned partnum, unsigned &crc) override
|
|
|
+ {
|
|
|
+ if (dfile.get())
|
|
|
+ return dfile->queryPart(partnum).getCrc(crc);
|
|
|
+ Owned<IFile> file = getPartFile(0,0);
|
|
|
+ if (file.get()) {
|
|
|
+ crc = file->getCRC();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual offset_t getPartFileSize(unsigned partnum) override
|
|
|
+ {
|
|
|
+ if (dfile.get())
|
|
|
+ return dfile->queryPart(partnum).getFileSize(true,false);
|
|
|
+ Owned<IFile> file = getPartFile(0,0);
|
|
|
+ if (file.get())
|
|
|
+ return file->size();
|
|
|
+ return (offset_t)-1;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual offset_t getFileSize() override
|
|
|
+ {
|
|
|
+ if (dfile.get())
|
|
|
+ dfile->getFileSize(true,false);
|
|
|
+ offset_t ret = 0;
|
|
|
+ unsigned np = numParts();
|
|
|
+ for (unsigned i = 0;i<np;i++)
|
|
|
+ ret += getPartFileSize(i);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual bool exists() const override
|
|
|
+ {
|
|
|
+ return fileExists;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual bool isExternal() const override
|
|
|
+ {
|
|
|
+ return lfn.isExternal();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+ILocalOrDistributedFile* createLocalOrDistributedFile(const char *fname,IUserDescriptor *user,bool onlylocal,bool onlydfs, bool iswrite, bool isPrivilegedUser, const StringArray *clusters)
|
|
|
+{
|
|
|
+ Owned<CLocalOrDistributedFile> ret = new CLocalOrDistributedFile();
|
|
|
+ if (ret->init(fname,user,onlylocal,onlydfs,iswrite,isPrivilegedUser,clusters))
|
|
|
+ return ret.getClear();
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+
|