Explorar el Código

HPCC-18086 Improve query dll copying/naming scheme

Signed-off-by: Anthony Fishbeck <anthony.fishbeck@lexisnexis.com>
Anthony Fishbeck hace 8 años
padre
commit
0d93456006

+ 37 - 9
esp/services/ws_workunits/ws_workunitsService.cpp

@@ -4244,7 +4244,13 @@ inline StringBuffer &buildFullDllPath(StringBuffer &dllpath, StringBuffer &dllna
     return addPathSepChar(dllpath.set(dir)).append(sharedObjectFileName(dllname, name, ext, copy));
 }
 
-void writeSharedObject(const char *srcpath, const MemoryBuffer &obj, const char *dir, StringBuffer &dllpath, StringBuffer &dllname, unsigned crc)
+void writeTempSharedObject(const MemoryBuffer &obj, const char *dir, StringBuffer &filename)
+{
+    OwnedIFileIO io = createUniqueFile(dir, "query_copy_dll_", NULL, filename);
+    io->write(0, obj.length(), obj.toByteArray());
+}
+
+void writeSharedObject(const char *srcpath, const MemoryBuffer &obj, const char *dir, StringBuffer &dllpath, StringBuffer &dllname)
 {
     StringBuffer name, ext;
     if (srcpath && *srcpath)
@@ -4252,18 +4258,40 @@ void writeSharedObject(const char *srcpath, const MemoryBuffer &obj, const char
 
     unsigned copy=0;
     buildFullDllPath(dllpath.clear(), dllname.clear(), dir, name.str(), ext.str(), copy);
-    while (checkFileExists(dllpath.str()))
+
+    unsigned crc=0;
+    StringBuffer tempDllName;
+    const unsigned attempts = 3; // max attempts
+    for (unsigned i=0; i<attempts; i++)
     {
-        if (crc && crc == crc_file(dllpath.str()))
+        while (checkFileExists(dllpath.str()))
+        {
+            if (crc==0)
+                crc = crc32(obj.toByteArray(), obj.length(), 0);
+            if (crc == crc_file(dllpath.str()))
+            {
+                DBGLOG("Workunit dll already exists: %s", dllpath.str());
+                if (tempDllName.length())
+                    removeFileTraceIfFail(tempDllName);
+                return;
+            }
+            buildFullDllPath(dllpath.clear(), dllname.clear(), dir, name.str(), ext.str(), ++copy);
+        }
+        try
         {
-            DBGLOG("Workunit dll already exists: %s", dllpath.str());
+            if (!tempDllName.length())
+                writeTempSharedObject(obj, dir, tempDllName);
+            renameFile(dllpath, tempDllName, false);
             return;
         }
-        buildFullDllPath(dllpath.clear(), dllname.clear(), dir, name.str(), ext.str(), ++copy);
+        catch (IException *e)
+        {
+            EXCLOG(e, "writeSharedObject"); //pretty small window for another copy of this dll to sneak by
+            e->Release();
+        }
     }
-    Owned<IFile> f = createIFile(dllpath.str());
-    Owned<IFileIO> io = f->open(IFOcreate);
-    io->write(0, obj.length(), obj.toByteArray());
+
+    throw MakeStringException(ECLWATCH_CANNOT_COPY_DLL, "Failed copying shared object %s", srcpath);
 }
 
 void deploySharedObject(IEspContext &context, StringBuffer &wuid, const char *filename, const char *cluster, const char *name, const MemoryBuffer &obj, const char *dir, const char *xml)
@@ -4299,7 +4327,7 @@ void deploySharedObject(IEspContext &context, StringBuffer &wuid, const char *fi
 
     if (!srcname.length())
         srcname.append(name).append(SharedObjectExtension);
-    writeSharedObject(srcname.str(), obj, dir, dllpath, dllname, crc);
+    writeSharedObject(srcname.str(), obj, dir, dllpath, dllname);
 
     NewWsWorkunit wu(context, wuid); //duplicate wuid made unique
 

+ 1 - 0
esp/smc/SMCLib/eclwatch_errorlist.hpp

@@ -124,6 +124,7 @@
 #define ECLWATCH_CANNOT_GET_STATUS_INFO     ECLWATCH_ERROR_START+104
 
 #define ECLWATCH_VIEW_ACCESS_DENIED         ECLWATCH_ERROR_START+105
+#define ECLWATCH_CANNOT_COPY_DLL            ECLWATCH_ERROR_START+106
 
 #endif //_ECLWATCH_ERRORLIST_HPP__