Browse Source

HPCC-9841 Deleting files from cluster other than original fails

If a file is present on more than one cluster, deleting the file from one
cluster is liable to delete the physical files from the original location of
the file rather than any subsequent copy.

Typically this means that when a file is created on thor then copied to Roxie,
an attempt to delete the roxie copy (via eclwatch) is liable to remove the
logical entry for the roxie copy, but the physical files for the thor entry.

The entire mechanism for multiple copies of data on more then one cluster
relies on the cluster descriptors being properly set up with directory
location at all times (but they were often not). This change should ensure
that they are, at least more often.

It may end up expanding the size of information stored in dali about file
locations though.

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 12 years ago
parent
commit
1fc21bbdca

+ 5 - 3
dali/base/dadfs.cpp

@@ -1181,7 +1181,7 @@ public:
         if (!file->canRemove(reason, false))
             ThrowStringException(-1, "Can't remove %s: %s", lfn.get(), reason.str());
 
-        // This will do the right thing for either super-files and logical-files
+        // This will do the right thing for either super-files and logical-files.
         file->detach();
     }
 };
@@ -3592,7 +3592,7 @@ public:
         if (newbasedir)
             diroverride = newbasedir;
 
-        const char *myBase = queryBaseDirectory(0, os);
+        const char *myBase = queryBaseDirectory(grp_unknown, 0, os);
         StringBuffer baseDir, newPath;
         makePhysicalPartName(logicalName.get(), 0, 0, newPath, false, os, diroverride);
         if (!getBase(directory, newPath, baseDir))
@@ -6210,8 +6210,10 @@ public:
             Owned<IPropertyTree> pt = getNamedPropTree(conn->queryRoot(),"Group","@name",gname.str(),true);
             if (!pt)
                 return NULL;
-            groupdir.set(pt->queryProp("@dir"));
             type = translateGroupType(pt->queryProp("@kind"));
+            groupdir.set(pt->queryProp("@dir"));
+            if (groupdir.isEmpty())
+                groupdir.set(queryBaseDirectory(type));
             Owned<IPropertyTreeIterator> pe2 = pt->getElements("Node");
             ForEach(*pe2) {
                 SocketEndpoint ep(pe2->query().queryProp("@ip"));

+ 0 - 2
dali/base/dadfs.hpp

@@ -570,8 +570,6 @@ extern da_decl IDistributedFileDirectory &queryDistributedFileDirectory();
 
 // ==GROUP STORE=================================================================================================
 
-enum GroupType { grp_thor, grp_thorspares, grp_roxie, grp_hthor, grp_unknown };
-
 interface INamedGroupIterator: extends IInterface
 {
     virtual bool first() = 0;

+ 101 - 55
dali/base/dafdesc.cpp

@@ -31,6 +31,7 @@
 #include "dasds.hpp"
 
 #include "dafdesc.hpp"
+#include "dadfs.hpp"
 
 #define INCLUDE_1_OF_1    // whether to use 1_of_1 for single part files
 
@@ -213,7 +214,7 @@ void ClusterPartDiskMapSpec::fromProp(IPropertyTree *tree)
     // if directory is specified then must match default base to be default replicated
     StringBuffer dir;
     if (tree&&tree->getProp("@directory",dir)) {
-        const char * base = queryBaseDirectory(0, SepCharBaseOs(getPathSepChar(dir.str())));
+        const char * base = queryBaseDirectory(grp_unknown, 0, SepCharBaseOs(getPathSepChar(dir.str())));
         size32_t l = strlen(base);
         if ((memcmp(base,dir.str(),l)!=0)||((l!=dir.length())&&!isPathSepChar(dir.charAt(l))))
             defrep = 0;
@@ -369,14 +370,22 @@ struct CClusterInfo: public CInterface, implements IClusterInfo
     StringAttr name; // group name
     StringAttr roxielabel; // roxie label (alternative to group name)
     ClusterPartDiskMapSpec mspec;
-    void checkClusterName(IGroupResolver *resolver)
+    void checkClusterName(INamedGroupStore *resolver)
     {
         // check name matches group
         if (resolver&&group) {
             if (!name.isEmpty()) {
-                Owned<IGroup> lgrp = resolver->lookup(name);
+                StringBuffer defaultDir;
+                GroupType groupType;
+                Owned<IGroup> lgrp = resolver->lookup(name, defaultDir, groupType);
                 if (lgrp&&lgrp->equals(group))
+                {
+                    if (mspec.defaultBaseDir.isEmpty())
+                    {
+                        mspec.setDefaultBaseDir(defaultDir);   // MORE - should possibly set up the rest of the mspec info from the group info here
+                    }
                     return; // ok
+                }
                 name.clear();
             }
             StringBuffer gname;
@@ -387,7 +396,7 @@ struct CClusterInfo: public CInterface, implements IClusterInfo
 
 public:
     IMPLEMENT_IINTERFACE;
-    CClusterInfo(MemoryBuffer &mb,IGroupResolver *resolver)
+    CClusterInfo(MemoryBuffer &mb,INamedGroupStore *resolver)
     {
         StringAttr grptext;
         mb.read(grptext);
@@ -402,7 +411,7 @@ public:
         checkClusterName(resolver);
     }
 
-    CClusterInfo(const char *_name,IGroup *_group,const ClusterPartDiskMapSpec &_mspec,IGroupResolver *resolver,const char *_roxielabel)
+    CClusterInfo(const char *_name,IGroup *_group,const ClusterPartDiskMapSpec &_mspec,INamedGroupStore *resolver,const char *_roxielabel)
         : name(_name),group(_group), roxielabel(_roxielabel)
     {
         name.toLowerCase();
@@ -410,19 +419,29 @@ public:
         mspec =_mspec;
         checkClusterName(resolver);
     }
-    CClusterInfo(IPropertyTree *pt,IGroupResolver *resolver,unsigned flags)
+    CClusterInfo(IPropertyTree *pt,INamedGroupStore *resolver,unsigned flags)
     {
         if (!pt)
             return;
         name.set(pt->queryProp("@name"));
         roxielabel.set(pt->queryProp("@roxieLabel"));
+        mspec.fromProp(pt);
         if ((((flags&IFDSF_EXCLUDE_GROUPS)==0)||name.isEmpty())&&pt->hasProp("Group"))
             group.setown(createIGroup(pt->queryProp("Group")));
         if (!name.isEmpty()&&!group.get()&&resolver)
-            group.setown(resolver->lookup(name.get()));
+        {
+            StringBuffer defaultDir;
+            GroupType groupType;
+            group.setown(resolver->lookup(name.get(), defaultDir, groupType));
+            if (mspec.defaultBaseDir.isEmpty())
+            {
+                mspec.setDefaultBaseDir(defaultDir);   // MORE - should possibly set up the rest of the mspec info from the group info here
+                // MORE - work out why this code pulled out of checkClusterName (to bypass the roxieLabel stuff, I assume)
+                // and work out what the roxielabel stuff is trying to do and if still needed/wanted
+            }
+        }
         else
             checkClusterName(resolver);
-        mspec.fromProp(pt);
     }
 
     const char *queryGroupName()
@@ -525,16 +544,16 @@ public:
 
     void getBaseDir(StringBuffer &basedir,DFD_OS os)
     {
-        if (mspec.defaultBaseDir.isEmpty())  // assume thor default
-            basedir.append(queryBaseDirectory(0, os));
+        if (mspec.defaultBaseDir.isEmpty())  // assume current platform's default
+            basedir.append(queryBaseDirectory(grp_unknown, 0, os));
         else
             basedir.append(mspec.defaultBaseDir);
     }
 
     void getReplicateDir(StringBuffer &basedir,DFD_OS os)
     {
-        if (mspec.defaultReplicateDir.isEmpty())  // assume thor default
-            basedir.append(queryBaseDirectory(1, os));
+        if (mspec.defaultReplicateDir.isEmpty())  // assume current platform's default
+            basedir.append(queryBaseDirectory(grp_unknown, 1, os));
         else
             basedir.append(mspec.defaultReplicateDir);
     }
@@ -563,19 +582,19 @@ public:
 IClusterInfo *createClusterInfo(const char *name,
                                 IGroup *grp,
                                 const ClusterPartDiskMapSpec &mspec,
-                                IGroupResolver *resolver,
+                                INamedGroupStore *resolver,
                                 const char *roxielabel)
 {
     return new CClusterInfo(name,grp,mspec,resolver,roxielabel);
 }
 IClusterInfo *deserializeClusterInfo(MemoryBuffer &mb,
-                                IGroupResolver *resolver)
+                                INamedGroupStore *resolver)
 {
     return new CClusterInfo(mb,resolver);
 }
 
 IClusterInfo *deserializeClusterInfo(IPropertyTree *pt,
-                                IGroupResolver *resolver,
+                                INamedGroupStore *resolver,
                                 unsigned flags)
 {
     return new CClusterInfo(pt,resolver,flags);
@@ -875,7 +894,7 @@ public:
     CPartDescriptorArray array;
 };
 
-void getClusterInfo(IPropertyTree &pt, IGroupResolver *resolver, unsigned flags, IArrayOf<IClusterInfo> &clusters)
+void getClusterInfo(IPropertyTree &pt, INamedGroupStore *resolver, unsigned flags, IArrayOf<IClusterInfo> &clusters)
 {
     unsigned nc = pt.getPropInt("@numclusters");
     if (!nc) { // legacy format
@@ -1348,7 +1367,7 @@ public:
 
 
 
-    CFileDescriptor(IPropertyTree *tree,IGroupResolver *resolver,unsigned flags)
+    CFileDescriptor(IPropertyTree *tree, INamedGroupStore *resolver, unsigned flags)
     {
         pending = NULL;
         if ((flags&IFDSF_ATTR_ONLY)||!tree) {
@@ -1541,7 +1560,7 @@ public:
             if (!sc)
                 sc = getPathSepChar(dirname);
             StringBuffer tmp;
-            tmp.append(queryBaseDirectory(0, SepCharBaseOs(sc))).append(sc).append(s);
+            tmp.append(queryBaseDirectory(grp_unknown, 0, SepCharBaseOs(sc))).append(sc).append(s);
             directory.set(tmp.str());
         }
         else
@@ -2208,9 +2227,9 @@ IFileDescriptor *deserializeFileDescriptor(MemoryBuffer &mb)
     return doDeserializePartFileDescriptors(mb,NULL);
 }
 
-IFileDescriptor *deserializeFileDescriptorTree(IPropertyTree *tree,IGroupResolver *resolver,unsigned flags)
+IFileDescriptor *deserializeFileDescriptorTree(IPropertyTree *tree, INamedGroupStore *resolver, unsigned flags)
 {
-    return new CFileDescriptor(tree,resolver,flags);
+    return new CFileDescriptor(tree, resolver, flags);
 }
 
 
@@ -2220,8 +2239,31 @@ inline bool validFNameChar(char c)
     return (c>=32 && c<127 && !strchr(invalids, c));
 }
 
-static StringAttr winbasedirs[MAX_REPLICATION_LEVELS];
-static StringAttr unixbasedirs[MAX_REPLICATION_LEVELS];
+static const char * defaultWindowsBaseDirectories[__grp_size][MAX_REPLICATION_LEVELS] =
+    {
+            { "c:\\thordata", "d:\\thordata" },
+            { "c:\\thordata", "d:\\thordata" },
+            { "c:\\roxiedata", "d:\\roxiedata" },
+            { "c:\\hthordata", "d:\\hthordata" },
+    };
+static const char * defaultUnixBaseDirectories[__grp_size][MAX_REPLICATION_LEVELS] =
+    {
+        { "/var/lib/HPCCSystems/hpcc-data/thor", "/var/lib/HPCCSystems/hpcc-mirror/thor" },
+        { "/var/lib/HPCCSystems/hpcc-data/thor", "/var/lib/HPCCSystems/hpcc-mirror/thor" },
+        { "/var/lib/HPCCSystems/hpcc-data/roxie", "/var/lib/HPCCSystems/hpcc-data2/roxie", "/var/lib/HPCCSystems/hpcc-data3/roxie", "/var/lib/HPCCSystems/hpcc-data4/roxie" },
+        { "/var/lib/HPCCSystems/hpcc-data/eclagent", "/var/lib/HPCCSystems/hpcc-mirror/eclagent" },
+    };
+static const char *componentNames[__grp_size] =
+    {
+        "thor", "thor", "roxie", "eclagent", "unknown"
+    };
+static const char *dirTypeNames[MAX_REPLICATION_LEVELS] =
+    {
+        "data", "data2", "data3", "data4"
+    };
+
+static StringAttr windowsBaseDirectories[__grp_size][MAX_REPLICATION_LEVELS];
+static StringAttr unixBaseDirectories[__grp_size][MAX_REPLICATION_LEVELS];
 
 static StringAttr defaultpartmask("$L$._$P$_of_$N$");
 
@@ -2233,39 +2275,42 @@ void loadDefaultBases()
     if (ldbDone)
         return;
     ldbDone = true;
-    // assumed default first thor
-    // first set 
-    if (winbasedirs[1].isEmpty())
-        winbasedirs[1].set("d:\\thordata");
-    if (winbasedirs[0].isEmpty())
-        winbasedirs[0].set("c:\\thordata");
+
     SessionId mysessid = myProcessSession();
-    if (mysessid && (unixbasedirs[1].isEmpty() || unixbasedirs[0].isEmpty())) {
+    if (mysessid)
+    {
         Owned<IRemoteConnection> conn = querySDS().connect("/Environment/Software/Directories", mysessid, RTM_LOCK_READ, SDS_CONNECT_TIMEOUT);
         if (conn) {
             IPropertyTree* dirs = conn->queryRoot();
-            StringBuffer dirout;
-            if (unixbasedirs[1].isEmpty())
-                if (getConfigurationDirectory(dirs,"mirror", "thor",
-                    "mythor",   // NB this is dummy value should really get 1st thor (but actually hopefully not used anyway)
-                    dirout))
-                    unixbasedirs[1].set(dirout.str());
-            if (unixbasedirs[0].isEmpty())
-                if (getConfigurationDirectory(dirs,"data", "thor",
-                    "mythor",   // NB this is dummy value should really get 1st thor (but actually hopefully not used anyway)
-                    dirout.clear()))
-                    unixbasedirs[0].set(dirout.str());
-
-        }
-    }
-    if (unixbasedirs[0].isEmpty())
-        unixbasedirs[0].set("/var/lib/HPCCSystems/hpcc-data/thor");
-    if (unixbasedirs[1].isEmpty())
-        unixbasedirs[1].set("/var/lib/HPCCSystems/hpcc-mirror/thor");
+            for (unsigned groupType = 0; groupType < __grp_size; groupType++)
+            {
+                const char *component = componentNames[groupType];
+                for (unsigned replicationLevel = 0; replicationLevel < MAX_REPLICATION_LEVELS; replicationLevel++)
+                {
+                    StringBuffer dirout;
+                    const char *dirType = dirTypeNames[replicationLevel];
+                    if (replicationLevel==1 && groupType!=grp_roxie)
+                        dirType = "mirror";
+                    if (getConfigurationDirectory(dirs, dirType, component,
+                        "dummy",   // NB this is dummy value (but actually hopefully not used anyway)
+                        dirout))
+                       unixBaseDirectories[groupType][replicationLevel].set(dirout.str());
+                }
+            }
+        }
+    }
+    for (unsigned groupType = 0; groupType < __grp_size; groupType++)
+        for (unsigned replicationLevel = 0; replicationLevel < MAX_REPLICATION_LEVELS; replicationLevel++)
+        {
+            if (unixBaseDirectories[groupType][replicationLevel].isEmpty())
+                unixBaseDirectories[groupType][replicationLevel].set(defaultUnixBaseDirectories[groupType][replicationLevel]);
+            if (windowsBaseDirectories[groupType][replicationLevel].isEmpty())
+                windowsBaseDirectories[groupType][replicationLevel].set(defaultWindowsBaseDirectories[groupType][replicationLevel]);
+        }
 }
 
 
-const char *queryBaseDirectory(unsigned replicateLevel, DFD_OS os)
+const char *queryBaseDirectory(GroupType groupType, unsigned replicateLevel, DFD_OS os)
 {
     if (os==DFD_OSdefault)
 #ifdef _WIN32
@@ -2278,9 +2323,9 @@ const char *queryBaseDirectory(unsigned replicateLevel, DFD_OS os)
     switch (os)
     {
     case DFD_OSwindows:
-        return winbasedirs[replicateLevel];
+        return windowsBaseDirectories[groupType][replicateLevel];
     case DFD_OSunix:
-        return unixbasedirs[replicateLevel];
+        return unixBaseDirectories[groupType][replicateLevel];
     }
     return NULL;
 }
@@ -2297,6 +2342,7 @@ void setBaseDirectory(const char * dir, unsigned replicateLevel, DFD_OS os)
         os = DFD_OSunix;
 #endif
     assertex(replicateLevel < MAX_REPLICATION_LEVELS);
+    loadDefaultBases();
     StringBuffer out;
     if (!dir||!*dir||!isAbsolutePath(dir))
         throw MakeStringException(-1,"setBaseDirectory(%s) requires an absolute path",dir ? dir : "null");
@@ -2305,10 +2351,10 @@ void setBaseDirectory(const char * dir, unsigned replicateLevel, DFD_OS os)
         l--;
     switch (os) {
     case DFD_OSwindows:
-        winbasedirs[replicateLevel].set(dir,l);
+        windowsBaseDirectories[grp_unknown][replicateLevel].set(dir,l);
         break;
     case DFD_OSunix:
-        unixbasedirs[replicateLevel].set(dir,l);
+        unixBaseDirectories[grp_unknown][replicateLevel].set(dir,l);
         break;
     }
 }
@@ -2462,7 +2508,7 @@ StringBuffer &makePhysicalPartName(const char *lname, unsigned partno, unsigned
         result.append(diroverride);
     }
     else
-        result.append(queryBaseDirectory(replicateLevel, os));
+        result.append(queryBaseDirectory(grp_unknown, replicateLevel, os));
 
     size32_t l = result.length();
     if ((l>3)&&(result.charAt(l-1)!=OsSepChar(os))) {
@@ -2540,7 +2586,7 @@ bool setReplicateDir(const char *dir,StringBuffer &out,bool isrep,const char *ba
     if (!sep)
         return false;
     DFD_OS os = SepCharBaseOs(*sep);
-    const char *d = baseDir?baseDir:queryBaseDirectory(isrep ? 0 : 1,os);
+    const char *d = baseDir?baseDir:queryBaseDirectory(grp_unknown, isrep ? 0 : 1,os);
     if (!d)
         return false;
     unsigned match = 0;
@@ -2551,7 +2597,7 @@ bool setReplicateDir(const char *dir,StringBuffer &out,bool isrep,const char *ba
             match = i;
             count++;
         }
-    const char *r = repDir?repDir:queryBaseDirectory(isrep ? 1 : 0,os);
+    const char *r = repDir?repDir:queryBaseDirectory(grp_unknown, isrep ? 1 : 0,os);
     if (d[i]==0) {
         if ((dir[i]==0)||isPathSepChar(dir[i])) {
             out.append(r).append(dir+i);

+ 10 - 6
dali/base/dafdesc.hpp

@@ -31,6 +31,7 @@ interface IPropertyTree;
 interface IFileDescriptor;
 interface IClusterInfo;
 interface IReplicatedFile;
+interface INamedGroupStore;
 
 #define SUPPORTS_MULTI_CLUSTERS  // always now set
 
@@ -49,6 +50,9 @@ enum DFD_Replicate
     DFD_DefaultCopies = 2
 };
 
+enum GroupType { grp_thor, grp_thorspares, grp_roxie, grp_hthor, grp_unknown, __grp_size };
+
+
 // ==CLUSTER PART MAPPING ==============================================================================================
 
 // repeatedPart flags
@@ -274,19 +278,19 @@ interface IClusterInfo: extends IInterface  // used by IFileDescriptor and IDist
 IClusterInfo *createClusterInfo(const char *grpname,                  // NULL if roxie label set
                                 IGroup *grp,
                                 const ClusterPartDiskMapSpec &mspec,
-                                IGroupResolver *resolver=NULL,
+                                INamedGroupStore *resolver=NULL,
                                 const char *roxielabel = NULL        // set for roxie 
                                 );
 IClusterInfo *createRoxieClusterInfo(const char *label,
                                 const ClusterPartDiskMapSpec &mspec
                                 );
 IClusterInfo *deserializeClusterInfo(MemoryBuffer &mb,
-                                IGroupResolver *resolver=NULL);
+                                INamedGroupStore *resolver=NULL);
 IClusterInfo *deserializeClusterInfo(IPropertyTree *pt,
-                                IGroupResolver *resolver=NULL,
+                                INamedGroupStore *resolver=NULL,
                                 unsigned flags=0);
 
-void getClusterInfo(IPropertyTree &pt, IGroupResolver *resolver, unsigned flags, IArrayOf<IClusterInfo> &clusters);
+void getClusterInfo(IPropertyTree &pt, INamedGroupStore *resolver, unsigned flags, IArrayOf<IClusterInfo> &clusters);
 
 
 
@@ -311,7 +315,7 @@ extern da_decl StringBuffer &makeSinglePhysicalPartName(const char *lname, // si
                                                         );    
 
 // set/get defaults
-extern da_decl const char *queryBaseDirectory(unsigned replicateLevel=0, DFD_OS os=DFD_OSdefault);
+extern da_decl const char *queryBaseDirectory(GroupType groupType, unsigned replicateLevel=0, DFD_OS os=DFD_OSdefault);
 extern da_decl void setBaseDirectory(const char * dir, unsigned replicateLevel=0, DFD_OS os=DFD_OSdefault);
 extern da_decl const char *queryPartMask();
 extern da_decl StringBuffer &getPartMask(StringBuffer &ret,const char *lname=NULL,unsigned partmax=0);
@@ -322,7 +326,7 @@ extern da_decl IFileDescriptor *createFileDescriptor();
 extern da_decl IFileDescriptor *createFileDescriptor(IPropertyTree *attr);      // ownership of attr tree is taken
 extern da_decl ISuperFileDescriptor *createSuperFileDescriptor(IPropertyTree *attr);        // ownership of attr tree is taken
 extern da_decl IFileDescriptor *deserializeFileDescriptor(MemoryBuffer &mb);
-extern da_decl IFileDescriptor *deserializeFileDescriptorTree(IPropertyTree *tree,IGroupResolver *resolver=NULL,unsigned flags=0);  // flags IFDSF_*
+extern da_decl IFileDescriptor *deserializeFileDescriptorTree(IPropertyTree *tree, INamedGroupStore *resolver=NULL, unsigned flags=0);  // flags IFDSF_*
 extern da_decl IFileDescriptor *createFileDescriptor(const char *lname,IGroup *grp,IPropertyTree *tree,DFD_OS os=DFD_OSdefault,unsigned width=0);  // creates default
 extern da_decl IPartDescriptor *deserializePartFileDescriptor(MemoryBuffer &mb);
 extern da_decl void deserializePartFileDescriptors(MemoryBuffer &mb,IArrayOf<IPartDescriptor> &parts);

+ 1 - 1
dali/base/dautils.cpp

@@ -979,7 +979,7 @@ bool CDfsLogicalFileName::setFromMask(const char *fname,const char *rootdir)
         return false;
     // first remove base dir from fname if present
     DFD_OS os = SepCharBaseOs(getPathSepChar(fname));
-    const char *dir = (rootdir&&*rootdir)?rootdir:queryBaseDirectory(0, os);
+    const char *dir = (rootdir&&*rootdir)?rootdir:queryBaseDirectory(grp_unknown, 0, os);
     // ignore drive if present
     if (os==DFD_OSwindows) {
         if (dir[1]==':')

+ 2 - 2
dali/dfuXRefLib/dfuxreflib.cpp

@@ -2677,8 +2677,8 @@ IPropertyTree *  runXRef(unsigned nclusters,const char **clusters,IXRefProgressC
     Owned<IGroup> group = queryNamedGroupStore().lookup(clusters[0]);
     if (group)
         islinux = queryOS(group->queryNode(0).endpoint())==MachineOsLinux;
-    dirs[0] = queryBaseDirectory(0,islinux?DFD_OSunix:DFD_OSwindows);
-    dirs[1] = queryBaseDirectory(1,islinux?DFD_OSunix:DFD_OSwindows);
+    dirs[0] = queryBaseDirectory(grp_unknown, 0,islinux?DFD_OSunix:DFD_OSwindows);  // MORE - should use the info from the group store
+    dirs[1] = queryBaseDirectory(grp_unknown, 1,islinux?DFD_OSunix:DFD_OSwindows);
     numdirs = 2;
     IPropertyTree *ret=NULL;
     try {

+ 1 - 1
dali/sasha/saxref.cpp

@@ -807,7 +807,7 @@ public:
             iswin = grp->ordinality()?(getDaliServixOs(grp->queryNode(0).endpoint())==DAFS_OSwindows):false;
             setBaseDirectory(ddir,0,iswin?DFD_OSwindows:DFD_OSunix);
             setBaseDirectory(rdir,1,iswin?DFD_OSwindows:DFD_OSunix);
-            rootdir.set(queryBaseDirectory(0,iswin?DFD_OSwindows:DFD_OSunix));
+            rootdir.set(queryBaseDirectory(grp_unknown, 0, iswin?DFD_OSwindows:DFD_OSunix));
         }
         else {
             rootdir.set(basedir);

+ 1 - 1
thorlcr/graph/thgraphmaster.cpp

@@ -1483,7 +1483,7 @@ void CJobMaster::saveSpills()
 
             StringBuffer newName;
             queryThorFileManager().addScope(*this, tmpName, newName, true, true);
-            verifyex(file->renamePhysicalPartFiles(newName.str(), NULL, NULL, queryBaseDirectory()));
+            verifyex(file->renamePhysicalPartFiles(newName.str(), NULL, NULL, queryBaseDirectory(grp_unknown)));
 
             file->attach(newName,userDesc);
 

+ 1 - 1
thorlcr/graph/thgraphslave.cpp

@@ -1107,7 +1107,7 @@ void CJobSlave::startJob()
     unsigned minFreeSpace = (unsigned)getWorkUnitValueInt("MINIMUM_DISK_SPACE", 0);
     if (minFreeSpace)
     {
-        unsigned __int64 freeSpace = getFreeSpace(queryBaseDirectory());
+        unsigned __int64 freeSpace = getFreeSpace(queryBaseDirectory(grp_unknown, 0));
         if (freeSpace < ((unsigned __int64)minFreeSpace)*0x100000)
         {
             SocketEndpoint ep;

+ 2 - 2
thorlcr/thorutil/thormisc.cpp

@@ -1236,8 +1236,8 @@ void sendInChunks(ICommunicator &comm, rank_t dst, mptag_t mpTag, IRowStream *in
 void logDiskSpace()
 {
     StringBuffer diskSpaceMsg("Disk space: ");
-    diskSpaceMsg.append(queryBaseDirectory()).append(" = ").append(getFreeSpace(queryBaseDirectory())/0x100000).append(" MB, ");
-    diskSpaceMsg.append(queryBaseDirectory(true)).append(" = ").append(getFreeSpace(queryBaseDirectory(true))/0x100000).append(" MB, ");
+    diskSpaceMsg.append(queryBaseDirectory(grp_unknown, 0)).append(" = ").append(getFreeSpace(queryBaseDirectory(grp_unknown, 0))/0x100000).append(" MB, ");
+    diskSpaceMsg.append(queryBaseDirectory(grp_unknown, 1)).append(" = ").append(getFreeSpace(queryBaseDirectory(grp_unknown, 1))/0x100000).append(" MB, ");
     const char *tempDir = globals->queryProp("@thorTempDirectory");
     diskSpaceMsg.append(tempDir).append(" = ").append(getFreeSpace(tempDir)/0x100000).append(" MB");
     PROGLOG("%s", diskSpaceMsg.str());