diff --git a/.github/workflows/build-assets.yml b/.github/workflows/build-assets.yml index 7d3ec45658d..6857a697ef2 100644 --- a/.github/workflows/build-assets.yml +++ b/.github/workflows/build-assets.yml @@ -112,6 +112,10 @@ jobs: - os: ubuntu-20.04 name: LN ln: true + - os: centos-8 + name: LN + cmake_options_extra: "" + ln: true - os: centos-7 name: LN cmake_options_extra: "-DVCPKG_TARGET_TRIPLET=x64-centos-7-dynamic" diff --git a/.gitmodules b/.gitmodules index cb5d20fdadd..7a1feb78615 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,3 @@ -[submodule "esp/src/xstyle"] - path = esp/src/xstyle - url = https://github.com/hpcc-systems/xstyle.git -[submodule "esp/src/put-selector"] - path = esp/src/put-selector - url = https://github.com/hpcc-systems/put-selector.git [submodule "esp/src/dgrid"] path = esp/src/dgrid url = https://github.com/hpcc-systems/dgrid.git diff --git a/common/wuanalysis/anaerrorcodes.hpp b/common/wuanalysis/anaerrorcodes.hpp index e2503c27759..37198fb970a 100644 --- a/common/wuanalysis/anaerrorcodes.hpp +++ b/common/wuanalysis/anaerrorcodes.hpp @@ -9,7 +9,7 @@ typedef enum ANA_DISTRIB_SKEW_INPUT_ID, ANA_DISTRIB_SKEW_OUTPUT_ID, ANA_IOSKEW_RECORDS_ID, - ANA_UNUSED_ID, /* May re-use but don't remove to avoid changing later id's */ + ANA_EXECUTE_SKEW_ID, ANA_KJ_EXCESS_PREFILTER_ID } AnalyzerErrorCode; diff --git a/common/wuanalysis/anarule.cpp b/common/wuanalysis/anarule.cpp index 0191d17271c..5180c22d44d 100644 --- a/common/wuanalysis/anarule.cpp +++ b/common/wuanalysis/anarule.cpp @@ -183,6 +183,57 @@ class IoSkewRule : public AActivityRule const char * category; }; +class LocalExecuteSkewRule : public AActivityRule +{ +public: + virtual bool isCandidate(IWuActivity & activity) const override + { + switch (activity.getAttr(WaKind)) + { + case TAKfirstn: // skew is expected, so ignore + case TAKtopn: + case TAKsort: + return false; + } + return true; + } + + virtual bool check(PerformanceIssue & result, IWuActivity & activity, const IAnalyserOptions & options) override + { + stat_type localExecuteMaxSkew = activity.getStatRaw(StTimeLocalExecute, StSkewMax); + if (localExecuteMaxSkewgetStatRaw(StNumRowsProcessed, StSkewMax)>options.queryOption(watOptSkewThreshold)) + { + inputSkewed = true; + break; + } + } + bool outputSkewed = false; + IWuEdge *wuOutputEdge = activity.queryOutput(0); + if (wuOutputEdge && (wuOutputEdge->getStatRaw(StNumRowsProcessed, StSkewMax)>options.queryOption(watOptSkewThreshold))) + outputSkewed = true; + + if (inputSkewed) + result.set(ANA_EXECUTE_SKEW_ID, timePenalty, "Significant skew in local execute time caused by uneven input"); + else if (outputSkewed) + result.set(ANA_EXECUTE_SKEW_ID, timePenalty, "Significant skew in local execute time caused by uneven output"); + else + result.set(ANA_EXECUTE_SKEW_ID, timePenalty, "Significant skew in local execute time"); + return true; + } +}; + class KeyedJoinExcessRejectedRowsRule : public ActivityKindRule { public: @@ -221,4 +272,5 @@ void gatherRules(CIArrayOf & rules) rules.append(*new IoSkewRule(StTimeDiskWriteIO, "disk write")); rules.append(*new IoSkewRule(StTimeSpillElapsed, "spill")); rules.append(*new KeyedJoinExcessRejectedRowsRule); + rules.append(*new LocalExecuteSkewRule); } diff --git a/dali/base/dadfs.cpp b/dali/base/dadfs.cpp index ae41b7d390f..31c3d422a0e 100644 --- a/dali/base/dadfs.cpp +++ b/dali/base/dadfs.cpp @@ -177,41 +177,49 @@ static IPropertyTree *getEmptyAttr() return createPTree("Attr"); } -extern da_decl void calcFileCost(const char * cluster, double sizeGB, double fileAgeDays, __int64 numDiskWrites, __int64 numDiskReads, double & atRestCost, double & accessCost) +static IPropertyTree *getCostPropTree(const char *cluster) { Owned plane = getStoragePlane(cluster); - Owned global; - IPropertyTree * costPT = nullptr; if (plane && plane->hasProp("cost/@storageAtRest")) { - costPT = plane->queryPropTree("cost"); + return plane->getPropTree("cost"); } else { - global.setown(getGlobalConfig()); - costPT = global->queryPropTree("cost"); + return getGlobalConfigSP()->getPropTree("cost"); } +} + +extern da_decl double calcFileAtRestCost(const char * cluster, double sizeGB, double fileAgeDays) +{ + Owned costPT = getCostPropTree(cluster); + if (costPT==nullptr) - { - atRestCost = 0.0; - accessCost = 0.0; - return; - } - constexpr int accessPriceScalingFactor = 10000; // read/write pricing based on 10,000 operations + return 0.0; double atRestPrice = costPT->getPropReal("@storageAtRest", 0.0); - double readPrice = costPT->getPropReal("@storageReads", 0.0); - double writePrice = costPT->getPropReal("@storageWrites", 0.0); double storageCostDaily = atRestPrice * 12 / 365; - atRestCost = storageCostDaily * sizeGB * fileAgeDays; - accessCost = (readPrice * numDiskReads / accessPriceScalingFactor) + (writePrice * numDiskWrites / accessPriceScalingFactor); + return storageCostDaily * sizeGB * fileAgeDays; } extern da_decl double calcFileAccessCost(const char * cluster, __int64 numDiskWrites, __int64 numDiskReads) { - double atRestCost, accessCost; - calcFileCost(cluster, 0, 0, numDiskWrites, numDiskReads, atRestCost, accessCost); - return accessCost; + Owned costPT = getCostPropTree(cluster); + + if (costPT==nullptr) + return 0.0; + constexpr int accessPriceScalingFactor = 10000; // read/write pricing based on 10,000 operations + double readPrice = costPT->getPropReal("@storageReads", 0.0); + double writePrice = costPT->getPropReal("@storageWrites", 0.0); + return (readPrice * numDiskReads / accessPriceScalingFactor) + (writePrice * numDiskWrites / accessPriceScalingFactor); +} + +extern da_decl double calcFileAccessCost(IDistributedFile *f, __int64 numDiskWrites, __int64 numDiskReads) +{ + StringBuffer clusterName; + // Should really specify the cluster number too, but this is the best we can do for now + f->getClusterName(0, clusterName); + return calcFileAccessCost(clusterName, numDiskWrites, numDiskReads); } RemoteFilename &constructPartFilename(IGroup *grp,unsigned partno,unsigned partmax,const char *name,const char *partmask,const char *partdir,unsigned copy,ClusterPartDiskMapSpec &mspec,RemoteFilename &rfn) @@ -4941,27 +4949,43 @@ protected: friend class CDistributedFilePart; double fileAgeDays = difftime(time(nullptr), dt.getSimple())/(24*60*60); double sizeGB = getDiskSize(true, false) / ((double)1024 * 1024 * 1024); const IPropertyTree *attrs = root->queryPropTree("Attr"); + bool doLegacyAccessCostCalc = false; __int64 numDiskWrites = 0, numDiskReads = 0; if (attrs) { - numDiskWrites = attrs->getPropInt64("@numDiskWrites"); - numDiskReads = attrs->getPropInt64("@numDiskReads"); + if (hasReadWriteCostFields(*attrs)) + { + // Newer files have readCost and writeCost attributes + accessCost = cost_type2money(attrs->getPropInt64(getDFUQResultFieldName(DFUQRFreadCost)) + attrs->getPropInt64(getDFUQResultFieldName(DFUQRFwriteCost))); + } + else + { + // Costs need to be calculated from numDiskReads and numDiskWrites for legacy files + numDiskWrites = attrs->getPropInt64(getDFUQResultFieldName(DFUQRFnumDiskWrites)); + doLegacyAccessCostCalc = true; + // NB: Costs of index reading can not be reliably estimated based on 'numDiskReads' + if (!isFileKey(*attrs)) + numDiskReads = attrs->getPropInt64(getDFUQResultFieldName(DFUQRFnumDiskReads)); + } } if (isEmptyString(cluster)) { StringArray clusterNames; unsigned countClusters = getClusterNames(clusterNames); for (unsigned i = 0; i < countClusters; i++) + atRestCost += calcFileAtRestCost(clusterNames[i], sizeGB, fileAgeDays); + if (countClusters && doLegacyAccessCostCalc) { - double tmpAtRestcost, tmpAccessCost; - calcFileCost(clusterNames[i], sizeGB, fileAgeDays, numDiskWrites, numDiskReads, tmpAtRestcost, tmpAccessCost); - atRestCost += tmpAtRestcost; - accessCost += tmpAccessCost; + // NB: numDiskReads/numDiskWrites are stored at the file level, not per cluster. + // So cannot calculate accessCost per cluster, assume cost is based on 1st. + accessCost = calcFileAccessCost(clusterNames[0], numDiskWrites, numDiskReads); } } else { - calcFileCost(cluster, sizeGB, fileAgeDays, numDiskWrites, numDiskReads, atRestCost, accessCost); + atRestCost += calcFileAtRestCost(cluster, sizeGB, fileAgeDays); + if (doLegacyAccessCostCalc) + accessCost = calcFileAccessCost(cluster, numDiskWrites, numDiskReads); } } }; @@ -13343,11 +13367,12 @@ IDFProtectedIterator *CDistributedFileDirectory::lookupProtectedFiles(const char const char* DFUQResultFieldNames[] = { "@name", "@description", "@group", "@kind", "@modified", "@job", "@owner", "@DFUSFrecordCount", "@recordCount", "@recordSize", "@DFUSFsize", "@size", "@workunit", "@DFUSFcluster", "@numsubfiles", "@accessed", "@numparts", "@compressedSize", "@directory", "@partmask", "@superowners", "@persistent", "@protect", "@compressed", - "@cost", "@numDiskReads", "@numDiskWrites", "@atRestCost", "@accessCost", "@maxSkew", "@minSkew", "@maxSkewPart", "@minSkewPart" }; + "@cost", "@numDiskReads", "@numDiskWrites", "@atRestCost", "@accessCost", "@maxSkew", "@minSkew", "@maxSkewPart", "@minSkewPart", + "@readCost", "@writeCost" }; -extern da_decl const char* getDFUQResultFieldName(DFUQResultField feild) +extern da_decl const char* getDFUQResultFieldName(DFUQResultField field) { - return DFUQResultFieldNames[feild]; + return DFUQResultFieldNames[field]; } IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, unsigned numFiles, DFUQResultField* localFilters, const char* localFilterBuf) @@ -13414,6 +13439,7 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, unsigned nu void setCost(IPropertyTree* file, const char *nodeGroup) { + // Set the following dynamic fields: atRestCost, accessCost, cost and for legacy files: readCost, writeCost StringBuffer str; double fileAgeDays = 0.0; if (file->getProp(getDFUQResultFieldName(DFUQRFtimemodified), str)) @@ -13428,13 +13454,29 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, unsigned nu else sizeDiskSize = file->getPropInt64(getDFUQResultFieldName(DFUQRForigsize), 0); double sizeGB = sizeDiskSize / ((double)1024 * 1024 * 1024); - __int64 numDiskWrites = file->getPropInt64(getDFUQResultFieldName(DFUQRFnumDiskReads), 0); - __int64 numDiskReads = file->getPropInt64(getDFUQResultFieldName(DFUQRFnumDiskWrites), 0); - double atRestCost, accessCost; - calcFileCost(nodeGroup, sizeGB, fileAgeDays, numDiskWrites, numDiskReads, atRestCost, accessCost); - file->setPropReal(getDFUQResultFieldName(DFUQRFcost), atRestCost+accessCost); - file->setPropReal(getDFUQResultFieldName(DFUQRFatRestCost), atRestCost); - file->setPropReal(getDFUQResultFieldName(DFUQRFaccessCost), accessCost); + cost_type atRestCost = money2cost_type(calcFileAtRestCost(nodeGroup, sizeGB, fileAgeDays)); + file->setPropInt64(getDFUQResultFieldName(DFUQRFatRestCost), atRestCost); + + // Dyamically calc and set the access cost field and for legacy files set read/write cost fields + cost_type accessCost = 0; + if (hasReadWriteCostFields(*file)) + { + accessCost = file->getPropInt64(getDFUQResultFieldName(DFUQRFreadCost)) + file->getPropInt64(getDFUQResultFieldName(DFUQRFwriteCost)); + } + else // Calc access cost from numDiskRead & numDiskWrites for Legacy files + { + cost_type legacyReadCost = getLegacyReadCost(*file, nodeGroup); + file->setPropInt64(getDFUQResultFieldName(DFUQRFreadCost), legacyReadCost); + + cost_type legacyWriteCost = getLegacyWriteCost(*file, nodeGroup); + file->setPropInt64(getDFUQResultFieldName(DFUQRFwriteCost), legacyWriteCost); + + accessCost = legacyReadCost + legacyWriteCost; + } + file->setPropInt64(getDFUQResultFieldName(DFUQRFaccessCost), accessCost); + + // Dymically calc and set the total cost field + file->setPropInt64(getDFUQResultFieldName(DFUQRFcost), atRestCost + accessCost); } IPropertyTree *deserializeFileAttr(MemoryBuffer &mb, StringArray& nodeGroupFilter) diff --git a/dali/base/dadfs.hpp b/dali/base/dadfs.hpp index c1fa5f44a5c..6e5eff9e37e 100644 --- a/dali/base/dadfs.hpp +++ b/dali/base/dadfs.hpp @@ -294,15 +294,17 @@ enum DFUQResultField DFUQRFminSkew = 30, DFUQRFmaxSkewPart = 31, DFUQRFminSkewPart = 32, - DFUQRFterm = 33, + DFUQRFreadCost = 33, + DFUQRFwriteCost = 34, + DFUQRFterm = 35, // must be last in list DFUQRFreverse = 256, DFUQRFnocase = 512, DFUQRFnumeric = 1024, DFUQRFfloat = 2048 }; -extern da_decl const char* getDFUQFilterFieldName(DFUQFilterField feild); -extern da_decl const char* getDFUQResultFieldName(DFUQResultField feild); +extern da_decl const char* getDFUQFilterFieldName(DFUQFilterField field); +extern da_decl const char* getDFUQResultFieldName(DFUQResultField field); /** * File operations can be included in a transaction to ensure that multiple @@ -861,7 +863,7 @@ extern da_decl GroupType translateGroupType(const char *groupType); // Useful property query functions -inline bool isFileKey(IPropertyTree &pt) { const char *kind = pt.queryProp("@kind"); return kind&&strieq(kind,"key"); } +inline bool isFileKey(const IPropertyTree &pt) { const char *kind = pt.queryProp("@kind"); return kind&&strieq(kind,"key"); } inline bool isFileKey(IDistributedFile *f) { return isFileKey(f->queryAttributes()); } inline bool isFileKey(IFileDescriptor *f) { return isFileKey(f->queryProperties()); } @@ -886,11 +888,43 @@ inline const char *queryFileKind(IFileDescriptor *f) { return queryFileKind(f->q extern da_decl void ensureFileScope(const CDfsLogicalFileName &dlfn, unsigned timeoutms=INFINITE); extern da_decl bool checkLogicalName(const char *lfn,IUserDescriptor *user,bool readreq,bool createreq,bool allowquery,const char *specialnotallowedmsg); -extern da_decl void calcFileCost(const char * cluster, double sizeGB, double fileAgeDays, __int64 numDiskWrites, __int64 numDiskReads, double & atRestCost, double & accessCost); + +extern da_decl double calcFileAtRestCost(const char * cluster, double sizeGB, double fileAgeDays); extern da_decl double calcFileAccessCost(const char * cluster, __int64 numDiskWrites, __int64 numDiskReads); +extern da_decl double calcFileAccessCost(IDistributedFile *f, __int64 numDiskWrites, __int64 numDiskReads); constexpr bool defaultPrivilegedUser = true; constexpr bool defaultNonPrivilegedUser = false; extern da_decl void configurePreferredPlanes(); +inline bool hasReadWriteCostFields(const IPropertyTree & fileAttr) +{ + return fileAttr.hasProp(getDFUQResultFieldName(DFUQRFreadCost)) || fileAttr.hasProp(getDFUQResultFieldName(DFUQRFwriteCost)); +} +template +inline cost_type getLegacyReadCost(const IPropertyTree & fileAttr, Source source) +{ + // Legacy files do not have @readCost attribute, so calculate from numDiskRead + // NB: Costs of index reading can not be reliably estimated based on 'numDiskReads' + if (!hasReadWriteCostFields(fileAttr) && fileAttr.hasProp(getDFUQResultFieldName(DFUQRFnumDiskReads)) + && !isFileKey(fileAttr)) + { + stat_type prevDiskReads = fileAttr.getPropInt64(getDFUQResultFieldName(DFUQRFnumDiskReads), 0); + return money2cost_type(calcFileAccessCost(source, 0, prevDiskReads)); + } + else + return 0; +} +template +inline cost_type getLegacyWriteCost(const IPropertyTree & fileAttr, Source source) +{ + // Legacy files do not have @writeCost attribute, so calculate from numDiskWrites + if (!hasReadWriteCostFields(fileAttr) && fileAttr.hasProp(getDFUQResultFieldName(DFUQRFnumDiskWrites))) + { + stat_type prevDiskWrites = fileAttr.getPropInt64(getDFUQResultFieldName(DFUQRFnumDiskWrites), 0); + return money2cost_type(calcFileAccessCost(source, prevDiskWrites, 0)); + } + else + return 0; +} #endif diff --git a/dali/dfuplus/dfuplus.cpp b/dali/dfuplus/dfuplus.cpp index d491a74bfa0..0a729edbee4 100644 --- a/dali/dfuplus/dfuplus.cpp +++ b/dali/dfuplus/dfuplus.cpp @@ -930,6 +930,8 @@ int CDfuPlusHelper::copy() if(globals->hasProp("expireDays")) req->setExpireDays(globals->getPropInt("expireDays")); + if(globals->hasProp("ensure")) + req->setEnsure(globals->getPropBool("ensure")); Owned result = sprayclient->Copy(req); const char* wuid = result->getResult(); diff --git a/dali/dfuplus/main.cpp b/dali/dfuplus/main.cpp index 9d25636ef36..9e37fe02587 100644 --- a/dali/dfuplus/main.cpp +++ b/dali/dfuplus/main.cpp @@ -123,6 +123,7 @@ void handleSyntax() out.append(" diffkeydst= -- use keydiff/keypatch (dst old name)\n"); out.append(" multicopy=0|1 -- each destination part gets whole file\n"); out.append(" preservecompression=1|0 -- optional, default is 1 (preserve)\n"); + out.append(" ensure=0|1 -- optional, only copy file parts if not copied\n"); out.append(" remove options:\n"); out.append(" name=\n"); out.append(" names=\n"); diff --git a/dali/ft/filecopy.cpp b/dali/ft/filecopy.cpp index 7af8139deda..f8a8b9bb8bb 100644 --- a/dali/ft/filecopy.cpp +++ b/dali/ft/filecopy.cpp @@ -3592,7 +3592,10 @@ void FileSprayer::updateTargetProperties() DistributedFilePropertyLock lock(distributedTarget); IPropertyTree &curProps = lock.queryAttributes(); - curProps.setPropInt64("@numDiskWrites", totalNumWrites); + cost_type writeCost = money2cost_type(calcFileAccessCost(distributedTarget, totalNumWrites, 0)); + curProps.setPropInt64(getDFUQResultFieldName(DFUQRFwriteCost), writeCost); + curProps.setPropInt64(getDFUQResultFieldName(DFUQRFnumDiskWrites), totalNumWrites); + if (calcCRC()) curProps.setPropInt(FAcrc, totalCRC.get()); curProps.setPropInt64(FAsize, totalLength); @@ -3771,7 +3774,13 @@ void FileSprayer::updateTargetProperties() if (distributedSource) { if (distributedSource->querySuperFile()==nullptr) - distributedSource->addAttrValue("@numDiskReads", totalNumReads); + { + IPropertyTree & fileAttr = distributedSource->queryAttributes(); + cost_type legacyReadCost = getLegacyReadCost(fileAttr, distributedSource); + cost_type curReadCost = money2cost_type(calcFileAccessCost(distributedSource, 0, totalNumReads)); + distributedSource->addAttrValue(getDFUQResultFieldName(DFUQRFreadCost), legacyReadCost+curReadCost); + distributedSource->addAttrValue(getDFUQResultFieldName(DFUQRFnumDiskReads), totalNumReads); + } } if (error) throw error.getClear(); diff --git a/devdoc/roxie.md b/devdoc/roxie.md index 184391d5cc6..de740e53276 100644 --- a/devdoc/roxie.md +++ b/devdoc/roxie.md @@ -321,3 +321,41 @@ We do pack into dataBuffers rather than MemoryBuffers, which avoids a need to co What is the lifespan issue? In-flight queries may be abandoned when a server-side query fails, times out, or no longer needs the data. Using DataBuffer does not have this issue as they are attached to the query's memory manager/allocation once read. Or we could bypass the agent queue altogether, but rather more refactoring needed for that (might almost be easier to extent the "local optimization" mode to use multiple threads at that point) abortPending, replyPending, and abortPendingData methods are unimplemented, which may lead to some inefficiencies? + +Some notes on UDP packet sending mechanism +========================================== + +Requests from server to agents are send via UDP (and have a size limit of 64k as a result). Historically they were sent using multicast to go to +all agents on a channel at the same time, but since most cloud providers do not support multicast, there has long been an option to +avoid multicast and send explicitly to the agent IPs. In bare metal systems these IPs are known via the topology file, and do not change. In cloud +systems the topology server provides the IPs of all agents for a channel. + +In cloud systems, the list of IPs that a message was sent to is included in the message header, so that the IBYTI messages can be sent without requiring +that all agents/servers have the same topology information at any given moment (they will stay in sync because of topology server, but may be +temporarily out of sync when nodes are added/removed, until next time topology info is retrieved). This is controled by the SUBCHANNELS_IN_HEADER define. + +Packets back from agents to server go via the udplib message-passing code. This can best be described by looking at the sending and receiving sides +separately. + +When sending, results are split into individual packets (DataBuffers), each designed to be under 1 MTU in size. Traditionally this meant they were 1k, +but they can be set larger (8k is good). They do have to be a power of 2 because of how they are allocated from the roxiemem heap. The sender maintains +a set of UdpReceiverEntry objects, one for each server that it is conversing with. Each UdpReceiverEntry maintains multiple queues of data packets +waiting to be sent, one queue for each priority. The UdpReceiverEntry maintains a count of how many packets are contained across all its queues in +packetsQueued, so that it knows if there is data to send. + +The priority levels are: + 0: Out Of Band + 1: Fast lane + 2: Standard + +This is designed to allow control information to be sent without getting blocked by data, and high priority queries to avoid being blocked by data going +to lower priority ones. The mechanism for deciding what packet to send next is a little odd though - rather than sending all higher-priorty packets +before any lower-priority ones, it round robins across the queues sending up to N^2 from queue 0 then up to N from queue 1 then 1 from queue 2, where N +is set by the UdpOutQsPriority option, or 1 if not set. This may be a mistake - probably any from queue 0 should be sent first, before round-robining +the other queues in this fashion. + +UdpReceiverEntry objects are also responsible for maintaining a list of packets that have been sent but receiver has not yet indicated that they have +arrived. + +If an agent has data ready for a given receiver, it will send a requestToSend to that receiver, and wait for a permitToSend response. Sequence numbers +are used to handle situations where these messages get lost. A permitToSend that does not contain the expected sequence number is ignored. diff --git a/docs/EN_US/images/AWS_01.jpg b/docs/EN_US/images/AWS_01.jpg deleted file mode 100644 index ba80c1efc53..00000000000 Binary files a/docs/EN_US/images/AWS_01.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_02.jpg b/docs/EN_US/images/AWS_02.jpg deleted file mode 100644 index c5cf3c8ade3..00000000000 Binary files a/docs/EN_US/images/AWS_02.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_03.jpg b/docs/EN_US/images/AWS_03.jpg deleted file mode 100644 index a67964d011c..00000000000 Binary files a/docs/EN_US/images/AWS_03.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_04.jpg b/docs/EN_US/images/AWS_04.jpg deleted file mode 100644 index d3010333c9b..00000000000 Binary files a/docs/EN_US/images/AWS_04.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_05.jpg b/docs/EN_US/images/AWS_05.jpg deleted file mode 100644 index fdc195f0e23..00000000000 Binary files a/docs/EN_US/images/AWS_05.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_06.jpg b/docs/EN_US/images/AWS_06.jpg deleted file mode 100644 index 9f602e2f10c..00000000000 Binary files a/docs/EN_US/images/AWS_06.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_07.jpg b/docs/EN_US/images/AWS_07.jpg deleted file mode 100644 index 5729313c732..00000000000 Binary files a/docs/EN_US/images/AWS_07.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_08.jpg b/docs/EN_US/images/AWS_08.jpg deleted file mode 100644 index 087bd33e55a..00000000000 Binary files a/docs/EN_US/images/AWS_08.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_09.jpg b/docs/EN_US/images/AWS_09.jpg deleted file mode 100644 index f821b48a888..00000000000 Binary files a/docs/EN_US/images/AWS_09.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_10.jpg b/docs/EN_US/images/AWS_10.jpg deleted file mode 100644 index 31be1f9ca72..00000000000 Binary files a/docs/EN_US/images/AWS_10.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_11.jpg b/docs/EN_US/images/AWS_11.jpg deleted file mode 100644 index 174a129922a..00000000000 Binary files a/docs/EN_US/images/AWS_11.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_12.jpg b/docs/EN_US/images/AWS_12.jpg deleted file mode 100644 index 183ee76ae7a..00000000000 Binary files a/docs/EN_US/images/AWS_12.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_12a.jpg b/docs/EN_US/images/AWS_12a.jpg deleted file mode 100644 index 659e51982a1..00000000000 Binary files a/docs/EN_US/images/AWS_12a.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_12c.jpg b/docs/EN_US/images/AWS_12c.jpg deleted file mode 100644 index c83972a5dfe..00000000000 Binary files a/docs/EN_US/images/AWS_12c.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_13.jpg b/docs/EN_US/images/AWS_13.jpg deleted file mode 100644 index be1022d1e40..00000000000 Binary files a/docs/EN_US/images/AWS_13.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_13a.jpg b/docs/EN_US/images/AWS_13a.jpg deleted file mode 100644 index 7b51f5f3f9f..00000000000 Binary files a/docs/EN_US/images/AWS_13a.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_14.jpg b/docs/EN_US/images/AWS_14.jpg deleted file mode 100644 index 6b161618469..00000000000 Binary files a/docs/EN_US/images/AWS_14.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_15.jpg b/docs/EN_US/images/AWS_15.jpg deleted file mode 100644 index 4d81b07816f..00000000000 Binary files a/docs/EN_US/images/AWS_15.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_16.jpg b/docs/EN_US/images/AWS_16.jpg deleted file mode 100644 index 40afa3cf8f7..00000000000 Binary files a/docs/EN_US/images/AWS_16.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_16a.jpg b/docs/EN_US/images/AWS_16a.jpg deleted file mode 100644 index 37ef366a607..00000000000 Binary files a/docs/EN_US/images/AWS_16a.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_17.jpg b/docs/EN_US/images/AWS_17.jpg deleted file mode 100644 index 301048e62e8..00000000000 Binary files a/docs/EN_US/images/AWS_17.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_18.jpg b/docs/EN_US/images/AWS_18.jpg deleted file mode 100644 index 57e7a3c4e84..00000000000 Binary files a/docs/EN_US/images/AWS_18.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_19.jpg b/docs/EN_US/images/AWS_19.jpg deleted file mode 100644 index ddb357c18b9..00000000000 Binary files a/docs/EN_US/images/AWS_19.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_20.jpg b/docs/EN_US/images/AWS_20.jpg deleted file mode 100644 index 7ee6dbb0811..00000000000 Binary files a/docs/EN_US/images/AWS_20.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_21.jpg b/docs/EN_US/images/AWS_21.jpg deleted file mode 100644 index 55979cc2dbd..00000000000 Binary files a/docs/EN_US/images/AWS_21.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_COVER_LN_Rightjustified.jpg b/docs/EN_US/images/AWS_COVER_LN_Rightjustified.jpg deleted file mode 100644 index d4ab6e3376d..00000000000 Binary files a/docs/EN_US/images/AWS_COVER_LN_Rightjustified.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_ECLWatchNextSteps.jpg b/docs/EN_US/images/AWS_ECLWatchNextSteps.jpg deleted file mode 100644 index af6fc4bfb75..00000000000 Binary files a/docs/EN_US/images/AWS_ECLWatchNextSteps.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_IDE_Preferences.jpg b/docs/EN_US/images/AWS_IDE_Preferences.jpg deleted file mode 100644 index 5e72ee71a8c..00000000000 Binary files a/docs/EN_US/images/AWS_IDE_Preferences.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_InstantCloud_COVER_registeredTm.jpg b/docs/EN_US/images/AWS_InstantCloud_COVER_registeredTm.jpg deleted file mode 100644 index b9c96dabbee..00000000000 Binary files a/docs/EN_US/images/AWS_InstantCloud_COVER_registeredTm.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_InstantCloud_Login.jpg b/docs/EN_US/images/AWS_InstantCloud_Login.jpg deleted file mode 100644 index 68ce431a104..00000000000 Binary files a/docs/EN_US/images/AWS_InstantCloud_Login.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_KeyPairsList.jpg b/docs/EN_US/images/AWS_KeyPairsList.jpg deleted file mode 100644 index 76862652052..00000000000 Binary files a/docs/EN_US/images/AWS_KeyPairsList.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_One-click_COVER_LN_Rightjustified.jpg b/docs/EN_US/images/AWS_One-click_COVER_LN_Rightjustified.jpg deleted file mode 100644 index 09f24edc25c..00000000000 Binary files a/docs/EN_US/images/AWS_One-click_COVER_LN_Rightjustified.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_001.jpg b/docs/EN_US/images/AWS_OneClick_001.jpg deleted file mode 100644 index a00df159dcc..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_001.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_002.jpg b/docs/EN_US/images/AWS_OneClick_002.jpg deleted file mode 100644 index 9031b517221..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_002.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_003.jpg b/docs/EN_US/images/AWS_OneClick_003.jpg deleted file mode 100644 index 517fe5c2132..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_003.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_003a.jpg b/docs/EN_US/images/AWS_OneClick_003a.jpg deleted file mode 100644 index ead8b22d411..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_003a.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_004.jpg b/docs/EN_US/images/AWS_OneClick_004.jpg deleted file mode 100644 index 9cb9071b97a..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_004.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_005.jpg b/docs/EN_US/images/AWS_OneClick_005.jpg deleted file mode 100644 index 087479883c5..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_005.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_006.jpg b/docs/EN_US/images/AWS_OneClick_006.jpg deleted file mode 100644 index 711c0a24bab..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_006.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_Error.jpg b/docs/EN_US/images/AWS_OneClick_Error.jpg deleted file mode 100644 index 2191149579f..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_Error.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_LaunchLog.jpg b/docs/EN_US/images/AWS_OneClick_LaunchLog.jpg deleted file mode 100644 index c157c9a9f31..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_LaunchLog.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_LaunchNew.jpg b/docs/EN_US/images/AWS_OneClick_LaunchNew.jpg deleted file mode 100644 index c3f34a4ea3e..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_LaunchNew.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_Login.jpg b/docs/EN_US/images/AWS_OneClick_Login.jpg deleted file mode 100644 index b274956f716..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_Login.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_Terminated.jpg b/docs/EN_US/images/AWS_OneClick_Terminated.jpg deleted file mode 100644 index 584ff723d4d..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_Terminated.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_ViewClusters.jpg b/docs/EN_US/images/AWS_OneClick_ViewClusters.jpg deleted file mode 100644 index f5c9da2c7ae..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_ViewClusters.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_OneClick_ViewClustersTerminate.jpg b/docs/EN_US/images/AWS_OneClick_ViewClustersTerminate.jpg deleted file mode 100644 index 455b9753fac..00000000000 Binary files a/docs/EN_US/images/AWS_OneClick_ViewClustersTerminate.jpg and /dev/null differ diff --git a/docs/EN_US/images/AWS_accessKey.jpg b/docs/EN_US/images/AWS_accessKey.jpg deleted file mode 100644 index 938c1b61cda..00000000000 Binary files a/docs/EN_US/images/AWS_accessKey.jpg and /dev/null differ diff --git a/docs/EN_US/images/VM-FIleOpenError.jpg b/docs/EN_US/images/VM-FIleOpenError.jpg deleted file mode 100644 index 4dbfa9a8e03..00000000000 Binary files a/docs/EN_US/images/VM-FIleOpenError.jpg and /dev/null differ diff --git a/docs/EN_US/images/VM1000.jpg b/docs/EN_US/images/VM1000.jpg deleted file mode 100644 index dc354aac54b..00000000000 Binary files a/docs/EN_US/images/VM1000.jpg and /dev/null differ diff --git a/docs/EN_US/images/VM1001.jpg b/docs/EN_US/images/VM1001.jpg deleted file mode 100644 index 86f036e8027..00000000000 Binary files a/docs/EN_US/images/VM1001.jpg and /dev/null differ diff --git a/docs/EN_US/images/VM1002.jpg b/docs/EN_US/images/VM1002.jpg deleted file mode 100644 index 59c651c218c..00000000000 Binary files a/docs/EN_US/images/VM1002.jpg and /dev/null differ diff --git a/docs/EN_US/images/vmimage.JPG b/docs/EN_US/images/vmimage.JPG deleted file mode 100644 index facf60b19da..00000000000 Binary files a/docs/EN_US/images/vmimage.JPG and /dev/null differ diff --git a/docs/EN_US/images/vmimg01.JPG b/docs/EN_US/images/vmimg01.JPG deleted file mode 100644 index b110bbaded0..00000000000 Binary files a/docs/EN_US/images/vmimg01.JPG and /dev/null differ diff --git a/docs/EN_US/images/vmimg01b.JPG b/docs/EN_US/images/vmimg01b.JPG deleted file mode 100644 index 564ee1386c7..00000000000 Binary files a/docs/EN_US/images/vmimg01b.JPG and /dev/null differ diff --git a/docs/EN_US/images/vmimg02.JPG b/docs/EN_US/images/vmimg02.JPG deleted file mode 100644 index d2855649837..00000000000 Binary files a/docs/EN_US/images/vmimg02.JPG and /dev/null differ diff --git a/docs/EN_US/images/vmimg03.JPG b/docs/EN_US/images/vmimg03.JPG deleted file mode 100644 index cbd4b951016..00000000000 Binary files a/docs/EN_US/images/vmimg03.JPG and /dev/null differ diff --git a/docs/EN_US/images/vmimg04.JPG b/docs/EN_US/images/vmimg04.JPG deleted file mode 100644 index ee4fbf2fc3b..00000000000 Binary files a/docs/EN_US/images/vmimg04.JPG and /dev/null differ diff --git a/docs/EN_US/images/vmimg07a.jpg b/docs/EN_US/images/vmimg07a.jpg deleted file mode 100644 index b7374c3ad40..00000000000 Binary files a/docs/EN_US/images/vmimg07a.jpg and /dev/null differ diff --git a/docs/EN_US/images/vmimg07aa2.JPG b/docs/EN_US/images/vmimg07aa2.JPG deleted file mode 100644 index 38f7eb38c4e..00000000000 Binary files a/docs/EN_US/images/vmimg07aa2.JPG and /dev/null differ diff --git a/docs/EN_US/images/vmimg07b.jpg b/docs/EN_US/images/vmimg07b.jpg deleted file mode 100644 index 22d242eb02d..00000000000 Binary files a/docs/EN_US/images/vmimg07b.jpg and /dev/null differ diff --git a/docs/EN_US/images/vmimg13.jpg b/docs/EN_US/images/vmimg13.jpg deleted file mode 100644 index 36a5b7ef4de..00000000000 Binary files a/docs/EN_US/images/vmimg13.jpg and /dev/null differ diff --git a/docs/EN_US/images/vmimg16.jpg b/docs/EN_US/images/vmimg16.jpg deleted file mode 100644 index 11574724f90..00000000000 Binary files a/docs/EN_US/images/vmimg16.jpg and /dev/null differ diff --git a/docs/EN_US/images/vmimg17.jpg b/docs/EN_US/images/vmimg17.jpg deleted file mode 100644 index 597dd7cfe9a..00000000000 Binary files a/docs/EN_US/images/vmimg17.jpg and /dev/null differ diff --git a/docs/EN_US/images/vmimg18.jpg b/docs/EN_US/images/vmimg18.jpg deleted file mode 100644 index d0ce5acf5c0..00000000000 Binary files a/docs/EN_US/images/vmimg18.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_01.jpg b/docs/PT_BR/images/AWS_01.jpg deleted file mode 100644 index ba80c1efc53..00000000000 Binary files a/docs/PT_BR/images/AWS_01.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_02.jpg b/docs/PT_BR/images/AWS_02.jpg deleted file mode 100644 index c5cf3c8ade3..00000000000 Binary files a/docs/PT_BR/images/AWS_02.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_03.jpg b/docs/PT_BR/images/AWS_03.jpg deleted file mode 100644 index a67964d011c..00000000000 Binary files a/docs/PT_BR/images/AWS_03.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_04.jpg b/docs/PT_BR/images/AWS_04.jpg deleted file mode 100644 index d3010333c9b..00000000000 Binary files a/docs/PT_BR/images/AWS_04.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_05.jpg b/docs/PT_BR/images/AWS_05.jpg deleted file mode 100644 index fdc195f0e23..00000000000 Binary files a/docs/PT_BR/images/AWS_05.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_06.jpg b/docs/PT_BR/images/AWS_06.jpg deleted file mode 100644 index 9f602e2f10c..00000000000 Binary files a/docs/PT_BR/images/AWS_06.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_07.jpg b/docs/PT_BR/images/AWS_07.jpg deleted file mode 100644 index 5729313c732..00000000000 Binary files a/docs/PT_BR/images/AWS_07.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_08.jpg b/docs/PT_BR/images/AWS_08.jpg deleted file mode 100644 index 087bd33e55a..00000000000 Binary files a/docs/PT_BR/images/AWS_08.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_09.jpg b/docs/PT_BR/images/AWS_09.jpg deleted file mode 100644 index f821b48a888..00000000000 Binary files a/docs/PT_BR/images/AWS_09.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_10.jpg b/docs/PT_BR/images/AWS_10.jpg deleted file mode 100644 index 31be1f9ca72..00000000000 Binary files a/docs/PT_BR/images/AWS_10.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_11.jpg b/docs/PT_BR/images/AWS_11.jpg deleted file mode 100644 index 174a129922a..00000000000 Binary files a/docs/PT_BR/images/AWS_11.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_12.jpg b/docs/PT_BR/images/AWS_12.jpg deleted file mode 100644 index 183ee76ae7a..00000000000 Binary files a/docs/PT_BR/images/AWS_12.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_12a.jpg b/docs/PT_BR/images/AWS_12a.jpg deleted file mode 100644 index 659e51982a1..00000000000 Binary files a/docs/PT_BR/images/AWS_12a.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_12c.jpg b/docs/PT_BR/images/AWS_12c.jpg deleted file mode 100644 index c83972a5dfe..00000000000 Binary files a/docs/PT_BR/images/AWS_12c.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_13.jpg b/docs/PT_BR/images/AWS_13.jpg deleted file mode 100644 index be1022d1e40..00000000000 Binary files a/docs/PT_BR/images/AWS_13.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_13a.jpg b/docs/PT_BR/images/AWS_13a.jpg deleted file mode 100644 index 7b51f5f3f9f..00000000000 Binary files a/docs/PT_BR/images/AWS_13a.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_14.jpg b/docs/PT_BR/images/AWS_14.jpg deleted file mode 100644 index 6b161618469..00000000000 Binary files a/docs/PT_BR/images/AWS_14.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_15.jpg b/docs/PT_BR/images/AWS_15.jpg deleted file mode 100644 index 4d81b07816f..00000000000 Binary files a/docs/PT_BR/images/AWS_15.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_16.jpg b/docs/PT_BR/images/AWS_16.jpg deleted file mode 100644 index 40afa3cf8f7..00000000000 Binary files a/docs/PT_BR/images/AWS_16.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_16a.jpg b/docs/PT_BR/images/AWS_16a.jpg deleted file mode 100644 index 37ef366a607..00000000000 Binary files a/docs/PT_BR/images/AWS_16a.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_17.jpg b/docs/PT_BR/images/AWS_17.jpg deleted file mode 100644 index 301048e62e8..00000000000 Binary files a/docs/PT_BR/images/AWS_17.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_18.jpg b/docs/PT_BR/images/AWS_18.jpg deleted file mode 100644 index 57e7a3c4e84..00000000000 Binary files a/docs/PT_BR/images/AWS_18.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_19.jpg b/docs/PT_BR/images/AWS_19.jpg deleted file mode 100644 index ddb357c18b9..00000000000 Binary files a/docs/PT_BR/images/AWS_19.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_20.jpg b/docs/PT_BR/images/AWS_20.jpg deleted file mode 100644 index 7ee6dbb0811..00000000000 Binary files a/docs/PT_BR/images/AWS_20.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_21.jpg b/docs/PT_BR/images/AWS_21.jpg deleted file mode 100644 index 55979cc2dbd..00000000000 Binary files a/docs/PT_BR/images/AWS_21.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_COVER_LN_Rightjustified.jpg b/docs/PT_BR/images/AWS_COVER_LN_Rightjustified.jpg deleted file mode 100644 index d4ab6e3376d..00000000000 Binary files a/docs/PT_BR/images/AWS_COVER_LN_Rightjustified.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_ECLWatchNextSteps.jpg b/docs/PT_BR/images/AWS_ECLWatchNextSteps.jpg deleted file mode 100644 index af6fc4bfb75..00000000000 Binary files a/docs/PT_BR/images/AWS_ECLWatchNextSteps.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_IDE_Preferences.jpg b/docs/PT_BR/images/AWS_IDE_Preferences.jpg deleted file mode 100644 index 5e72ee71a8c..00000000000 Binary files a/docs/PT_BR/images/AWS_IDE_Preferences.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_InstantCloud_COVER_registeredTm.jpg b/docs/PT_BR/images/AWS_InstantCloud_COVER_registeredTm.jpg deleted file mode 100644 index b9c96dabbee..00000000000 Binary files a/docs/PT_BR/images/AWS_InstantCloud_COVER_registeredTm.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_InstantCloud_Login.jpg b/docs/PT_BR/images/AWS_InstantCloud_Login.jpg deleted file mode 100644 index 68ce431a104..00000000000 Binary files a/docs/PT_BR/images/AWS_InstantCloud_Login.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_KeyPairsList.jpg b/docs/PT_BR/images/AWS_KeyPairsList.jpg deleted file mode 100644 index 76862652052..00000000000 Binary files a/docs/PT_BR/images/AWS_KeyPairsList.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_One-click_COVER_LN_Rightjustified.jpg b/docs/PT_BR/images/AWS_One-click_COVER_LN_Rightjustified.jpg deleted file mode 100644 index 09f24edc25c..00000000000 Binary files a/docs/PT_BR/images/AWS_One-click_COVER_LN_Rightjustified.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_001.jpg b/docs/PT_BR/images/AWS_OneClick_001.jpg deleted file mode 100644 index a00df159dcc..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_001.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_002.jpg b/docs/PT_BR/images/AWS_OneClick_002.jpg deleted file mode 100644 index 9031b517221..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_002.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_003.jpg b/docs/PT_BR/images/AWS_OneClick_003.jpg deleted file mode 100644 index 517fe5c2132..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_003.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_003a.jpg b/docs/PT_BR/images/AWS_OneClick_003a.jpg deleted file mode 100644 index ead8b22d411..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_003a.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_004.jpg b/docs/PT_BR/images/AWS_OneClick_004.jpg deleted file mode 100644 index 9cb9071b97a..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_004.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_005.jpg b/docs/PT_BR/images/AWS_OneClick_005.jpg deleted file mode 100644 index 087479883c5..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_005.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_006.jpg b/docs/PT_BR/images/AWS_OneClick_006.jpg deleted file mode 100644 index 711c0a24bab..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_006.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_Error.jpg b/docs/PT_BR/images/AWS_OneClick_Error.jpg deleted file mode 100644 index 2191149579f..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_Error.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_LaunchLog.jpg b/docs/PT_BR/images/AWS_OneClick_LaunchLog.jpg deleted file mode 100644 index c157c9a9f31..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_LaunchLog.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_LaunchNew.jpg b/docs/PT_BR/images/AWS_OneClick_LaunchNew.jpg deleted file mode 100644 index c3f34a4ea3e..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_LaunchNew.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_Login.jpg b/docs/PT_BR/images/AWS_OneClick_Login.jpg deleted file mode 100644 index b274956f716..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_Login.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_Terminated.jpg b/docs/PT_BR/images/AWS_OneClick_Terminated.jpg deleted file mode 100644 index 584ff723d4d..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_Terminated.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_ViewClusters.jpg b/docs/PT_BR/images/AWS_OneClick_ViewClusters.jpg deleted file mode 100644 index f5c9da2c7ae..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_ViewClusters.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_OneClick_ViewClustersTerminate.jpg b/docs/PT_BR/images/AWS_OneClick_ViewClustersTerminate.jpg deleted file mode 100644 index 455b9753fac..00000000000 Binary files a/docs/PT_BR/images/AWS_OneClick_ViewClustersTerminate.jpg and /dev/null differ diff --git a/docs/PT_BR/images/AWS_accessKey.jpg b/docs/PT_BR/images/AWS_accessKey.jpg deleted file mode 100644 index 938c1b61cda..00000000000 Binary files a/docs/PT_BR/images/AWS_accessKey.jpg and /dev/null differ diff --git a/docs/PT_BR/images/VM-FIleOpenError.jpg b/docs/PT_BR/images/VM-FIleOpenError.jpg deleted file mode 100644 index 4dbfa9a8e03..00000000000 Binary files a/docs/PT_BR/images/VM-FIleOpenError.jpg and /dev/null differ diff --git a/docs/PT_BR/images/VM1000.jpg b/docs/PT_BR/images/VM1000.jpg deleted file mode 100644 index dc354aac54b..00000000000 Binary files a/docs/PT_BR/images/VM1000.jpg and /dev/null differ diff --git a/docs/PT_BR/images/VM1001.jpg b/docs/PT_BR/images/VM1001.jpg deleted file mode 100644 index 86f036e8027..00000000000 Binary files a/docs/PT_BR/images/VM1001.jpg and /dev/null differ diff --git a/docs/PT_BR/images/VM1002.jpg b/docs/PT_BR/images/VM1002.jpg deleted file mode 100644 index 59c651c218c..00000000000 Binary files a/docs/PT_BR/images/VM1002.jpg and /dev/null differ diff --git a/docs/PT_BR/images/vmimage.JPG b/docs/PT_BR/images/vmimage.JPG deleted file mode 100644 index facf60b19da..00000000000 Binary files a/docs/PT_BR/images/vmimage.JPG and /dev/null differ diff --git a/docs/PT_BR/images/vmimg01.JPG b/docs/PT_BR/images/vmimg01.JPG deleted file mode 100644 index b110bbaded0..00000000000 Binary files a/docs/PT_BR/images/vmimg01.JPG and /dev/null differ diff --git a/docs/PT_BR/images/vmimg01b.JPG b/docs/PT_BR/images/vmimg01b.JPG deleted file mode 100644 index 564ee1386c7..00000000000 Binary files a/docs/PT_BR/images/vmimg01b.JPG and /dev/null differ diff --git a/docs/PT_BR/images/vmimg02.JPG b/docs/PT_BR/images/vmimg02.JPG deleted file mode 100644 index d2855649837..00000000000 Binary files a/docs/PT_BR/images/vmimg02.JPG and /dev/null differ diff --git a/docs/PT_BR/images/vmimg03.JPG b/docs/PT_BR/images/vmimg03.JPG deleted file mode 100644 index cbd4b951016..00000000000 Binary files a/docs/PT_BR/images/vmimg03.JPG and /dev/null differ diff --git a/docs/PT_BR/images/vmimg04.JPG b/docs/PT_BR/images/vmimg04.JPG deleted file mode 100644 index ee4fbf2fc3b..00000000000 Binary files a/docs/PT_BR/images/vmimg04.JPG and /dev/null differ diff --git a/docs/PT_BR/images/vmimg07a.jpg b/docs/PT_BR/images/vmimg07a.jpg deleted file mode 100644 index b7374c3ad40..00000000000 Binary files a/docs/PT_BR/images/vmimg07a.jpg and /dev/null differ diff --git a/docs/PT_BR/images/vmimg07aa2.JPG b/docs/PT_BR/images/vmimg07aa2.JPG deleted file mode 100644 index 38f7eb38c4e..00000000000 Binary files a/docs/PT_BR/images/vmimg07aa2.JPG and /dev/null differ diff --git a/docs/PT_BR/images/vmimg07b.jpg b/docs/PT_BR/images/vmimg07b.jpg deleted file mode 100644 index 22d242eb02d..00000000000 Binary files a/docs/PT_BR/images/vmimg07b.jpg and /dev/null differ diff --git a/docs/PT_BR/images/vmimg13.jpg b/docs/PT_BR/images/vmimg13.jpg deleted file mode 100644 index 36a5b7ef4de..00000000000 Binary files a/docs/PT_BR/images/vmimg13.jpg and /dev/null differ diff --git a/docs/PT_BR/images/vmimg16.jpg b/docs/PT_BR/images/vmimg16.jpg deleted file mode 100644 index 11574724f90..00000000000 Binary files a/docs/PT_BR/images/vmimg16.jpg and /dev/null differ diff --git a/docs/PT_BR/images/vmimg17.jpg b/docs/PT_BR/images/vmimg17.jpg deleted file mode 100644 index 597dd7cfe9a..00000000000 Binary files a/docs/PT_BR/images/vmimg17.jpg and /dev/null differ diff --git a/docs/PT_BR/images/vmimg18.jpg b/docs/PT_BR/images/vmimg18.jpg deleted file mode 100644 index d0ce5acf5c0..00000000000 Binary files a/docs/PT_BR/images/vmimg18.jpg and /dev/null differ diff --git a/ecl/hthor/hthor.cpp b/ecl/hthor/hthor.cpp index 18e0016fcbd..3951a5b632a 100644 --- a/ecl/hthor/hthor.cpp +++ b/ecl/hthor/hthor.cpp @@ -774,7 +774,7 @@ void CHThorDiskWriteActivity::publish() if (helper.getFlags() & TDWrestricted) properties.setPropBool("restricted", true); - properties.setPropInt64("@numDiskWrites", numDiskWrites); + properties.setPropInt64(getDFUQResultFieldName(DFUQRFnumDiskWrites), numDiskWrites); StringBuffer lfn; expandLogicalFilename(lfn, mangledHelperFileName.str(), agent.queryWorkUnit(), agent.queryResolveFilesLocally(), false); CDfsLogicalFileName logicalName; @@ -790,6 +790,7 @@ void CHThorDiskWriteActivity::publish() StringBuffer clusterName; file->getClusterName(0, clusterName); diskAccessCost = money2cost_type(calcFileAccessCost(clusterName, numDiskWrites, 0)); + properties.setPropInt64(getDFUQResultFieldName(DFUQRFwriteCost), diskAccessCost); } file->attach(logicalName.get(), agent.queryCodeContext()->queryUserDescriptor()); agent.logFileAccess(file, "HThor", "CREATED", graph); @@ -1366,7 +1367,7 @@ void CHThorIndexWriteActivity::execute() properties.setProp("@workunit", agent.queryWorkUnit()->queryWuid()); properties.setProp("@job", agent.queryWorkUnit()->queryJobName()); properties.setPropInt64("@duplicateKeyCount",duplicateKeyCount); - properties.setPropInt64("@numDiskWrites", numDiskWrites); + properties.setPropInt64(getDFUQResultFieldName(DFUQRFnumDiskWrites), numDiskWrites); properties.setPropInt64("@numLeafNodes", numLeafNodes); properties.setPropInt64("@numBranchNodes", numBranchNodes); properties.setPropInt64("@numBlobNodes", numBlobNodes); @@ -1437,6 +1438,7 @@ void CHThorIndexWriteActivity::execute() StringBuffer clusterName; dfile->getClusterName(0, clusterName); diskAccessCost = money2cost_type(calcFileAccessCost(clusterName, numDiskWrites, 0)); + properties.setPropInt64(getDFUQResultFieldName(DFUQRFwriteCost), diskAccessCost); } else lfn = filename; @@ -8539,10 +8541,12 @@ void CHThorDiskReadBaseActivity::closepart() dFile = &(super->querySubFile(subfile, true)); } } - dFile->addAttrValue("@numDiskReads", curDiskReads); - StringBuffer clusterName; - dFile->getClusterName(0, clusterName); - diskAccessCost = money2cost_type(calcFileAccessCost(clusterName, 0, curDiskReads)); + IPropertyTree & fileAttr = dFile->queryAttributes(); + cost_type legacyReadCost = getLegacyReadCost(fileAttr, dFile); + cost_type curReadCost = money2cost_type(calcFileAccessCost(dFile, 0, curDiskReads)); + + dFile->addAttrValue(getDFUQResultFieldName(DFUQRFreadCost), legacyReadCost + curReadCost); + dFile->addAttrValue(getDFUQResultFieldName(DFUQRFnumDiskReads), curDiskReads); } numDiskReads += curDiskReads; } diff --git a/ecllibrary/std/File.ecl b/ecllibrary/std/File.ecl index b8c30dacc36..4371f36dfa7 100644 --- a/ecllibrary/std/File.ecl +++ b/ecllibrary/std/File.ecl @@ -640,11 +640,12 @@ EXPORT Despray(varstring logicalName, varstring destinationIP='', varstring dest * @param transferBufferSize Overrides the size (in bytes) of the internal buffer used to copy the file. Default is 64k. * @param noSplit Don't split a file part to multiple target parts. Default is FALSE. * @param expireDays Number of days to auto-remove file. Default is -1, not expire. + * @param ensure Only copy file parts if not copied. Defaults to FALSE. * @return The DFU workunit id for the job. */ -EXPORT varstring fCopy(varstring sourceLogicalName, varstring destinationGroup, varstring destinationLogicalName, varstring sourceDali='', integer4 timeOut=-1, varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowOverwrite=FALSE, boolean replicate=FALSE, boolean asSuperfile=FALSE, boolean compress=FALSE, boolean forcePush=FALSE, integer4 transferBufferSize=0, boolean preserveCompression=TRUE, boolean noSplit=FALSE, integer4 expireDays=-1) := - lib_fileservices.FileServices.fCopy(sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, allowOverwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays); +EXPORT varstring fCopy(varstring sourceLogicalName, varstring destinationGroup, varstring destinationLogicalName, varstring sourceDali='', integer4 timeOut=-1, varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowOverwrite=FALSE, boolean replicate=FALSE, boolean asSuperfile=FALSE, boolean compress=FALSE, boolean forcePush=FALSE, integer4 transferBufferSize=0, boolean preserveCompression=TRUE, boolean noSplit=FALSE, integer4 expireDays=-1, boolean ensure=false) := + lib_fileservices.FileServices.fCopy(sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, allowOverwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays, ensure); /** * Same as fCopy, but does not return the DFU Workunit ID. @@ -652,8 +653,8 @@ EXPORT varstring fCopy(varstring sourceLogicalName, varstring destinationGroup, * @see fCopy */ -EXPORT Copy(varstring sourceLogicalName, varstring destinationGroup, varstring destinationLogicalName, varstring sourceDali='', integer4 timeOut=-1, varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowOverwrite=FALSE, boolean replicate=FALSE, boolean asSuperfile=FALSE, boolean compress=FALSE, boolean forcePush=FALSE, integer4 transferBufferSize=0, boolean preserveCompression=TRUE, boolean noSplit=FALSE, integer4 expireDays=-1) := - lib_fileservices.FileServices.Copy(sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, allowOverwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays); +EXPORT Copy(varstring sourceLogicalName, varstring destinationGroup, varstring destinationLogicalName, varstring sourceDali='', integer4 timeOut=-1, varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowOverwrite=FALSE, boolean replicate=FALSE, boolean asSuperfile=FALSE, boolean compress=FALSE, boolean forcePush=FALSE, integer4 transferBufferSize=0, boolean preserveCompression=TRUE, boolean noSplit=FALSE, integer4 expireDays=-1, boolean ensure=false) := + lib_fileservices.FileServices.Copy(sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, allowOverwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays, ensure); /** * Ensures the specified file is replicated to its mirror copies. diff --git a/esp/services/ws_dfu/ws_dfuHelpers.cpp b/esp/services/ws_dfu/ws_dfuHelpers.cpp index 169792c5411..e17bad67db4 100644 --- a/esp/services/ws_dfu/ws_dfuHelpers.cpp +++ b/esp/services/ws_dfu/ws_dfuHelpers.cpp @@ -186,11 +186,16 @@ bool WsDFUHelpers::addToLogicalFileList(IPropertyTree& file, const char* nodeGro if (version >= 1.61) { if (version < 1.62) - lFile->setCost(file.getPropReal(getDFUQResultFieldName(DFUQRFcost))); + { + cost_type cost = file.getPropInt64(getDFUQResultFieldName(DFUQRFcost)); + lFile->setCost(cost_type2money(cost)); + } else { - lFile->setAtRestCost(file.getPropReal(getDFUQResultFieldName(DFUQRFatRestCost))); - lFile->setAccessCost(file.getPropReal(getDFUQResultFieldName(DFUQRFaccessCost))); + cost_type atRestCost = file.getPropInt64(getDFUQResultFieldName(DFUQRFatRestCost)); + lFile->setAtRestCost(cost_type2money(atRestCost)); + cost_type accessCost = file .getPropInt64(getDFUQResultFieldName(DFUQRFaccessCost)); + lFile->setAccessCost(cost_type2money(accessCost)); } } if ((version >= 1.63) && (file.hasProp(getDFUQResultFieldName(DFUQRFmaxSkew)))) diff --git a/esp/services/ws_esdlconfig/ws_esdlconfigservice.cpp b/esp/services/ws_esdlconfig/ws_esdlconfigservice.cpp index da81cfc31a4..e121a464459 100644 --- a/esp/services/ws_esdlconfig/ws_esdlconfigservice.cpp +++ b/esp/services/ws_esdlconfig/ws_esdlconfigservice.cpp @@ -695,6 +695,31 @@ bool CWsESDLConfigEx::onPublishESDLBinding(IEspContext &context, IEspPublishESDL return true; } +void setContainerizedEspBindingNameByPort(StringBuffer& espPort, StringBuffer& espBindingName) +{ + VStringBuffer xpath("services[@class='esp'][@port='%s']", espPort.str()); + Owned process = getGlobalConfigSP()->getPropTree(xpath); + if (nullptr == process) + throw makeStringExceptionV(-1, "No ESP process configured for port %s", espPort.str()); + const char* applicationType = process->queryProp("@type"); + if (isEmptyString(applicationType)) + throw makeStringExceptionV(-1, "ESP process configured for port %s is missing 'type'", espPort.str()); + + char sepchar = getPathSepChar(hpccBuildInfo.componentDir); + StringBuffer path(hpccBuildInfo.componentDir); + addPathSepChar(path, sepchar).append("applications").append(sepchar).append(applicationType).append(sepchar).append("application.yaml"); + if (checkFileExists(path)) + { + Owned applicationProfile = createPTreeFromYAMLFile(path); + const char* serviceName = applicationProfile->queryProp("application/services[1]"); + if (isEmptyString(serviceName)) + throw makeStringExceptionV(-1, "No service entry found in ESP application profile '%s' while trying to build service binding name for port %s", path.str(), espPort.str()); + espBindingName.setf("%s_binding", serviceName); + } + else + throw makeStringExceptionV(-1, "Can't open platform ESP application profile '%s' to build service binding name for port %s", path.str(), espPort.str()); +} + bool CWsESDLConfigEx::onConfigureESDLBindingMethod(IEspContext &context, IEspConfigureESDLBindingMethodRequest &req, IEspConfigureESDLBindingMethodResponse &resp) { int success = 0; @@ -816,19 +841,24 @@ bool CWsESDLConfigEx::onConfigureESDLBindingMethod(IEspContext &context, IEspCon if (espPort.length() <= 0 && espServiceName.length() <= 0) throw MakeStringException(-1, "Must provide either ESP Port, or Service Name"); - VStringBuffer xpath("/Environment/Software/EspProcess[@name='%s']/EspBinding[@port='%s']", espProcName.str(), espPort.str()); - Owned conn = querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_READ , SDS_LOCK_TIMEOUT_DESDL); - if (!conn) + if (isContainerized()) + setContainerizedEspBindingNameByPort(espPort, espBindingName); + else { - StringBuffer msg; - msg.appendf( - "Could not find ESP binding associated with Esp Process '%s' and either port '%s' or Esp Service Name '%s'", - espProcName.str(), espPort.isEmpty() ? "N/A" : espPort.str(), espServiceName.isEmpty() ? "N/A" : espServiceName.str()); - resp.updateStatus().setCode(-1); - resp.updateStatus().setDescription(msg.str()); - return false; + VStringBuffer xpath("/Environment/Software/EspProcess[@name='%s']/EspBinding[@port='%s']", espProcName.str(), espPort.str()); + Owned conn = querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_READ , SDS_LOCK_TIMEOUT_DESDL); + if (!conn) + { + StringBuffer msg; + msg.appendf( + "Could not find ESP binding associated with Esp Process '%s' and either port '%s' or Esp Service Name '%s'", + espProcName.str(), espPort.isEmpty() ? "N/A" : espPort.str(), espServiceName.isEmpty() ? "N/A" : espServiceName.str()); + resp.updateStatus().setCode(-1); + resp.updateStatus().setDescription(msg.str()); + return false; + } + espBindingName.set(conn->queryRoot()->queryProp("@name")); } - espBindingName.set(conn->queryRoot()->queryProp("@name")); } } @@ -1158,12 +1188,17 @@ bool CWsESDLConfigEx::onGetESDLBinding(IEspContext &context, IEspGetESDLBindingR throw MakeStringException(-1, "Must provide EsdlBindingId, or EspProcName plus EspBinding or EspPort"); if (espBindingName.length() == 0) { - VStringBuffer xpath("/Environment/Software/EspProcess[@name='%s']/EspBinding[@port='%s']", espProcName.str(), espPort.str()); - Owned conn = querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_READ , SDS_LOCK_TIMEOUT_DESDL); - if(conn) - espBindingName.set(conn->queryRoot()->queryProp("@name")); + if (isContainerized()) + setContainerizedEspBindingNameByPort(espPort, espBindingName); else - throw MakeStringException(-1, "Can't find any esp binding for port %s", espPort.str()); + { + VStringBuffer xpath("/Environment/Software/EspProcess[@name='%s']/EspBinding[@port='%s']", espProcName.str(), espPort.str()); + Owned conn = querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_READ , SDS_LOCK_TIMEOUT_DESDL); + if(conn) + espBindingName.set(conn->queryRoot()->queryProp("@name")); + else + throw MakeStringException(-1, "Can't find any esp binding for port %s", espPort.str()); + } } } } @@ -1831,16 +1866,31 @@ static int bindingCompareFunc(IInterface * const *_itm1, IInterface * const* _it void getAllEspProcessesSorted(StringArray& processes) { - Owned conn = querySDS().connect("/Environment/Software", myProcessSession(), RTM_LOCK_READ , SDS_LOCK_TIMEOUT_DESDL); - if (!conn) - throw MakeStringException(-1, "Unable to connect to /Environment/Software dali path"); - Owned iter = conn->queryRoot()->getElements("EspProcess"); - ForEach (*iter) + if (isContainerized()) { - IPropertyTree &item = iter->query(); - processes.append(item.queryProp("@name")); + Owned iter = getGlobalConfigSP()->getElements("services[@class='esp']"); + ForEach (*iter) + { + IPropertyTree &item = iter->query(); + const char* type = item.queryProp("@type"); + bool loadDaliBindings = item.getPropBool("@loadDaliBindings"); + if (strncmp(type, "esdl-sandbox", 12)==0 || loadDaliBindings) + processes.append(item.queryProp("@name")); + } } + else + { + Owned conn = querySDS().connect("/Environment/Software", myProcessSession(), RTM_LOCK_READ , SDS_LOCK_TIMEOUT_DESDL); + if (!conn) + throw MakeStringException(-1, "Unable to connect to /Environment/Software dali path"); + Owned iter = conn->queryRoot()->getElements("EspProcess"); + ForEach (*iter) + { + IPropertyTree &item = iter->query(); + processes.append(item.queryProp("@name")); + } + } processes.sortAscii(); } diff --git a/esp/src/.vscode/tasks.json b/esp/src/.vscode/tasks.json index 76afeea0be3..b84a07ad35d 100644 --- a/esp/src/.vscode/tasks.json +++ b/esp/src/.vscode/tasks.json @@ -47,7 +47,9 @@ "tsc watch", "webpack-dev-server" ], - "group": "build", + "group": { + "kind": "build" + }, "problemMatcher": [] }, { diff --git a/esp/src/CMakeLists.txt b/esp/src/CMakeLists.txt index c3e1426dc40..e53f58d64d5 100644 --- a/esp/src/CMakeLists.txt +++ b/esp/src/CMakeLists.txt @@ -28,10 +28,8 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/eslint ${CMAKE_CURRENT_SOURCE_DIR}/ganglia ${CMAKE_CURRENT_SOURCE_DIR}/loader - ${CMAKE_CURRENT_SOURCE_DIR}/put-selector ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src-react - ${CMAKE_CURRENT_SOURCE_DIR}/xstyle ${CMAKE_CURRENT_SOURCE_DIR}/.eslintrc.js ${CMAKE_CURRENT_SOURCE_DIR}/GetUserName.html ${CMAKE_CURRENT_SOURCE_DIR}/index.html diff --git a/esp/src/eclwatch/InfoGridWidget.js b/esp/src/eclwatch/InfoGridWidget.js index 3effa1b5c72..2e5ab2fb00b 100755 --- a/esp/src/eclwatch/InfoGridWidget.js +++ b/esp/src/eclwatch/InfoGridWidget.js @@ -222,7 +222,7 @@ define([ this.widget.ErrWarnDialogTextArea.domNode.select(); }, _onDownload: function (evt) { - Utility.downloadText(Utility.toCSV(this.infoData, ","), "ErrWarn.csv"); + Utility.downloadCSV(Utility.toCSV(this.infoData, ","), "ErrWarn.csv"); }, _onErrors: function (args) { diff --git a/esp/src/eclwatch/css/hpcc.css b/esp/src/eclwatch/css/hpcc.css index fd48fd1d186..e11e8c1978c 100644 --- a/esp/src/eclwatch/css/hpcc.css +++ b/esp/src/eclwatch/css/hpcc.css @@ -1297,6 +1297,7 @@ table.miniSelect span { .WarningCell { padding-left: 4px; background: yellow; + color: black; } .NormalCell { diff --git a/esp/src/package-lock.json b/esp/src/package-lock.json index 949ee27f19c..780f026d49b 100644 --- a/esp/src/package-lock.json +++ b/esp/src/package-lock.json @@ -41,6 +41,7 @@ "font-awesome": "4.7.0", "formik": "2.2.9", "octokit": "3.1.1", + "put-selector": "0.3.6", "query-string": "7.1.3", "react": "17.0.2", "react-dom": "17.0.2", @@ -48,7 +49,8 @@ "react-hot-toast": "2.4.0", "react-reflex": "4.0.9", "react-sizeme": "3.0.2", - "universal-router": "9.1.0" + "universal-router": "9.1.0", + "xstyle": "0.3.2" }, "devDependencies": { "@simbathesailor/use-what-changed": "^2.0.0", @@ -74,7 +76,8 @@ "typescript": "4.9.5", "url-loader": "4.1.1", "webpack": "5.89.0", - "webpack-cli": "5.1.4" + "webpack-cli": "5.1.4", + "webpack-dev-server": "4.15.1" } }, "eslint": { @@ -2895,6 +2898,12 @@ "openid-client": "^5.3.0" } }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", + "dev": true + }, "node_modules/@lumino/algorithm": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@lumino/algorithm/-/algorithm-1.9.2.tgz", @@ -3409,6 +3418,25 @@ "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.129.tgz", "integrity": "sha512-0Rl7CpTPVws5cp0Ui1gZh4Q+TXC65bXVwTOGoI2RKW45dxWzyZGbjIX0uFjFYdIJ8vnD45y584rIIqvD2vBBfQ==" }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/btoa-lite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.2.tgz", @@ -3419,6 +3447,25 @@ "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, "node_modules/@types/d3-array": { "version": "1.2.10", "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-1.2.10.tgz", @@ -3550,11 +3597,50 @@ "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", "dev": true }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, "node_modules/@types/geojson": { "version": "7946.0.12", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.12.tgz", "integrity": "sha512-uK2z1ZHJyC0nQRbuovXFt4mzXDwf27vQeUWNhfKGwRcWW429GOhP8HxUHlM6TLH4bzmlv/HlEjpvJh3JfmGsAA==" }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/js-yaml": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", @@ -3582,16 +3668,43 @@ "@types/geojson": "*" } }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, "node_modules/@types/node": { "version": "18.14.6", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==" }, + "node_modules/@types/node-forge": { + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.10.tgz", + "integrity": "sha512-y6PJDYN4xYBxwd22l+OVH35N+1fCYWiuC3aiP2SlXVE6Lo7SS+rSx9r89hLxrP4pn6n1lBGhHJ12pj3F3Mpttw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/prop-types": { "version": "15.7.4", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" }, + "node_modules/@types/qs": { + "version": "6.9.10", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", + "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, "node_modules/@types/react": { "version": "17.0.62", "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.62.tgz", @@ -3621,6 +3734,12 @@ "form-data": "^2.5.0" } }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, "node_modules/@types/scheduler": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", @@ -3632,15 +3751,54 @@ "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/tough-cookie": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==" }, "node_modules/@types/ws": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", - "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dependencies": { "@types/node": "*" } @@ -4142,6 +4300,45 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -4163,6 +4360,18 @@ "node": ">=12.17" } }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4193,6 +4402,19 @@ "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", "dev": true }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4207,6 +4429,12 @@ "node": ">=12.17" } }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -4300,6 +4528,91 @@ "node": "*" } }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour-service": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", + "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "dev": true, + "dependencies": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, "node_modules/bottleneck": { "version": "2.19.5", "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", @@ -4457,6 +4770,45 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -4741,11 +5093,62 @@ "node": ">= 0.6" } }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -4787,6 +5190,21 @@ "node": ">= 0.6" } }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, "node_modules/cookies": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", @@ -5032,6 +5450,18 @@ "node": ">=0.10.0" } }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -5096,6 +5526,12 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, "node_modules/dijit": { "version": "1.17.3", "resolved": "https://registry.npmjs.org/dijit/-/dijit-1.17.3.tgz", @@ -5125,7 +5561,25 @@ "node": ">=8" } }, - "node_modules/doctrine": { + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", + "dev": true + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", @@ -5683,6 +6137,12 @@ "node": ">=6" } }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -5692,6 +6152,143 @@ "node": ">=0.8.x" } }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -5764,6 +6361,18 @@ "reusify": "^1.0.4" } }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -5816,6 +6425,48 @@ "node": ">=0.10.0" } }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/finalhandler/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/find-replace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", @@ -5869,6 +6520,26 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/font-awesome": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", @@ -5926,6 +6597,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -5946,11 +6626,31 @@ "node": ">= 8" } }, + "node_modules/fs-monkey": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", + "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", + "dev": true + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -5985,6 +6685,18 @@ "resolved": "https://registry.npmjs.org/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz", "integrity": "sha512-2MSPMu7S1iOTL+BOa6K1S62hB2zUAYNF/lV0gSVlOaacd087lc6nR1H1r0e3B1CerTo+RceOmi1iJW+vp21xcQ==" }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -6109,6 +6821,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -6201,6 +6919,64 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, "node_modules/http-assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", @@ -6214,6 +6990,12 @@ "node": ">= 0.8" } }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, "node_modules/http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -6239,6 +7021,26 @@ "node": ">= 0.6" } }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -6253,6 +7055,30 @@ "node": ">= 6" } }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -6280,6 +7106,15 @@ "node": ">= 6" } }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -6419,6 +7254,15 @@ "loose-envify": "^1.0.0" } }, + "node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -6437,6 +7281,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -6605,6 +7461,18 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -6642,6 +7510,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -7162,6 +8042,16 @@ "ms": "^2.1.1" } }, + "node_modules/launch-editor": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, "node_modules/leaflet": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", @@ -7614,6 +8504,18 @@ "node": ">= 0.6" } }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -7623,6 +8525,12 @@ "node": ">= 0.10.0" } }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -7660,6 +8568,18 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -7688,6 +8608,21 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -7781,6 +8716,19 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -7862,6 +8810,15 @@ } } }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, "node_modules/node-releases": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", @@ -7908,6 +8865,15 @@ "semver": "bin/semver" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-all": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", @@ -8071,6 +9037,18 @@ "which": "bin/which" } }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -8132,6 +9110,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, "node_modules/octokit": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/octokit/-/octokit-3.1.1.tgz", @@ -8190,6 +9174,21 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/only": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", @@ -8281,6 +9280,19 @@ "node": ">=8" } }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -8566,6 +9578,28 @@ "react-is": "^16.13.1" } }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -8579,6 +9613,11 @@ "node": ">=6" } }, + "node_modules/put-selector": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/put-selector/-/put-selector-0.3.6.tgz", + "integrity": "sha512-usnm25gsnYkxRnSK5n0tXAgnQQ5DZV4zOqW8VwcDKSo0YebzOGMRx1Xl+LahwtnH+vqg97hlAi6qPUpqgIhX8g==" + }, "node_modules/qrcode-terminal": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", @@ -8589,9 +9628,9 @@ } }, "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dev": true, "dependencies": { "side-channel": "^1.0.4" @@ -8649,6 +9688,15 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/raw-body": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", @@ -8853,6 +9901,18 @@ "string_decoder": "~0.10.x" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -8952,6 +10012,21 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", @@ -9053,6 +10128,15 @@ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -9160,6 +10244,25 @@ "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -9174,6 +10277,76 @@ "node": ">=10" } }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/serialize-javascript": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", @@ -9183,6 +10356,24 @@ "randombytes": "^2.1.0" } }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/serve-index-75lb": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/serve-index-75lb/-/serve-index-75lb-2.0.1.tgz", @@ -9252,6 +10443,72 @@ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -9297,10 +10554,13 @@ } }, "node_modules/shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/side-channel": { "version": "1.0.4", @@ -9316,6 +10576,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -9325,6 +10591,26 @@ "node": ">=8" } }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -9418,6 +10704,79 @@ "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", "dev": true }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/spdy-transport/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/spdy-transport/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/split-on-first": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", @@ -9678,6 +11037,15 @@ "node": ">=4" } }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -9935,6 +11303,12 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, "node_modules/tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", @@ -10235,6 +11609,15 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", @@ -10303,6 +11686,15 @@ "node": ">=10.13.0" } }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -10409,6 +11801,194 @@ "node": ">=14" } }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/webpack-merge": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", @@ -10431,6 +12011,29 @@ "node": ">=10.13.0" } }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -10531,9 +12134,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/ws": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz", - "integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==", + "version": "8.14.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", + "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", "engines": { "node": ">=10.0.0" }, @@ -10550,6 +12153,14 @@ } } }, + "node_modules/xstyle": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/xstyle/-/xstyle-0.3.2.tgz", + "integrity": "sha512-NgElqDZ5ACAN8S3X+DhZlDLdSyKRW7dCml6VqDrh5iR5b5+x3APHGQd7F+AQAcGxmUx1yoMlt1V3kyyksxhjtA==", + "dependencies": { + "put-selector": "0.3.6" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/esp/src/package.json b/esp/src/package.json index 21ba22fbdf8..a0f40412ddb 100644 --- a/esp/src/package.json +++ b/esp/src/package.json @@ -28,7 +28,7 @@ "dev-start": "run-p bundle-watch dev-start-ws", "dev-start-verbose": "ws --verbose.include request response", "rm-hpcc": "rimraf ./node_modules/@hpcc-js", - "start": "webpack-dev-server -d --env development", + "start": "webpack serve --env development --config webpack.config.js", "test": "run-s lint", "update": "npx npm-check-updates -u -t minor", "update-major": "npx npm-check-updates -u" @@ -66,6 +66,7 @@ "es6-promise": "4.2.8", "font-awesome": "4.7.0", "formik": "2.2.9", + "put-selector": "0.3.6", "query-string": "7.1.3", "octokit": "3.1.1", "react": "17.0.2", @@ -74,7 +75,8 @@ "react-hot-toast": "2.4.0", "react-reflex": "4.0.9", "react-sizeme": "3.0.2", - "universal-router": "9.1.0" + "universal-router": "9.1.0", + "xstyle": "0.3.2" }, "devDependencies": { "@simbathesailor/use-what-changed": "^2.0.0", @@ -100,7 +102,8 @@ "typescript": "4.9.5", "url-loader": "4.1.1", "webpack": "5.89.0", - "webpack-cli": "5.1.4" + "webpack-cli": "5.1.4", + "webpack-dev-server": "4.15.1" }, "author": "HPCC Systems", "license": "Apache-2.0", diff --git a/esp/src/put-selector b/esp/src/put-selector deleted file mode 160000 index 06358997b45..00000000000 --- a/esp/src/put-selector +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 06358997b4523e03e150b40bdf666a590b72cb40 diff --git a/esp/src/src-react/components/Common.tsx b/esp/src/src-react/components/Common.tsx index 7c122c8e0d6..d39e49bcfb8 100644 --- a/esp/src/src-react/components/Common.tsx +++ b/esp/src/src-react/components/Common.tsx @@ -17,7 +17,7 @@ export function createCopyDownloadSelection(columns, selection: any, filename: s key: "download", text: nlsHPCC.DownloadSelectionAsCSV, disabled: !selection.length, iconOnly: true, iconProps: { iconName: "Download" }, onClick: () => { const csv = Utility.formatAsDelim(columns, selection, ","); - Utility.downloadText(csv, filename); + Utility.downloadCSV(csv, filename); } }]; } diff --git a/esp/src/src-react/components/FileDetails.tsx b/esp/src/src-react/components/FileDetails.tsx index 4111fe870f6..599339bc7da 100644 --- a/esp/src/src-react/components/FileDetails.tsx +++ b/esp/src/src-react/components/FileDetails.tsx @@ -105,7 +105,7 @@ export const FileDetails: React.FunctionComponent = ({ return {({ size }) =>
- + {file?.ContentType === "key" ? diff --git a/esp/src/src-react/components/Metrics.tsx b/esp/src/src-react/components/Metrics.tsx index ee87e620eec..f31cf7a4f1f 100644 --- a/esp/src/src-react/components/Metrics.tsx +++ b/esp/src/src-react/components/Metrics.tsx @@ -1,6 +1,7 @@ import * as React from "react"; import { CommandBar, ContextualMenuItemType, ICommandBarItemProps, IIconProps, SearchBox } from "@fluentui/react"; -import { Breadcrumb, BreadcrumbButton, BreadcrumbDivider, BreadcrumbItem, Spinner } from "@fluentui/react-components"; +import { Label, Spinner } from "@fluentui/react-components"; +import { typographyStyles } from "@fluentui/react-theme"; import { useConst } from "@fluentui/react-hooks"; import { bundleIcon, Folder20Filled, Folder20Regular, FolderOpen20Filled, FolderOpen20Regular, } from "@fluentui/react-icons"; import { WorkunitsServiceEx } from "@hpcc-js/comms"; @@ -13,12 +14,13 @@ import { FetchStatus, useMetricsOptions, useWorkunitMetrics } from "../hooks/met import { HolyGrail } from "../layouts/HolyGrail"; import { AutosizeComponent, AutosizeHpccJSComponent } from "../layouts/HpccJSAdapter"; import { DockPanel, DockPanelItems, ReactWidget, ResetableDockPanel } from "../layouts/DockPanel"; -import { IScope, MetricGraph, MetricGraphWidget, isGraphvizWorkerResponse, layoutCache } from "../util/metricGraph"; +import { IScope, LayoutStatus, MetricGraph, MetricGraphWidget, isGraphvizWorkerResponse, layoutCache } from "../util/metricGraph"; import { pushUrl } from "../util/history"; import { debounce } from "../util/throttle"; import { ErrorBoundary } from "../util/errorBoundary"; import { ShortVerticalDivider } from "./Common"; import { MetricsOptions } from "./MetricsOptions"; +import { BreadcrumbInfo, OverflowBreadcrumb } from "./controls/OverflowBreadcrumb"; const logger = scopedLogger("src-react/components/Metrics.tsx"); @@ -303,7 +305,7 @@ export const Metrics: React.FunctionComponent = ({ for (let i = 0; i < minLen; ++i) { const item = lineages[0][i]; if (lineages.every(lineage => lineage[i] === item)) { - if (metricGraph.isSubgraph(item) && item.name) { + if (item.id && item.type !== "child" && metricGraph.isSubgraph(item) && !metricGraph.isVertex(item)) { newLineage.push(item); } } else { @@ -321,7 +323,8 @@ export const Metrics: React.FunctionComponent = ({ const updateMetricGraph = React.useCallback((svg: string, selection: IScope[]) => { let cancelled = false; if (metricGraphWidget?.renderCount() > 0) { - setIsRenderComplete(false); + const sameSVG = metricGraphWidget.svg() === svg; + setIsRenderComplete(sameSVG); metricGraphWidget .svg(svg) .visible(false) @@ -335,7 +338,11 @@ export const Metrics: React.FunctionComponent = ({ ; if (trackSelection && selectedMetricsSource !== "metricGraphWidget") { if (newSel.length) { - metricGraphWidget.zoomToSelection(0); + if (sameSVG) { + metricGraphWidget.centerOnSelection(); + } else { + metricGraphWidget.zoomToSelection(0); + } } else { metricGraphWidget.zoomToFit(0); } @@ -410,38 +417,42 @@ export const Metrics: React.FunctionComponent = ({ } else if (!isLayoutComplete) { return `${nlsHPCC.PerformingLayout} (${dot.split("\n").length})`; } else if (!isRenderComplete) { - return `${nlsHPCC.RenderSVG}`; + return nlsHPCC.RenderSVG; } return ""; }, [fetchStatus, isLayoutComplete, isRenderComplete, dot]); + const breadcrumbs = React.useMemo(() => { + return lineage.map(item => { + return { + id: item.id, + label: item.id, + props: { + icon: selectedLineage === item ? : + } + }; + }); + }, [lineage, selectedLineage]); + const graphComponent = React.useMemo(() => { return - { - lineage.map((item, idx) => { - return <> - - : } onClick={() => setSelectedLineage(item)}> - {item.id} - - - {idx < lineage.length - 1 && } - ; - }) - } + setSelectedLineage(lineage.find(l => l.id === item.id))} /> } main={<> + } />; - }, [graphButtons, graphRightButtons, lineage, spinnerLabel, metricGraphWidget, selectedLineage]); + }, [graphButtons, graphRightButtons, breadcrumbs, selectedLineage?.id, spinnerLabel, selectedMetrics.length, metricGraphWidget, lineage]); // Props Table --- const propsTable = useConst(() => new Table() @@ -518,7 +529,7 @@ export const Metrics: React.FunctionComponent = ({ React.useEffect(() => { let cancelled = false; if (metricGraphWidget?.renderCount() > 0) { - setIsLayoutComplete(false); + setIsLayoutComplete(layoutCache.status(dot) === LayoutStatus.COMPLETED); layoutCache.calcSVG(dot).then(response => { if (!cancelled) { if (isGraphvizWorkerResponse(response)) { @@ -642,7 +653,7 @@ export const Metrics: React.FunctionComponent = ({ iconProps: { iconName: "Table" }, onClick: () => { const csv = Utility.formatAsDelim(formatColumns, metrics, ","); - Utility.downloadText(csv, `metrics-${wuid}.csv`); + Utility.downloadCSV(csv, `metrics-${wuid}.csv`); } }, { @@ -650,7 +661,7 @@ export const Metrics: React.FunctionComponent = ({ text: nlsHPCC.DownloadToDOT, iconProps: { iconName: "Relationship" }, onClick: () => { - Utility.downloadText(dot, `metrics-${wuid}.dot`); + Utility.downloadPlain(dot, `metrics-${wuid}.dot`); } }] } diff --git a/esp/src/src-react/components/QueryDetails.tsx b/esp/src/src-react/components/QueryDetails.tsx index 92a58a014c6..40b7b97061d 100644 --- a/esp/src/src-react/components/QueryDetails.tsx +++ b/esp/src/src-react/components/QueryDetails.tsx @@ -99,7 +99,7 @@ export const QueryDetails: React.FunctionComponent = ({ return {({ size }) =>
- + diff --git a/esp/src/src-react/components/WorkunitDetails.tsx b/esp/src/src-react/components/WorkunitDetails.tsx index 66d016c479b..2373e601687 100644 --- a/esp/src/src-react/components/WorkunitDetails.tsx +++ b/esp/src/src-react/components/WorkunitDetails.tsx @@ -112,7 +112,7 @@ export const WorkunitDetails: React.FunctionComponent = ({ return {({ size }) =>
- + diff --git a/esp/src/src-react/components/controls/OverflowBreadcrumb.tsx b/esp/src/src-react/components/controls/OverflowBreadcrumb.tsx new file mode 100644 index 00000000000..a9298c87420 --- /dev/null +++ b/esp/src/src-react/components/controls/OverflowBreadcrumb.tsx @@ -0,0 +1,62 @@ +import * as React from "react"; +import { Overflow, Breadcrumb, OverflowItem, BreadcrumbItem, BreadcrumbButton, BreadcrumbButtonProps, BreadcrumbDivider, OverflowDivider } from "@fluentui/react-components"; +import { bundleIcon, Folder20Filled, Folder20Regular, FolderOpen20Filled, FolderOpen20Regular, } from "@fluentui/react-icons"; +import { OverflowMenu } from "./OverflowMenu"; + +const LineageIcon = bundleIcon(Folder20Filled, Folder20Regular); +const SelectedLineageIcon = bundleIcon(FolderOpen20Filled, FolderOpen20Regular); + +export interface BreadcrumbInfo { + id: string; + label: string; + props?: BreadcrumbButtonProps +} + +interface OverflowGroupDividerProps { + groupId: string; +} + +const OverflowGroupDivider: React.FunctionComponent = ({ + groupId, +}) => { + return + + ; +}; + +function icon(breadcrumb: BreadcrumbInfo, selected: string) { + return breadcrumb.id === selected ? : ; +} + +export interface OverflowBreadcrumbProps { + breadcrumbs: BreadcrumbInfo[]; + selected: string; + onSelect: (tab: BreadcrumbInfo) => void; +} + +export const OverflowBreadcrumb: React.FunctionComponent = ({ + breadcrumbs, + selected, + onSelect +}) => { + + const overflowItems = React.useMemo(() => { + return breadcrumbs.map((breadcrumb, idx) => <> + + + onSelect(breadcrumb)}> + {breadcrumb.label} + + + + {idx < breadcrumbs.length - 1 && } + ); + }, [breadcrumbs, onSelect, selected]); + + return + + {...overflowItems} + ({ ...breadcrumb, icon: icon(breadcrumb, selected) }))} onMenuSelect={onSelect} /> + + ; +}; diff --git a/esp/src/src-react/components/controls/TabbedPanes/OverflowMenu.tsx b/esp/src/src-react/components/controls/OverflowMenu.tsx similarity index 62% rename from esp/src/src-react/components/controls/TabbedPanes/OverflowMenu.tsx rename to esp/src/src-react/components/controls/OverflowMenu.tsx index 018b0e75ce6..fa41b4903ac 100644 --- a/esp/src/src-react/components/controls/TabbedPanes/OverflowMenu.tsx +++ b/esp/src/src-react/components/controls/OverflowMenu.tsx @@ -2,26 +2,35 @@ import * as React from "react"; import { makeStyles, tokens, Button, Menu, MenuList, MenuPopover, MenuTrigger, useOverflowMenu, useIsOverflowItemVisible, MenuItem, } from "@fluentui/react-components"; import { MoreHorizontalRegular, MoreHorizontalFilled, bundleIcon, } from "@fluentui/react-icons"; import type { ARIAButtonElement } from "@fluentui/react-aria"; -import { TabInfo } from "./TabInfo"; -import { Count } from "./Count"; +import { Count } from "./TabbedPanes/Count"; const MoreHorizontal = bundleIcon(MoreHorizontalFilled, MoreHorizontalRegular); +export interface MenuItem { + id: string; + icon?: React.ReactElement; + label: string; + count?: string | number; + disabled?: boolean; +} + type OverflowMenuItemProps = { - tab: TabInfo; + item: MenuItem; onClick: React.MouseEventHandler>; }; -const OverflowMenuItem = (props: OverflowMenuItemProps) => { - const { tab, onClick } = props; - const isVisible = useIsOverflowItemVisible(tab.id); +const OverflowMenuItem: React.FunctionComponent = ({ + item, + onClick +}) => { + const isVisible = useIsOverflowItemVisible(item.id); if (isVisible) { return <>; } - return -
{tab.label}
+ return +
{item.label}
; }; @@ -34,13 +43,13 @@ const useOverflowMenuStyles = makeStyles({ }, }); -export type OverflowMenuProps = { - tabs: TabInfo[]; - onMenuSelect: (tab: TabInfo) => void; -}; +export interface OverflowMenuProps { + menuItems: readonly MenuItem[]; + onMenuSelect: (menuItem: MenuItem) => void; +} export const OverflowMenu: React.FunctionComponent = ({ - tabs, + menuItems, onMenuSelect }) => { const { ref, isOverflowing, overflowCount } = useOverflowMenu(); @@ -58,17 +67,17 @@ export const OverflowMenu: React.FunctionComponent = ({ className={styles.menuButton} ref={ref} icon={} - aria-label={`${overflowCount} more tabs`} - role="tab" + aria-label={`${overflowCount} more menu items`} + role="menuItem" /> - {tabs.map((tab) => ( + {menuItems.map((menuItem) => ( onMenuSelect(tab)} + key={menuItem.id} + item={menuItem} + onClick={() => onMenuSelect(menuItem)} /> ))} diff --git a/esp/src/src-react/components/controls/TabbedPanes/OverflowTabList.tsx b/esp/src/src-react/components/controls/TabbedPanes/OverflowTabList.tsx index 585d74c080b..e9cf3520ccf 100644 --- a/esp/src/src-react/components/controls/TabbedPanes/OverflowTabList.tsx +++ b/esp/src/src-react/components/controls/TabbedPanes/OverflowTabList.tsx @@ -2,18 +2,18 @@ import * as React from "react"; import { Overflow, OverflowItem, SelectTabData, SelectTabEvent, Tab, TabList } from "@fluentui/react-components"; import { Count } from "./Count"; import { TabInfo } from "./TabInfo"; -import { OverflowMenu } from "./OverflowMenu"; +import { OverflowMenu } from "../OverflowMenu"; export interface OverflowTabListProps { tabs: TabInfo[]; - selectedTab: string; + selected: string; onTabSelect: (tab: TabInfo) => void; size?: "small" | "medium" | "large"; } export const OverflowTabList: React.FunctionComponent = ({ tabs, - selectedTab, + selected, onTabSelect, size = "medium" }) => { @@ -24,23 +24,23 @@ export const OverflowTabList: React.FunctionComponent = ({ const tabsIndex = {}; return [tabs.map(tab => { tabsIndex[tab.id] = tab; - if (tab.id === selectedTab) { + if (tab.id === selected) { tab.__state = state; } - return + return {tab.label} ; }), tabsIndex]; - }, [selectedTab, state, tabs]); + }, [selected, state, tabs]); const localTabSelect = React.useCallback((evt: SelectTabEvent, data: SelectTabData) => { onTabSelect(tabsIndex[data.value as string]); }, [onTabSelect, tabsIndex]); return - + {...overflowItems} - + ; }; diff --git a/esp/src/src-react/components/forms/Fields.tsx b/esp/src/src-react/components/forms/Fields.tsx index 9efe0fdc8a7..16bdf49b754 100644 --- a/esp/src/src-react/components/forms/Fields.tsx +++ b/esp/src/src-react/components/forms/Fields.tsx @@ -495,7 +495,8 @@ export const TargetGroupTextField: React.FunctionComponent { TpGroupQuery({}).then(({ TpGroupQueryResponse }) => { - setTargetGroups(TpGroupQueryResponse.TpGroups.TpGroup.map(group => { + const groups = TpGroupQueryResponse?.TpGroups?.TpGroup ?? []; + setTargetGroups(groups.map(group => { switch (group?.Kind) { case "Thor": case "hthor": diff --git a/esp/src/src-react/components/forms/RemoteCopy.tsx b/esp/src/src-react/components/forms/RemoteCopy.tsx index 113c819bd8c..160c29d3885 100644 --- a/esp/src/src-react/components/forms/RemoteCopy.tsx +++ b/esp/src/src-react/components/forms/RemoteCopy.tsx @@ -97,7 +97,7 @@ export const RemoteCopy: React.FunctionComponent = ({ WsTopology.TpGroupQuery({ request: {} }).then(response => { - const groups = response.TpGroupQueryResponse.TpGroups?.TpGroup ?? []; + const groups = response.TpGroupQueryResponse?.TpGroups?.TpGroup ?? []; for (const index in groups) { if (groups[index].Name === selectedDestGroup) { if (groups[index].ReplicateOutputs === true) { diff --git a/esp/src/src-react/util/metricGraph.ts b/esp/src/src-react/util/metricGraph.ts index 9e28bfea2d3..ba799585eee 100644 --- a/esp/src/src-react/util/metricGraph.ts +++ b/esp/src/src-react/util/metricGraph.ts @@ -10,6 +10,10 @@ const logger = scopedLogger("src-react/util/metricGraph.ts"); declare const dojoConfig; +const TypeShape = { + "function": 'plain" fillcolor="" style="' +}; + const KindShape = { 2: "cylinder", // Disk Write 3: "tripleoctagon", // Local Sort @@ -36,8 +40,8 @@ const KindShape = { 196: "cylinder", // Spill Write }; -function shape(kind: string) { - return KindShape[kind] || "rectangle"; +function shape(v: IScope) { + return TypeShape[v.type] ?? KindShape[v.kind] ?? "rectangle"; } const CHARS = new Set("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); @@ -243,11 +247,18 @@ export class MetricGraph extends Graph2 { return this.outEdges(v.name).filter(e => e.__parentName === v.__parentName); } + protected _dedupVertices: { [scopeName: string]: boolean } = {}; vertexTpl(v: IScope, options: MetricsOptions): string { - return `"${v.id}" [id="${encodeID(v.name)}" label="${encodeLabel(this.vertexLabel(v, options))}" shape="${shape(v.Kind)}" class="${this.vertexStatus(v)}"]`; + if (this._dedupVertices[v.id] === true) return ""; + this._dedupVertices[v.id] = true; + return `"${v.id}" [id="${encodeID(v.name)}" label="${encodeLabel(this.vertexLabel(v, options))}" shape="${shape(v)}" class="${this.vertexStatus(v)}"]`; } - protected _dedupEdges: { [scopeName: string]: boolean } = {}; + hiddenTpl(v: IScope, options: MetricsOptions): string { + if (this._dedupVertices[v.id] === true) return ""; + this._dedupVertices[v.id] = true; + return `"${v.id}" [id="${encodeID(v.name)}" label="${encodeLabel(this.vertexLabel(v, options))}" shape="${shape(v)}" class="${this.vertexStatus(v)}" rank="min"]`; + } findFirstVertex(scopeName: string) { if (this.vertexExists(scopeName)) { @@ -275,14 +286,15 @@ export class MetricGraph extends Graph2 { return "unknown"; } + protected _dedupEdges: { [scopeName: string]: boolean } = {}; edgeTpl(e: IScopeEdge, options: MetricsOptions) { if (this._dedupEdges[e.id] === true) return ""; this._dedupEdges[e.id] = true; if (options.ignoreGlobalStoreOutEdges && this.vertex(this._activityIndex[e.IdSource]).Kind === "22") { return ""; } - const ltail = this.subgraphExists(this._sourceFunc(e.IdSource)) ? `ltail="cluster_${e.IdSource}"` : ""; - const lhead = this.subgraphExists(this._targetFunc(e.IdTarget)) ? `lhead="cluster_${e.IdTarget}"` : ""; + const ltail = this.subgraphExists(this._sourceFunc(e)) ? `ltail=cluster_${e.IdSource}` : ""; + const lhead = this.subgraphExists(this._targetFunc(e)) ? `lhead=cluster_${e.IdTarget}` : ""; return `"${e.IdSource}" -> "${e.IdTarget}" [id="${encodeID(e.name)}" label="${encodeLabel(format(options.edgeTpl, { ...e, ...e.__formattedProps }))}" style="${this.vertexParent(this._activityIndex[e.IdSource]) === this.vertexParent(this._activityIndex[e.IdTarget]) ? "solid" : "dashed"}" class="${this.edgeStatus(e)}" ${ltail} ${lhead}]`; } @@ -298,11 +310,17 @@ export class MetricGraph extends Graph2 { return "unknown"; } + protected _dedupSubgraphs: { [scopeName: string]: boolean } = {}; subgraphTpl(sg: IScope, options: MetricsOptions): string { + if (this._dedupSubgraphs[sg.id] === true) return ""; + this._dedupSubgraphs[sg.id] = true; const childTpls: string[] = []; this.subgraphSubgraphs(sg.name).forEach(child => { childTpls.push(this.subgraphTpl(child, options)); }); + if (this.vertexExists(this.id(sg))) { + childTpls.push(this.hiddenTpl(this.vertex(this.id(sg)), options)); + } this.subgraphVertices(sg.name).forEach(child => { childTpls.push(this.vertexTpl(child, options)); }); @@ -323,7 +341,8 @@ subgraph cluster_${encodeID(sg.id)} { } graphTpl(items: IScope[] = [], options: MetricsOptions) { - // subgraphs.sort(); + this._dedupSubgraphs = {}; + this._dedupVertices = {}; this._dedupEdges = {}; const childTpls: string[] = []; if (items?.length) { @@ -359,6 +378,8 @@ subgraph cluster_${encodeID(sg.id)} { } return `\ digraph G { + compound=true; + oredering=in; graph [fontname="arial"];// fontsize=11.0]; // graph [rankdir=TB]; // node [shape=rect fontname=arial fontsize=11.0 fixedsize=true]; @@ -589,6 +610,11 @@ export class MetricGraphWidget extends SVGZoomWidget { return this; } + centerOnSelection(transitionDuration?: number) { + this.centerOnBBox(this.selectionBBox(), transitionDuration); + return this; + } + zoomToItem(scopeID: string) { this.zoomToBBox(this.itemBBox(scopeID)); return this; diff --git a/esp/src/src/Utility.ts b/esp/src/src/Utility.ts index 010e403cc53..0c225ad67c0 100644 --- a/esp/src/src/Utility.ts +++ b/esp/src/src/Utility.ts @@ -1056,17 +1056,25 @@ export function toCSV(data, delim = ",") { return retVal; } -export function downloadText(content: string, fileName: string) { - const encodedUri = "data:text/csv;charset=utf-8,\uFEFF" + encodeURI(content); +function downloadText(content: string, fileName: string, type: "csv" | "plain" = "csv") { + const textBlob = new Blob([content], { type: `text/${type}` }); const link = document.createElement("a"); - link.setAttribute("href", encodedUri); link.setAttribute("download", fileName); + link.setAttribute("href", window.URL.createObjectURL(textBlob)); link.style.visibility = "hidden"; document.body.appendChild(link); link.click(); document.body.removeChild(link); } +export function downloadCSV(content: string, fileName: string) { + downloadText(content, fileName, "csv"); +} + +export function downloadPlain(content: string, fileName: string) { + downloadText(content, fileName, "plain"); +} + const d3FormatNum = d3Format(","); export function parseCookies(): Record { diff --git a/esp/src/src/nls/hpcc.ts b/esp/src/src/nls/hpcc.ts index 4bdd7b53eef..e026a6d7e7f 100644 --- a/esp/src/src/nls/hpcc.ts +++ b/esp/src/src/nls/hpcc.ts @@ -577,6 +577,7 @@ export = { NewPassword: "New Password", NextSelection: "Next Selection", NoContent: "(No content)", + NoContentPleaseSelectItem: "No content - please select an item", NoCommon: "No Common", noDataMessage: "...Zero Rows...", Node: "Node", @@ -688,9 +689,9 @@ export = { PleaseSelectADynamicESDLService: "Please select a dynamic ESDL service", PleaseSelectAServiceToBind: "Please select a service to bind", PleaseSelectATopologyItem: "Please select a target, service or machine.", - Plugins: "Plugins", PleaseEnterANumber: "Please enter a number 1 - ", PleaseLogin: "Please log in using your username and password", + Plugins: "Plugins", PodName: "Pod Name", Pods: "Pods", PodsAccessError: "Cannot retrieve list of pods", diff --git a/esp/src/webpack.config.js b/esp/src/webpack.config.js index ec4a7846b1a..3ac67a2ddbe 100644 --- a/esp/src/webpack.config.js +++ b/esp/src/webpack.config.js @@ -12,7 +12,7 @@ if (fs.existsSync("./lws.target.txt")) { } console.log("debugServerIP: ", debugServerIP); const proxy = {}; -const proxyItems = ["/WsWorkunits", "/WsStore", "/WsSMC", "/WsTopology", "/WsDfu", "/FileSpray", "/ws_machine", "/ws_account", "/ws_elk", "/esp/getauthtype", "/esp/reset_session_timeout", "/esp/titlebar"]; +const proxyItems = ["/WsWorkunits", "/WsStore", "/WsSMC", "/WsTopology", "/WsDfu", "/FileSpray", "/ws_machine", "/ws_account", "/Ws_Account", "WsResources", "/ws_logaccess", "/ws_elk", "/esp/getauthtype", "/esp/reset_session_timeout", "/esp/titlebar"]; proxyItems.forEach(item => { proxy[item] = { target: "http://" + debugServerIP + ":8010", @@ -108,9 +108,14 @@ module.exports = function (env) { }, devServer: isProduction ? undefined : { - contentBase: path.join(__dirname, "build"), - contentBasePublicPath: "/esp/files", - proxy + hot: "only", + static: { + directory: path.join(__dirname, './build'), + publicPath: "/esp/files" + }, + liveReload: false, + proxy, + port: 8080 } } }; \ No newline at end of file diff --git a/esp/src/xstyle b/esp/src/xstyle deleted file mode 160000 index 87c414981d6..00000000000 --- a/esp/src/xstyle +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 87c414981d6810aac82204291c25a138720cd3d2 diff --git a/helm/examples/metrics/filesink.yaml b/helm/examples/metrics/filesink.yaml index beb9b2224f2..7451857d195 100644 --- a/helm/examples/metrics/filesink.yaml +++ b/helm/examples/metrics/filesink.yaml @@ -1,12 +1,13 @@ # # Defines a file sink for accepting metric reports. # Settings: -# type - type of sink (must be file for the file sink) -# name - name for the sink instance -# settings.filename - name of the file where metrics are to be written -# settings.clear - true to clear the file when metric reporting begins -# false to append to an existing file -# settings.period - period in seconds between collections +# type - type of sink (must be file for the file sink) +# name - name for the sink instance +# settings.filename - name of the file where metrics are to be written +# settings.clear - true to clear the file when metric reporting begins +# false to append to an existing file +# settings.period - period in seconds between collections +# settings.ignoreZeroMetrics - true|false true to ignore zero metrics, false to output regardless global: metrics: diff --git a/helm/examples/metrics/loggingsink.yaml b/helm/examples/metrics/loggingsink.yaml index 695927de490..b2011230038 100644 --- a/helm/examples/metrics/loggingsink.yaml +++ b/helm/examples/metrics/loggingsink.yaml @@ -1,9 +1,11 @@ # # Defines a logging sink that writes metric reports to the component defined log # Settings: -# type - sink type (must be log for the logging sink) -# name - name for the sink instance -# settings.period - period in seconds between collections +# type - sink type (must be log for the logging sink) +# name - name for the sink instance +# settings.period - period in seconds between collections +# settings.ignoreZeroMetrics - true|false true to ignore zero metrics, false to output regardless + global: metrics: sinks: diff --git a/helm/hpcc/templates/_helpers.tpl b/helm/hpcc/templates/_helpers.tpl index 91a867fceca..86929c96b01 100644 --- a/helm/hpcc/templates/_helpers.tpl +++ b/helm/hpcc/templates/_helpers.tpl @@ -1211,6 +1211,9 @@ Generate list of available services workunitsBasedn: {{ $esp.ldap.workunitsBasedn }} {{ end -}} {{ end -}} + {{- if (hasKey $esp "loadDaliBindings") }} + loadDaliBindings: {{ $esp.loadDaliBindings }} + {{ end -}} {{- include "hpcc.addTLSServiceEntries" (dict "root" $ "service" $esp "component" $esp "visibility" $esp.service.visibility "remoteClients" $esp.remoteClients "trustClients" $esp.trustClients) }} {{ end -}} {{- range $dali := $.Values.dali -}} diff --git a/plugins/fileservices/fileservices.cpp b/plugins/fileservices/fileservices.cpp index 38947c6511e..cc91a866ded 100644 --- a/plugins/fileservices/fileservices.cpp +++ b/plugins/fileservices/fileservices.cpp @@ -1335,7 +1335,7 @@ FILESERVICES_API char * FILESERVICES_CALL fsfDespray2(ICodeContext *ctx, const c return implementDespray(ctx, sourceLogicalName, destinationIP, destinationPath, timeOut, espServerIpPort, maxConnections, overwrite, destinationPlane); } -FILESERVICES_API char * FILESERVICES_CALL implementCopy(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression, bool noSplit, int expireDays) +FILESERVICES_API char * FILESERVICES_CALL implementCopy(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression, bool noSplit, int expireDays, bool ensure) { LOG(MCauditInfo, "Copy: %s%s", sourceLogicalName,asSuperfile?" as superfile":""); @@ -1373,6 +1373,8 @@ FILESERVICES_API char * FILESERVICES_CALL implementCopy(ICodeContext *ctx, const req->setMaxConnections(maxConnections); if (noSplit) req->setNosplit(true); + if (ensure) + req->setEnsure(true); req->setExpireDays(expireDays); Owned result = server.Copy(req); @@ -1401,32 +1403,42 @@ FILESERVICES_API char * FILESERVICES_CALL implementCopy(ICodeContext *ctx, const FILESERVICES_API void FILESERVICES_CALL fsCopy(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize) { - CTXFREE(parentCtx, implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, true, false, -1)); + CTXFREE(parentCtx, implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, true, false, -1, false)); } FILESERVICES_API void FILESERVICES_CALL fsCopy_v2(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression) { - CTXFREE(parentCtx, implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, false, -1)); + CTXFREE(parentCtx, implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, false, -1, false)); } FILESERVICES_API void FILESERVICES_CALL fsCopy_v3(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression, bool noSplit, int expireDays) { - CTXFREE(parentCtx, implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays)); + CTXFREE(parentCtx, implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays, false)); +} + +FILESERVICES_API void FILESERVICES_CALL fsCopy_v4(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression, bool noSplit, int expireDays, bool ensure) +{ + CTXFREE(parentCtx, implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays, ensure)); } FILESERVICES_API char * FILESERVICES_CALL fsfCopy(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize) { - return implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, true, false, -1); + return implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, true, false, -1, false); } FILESERVICES_API char * FILESERVICES_CALL fsfCopy_v2(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression) { - return implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, false,-1); + return implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, false, -1, false); } FILESERVICES_API char * FILESERVICES_CALL fsfCopy_v3(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression, bool noSplit, int expireDays) { - return implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays); + return implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays, false); +} + +FILESERVICES_API char * FILESERVICES_CALL fsfCopy_v4(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression, bool noSplit, int expireDays, bool ensure) +{ + return implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays, ensure); } diff --git a/plugins/fileservices/fileservices.hpp b/plugins/fileservices/fileservices.hpp index a34fc86ab7f..db1c52a049f 100644 --- a/plugins/fileservices/fileservices.hpp +++ b/plugins/fileservices/fileservices.hpp @@ -85,6 +85,7 @@ FILESERVICES_API void FILESERVICES_CALL fsDespray2(ICodeContext *ctx, const char FILESERVICES_API void FILESERVICES_CALL fsCopy(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize); FILESERVICES_API void FILESERVICES_CALL fsCopy_v2(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression); FILESERVICES_API void FILESERVICES_CALL fsCopy_v3(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression, bool noSplit=false, int expireDays=-1); +FILESERVICES_API void FILESERVICES_CALL fsCopy_v4(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression, bool noSplit=false, int expireDays=-1, bool ensure=false); FILESERVICES_API void FILESERVICES_CALL fsDkc(ICodeContext *ctx, const char * sourceLogicalName, const char * destinationIP, const char * destinationPath, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite); FILESERVICES_API void FILESERVICES_CALL fsReplicate(ICodeContext *ctx, const char * sourceLogicalName, int timeOut, const char * espServerIpPort); FILESERVICES_API void FILESERVICES_CALL fsCreateSuperFile(ICodeContext *ctx, const char *lsuperfn, bool sequentialparts, bool ifdoesnotexist); @@ -138,6 +139,7 @@ FILESERVICES_API char * FILESERVICES_CALL fsfDespray2(ICodeContext *ctx, const c FILESERVICES_API char * FILESERVICES_CALL fsfCopy(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize); FILESERVICES_API char * FILESERVICES_CALL fsfCopy_v2(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression); FILESERVICES_API char * FILESERVICES_CALL fsfCopy_v3(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression, bool noSplit=false, int expireDays=-1); +FILESERVICES_API char * FILESERVICES_CALL fsfCopy_v4(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize, bool preserveCompression, bool noSplit=false, int expireDays=-1, bool ensure=false); FILESERVICES_API char * FILESERVICES_CALL fsfDkc(ICodeContext *ctx, const char * sourceLogicalName, const char * destinationIP, const char * destinationPath, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite); FILESERVICES_API char * FILESERVICES_CALL fsfReplicate(ICodeContext *ctx, const char * sourceLogicalName, int timeOut, const char * espServerIpPort); FILESERVICES_API char * FILESERVICES_CALL fsfMonitorLogicalFileName(ICodeContext *ctx, const char *eventname, const char *_lfn,int shotcount, const char * espServerIpPort); diff --git a/plugins/parquet/parquetembed.cpp b/plugins/parquet/parquetembed.cpp index e07ef588779..4ebe9760bbc 100644 --- a/plugins/parquet/parquetembed.cpp +++ b/plugins/parquet/parquetembed.cpp @@ -163,7 +163,7 @@ arrow::Status ParquetReader::openReadFile() failx("Incorrect partitioning type %s.", partOption.c_str()); } // Create the dataset factory - PARQUET_ASSIGN_OR_THROW(auto datasetFactory, arrow::dataset::FileSystemDatasetFactory::Make(fs, selector, format, options)); + PARQUET_ASSIGN_OR_THROW(auto datasetFactory, arrow::dataset::FileSystemDatasetFactory::Make(std::move(fs), std::move(selector), format, std::move(options))); // Get scanner PARQUET_ASSIGN_OR_THROW(auto dataset, datasetFactory->Finish()); @@ -372,7 +372,7 @@ arrow::Result> ParquetReader::queryRows() // Convert the current batch to a table PARQUET_ASSIGN_OR_THROW(auto batch, *rbatchItr); rbatchItr++; - std::vector> toTable = {batch}; + std::vector> toTable = {std::move(batch)}; return std::move(arrow::Table::FromRecordBatches(std::move(toTable))); } @@ -457,7 +457,7 @@ arrow::Status ParquetWriter::openWriteFile() ARROW_ASSIGN_OR_RAISE(auto filesystem, arrow::fs::FileSystemFromUriOrPath(destination)); auto format = std::make_shared(); writeOptions.file_write_options = format->DefaultWriteOptions(); - writeOptions.filesystem = filesystem; + writeOptions.filesystem = std::move(filesystem); writeOptions.base_dir = destination; writeOptions.partitioning = partitionType; writeOptions.existing_data_behavior = arrow::dataset::ExistingDataBehavior::kOverwriteOrIgnore; @@ -484,7 +484,7 @@ arrow::Status ParquetWriter::openWriteFile() std::shared_ptr arrowProps = parquet::ArrowWriterProperties::Builder().store_schema()->build(); // Create a writer - ARROW_ASSIGN_OR_RAISE(writer, parquet::arrow::FileWriter::Open(*schema.get(), pool, outfile, props, arrowProps)); + ARROW_ASSIGN_OR_RAISE(writer, parquet::arrow::FileWriter::Open(*schema.get(), pool, outfile, std::move(props), std::move(arrowProps))); } return arrow::Status::OK(); } diff --git a/plugins/parquet/parquetembed.hpp b/plugins/parquet/parquetembed.hpp index f537eba588b..b9db5085c82 100644 --- a/plugins/parquet/parquetembed.hpp +++ b/plugins/parquet/parquetembed.hpp @@ -878,7 +878,7 @@ class ParquetRowStream : public RtlCInterface, implements IRowStream { public: ParquetRowStream(IEngineRowAllocator *_resultAllocator, std::shared_ptr _parquetReader) - : resultAllocator(_resultAllocator), parquetReader(_parquetReader) {} + : resultAllocator(_resultAllocator), parquetReader(std::move(_parquetReader)) {} virtual ~ParquetRowStream() = default; RTLIMPLEMENT_IINTERFACE @@ -947,7 +947,7 @@ class ParquetRecordBinder : public CInterfaceOf { public: ParquetRecordBinder(const IContextLogger &_logctx, const RtlTypeInfo *_typeInfo, int _firstParam, std::shared_ptr _parquetWriter) - : logctx(_logctx), typeInfo(_typeInfo), firstParam(_firstParam), dummyField("", NULL, typeInfo), thisParam(_firstParam), parquetWriter(_parquetWriter) {} + : logctx(_logctx), typeInfo(_typeInfo), firstParam(_firstParam), dummyField("", NULL, typeInfo), thisParam(_firstParam), parquetWriter(std::move(_parquetWriter)) {} virtual ~ParquetRecordBinder() = default; int numFields(); void processRow(const byte *row); diff --git a/plugins/proxies/lib_fileservices.ecllib b/plugins/proxies/lib_fileservices.ecllib index a63d05e8431..33e8412ce2e 100644 --- a/plugins/proxies/lib_fileservices.ecllib +++ b/plugins/proxies/lib_fileservices.ecllib @@ -44,7 +44,7 @@ export FileServices := SERVICE : plugin('fileservices'), time SprayXml(const varstring sourceIP='', const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceRowTag, const varstring sourceEncoding='utf8', const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false,boolean compress=false, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false, const varstring sourcePlane='', unsigned4 destinationNumParts=0, boolean noCommon=true) : c,action,context,entrypoint='fsSprayXml_v6'; SprayJson(const varstring sourceIP='', const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceRowPath='/', const varstring sourceEncoding='utf8', const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false,boolean compress=false, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false, const varstring username = '', const varstring userPw = '', const varstring sourcePlane='', unsigned4 destinationNumParts=0, boolean noCommon=true) : c,action,context,entrypoint='fsSprayJson_v3'; Despray(const varstring logicalName, const varstring destinationIP='', const varstring destinationPath, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, const varstring destinationPlane='') : c,action,context,entrypoint='fsDespray2'; - Copy(const varstring sourceLogicalName, const varstring destinationGroup, const varstring destinationLogicalName, const varstring sourceDali='', integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean asSuperfile=false, boolean compress=false, boolean forcePush=false, integer4 transferBufferSize=0, boolean preserveCompression=true, boolean noSplit=false, integer4 expireDays=-1) : c,action,context,entrypoint='fsCopy_v3'; + Copy(const varstring sourceLogicalName, const varstring destinationGroup, const varstring destinationLogicalName, const varstring sourceDali='', integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean asSuperfile=false, boolean compress=false, boolean forcePush=false, integer4 transferBufferSize=0, boolean preserveCompression=true, boolean noSplit=false, integer4 expireDays=-1, boolean ensure=false) : c,action,context,entrypoint='fsCopy_v4'; Replicate(const varstring logicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsReplicate'; CreateSuperFile(const varstring lsuperfn, boolean sequentialparts=false,boolean ifdoesnotexist=false) : c,action,context,entrypoint='fsCreateSuperFile'; boolean SuperFileExists(const varstring lsuperfn) : c,context,entrypoint='fsSuperFileExists'; @@ -71,7 +71,7 @@ export FileServices := SERVICE : plugin('fileservices'), time varstring fSprayXml(const varstring sourceIP='', const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceRowTag, const varstring sourceEncoding='utf8', const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean compress=false, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false, const varstring sourcePlane='', unsigned4 destinationNumParts=0, boolean noCommon=true) : c,action,context,entrypoint='fsfSprayXml_v6'; varstring fSprayJson(const varstring sourceIP='', const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceRowPath='/', const varstring sourceEncoding='utf8', const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean compress=false, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false, const varstring username = '', const varstring userPw = '', const varstring sourcePlane='', unsigned4 destinationNumParts=0, boolean noCommon=true) : c,action,context,entrypoint='fsfSprayJson_v3'; varstring fDespray(const varstring logicalName, const varstring destinationIP='', const varstring destinationPath, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, const varstring destinationPlane='') : c,action,context,entrypoint='fsfDespray2'; - varstring fCopy(const varstring sourceLogicalName, const varstring destinationGroup, const varstring destinationLogicalName, const varstring sourceDali='', integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean asSuperfile=false, boolean compress=false, boolean forcePush=false, integer4 transferBufferSize=0, boolean preserveCompression=true, boolean noSplit=false, integer4 expireDays=-1) : c,action,context,entrypoint='fsfCopy_v3'; + varstring fCopy(const varstring sourceLogicalName, const varstring destinationGroup, const varstring destinationLogicalName, const varstring sourceDali='', integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean asSuperfile=false, boolean compress=false, boolean forcePush=false, integer4 transferBufferSize=0, boolean preserveCompression=true, boolean noSplit=false, integer4 expireDays=-1, boolean ensure=false) : c,action,context,entrypoint='fsfCopy_v4'; varstring fMonitorLogicalFileName(const varstring event_name, const varstring name, integer4 shotcount=1,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsfMonitorLogicalFileName'; varstring fMonitorFile(const varstring event_name, const varstring ip, const varstring filename, boolean subdirs=false, integer4 shotcount=1,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsfMonitorFile'; varstring fReplicate(const varstring logicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsfReplicate'; diff --git a/roxie/ccd/ccdserver.cpp b/roxie/ccd/ccdserver.cpp index 3e4dfa92b21..21de9c67b1d 100644 --- a/roxie/ccd/ccdserver.cpp +++ b/roxie/ccd/ccdserver.cpp @@ -390,6 +390,60 @@ class IndirectAgentContext : implements IRoxieAgentContext, public CInterface //================================================================================= +class MergingStatsGatherer : implements CUnsharedInterfaceOf +{ +public: + MergingStatsGatherer(IStatisticGatherer * _gatherer) : gatherer(_gatherer) + { + } + + virtual void beginScope(const StatsScopeId & id) override + { + gatherer->beginScope(id); + } + virtual void beginSubGraphScope(unsigned id) override + { + gatherer->beginSubGraphScope(id); + } + virtual void beginActivityScope(unsigned id) override + { + gatherer->beginActivityScope(id); + } + virtual void beginEdgeScope(unsigned id, unsigned oid) override + { + gatherer->beginEdgeScope(id, oid); + } + virtual void beginChildGraphScope(unsigned id) override + { + gatherer->beginChildGraphScope(id); + } + virtual void beginChannelScope(unsigned id) override + { + gatherer->beginChannelScope(id); + } + virtual void endScope() override + { + gatherer->endScope(); + } + virtual void addStatistic(StatisticKind kind, unsigned __int64 value) override + { + //Always merge rather than add (otherwise it may create duplicate entries) + gatherer->updateStatistic(kind, value, queryMergeMode(kind)); + } + virtual void updateStatistic(StatisticKind kind, unsigned __int64 value, StatsMergeAction mergeAction) override + { + gatherer->updateStatistic(kind, value, mergeAction); + } + virtual IStatisticCollection * getResult() override + { + return gatherer->getResult(); + } + +private: + IStatisticGatherer * gatherer; +}; + +//================================================================================= #define RESULT_FLUSH_THRESHOLD 10000u #ifdef _DEBUG @@ -1942,7 +1996,7 @@ class CRoxieServerActivity : implements CInterfaceOf, impl if (statsBuilder) { StatsEdgeScope scope(*statsBuilder, activityId, oid); - if (_strands) + if (_strands > 1) statsBuilder->addStatistic(StNumStrands, _strands); if (starts != 0) { @@ -16532,8 +16586,9 @@ class CRoxieServerParallelGraphLoopActivity : public CRoxieServerGraphLoopActivi resultStream = NULL; resultJunction.clear(); + MergingStatsGatherer mergeStats(childStats); ForEachItemIn(i, iterationGraphs) - iterationGraphs.item(i).gatherStatistics(childStats); + iterationGraphs.item(i).gatherStatistics(childStats ? &mergeStats : nullptr); outputs.kill(); iterationGraphs.kill(); // must be done after all activities killed @@ -28506,9 +28561,11 @@ class CProxyActivityGraph : implements IActivityGraph, implements IThorChildGrap virtual const char *queryName() const override { throwUnexpected(); } virtual void gatherStatistics(IStatisticGatherer * statsBuilder) const override { + //Merge the stats from multiple graph instances. + MergingStatsGatherer mergeStatsBuilder(statsBuilder); CriticalBlock b(graphCrit); ForEachItemIn(i, stack) - stack.item(i).gatherStatistics(statsBuilder); + stack.item(i).gatherStatistics(statsBuilder ? &mergeStatsBuilder : nullptr); } virtual IEclGraphResults * evaluate(unsigned parentExtractSize, const byte * parentExtract) override { diff --git a/roxie/udplib/udpsha.cpp b/roxie/udplib/udpsha.cpp index b1a0bd0bbfa..de33bc6243e 100644 --- a/roxie/udplib/udpsha.cpp +++ b/roxie/udplib/udpsha.cpp @@ -398,9 +398,10 @@ bool PacketTracker::noteSeen(UdpPacketHeader &hdr) else if (!resent) packetsOOO++; } - else if (resent) + else if (resent && base) // Don't treat a resend that goes out of range as indicative of a restart - it probably just means - // that the resend was not needed and the original moved things on when it arrived + // that the resend was not needed and the original moved things on when it arrived. Unless base is 0 + // in which case it probably means I restarted duplicate = true; else { diff --git a/roxie/udplib/udpsim.cpp b/roxie/udplib/udpsim.cpp index 9015e7b2811..a4f20351936 100644 --- a/roxie/udplib/udpsim.cpp +++ b/roxie/udplib/udpsim.cpp @@ -254,8 +254,11 @@ void simulateTraffic() { if (restartReceiver) { - Sleep(100); + Sleep(1000); rm.clear(); + DBGLOG("Killed receiver"); + Sleep(500); + DBGLOG("Restarting receiver"); rm.setown(createReceiveManager(CCD_SERVER_FLOW_PORT, CCD_DATA_PORT, CCD_CLIENT_FLOW_PORT, numReceiveSlots, false)); } } diff --git a/roxie/udplib/udptrs.cpp b/roxie/udplib/udptrs.cpp index e9dd155b351..e9aad21ce78 100644 --- a/roxie/udplib/udptrs.cpp +++ b/roxie/udplib/udptrs.cpp @@ -252,7 +252,6 @@ class UdpReceiverEntry : public IUdpReceiverEntry const IpAddress ip; std::atomic timeouts{0}; // Number of consecutive timeouts std::atomic requestExpiryTime{0}; // Updated by send_flow thread, read by send_resend thread and send_data thread - static bool comparePacket(const void *pkData, const void *key) { UdpPacketHeader *dataHdr = (UdpPacketHeader*) ((DataBuffer*)pkData)->data; diff --git a/system/jhtree/jhtree.cpp b/system/jhtree/jhtree.cpp index 705cca9dce2..53265d82167 100644 --- a/system/jhtree/jhtree.cpp +++ b/system/jhtree/jhtree.cpp @@ -1953,6 +1953,8 @@ bool CKeyCursor::_lookup(bool exact, unsigned lastSeg, bool unfiltered, KeyStats ret = true; break; } + if (eof) + break; lwildseeks++; } else diff --git a/system/jlib/jfile.cpp b/system/jlib/jfile.cpp index c11c666897a..cc87f6afd0e 100644 --- a/system/jlib/jfile.cpp +++ b/system/jlib/jfile.cpp @@ -4256,8 +4256,20 @@ void recursiveRemoveDirectory(IFile *dir) recursiveRemoveDirectory(thisFile); else { + try + { + thisFile->remove(); + continue; // i.e. continue if returns true (removed), or false (file no longer exists) + } + catch(IException *e) + { + e->Release(); + } + + // NB: not sure this is worth it. In linux the file can be read-only and still be deleted if the directory is writable + // Perhaps should ensure that the parent directory is writable, but that would require extra file ops. or interface changes thisFile->setReadOnly(false); - thisFile->remove(); + thisFile->remove(); // if gets here, the file should exist (ignore return false if doesn't), throws an exception if fails for other reason } } dir->remove(); diff --git a/system/jlib/jstats.cpp b/system/jlib/jstats.cpp index 6b694eb46c5..46a20cd6355 100644 --- a/system/jlib/jstats.cpp +++ b/system/jlib/jstats.cpp @@ -2002,8 +2002,15 @@ class CStatisticCollection : public CInterfaceOf } //other public interface functions + // addStatistic() should only be used if it is known that the kind is not already there void addStatistic(StatisticKind kind, unsigned __int64 value) { +#ifdef _DEBUG + // In debug builds check that a value for this kind has not already been added. + // We do not want the O(N) overhead in release mode, especially as N is beginning to get larger + unsigned __int64 debugTest; + assertex(getStatistic(kind,debugTest)==false); +#endif Statistic s(kind, value); stats.append(s); } diff --git a/system/jlib/jstats.h b/system/jlib/jstats.h index cacdb23684e..86e3ff9163b 100644 --- a/system/jlib/jstats.h +++ b/system/jlib/jstats.h @@ -163,7 +163,7 @@ interface IStatisticGatherer : public IInterface virtual void beginChildGraphScope(unsigned id) = 0; virtual void beginChannelScope(unsigned id) = 0; virtual void endScope() = 0; - virtual void addStatistic(StatisticKind kind, unsigned __int64 value) = 0; + virtual void addStatistic(StatisticKind kind, unsigned __int64 value) = 0; // use updateStatistic() if kind could already be defined for the active scope virtual void updateStatistic(StatisticKind kind, unsigned __int64 value, StatsMergeAction mergeAction) = 0; virtual IStatisticCollection * getResult() = 0; }; diff --git a/system/metrics/sinks/file/fileSink.cpp b/system/metrics/sinks/file/fileSink.cpp index 5011102b0f3..948f1aab976 100644 --- a/system/metrics/sinks/file/fileSink.cpp +++ b/system/metrics/sinks/file/fileSink.cpp @@ -25,10 +25,12 @@ extern "C" MetricSink* getSinkInstance(const char *name, const IPropertyTree *pS FileMetricSink::FileMetricSink(const char *name, const IPropertyTree *pSettingsTree) : - PeriodicMetricSink(name, "file", pSettingsTree) + PeriodicMetricSink(name, "file", pSettingsTree), + ignoreZeroMetrics(false) { pSettingsTree->getProp("@filename", fileName); clearFileOnStartCollecting = pSettingsTree->getPropBool("@clear", false); + ignoreZeroMetrics = pSettingsTree->getPropBool("@ignoreZeroMetrics", true); } @@ -68,36 +70,47 @@ void FileMetricSink::writeMeasurementToFile(const std::shared_ptr &pMet if (pMetric->queryMetricType() != METRICS_HISTOGRAM) { - if (!isEmptyString(unitsStr)) + __uint64 metricValue = pMetric->queryValue(); + if (!ignoreZeroMetrics || metricValue) { - name.append(".").append(unitsStr); + if (!isEmptyString(unitsStr)) + { + name.append(".").append(unitsStr); + } + fprintf(fhandle, "%s -> %" I64F "d, %s\n", name.c_str(), metricValue, pMetric->queryDescription().c_str()); } - fprintf(fhandle, "%s -> %" I64F "d, %s\n", name.c_str(), pMetric->queryValue(), pMetric->queryDescription().c_str()); } else { std::vector<__uint64> values = pMetric->queryHistogramValues(); std::vector<__uint64> limits = pMetric->queryHistogramBucketLimits(); size_t countBucketValues = values.size(); - __uint64 cumulative = 0; - for (size_t i=0; i < countBucketValues - 1; ++i) + // If not ignoring or measurements exist, output the log entries + __uint64 sum = pMetric->queryValue(); + if (!ignoreZeroMetrics || sum) { - cumulative += values[i]; - fprintf(fhandle, "name=%s, bucket le %" I64F "d=%" I64F "d\n", name.c_str(), limits[i], cumulative); + __uint64 cumulative = 0; + for (size_t i = 0; i < countBucketValues - 1; ++i) + { + cumulative += values[i]; + if (!ignoreZeroMetrics || values[i]) + { + fprintf(fhandle, "name=%s, bucket le %" I64F "d=%" I64F "d\n", name.c_str(), limits[i], cumulative); + } + } + + // The inf bucket count is the last element in the array of values returned. + // Add it to the cumulative count and print the value + cumulative += values[countBucketValues - 1]; + fprintf(fhandle, "name=%s, bucket inf=%" I64F "d\n", name.c_str(), cumulative); + + // sum - total of all observations + fprintf(fhandle, "name=%s, sum=%" I64F "d\n", name.c_str(), sum); + + // count - total of all bucket counts (same as inf) + fprintf(fhandle, "name=%s, count=%" I64F "d\n", name.c_str(), cumulative); } - - // The inf bucket count is the last element in the array of values returned. - // Add it to the cumulative count and print the value - cumulative += values[countBucketValues - 1]; - fprintf(fhandle, "name=%s, bucket inf=%" I64F "d\n", name.c_str(), cumulative); - - // sum - total of all observations - fprintf(fhandle, "name=%s, sum=%" I64F "d\n", name.c_str(), pMetric->queryValue()); - - // count - total of all bucket counts (same as inf) - fprintf(fhandle, "name=%s, count=%" I64F "d\n", name.c_str(), cumulative); - } fflush(fhandle); } diff --git a/system/metrics/sinks/file/fileSink.hpp b/system/metrics/sinks/file/fileSink.hpp index b6a3ac0fe87..2c8b3ee5643 100644 --- a/system/metrics/sinks/file/fileSink.hpp +++ b/system/metrics/sinks/file/fileSink.hpp @@ -44,4 +44,5 @@ class FILESINK_API FileMetricSink : public PeriodicMetricSink StringBuffer fileName; bool clearFileOnStartCollecting = false; FILE *fhandle = nullptr; + bool ignoreZeroMetrics; }; diff --git a/system/metrics/sinks/log/logSink.cpp b/system/metrics/sinks/log/logSink.cpp index cb8eb1091c1..d9ce1b4fc99 100644 --- a/system/metrics/sinks/log/logSink.cpp +++ b/system/metrics/sinks/log/logSink.cpp @@ -28,8 +28,10 @@ extern "C" MetricSink* getSinkInstance(const char *name, const IPropertyTree *pS LogMetricSink::LogMetricSink(const char *name, const IPropertyTree *pSettingsTree) : - PeriodicMetricSink(name, "log", pSettingsTree) + PeriodicMetricSink(name, "log", pSettingsTree), + ignoreZeroMetrics(false) { + ignoreZeroMetrics = pSettingsTree->getPropBool("@ignoreZeroMetrics", true); } @@ -56,34 +58,46 @@ void LogMetricSink::writeLogEntry(const std::shared_ptr &pMetric) if (pMetric->queryMetricType() != METRICS_HISTOGRAM) { - if (!isEmptyString(unitsStr)) + __uint64 metricValue = pMetric->queryValue(); + if (!ignoreZeroMetrics || metricValue) { - name.append(".").append(unitsStr); + if (!isEmptyString(unitsStr)) + { + name.append(".").append(unitsStr); + } + LOG(MCoperatorMetric, "name=%s,value=%" I64F "d", name.c_str(), metricValue); } - LOG(MCoperatorMetric, "name=%s,value=%" I64F "d", name.c_str(), pMetric->queryValue()); } else { std::vector<__uint64> values = pMetric->queryHistogramValues(); std::vector<__uint64> limits = pMetric->queryHistogramBucketLimits(); size_t countBucketValues = values.size(); - __uint64 cumulative = 0; - for (size_t i=0; i < countBucketValues - 1; ++i) + // If not ignoring or measurements exist, output the log entries + __uint64 sum = pMetric->queryValue(); + if (!ignoreZeroMetrics || sum) { - cumulative += values[i]; - LOG(MCoperatorMetric, "name=%s, bucket le %" I64F "d=%" I64F "d", name.c_str(), limits[i], cumulative); + __uint64 cumulative = 0; + for (size_t i=0; i < countBucketValues - 1; ++i) + { + cumulative += values[i]; + if (!ignoreZeroMetrics || values[i]) + { + LOG(MCoperatorMetric, "name=%s, bucket le %" I64F "d=%" I64F "d", name.c_str(), limits[i], cumulative); + } + } + + // The inf bucket count is the last element in the array of values returned. + // Add it to the cumulative count and print the value + cumulative += values[countBucketValues - 1]; + LOG(MCoperatorMetric, "name=%s, bucket inf=%" I64F "d", name.c_str(), cumulative); + + // sum - total of all observations + LOG(MCoperatorMetric, "name=%s, sum=%" I64F "d", name.c_str(), sum); + + // count - total of all bucket counts (same as inf) + LOG(MCoperatorMetric, "name=%s, count=%" I64F "d", name.c_str(), cumulative); } - - // The inf bucket count is the last element in the array of values returned. - // Add it to the cumulative count and print the value - cumulative += values[countBucketValues - 1]; - LOG(MCoperatorMetric, "name=%s, bucket inf=%" I64F "d", name.c_str(), cumulative); - - // sum - total of all observations - LOG(MCoperatorMetric, "name=%s, sum=%" I64F "d", name.c_str(), pMetric->queryValue()); - - // count - total of all bucket counts (same as inf) - LOG(MCoperatorMetric, "name=%s, count=%" I64F "d", name.c_str(), cumulative); } } diff --git a/system/metrics/sinks/log/logSink.hpp b/system/metrics/sinks/log/logSink.hpp index 248a0e51f74..1e19e603512 100644 --- a/system/metrics/sinks/log/logSink.hpp +++ b/system/metrics/sinks/log/logSink.hpp @@ -39,4 +39,7 @@ class LOGSINK_API LogMetricSink : public PeriodicMetricSink virtual void doCollection() override; void writeLogEntry(const std::shared_ptr &pMetric); void writeHistogramLogEntry(const std::shared_ptr &pMetric); + +protected: + bool ignoreZeroMetrics; }; diff --git a/system/security/securesocket/securesocket.cpp b/system/security/securesocket/securesocket.cpp index cf35bd3ef40..0b2452cf564 100644 --- a/system/security/securesocket/securesocket.cpp +++ b/system/security/securesocket/securesocket.cpp @@ -1413,34 +1413,28 @@ class CSecureSocketContext : implements ISecureSocketContext, implements ISecure if(onepeerbuf.length() == 0) break; - char* onepeer = onepeerbuf.detach(); + const char * onepeer = onepeerbuf.str(); if (isdigit(*onepeer)) { - char *dash = strrchr(onepeer, '-'); - if (dash) + const char *dash = strrchr(onepeer, '-'); + const char *dot = strrchr(onepeer, '.'); + //Allow a range in the form a.b.c.d-e + if (dash && dot && dot < dash) { - *dash = 0; - int last = atoi(dash+1); - char *dot = strrchr(onepeer, '.'); - *dot = 0; int first = atoi(dot+1); + int last = atoi(dash+1); for (int i = first; i <= last; i++) { StringBuffer t; - t.append(onepeer).append('.').append(i); + t.append(dot-onepeer, onepeer).append('.').append(i); m_peers->add(t.str()); } } else - { m_peers->add(onepeer); - } } else - { m_peers->add(onepeer); - } - free(onepeer); } } } diff --git a/thorlcr/graph/thgraphmaster.cpp b/thorlcr/graph/thgraphmaster.cpp index 9230dbe112d..8a313fc4090 100644 --- a/thorlcr/graph/thgraphmaster.cpp +++ b/thorlcr/graph/thgraphmaster.cpp @@ -649,9 +649,22 @@ void CMasterActivity::done() void CMasterActivity::updateFileReadCostStats() { + // Updates numDiskReads & readCost in the file attributes and returns the readCost + auto updateReadCosts = [](IDistributedFile *file, CThorStatsCollection &stats) + { + stat_type curDiskReads = stats.getStatisticSum(StNumDiskReads); + IPropertyTree & fileAttr = file->queryAttributes(); + cost_type legacyReadCost = getLegacyReadCost(fileAttr, file); + cost_type curReadCost = money2cost_type(calcFileAccessCost(file, 0, curDiskReads)); + file->addAttrValue(getDFUQResultFieldName(DFUQRFreadCost), legacyReadCost + curReadCost); + file->addAttrValue(getDFUQResultFieldName(DFUQRFnumDiskReads), curDiskReads); + return curReadCost; + }; + if (fileStats.size()>0) { unsigned fileIndex = 0; + diskAccessCost = 0; for (unsigned i=0; iquerySubFile(i, true); - stat_type numDiskReads = fileStats[fileIndex]->getStatisticSum(StNumDiskReads); - StringBuffer clusterName; - subFile.getClusterName(0, clusterName); - diskAccessCost += money2cost_type(calcFileAccessCost(clusterName, 0, numDiskReads)); - subFile.addAttrValue("@numDiskReads", numDiskReads); + diskAccessCost += updateReadCosts(&subFile, *fileStats[fileIndex]); fileIndex++; } } else { - stat_type numDiskReads = fileStats[fileIndex]->getStatisticSum(StNumDiskReads); - StringBuffer clusterName; - file->getClusterName(0, clusterName); - diskAccessCost += money2cost_type(calcFileAccessCost(clusterName, 0, numDiskReads)); - file->addAttrValue("@numDiskReads", numDiskReads); + diskAccessCost += updateReadCosts(file, *fileStats[fileIndex]); fileIndex++; } } @@ -688,13 +693,7 @@ void CMasterActivity::updateFileReadCostStats() { IDistributedFile *file = queryReadFile(0); if (file) - { - stat_type numDiskReads = statsCollection.getStatisticSum(StNumDiskReads); - StringBuffer clusterName; - file->getClusterName(0, clusterName); - diskAccessCost += money2cost_type(calcFileAccessCost(clusterName, 0, numDiskReads)); - file->addAttrValue("@numDiskReads", numDiskReads); - } + diskAccessCost = updateReadCosts(file, statsCollection); } } @@ -702,11 +701,13 @@ void CMasterActivity::updateFileWriteCostStats(IFileDescriptor & fileDesc, IProp { if (numDiskWrites) { - props.setPropInt64("@numDiskWrites", numDiskWrites); + props.setPropInt64(getDFUQResultFieldName(DFUQRFnumDiskWrites), numDiskWrites); assertex(fileDesc.numClusters()>=1); StringBuffer clusterName; fileDesc.getClusterGroupName(0, clusterName);// Note: calculating for 1st cluster. (Future: calc for >1 clusters) - diskAccessCost = money2cost_type(calcFileAccessCost(clusterName, numDiskWrites, 0)); + cost_type writeCost = money2cost_type(calcFileAccessCost(clusterName, numDiskWrites, 0)); + props.setPropInt64(getDFUQResultFieldName(DFUQRFwriteCost), writeCost); + diskAccessCost = writeCost; } }