diff --git a/common/thorhelper/thorsoapcall.cpp b/common/thorhelper/thorsoapcall.cpp index 30111ded600..05adb49cb12 100644 --- a/common/thorhelper/thorsoapcall.cpp +++ b/common/thorhelper/thorsoapcall.cpp @@ -468,7 +468,7 @@ class BlackLister : public CInterface, implements IThreadFactory { if (e->errorCode() == ROXIE_ABORT_EVENT) throw; - // MCK - do we checkTimeLimitExceeded(&remainingMS) and possibly error out if timelimit exceeded ? + // TODO: do we checkTimeLimitExceeded(&remainingMS) and possibly error out if timelimit exceeded ? if (numAttemptsRemaining > 0) { e->Release(); @@ -2457,7 +2457,10 @@ class CWSCAsyncFor : implements IWSCAsyncFor, public CInterface, public CAsyncFo { checkTimeLimitExceeded(&remainingMS); Url &connUrl = master->proxyUrlArray.empty() ? url : master->proxyUrlArray.item(0); - ep.set(connUrl.host.get(), connUrl.port); + + // TODO: for DNS, do we use timeoutMS or remainingMS or remainingMS / maxRetries+1 or ? + ep.set(connUrl.host.get(), connUrl.port, master->timeoutMS); + if (ep.isNull()) throw MakeStringException(-1, "Failed to resolve host '%s'", nullText(connUrl.host.get())); @@ -2477,7 +2480,10 @@ class CWSCAsyncFor : implements IWSCAsyncFor, public CInterface, public CAsyncFo { isReused = false; keepAlive = true; + + // TODO: for each connect attempt, do we use timeoutMS or remainingMS or remainingMS / maxRetries or ? socket.setown(blacklist->connect(ep, master->logctx, (unsigned)master->maxRetries, master->timeoutMS, master->roxieAbortMonitor, master->rowProvider)); + if (proto == PersistentProtocol::ProtoTLS) { #ifdef _USE_OPENSSL @@ -2503,7 +2509,6 @@ class CWSCAsyncFor : implements IWSCAsyncFor, public CInterface, public CAsyncFo err.append(": OpenSSL disabled in build"); throw makeStringException(0, err.str()); #endif - } } break; diff --git a/common/workunit/workunit.cpp b/common/workunit/workunit.cpp index 7fb51f419df..ba694168327 100644 --- a/common/workunit/workunit.cpp +++ b/common/workunit/workunit.cpp @@ -1494,7 +1494,14 @@ class GraphScopeIterator : public CInterfaceOf { if (whichProperties & PTattributes) { - playAttribute(visitor, WaLabel); + Owned nodeAttrs = cur.getAttributes(); + ForEach(*nodeAttrs) + { + const char * name = nodeAttrs->queryName(); + WuAttr attr = queryGraphAttrToWuAttr(name+1); + if (attr != WaNone) + visitor.noteAttribute(attr, nodeAttrs->queryValue()); + } Owned attrs = cur.getElements("att"); ForEach(*attrs) { @@ -1515,7 +1522,6 @@ class GraphScopeIterator : public CInterfaceOf } if (whichProperties & PTstatistics) { - playAttribute(visitor, WaLabel); Owned attrs = cur.getElements("att"); ForEach(*attrs) { diff --git a/common/workunit/wuattr.cpp b/common/workunit/wuattr.cpp index d9419520af2..a174337d2b8 100644 --- a/common/workunit/wuattr.cpp +++ b/common/workunit/wuattr.cpp @@ -151,6 +151,7 @@ const static WuAttrInfo attrInfo[] = { CHILD(RecordFormat, SMeasureText, "recordFormat"), CHILD(ServiceName, SMeasureText, "serviceName"), CHILD(SizeComplexHelper, SMeasureSize, "complexHelperSize"), + CHILD(IsBalanced, SMeasureBool, "balanced"), { WaMax, SMeasureNone, nullptr, nullptr, nullptr, nullptr, nullptr, WaNone, WaNone } }; diff --git a/common/workunit/wuattr.hpp b/common/workunit/wuattr.hpp index 7dc1d098768..6e7639293b6 100644 --- a/common/workunit/wuattr.hpp +++ b/common/workunit/wuattr.hpp @@ -136,6 +136,7 @@ enum WuAttr : unsigned WaRecordFormat, WaServiceName, WaSizeComplexHelper, + WaIsBalanced, WaMax }; inline WuAttr & operator++(WuAttr & x) { assert(x, ds) with PROJECT"); + if (doTrace(traceOptimizations)) + DBGLOG("Folder: Replace JOIN(, ds) with PROJECT"); return ret.getClear(); } break; @@ -4761,7 +4764,8 @@ IHqlExpression * NullFolderMixin::foldNullDataset(IHqlExpression * expr) case 1: if (op == no_cogroup) { - DBGLOG("Folder: Replace %s with group", getOpString(op)); + if (doTrace(traceOptimizations)) + DBGLOG("Folder: Replace %s with group", getOpString(op)); IHqlExpression * grouping = queryAttributeChild(expr, groupAtom, 0); IHqlExpression * mappedGrouping = replaceSelector(grouping, queryActiveTableSelector(), lastInput); OwnedHqlExpr group = createDataset(no_group, LINK(lastInput), mappedGrouping); @@ -4769,11 +4773,13 @@ IHqlExpression * NullFolderMixin::foldNullDataset(IHqlExpression * expr) } else { - DBGLOG("Folder: Replace %s with child", getOpString(op)); + if (doTrace(traceOptimizations)) + DBGLOG("Folder: Replace %s with child", getOpString(op)); return LINK(lastInput); } default: - DBGLOG("Folder: Remove %d inputs from %s", expr->numChildren()-args.ordinality(), getOpString(op)); + if (doTrace(traceOptimizations)) + DBGLOG("Folder: Remove %d inputs from %s", expr->numChildren()-args.ordinality(), getOpString(op)); return expr->clone(args); } } @@ -5632,9 +5638,12 @@ IHqlExpression * CExprFolderTransformer::doFoldTransformed(IHqlExpression * unfo if (expandedFilter->isConstant()) { //Following would be sensible, but can't call transform at this point, so replace arg, and wait for it to re-iterate - IIdAtom * nameF = expr->queryId(); - IIdAtom * nameP = child->queryId(); - DBGLOG("Folder: Combining FILTER %s with %s %s produces constant filter", nameF ? str(nameF) : "", getOpString(child->getOperator()), nameP ? str(nameP) : ""); + if (doTrace(traceOptimizations)) + { + IIdAtom * nameF = expr->queryId(); + IIdAtom * nameP = child->queryId(); + DBGLOG("Folder: Combining FILTER %s with %s %s produces constant filter", nameF ? str(nameF) : "", getOpString(child->getOperator()), nameP ? str(nameP) : ""); + } expandedFilter.setown(transformExpanded(expandedFilter)); IValue * value = expandedFilter->queryValue(); if (value) @@ -5685,8 +5694,11 @@ IHqlExpression * CExprFolderTransformer::doFoldTransformed(IHqlExpression * unfo return replaceWithNull(expr); if (filtered.ordinality() == values->numChildren()) return removeParentNode(expr); - StringBuffer s1, s2; - DBGLOG("Folder: Node %s reduce values in child: %s from %d to %d", queryChildNodeTraceText(s1, expr), queryChildNodeTraceText(s2, child), values->numChildren(), filtered.ordinality()); + if (doTrace(traceOptimizations)) + { + StringBuffer s1, s2; + DBGLOG("Folder: Node %s reduce values in child: %s from %d to %d", queryChildNodeTraceText(s1, expr), queryChildNodeTraceText(s2, child), values->numChildren(), filtered.ordinality()); + } HqlExprArray args; args.append(*values->clone(filtered)); unwindChildren(args, child, 1); @@ -6587,7 +6599,10 @@ IHqlExpression * CExprFolderTransformer::createTransformed(IHqlExpression * expr #ifdef LOG_ALL_FOLDING if ((op != transformed->getOperator()) || (expr->numChildren() != transformed->numChildren())) - DBGLOG("Folding %s to %s", getOpString(updated->getOperator()), getOpString(transformed->getOperator())); + { + if (doTrace(traceOptimizations)) + DBGLOG("Folding %s to %s", getOpString(updated->getOperator()), getOpString(transformed->getOperator())); + } #endif #ifdef _DEBUG @@ -7183,21 +7198,24 @@ IHqlExpression * CExprFolderTransformer::percolateConstants(IHqlExpression * exp IHqlExpression * CExprFolderTransformer::removeParentNode(IHqlExpression * expr) { IHqlExpression * child = expr->queryChild(0); - DBGLOG("Folder: Node %s remove self (now %s)", queryNode0Text(expr), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Folder: Node %s remove self (now %s)", queryNode0Text(expr), queryNode1Text(child)); return LINK(child); } IHqlExpression * CExprFolderTransformer::replaceWithNull(IHqlExpression * expr) { IHqlExpression * ret = createNullExpr(expr); - DBGLOG("Folder: Replace %s with %s", queryNode0Text(expr), queryNode1Text(ret)); + if (doTrace(traceOptimizations)) + DBGLOG("Folder: Replace %s with %s", queryNode0Text(expr), queryNode1Text(ret)); return ret; } IHqlExpression * CExprFolderTransformer::replaceWithNullRow(IHqlExpression * expr) { IHqlExpression * ret = createRow(no_null, LINK(expr->queryRecord())); - DBGLOG("Folder: Replace %s with %s", queryNode0Text(expr), queryNode1Text(ret)); + if (doTrace(traceOptimizations)) + DBGLOG("Folder: Replace %s with %s", queryNode0Text(expr), queryNode1Text(ret)); return ret; } diff --git a/ecl/hql/hqlopt.cpp b/ecl/hql/hqlopt.cpp index 53786c35d1e..e0bfbd2bfe6 100644 --- a/ecl/hql/hqlopt.cpp +++ b/ecl/hql/hqlopt.cpp @@ -269,7 +269,8 @@ inline IHqlExpression * makeChildList(IHqlExpression * expr) IHqlExpression * CTreeOptimizer::removeChildNode(IHqlExpression * expr) { IHqlExpression * child = expr->queryChild(0); - DBGLOG("Optimizer: Node %s remove child: %s", queryNode0Text(expr), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Node %s remove child: %s", queryNode0Text(expr), queryNode1Text(child)); noteUnused(child); //If removing an operator that also has the side-effect of removing grouping (e.g. distribute), make sure the dataset is still ungrouped @@ -285,7 +286,8 @@ IHqlExpression * CTreeOptimizer::removeChildNode(IHqlExpression * expr) IHqlExpression * CTreeOptimizer::removeParentNode(IHqlExpression * expr) { IHqlExpression * child = expr->queryChild(0); - DBGLOG("Optimizer: Node %s remove self (now %s)", queryNode0Text(expr), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Node %s remove self (now %s)", queryNode0Text(expr), queryNode1Text(child)); // Need to dec link count of child because it is just about to inherited the link count from the parent decUsage(child); @@ -295,7 +297,8 @@ IHqlExpression * CTreeOptimizer::removeParentNode(IHqlExpression * expr) IHqlExpression * CTreeOptimizer::swapNodeWithChild(IHqlExpression * parent) { IHqlExpression * child = parent->queryChild(0); - DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(parent), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(parent), queryNode1Text(child)); OwnedHqlExpr newParent = swapDatasets(parent); //if this is the only reference to the child (almost certainly true) then no longer refd, so don't inc usage for child. noteUnused(child); @@ -314,7 +317,8 @@ IHqlExpression * CTreeOptimizer::forceSwapNodeWithChild(IHqlExpression * parent) IHqlExpression * CTreeOptimizer::swapNodeWithChild(IHqlExpression * parent, unsigned childIndex) { IHqlExpression * child = parent->queryChild(0); - DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(parent), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(parent), queryNode1Text(child)); OwnedHqlExpr newChild = replaceChildDataset(parent, child->queryChild(childIndex), 0); OwnedHqlExpr swapped = insertChildDataset(child, newChild, childIndex); if (!alreadyHasUsage(swapped)) @@ -364,7 +368,8 @@ IHqlExpression * CTreeOptimizer::swapIntoIf(IHqlExpression * expr, bool force) decUsage(newRight); } noteUnused(child); - DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(expr), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(expr), queryNode1Text(child)); return transformedIf.getClear(); } @@ -420,7 +425,8 @@ IHqlExpression * CTreeOptimizer::swapIntoAddFiles(IHqlExpression * expr, bool fo noteUnused(child); //And create the new funnel - DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(expr), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(expr), queryNode1Text(child)); return child->clone(transformedArgs); } @@ -463,7 +469,8 @@ IHqlExpression * CTreeOptimizer::moveFilterOverSelect(IHqlExpression * expr) if (hoisted.ordinality() == 0) return NULL; - DBGLOG("Optimizer: Move filter over select (%d/%d)", hoisted.ordinality(), args.ordinality()); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Move filter over select (%d/%d)", hoisted.ordinality(), args.ordinality()); //Create a filtered dataset IHqlExpression * inDs = LINK(ds); @@ -742,7 +749,8 @@ IHqlExpression * CTreeOptimizer::optimizeAggregateDataset(IHqlExpression * trans incUsage(ds); } - DBGLOG("Optimizer: Aggregate replace %s with %s", queryNode0Text(root), queryNode1Text(ds)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Aggregate replace %s with %s", queryNode0Text(root), queryNode1Text(ds)); children.replace(*ds.getClear(), 0); return transformed->clone(children); } @@ -794,7 +802,8 @@ IHqlExpression * CTreeOptimizer::optimizeDatasetIf(IHqlExpression * transformed) OwnedHqlExpr ret = createDataset(no_filter, args); - DBGLOG("Optimizer: Convert %s to a filter", queryNode0Text(transformed)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Convert %s to a filter", queryNode0Text(transformed)); //NOTE: left and right never walk over any shared nodes, so don't need to decrement usage for //child(1), child(2) or intermediate nodes to left/right, since not referenced any more. @@ -869,7 +878,8 @@ IHqlExpression * CTreeOptimizer::optimizeIfAppend(IHqlExpression * expr, node_op args.append(*newIf.getClear()); unwindChildren(args, appendExpr, 2); OwnedHqlExpr ret = appendExpr->clone(args); - DBGLOG("Optimizer: Extract common branch - replace %s with %s", queryNode0Text(expr), queryNode1Text(ret)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Extract common branch - replace %s with %s", queryNode0Text(expr), queryNode1Text(ret)); return ret.getClear(); } @@ -1045,7 +1055,8 @@ IHqlExpression * CTreeOptimizer::optimizeIf(IHqlExpression * expr) if (args.ordinality()) { - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(expr), queryNode1Text(trueExpr)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(expr), queryNode1Text(trueExpr)); noteUnused(falseExpr); } } @@ -1072,7 +1083,8 @@ IHqlExpression * CTreeOptimizer::optimizeIf(IHqlExpression * expr) if (args.ordinality()) { - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(expr), queryNode1Text(falseExpr)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(expr), queryNode1Text(falseExpr)); noteUnused(trueExpr); } } @@ -1122,7 +1134,7 @@ bool CTreeOptimizer::expandFilterCondition(HqlExprArray & expanded, HqlExprArray IValue * value = expandedFilter->queryValue(); if (value && !value->getBoolValue()) { - if (onlyKeyed) + if (onlyKeyed && doTrace(traceOptimizations)) DBGLOG("Optimizer: Merging filter over shared project always false"); expanded.kill(); expanded.append(*LINK(expandedFilter)); @@ -1197,9 +1209,15 @@ IHqlExpression * CTreeOptimizer::hoistFilterOverProject(IHqlExpression * transfo OwnedHqlExpr filterExpr = createFilterCondition(expanded); if (unexpanded.ordinality()) - DBGLOG("Optimizer: Move %d/%d filters over %s", expanded.ordinality(), expanded.ordinality()+unexpanded.ordinality(), queryNode1Text(child)); + { + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Move %d/%d filters over %s", expanded.ordinality(), expanded.ordinality()+unexpanded.ordinality(), queryNode1Text(child)); + } else - DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + { + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + } IHqlExpression * newGrandchild = child->queryChild(0); OwnedHqlExpr newFilter = createDataset(no_filter, LINK(newGrandchild), LINK(filterExpr)); @@ -1331,7 +1349,8 @@ IHqlExpression * CTreeOptimizer::getHoistedFilter(IHqlExpression * transformed, //extend the join condition where appropriate if (expanded.ordinality()) { - DBGLOG("Optimizer: Merge filters(%d/%d) into %s condition", expanded.ordinality(), conds.ordinality(), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge filters(%d/%d) into %s condition", expanded.ordinality(), conds.ordinality(), queryNode1Text(child)); OwnedITypeInfo boolType = makeBoolType(); HqlExprArray args; unwindChildren(args, ret); @@ -1366,7 +1385,8 @@ IHqlExpression * CTreeOptimizer::getHoistedFilter(IHqlExpression * transformed, IHqlExpression * CTreeOptimizer::createHoistedFilter(IHqlExpression * expr, HqlExprArray & conditions, unsigned childIndex, unsigned maxConditions) { IHqlExpression * grand = expr->queryChild(childIndex); - DBGLOG("Optimizer: Hoisting filter(%d/%d) over %s.%d", conditions.ordinality(), maxConditions, queryNode0Text(expr), childIndex); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Hoisting filter(%d/%d) over %s.%d", conditions.ordinality(), maxConditions, queryNode0Text(expr), childIndex); conditions.add(*LINK(grand), 0); OwnedHqlExpr hoistedFilter = createDataset(no_filter, conditions); OwnedHqlExpr ret = insertChildDataset(expr, hoistedFilter, childIndex); @@ -1401,7 +1421,8 @@ IHqlExpression * CTreeOptimizer::queryPromotedFilter(IHqlExpression * expr, node if (hoisted.ordinality() == 0) return NULL; - DBGLOG("Optimizer: Hoisting filter(%d/%d) over %s", hoisted.ordinality(), hoisted.ordinality()+unhoisted.ordinality(), queryNode0Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Hoisting filter(%d/%d) over %s", hoisted.ordinality(), hoisted.ordinality()+unhoisted.ordinality(), queryNode0Text(child)); OwnedHqlExpr newChild = createHoistedFilter(child, hoisted, childIndex, conds.ordinality()); noteUnused(child); @@ -1569,7 +1590,8 @@ IHqlExpression * CTreeOptimizer::optimizeJoinCondition(IHqlExpression * expr) if (leftOnly.ordinality()) { - DBGLOG("Optimizer: Hoist %d LEFT conditions out of %s", leftOnly.ordinality(), queryNode0Text(expr)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Hoist %d LEFT conditions out of %s", leftOnly.ordinality(), queryNode0Text(expr)); IHqlExpression * lhs = expr->queryChild(0); OwnedHqlExpr left = createSelector(no_left, lhs, seq); OwnedHqlExpr leftFilter = createFilterCondition(leftOnly); @@ -1580,7 +1602,8 @@ IHqlExpression * CTreeOptimizer::optimizeJoinCondition(IHqlExpression * expr) if (rightOnly.ordinality()) { - DBGLOG("Optimizer: Hoist %d RIGHT conditions out of %s", rightOnly.ordinality(), queryNode0Text(expr)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Hoist %d RIGHT conditions out of %s", rightOnly.ordinality(), queryNode0Text(expr)); IHqlExpression * rhs = expr->queryChild(1); OwnedHqlExpr right = createSelector(no_right, rhs, seq); OwnedHqlExpr rightFilter = createFilterCondition(rightOnly); @@ -1617,7 +1640,8 @@ IHqlExpression * CTreeOptimizer::optimizeDistributeDedup(IHqlExpression * expr) if (!matchDedupDistribution(dist, info.equalities)) return NULL; - DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(expr), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(expr), queryNode1Text(child)); OwnedHqlExpr distn; @@ -1717,7 +1741,8 @@ IHqlExpression * CTreeOptimizer::optimizeProjectInlineTable(IHqlExpression * tra newValues.append(*ensureTransformType(next, no_transform)); } - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); HqlExprArray args; args.append(*createValue(no_transformlist, makeNullType(), newValues)); if (projectOp == no_newusertable) @@ -1848,7 +1873,8 @@ IHqlExpression * CTreeOptimizer::expandProjectedDataset(IHqlExpression * child, IHqlExpression * oldTransform = child->queryChild(transformIndex); expandedTransform.setown(ensureTransformType(expandedTransform, oldTransform->getOperator())); - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(expr), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(expr), queryNode1Text(child)); HqlExprArray args; unwindChildren(args, child); args.replace(*expandedTransform.getClear(), transformIndex); @@ -2093,7 +2119,8 @@ IHqlExpression * CTreeOptimizer::moveProjectionOverSimple(IHqlExpression * trans } } - DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(transformed), queryNode1Text(child)); OwnedHqlExpr swapped = child->clone(args); if (!alreadyHasUsage(swapped)) incUsage(newProject); @@ -2135,7 +2162,8 @@ IHqlExpression * CTreeOptimizer::moveProjectionOverLimit(IHqlExpression * transf if (monitor.isComplex()) return LINK(transformed); - DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Swap %s and %s", queryNode0Text(transformed), queryNode1Text(child)); OwnedHqlExpr swapped = child->clone(args); if (!alreadyHasUsage(swapped)) incUsage(newProject); @@ -2249,7 +2277,8 @@ IHqlExpression * CTreeOptimizer::getOptimizedFilter(IHqlExpression * transformed noteUnused(transformed->queryChild(0)); //MORE: Really wants to walk down the entire chain until we hit something that is shared. IHqlExpression * ret = createNullDataset(transformed); - DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(transformed), queryNode1Text(ret)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(transformed), queryNode1Text(ret)); return ret; } } @@ -2310,7 +2339,8 @@ void CTreeOptimizer::recursiveDecChildUsage(IHqlExpression * expr) IHqlExpression * CTreeOptimizer::replaceWithNull(IHqlExpression * transformed) { IHqlExpression * ret = createNullExpr(transformed); - DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(transformed), queryNode1Text(ret)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(transformed), queryNode1Text(ret)); recursiveDecChildUsage(transformed); return ret; @@ -2320,7 +2350,8 @@ IHqlExpression * CTreeOptimizer::replaceWithNull(IHqlExpression * transformed) IHqlExpression * CTreeOptimizer::replaceWithNullRow(IHqlExpression * expr) { IHqlExpression * ret = createRow(no_null, LINK(expr->queryRecord())); - DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(expr), queryNode1Text(ret)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(expr), queryNode1Text(ret)); recursiveDecChildUsage(expr); return ret; @@ -2329,7 +2360,8 @@ IHqlExpression * CTreeOptimizer::replaceWithNullRowDs(IHqlExpression * expr) { assertex(!isGrouped(expr)); IHqlExpression * ret = createDatasetFromRow(createRow(no_null, LINK(expr->queryRecord()))); - DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(expr), queryNode1Text(ret)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(expr), queryNode1Text(ret)); recursiveDecChildUsage(expr); return ret; @@ -2452,7 +2484,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme IHqlExpression * ret = optimizeCreateRow(transformed); if (ret) { - DBGLOG("Optimizer: Remove Redundant %s", queryNode0Text(transformed)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Remove Redundant %s", queryNode0Text(transformed)); if (ret->isDataset()) return ensureActiveRow(ret); return LINK(ret); @@ -2529,7 +2562,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme IHqlExpression * rhs = transformed->queryChild(1); if (rhs->getOperator() == no_distribute) { - DBGLOG("Optimizer: Remove %s from RHS of global LOOKUP JOIN", queryNode0Text(rhs)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Remove %s from RHS of global LOOKUP JOIN", queryNode0Text(rhs)); return ::replaceChild(transformed, 1, rhs->queryChild(0)); } } @@ -2638,7 +2672,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme //MORE If trivial projection then might be worth merging with multiple items, but unlikely to occur in practice OwnedHqlExpr ret = createRow(no_createrow, LINK(values->queryChild((unsigned)index-1))); noteUnused(child); - DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(transformed), queryNode1Text(ret)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(transformed), queryNode1Text(ret)); return ret.getClear(); } case no_datasetfromrow: @@ -2653,7 +2688,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme IHqlExpression * ret = child->queryChild(0); noteUnused(child); decUsage(ret); // will inherit later - DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(transformed), queryNode1Text(ret)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(transformed), queryNode1Text(ret)); return LINK(ret); } #if 0 @@ -2693,7 +2729,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme //being used conditionally within transforms. See HPCC-11018 for details. if ((options & HOOexpandselectcreaterow) || isIndependentOfScope(match)) { - DBGLOG("Optimizer: Extract value %s from %s", queryNode0Text(cur), queryNode1Text(transformed)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Extract value %s from %s", queryNode0Text(cur), queryNode1Text(transformed)); noteUnused(child); return match.getClear(); } @@ -2705,7 +2742,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme case no_null: case no_getresult: case no_getgraphresult: - DBGLOG("Optimizer: Extract value %s from %s", queryNode0Text(match), queryNode1Text(transformed)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Extract value %s from %s", queryNode0Text(match), queryNode1Text(transformed)); noteUnused(child); return match.getClear(); } @@ -2745,7 +2783,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme case no_left: case no_right: { - DBGLOG("Optimizer: Extract value %s from %s", queryNode0Text(match), queryNode1Text(transformed)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Extract value %s from %s", queryNode0Text(match), queryNode1Text(transformed)); noteUnused(child); return match.getClear(); } @@ -2788,7 +2827,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme case no_getresult: case no_getgraphresult: { - DBGLOG("Optimizer: Extract value %s from %s", queryNode0Text(match), queryNode1Text(transformed)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Extract value %s from %s", queryNode0Text(match), queryNode1Text(transformed)); noteUnused(child); HqlExprArray args; @@ -2816,7 +2856,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme { assertex(isGrouped(child)); // not grouped handled already. OwnedHqlExpr ret = createDataset(no_group, LINK(child)); - DBGLOG("Optimizer: replace %s with %s", queryNode0Text(transformed), queryNode1Text(ret)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: replace %s with %s", queryNode0Text(transformed), queryNode1Text(ret)); return transformed->cloneAllAnnotations(ret); } break; @@ -2890,7 +2931,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme else args.append(*LINK(transform)); - DBGLOG("Optimizer: Convert %s(,1) into PROJECT", queryNode0Text(transformed)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Convert %s(,1) into PROJECT", queryNode0Text(transformed)); unwindChildren(args, transformed, 3); //This is not a count project.. so remove the attribute. removeAttribute(args, _countProject_Atom); @@ -3020,7 +3062,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme else newLimit = const2; - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); return createDataset(no_choosen, LINK(child->queryChild(0)), LINK(newLimit)); //don't bother to transform } @@ -3188,7 +3231,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme { case no_filter: { - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); HqlExprArray args; unwindChildren(args, child); unwindChildren(args, transformed, 1); @@ -3395,7 +3439,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme if (filtered.ordinality() == values->numChildren()) return removeParentNode(transformed); - DBGLOG("Optimizer: Node %s reduce values in child: %s from %d to %d", queryNode0Text(transformed), queryNode1Text(child), values->numChildren(), filtered.ordinality()); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Node %s reduce values in child: %s from %d to %d", queryNode0Text(transformed), queryNode1Text(child), values->numChildren(), filtered.ordinality()); HqlExprArray args; args.append(*values->clone(filtered)); unwindChildren(args, child, 1); @@ -3493,7 +3538,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme if (expandedTransform && !monitor.isComplex()) { expandedTransform.setown(inheritSkips(expandedTransform, child->queryChild(1), mapper->queryTransformSelector(), newLeft)); - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); //NB: Merging a project with a count project can actually remove the count project.. IHqlExpression * countProjectAttr = transformedCountProject; if (childCountProject && transformContainsCounter(expandedTransform, childCountProject->queryChild(0))) @@ -3632,7 +3678,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme OwnedHqlExpr expandedTransform = expandFields(mapper, transform, oldLeft, NULL, &monitor); if (expandedTransform && !monitor.isComplex()) { - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); HqlExprArray args; unwindChildren(args, child); args.replace(*expandedTransform.getClear(), queryTransformIndex(child)); @@ -3748,7 +3795,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme if (!monitor.isComplex()) { - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); removeAttribute(args, _internal_Atom); noteUnused(child); return exprToClone->clone(args); @@ -3933,7 +3981,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme break; OwnedHqlExpr newOrder = replaceSelector(sortOrder, queryActiveTableSelector(), child->queryNormalizedSelector()); decUsage(child); - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); return ::replaceChild(child, 1, newOrder); } @@ -4088,7 +4137,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme IHqlExpression * expanded = expandFields(mapper, transformed->queryChild(3), oldLeft, newLeft); if (expanded) { - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); HqlExprArray args; args.append(*LINK(child->queryChild(0))); args.append(*LINK(transformed->queryChild(1))); @@ -4122,7 +4172,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme } if (!ok) break; - DBGLOG("Optimizer: Merge inline tables for %s", queryNode0Text(transformed)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge inline tables for %s", queryNode0Text(transformed)); HqlExprArray args; args.append(*createValue(no_transformlist, makeNullType(), allTransforms)); args.append(*LINK(child->queryRecord())); @@ -4146,7 +4197,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme OwnedHqlExpr ret = transformTrivialSelectProject(transformed); if (ret) { - DBGLOG("Optimizer: Select %s from %s optimized", ret->queryChild(1)->queryName()->str(), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Select %s from %s optimized", ret->queryChild(1)->queryName()->str(), queryNode1Text(child)); noteUnused(child); return ret.getClear(); } @@ -4161,7 +4213,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme { case no_createrow: { - DBGLOG("Optimizer: Merge %s and %s to Inline table", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s to Inline table", queryNode0Text(transformed), queryNode1Text(child)); HqlExprArray args; args.append(*createValue(no_transformlist, makeNullType(), LINK(child->queryChild(0)))); args.append(*LINK(child->queryRecord())); @@ -4219,7 +4272,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme //If expanding the project removed all references to left (very silly join....) make it an all join if (transformed->hasAttribute(lookupAtom) && !exprReferencesDataset(&args.item(2), newLeft)) args.append(*createAttribute(allAtom)); - DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Merge %s and %s", queryNode0Text(transformed), queryNode1Text(child)); noteUnused(child); OwnedHqlExpr merged = transformed->clone(args); @@ -4255,7 +4309,8 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme topnArgs.add(*LINK(index), 2); OwnedHqlExpr topn = createDataset(no_topn, topnArgs); incUsage(topn); - DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(child), queryNode1Text(topn)); + if (doTrace(traceOptimizations)) + DBGLOG("Optimizer: Replace %s with %s", queryNode0Text(child), queryNode1Text(topn)); HqlExprArray selectnArgs; selectnArgs.append(*child->cloneAllAnnotations(topn)); unwindChildren(selectnArgs, transformed, 1); diff --git a/ecl/hqlcpp/hqlcpp.cpp b/ecl/hqlcpp/hqlcpp.cpp index fde385d0a18..5009be858f4 100644 --- a/ecl/hqlcpp/hqlcpp.cpp +++ b/ecl/hqlcpp/hqlcpp.cpp @@ -1946,6 +1946,8 @@ void HqlCppTranslator::cacheOptions() } } + updateTraceFlags(loadTraceFlags(wu(), eclccTraceOptions, queryTraceFlags())); + //Configure the divide by zero action options.divideByZeroAction = DBZzero; const char * dbz = wu()->getDebugValue("divideByZero",val).str(); diff --git a/ecl/hqlcpp/hqlhtcpp.cpp b/ecl/hqlcpp/hqlhtcpp.cpp index ea303805449..b31e9667a7e 100644 --- a/ecl/hqlcpp/hqlhtcpp.cpp +++ b/ecl/hqlcpp/hqlhtcpp.cpp @@ -8740,6 +8740,8 @@ ABoundActivity * HqlCppTranslator::doBuildActivitySplit(BuildCtx & ctx, IHqlExpr instance->addConstructorParameter(numWays); instance->addConstructorParameter(queryBoolExpr(balanced)); } + if (balanced) + instance->addAttributeBool(WaIsBalanced, true); buildInstanceSuffix(instance); buildConnectInputOutput(ctx, instance, boundDataset, 0, 0); diff --git a/ecl/hqlcpp/hqliproj.cpp b/ecl/hqlcpp/hqliproj.cpp index 22c8e6b8561..77b26c9a8bd 100644 --- a/ecl/hqlcpp/hqliproj.cpp +++ b/ecl/hqlcpp/hqliproj.cpp @@ -2729,7 +2729,8 @@ void ImplicitProjectTransformer::logChange(const char * message, IHqlExpression const char * const format = "ImplicitProject: %s %s now %s"; - DBGLOG(format, message, name.str(), fieldText.str()); + if (doTrace(traceOptimizations)) + DBGLOG(format, message, name.str(), fieldText.str()); if (options.notifyOptimizedProjects) { if (options.notifyOptimizedProjects >= 2 || exprName) @@ -3101,10 +3102,13 @@ void ImplicitProjectTransformer::finalizeFields(IHqlExpression * expr) extra->fieldsToBlank.optimizeFieldsToBlank(extra->outputFields, queryNewColumnProvider(expr)); if (!extra->fieldsToBlank.isEmpty()) { - const char * opString = getOpString(expr->getOperator()); - StringBuffer fieldText; - extra->fieldsToBlank.getText(fieldText); - DBGLOG("ImplicitProject: Fields %s for %s not required by outputs - so blank in transform", fieldText.str(), opString); + if (doTrace(traceOptimizations)) + { + const char * opString = getOpString(expr->getOperator()); + StringBuffer fieldText; + extra->fieldsToBlank.getText(fieldText); + DBGLOG("ImplicitProject: Fields %s for %s not required by outputs - so blank in transform", fieldText.str(), opString); + } } extra->finalizeOutputRecord(false); break; diff --git a/ecl/hqlcpp/hqlttcpp.cpp b/ecl/hqlcpp/hqlttcpp.cpp index 49d13191769..87db9e249cc 100644 --- a/ecl/hqlcpp/hqlttcpp.cpp +++ b/ecl/hqlcpp/hqlttcpp.cpp @@ -6493,7 +6493,9 @@ IHqlExpression * WorkflowTransformer::extractCommonWorkflow(IHqlExpression * exp if (expr->queryName()) s.append("[").append(expr->queryName()).append("] "); s.append(" to common up code between workflow items"); - DBGLOG("%s", s.str()); + if (doTrace(traceOptimizations)) + DBGLOG("%s", s.str()); + translator.addWorkunitException(SeverityInformation, HQLWRN_TryAddingIndependent, s.str(), location); if (!translator.queryOptions().performWorkflowCse) return LINK(transformed); @@ -6503,11 +6505,12 @@ IHqlExpression * WorkflowTransformer::extractCommonWorkflow(IHqlExpression * exp // e.g., ensure it really is worth commoning up, the expressions aren't to be evaluated on different clusters etc. etc. unsigned wfid = ++wfidCount; - s.appendf("AutoWorkflow: Spotted %s ", getOpString(expr->getOperator())); + s.clear().appendf("AutoWorkflow: Spotted %s ", getOpString(expr->getOperator())); if (expr->queryId()) s.append("[").append(expr->queryId()->queryStr()).append("] "); s.append(" to common up between workflow items [").append(wfid).append("]"); - DBGLOG("%s", s.str()); + if (doTrace(traceOptimizations)) + DBGLOG("%s", s.str()); translator.addWorkunitException(SeverityInformation, 0, s.str(), location); GlobalAttributeInfo info("jobtemp::wfa", "wfa", transformed); @@ -8832,12 +8835,15 @@ IHqlExpression * AutoScopeMigrateTransformer::createTransformed(IHqlExpression * AutoScopeMigrateInfo * extra = queryBodyExtra(expr); if (extra->doAutoHoist(transformed, translator.queryOptions().minimizeWorkunitTemporaries)) { - StringBuffer s; - s.appendf("AutoGlobal: Spotted %s ", getOpString(expr->getOperator())); - if (expr->queryName()) - s.append("[").append(expr->queryName()).append("] "); - s.append("as an item to hoist"); - DBGLOG("%s", s.str()); + if (doTrace(traceOptimizations)) + { + StringBuffer s; + s.appendf("AutoGlobal: Spotted %s ", getOpString(expr->getOperator())); + if (expr->queryName()) + s.append("[").append(expr->queryName()).append("] "); + s.append("as an item to hoist"); + DBGLOG("%s", s.str()); + } if (extra->globalInsideChild) { StringBuffer nameText; @@ -9394,7 +9400,8 @@ IHqlExpression * KeyedProjectTransformer::createTransformed(IHqlExpression * exp expandedTransform.setown(mapper.expandFields(transformed->queryChild(3), oldRight, newRight)); if (translatedFilter && (expandedTransform || op == no_keyeddistribute)) { - DBGLOG("KeyedProjectTransformer: Merge KEYED PROJECT into JOIN"); + if (doTrace(traceOptimizations)) + DBGLOG("KeyedProjectTransformer: Merge KEYED PROJECT into JOIN"); HqlExprArray args; args.append(*LINK(transformed->queryChild(0))); args.append(*LINK(rhs->queryChild(0))); diff --git a/ecl/regress/regress.sh b/ecl/regress/regress.sh index 8a6ab7a45c5..95b7b9f525c 100755 --- a/ecl/regress/regress.sh +++ b/ecl/regress/regress.sh @@ -122,7 +122,7 @@ fi if [[ $eclcc != '' ]]; then ## Set flags default_flags="-P$target_dir -legacy -platform=thorlcr -fforceGenerate -fregressionTest -b -S -shared -meta+" - flags="$default_flags $include_dir -fshowMetaInGraph -fspanMultipleCpp- $userflags" + flags="$default_flags $include_dir -fshowMetaInGraph -fspanMultipleCpp- -ftraceOptimizations $userflags" ## Prepare target directory if [[ $query == '' ]]; then diff --git a/esp/src/package-lock.json b/esp/src/package-lock.json index 42a17c1b2cc..bb858aa4279 100644 --- a/esp/src/package-lock.json +++ b/esp/src/package-lock.json @@ -9,16 +9,16 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@fluentui/react": "8.117.0", - "@fluentui/react-components": "9.47.2", - "@fluentui/react-experiments": "8.14.137", - "@fluentui/react-hooks": "8.7.0", - "@fluentui/react-icons-mdl2": "1.3.59", - "@fluentui/react-migration-v8-v9": "9.6.3", + "@fluentui/react": "8.119.3", + "@fluentui/react-components": "9.54.6", + "@fluentui/react-experiments": "8.14.160", + "@fluentui/react-hooks": "8.8.10", + "@fluentui/react-icons-mdl2": "1.3.72", + "@fluentui/react-migration-v8-v9": "9.6.22", "@hpcc-js/chart": "2.83.4", "@hpcc-js/codemirror": "2.62.1", "@hpcc-js/common": "2.71.18", - "@hpcc-js/comms": "2.93.0", + "@hpcc-js/comms": "2.94.0", "@hpcc-js/dataflow": "8.1.7", "@hpcc-js/eclwatch": "2.74.8", "@hpcc-js/graph": "2.85.16", @@ -138,9 +138,10 @@ } }, "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", @@ -209,11 +210,12 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", - "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.5.tgz", + "integrity": "sha512-8GrTWmoFhm5BsMZOTHeGD2/0FLKLQQHvO/ZmQga4tKempYRLz8aqJGqXVuQgisnMObq2YZ2SgkwctN1LOOxcqA==", + "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.1" + "@floating-ui/utils": "^0.2.5" } }, "node_modules/@floating-ui/devtools": { @@ -225,75 +227,83 @@ } }, "node_modules/@floating-ui/dom": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", - "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.8.tgz", + "integrity": "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q==", + "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.0.0", - "@floating-ui/utils": "^0.2.0" + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.5" } }, "node_modules/@floating-ui/utils": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", - "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.5.tgz", + "integrity": "sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ==", + "license": "MIT" }, "node_modules/@fluentui/date-time-utilities": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-8.6.0.tgz", - "integrity": "sha512-fpdR2pesIewgfgErX0eS+YBPengNH4Qf21Q6bNFTfQsBYXaJZMUqD4V/57JRfIFz4fYXZ6lWKFTTQe50wXKlWA==", + "version": "8.6.9", + "resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-8.6.9.tgz", + "integrity": "sha512-dgOlVm4nXBWDLqijmvn4iAtyv1hVpQZjN6p0So74BW+7ASUTkQGe3lf8PHV/OjBiXfZa4qwONvmTQBGCheNU0w==", + "license": "MIT", "dependencies": { - "@fluentui/set-version": "^8.2.14", + "@fluentui/set-version": "^8.2.23", "tslib": "^2.1.0" } }, "node_modules/@fluentui/dom-utilities": { - "version": "2.2.14", - "resolved": "https://registry.npmjs.org/@fluentui/dom-utilities/-/dom-utilities-2.2.14.tgz", - "integrity": "sha512-+4DVm5sNfJh+l8fM+7ylpOkGNZkNr4X1z1uKQPzRJ1PRhlnvc6vLpWNNicGwpjTbgufSrVtGKXwP5sf++r81lg==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@fluentui/dom-utilities/-/dom-utilities-2.3.7.tgz", + "integrity": "sha512-AaTR9BhJEF0i042NS1Ju8l95f24p2tBMq6jVVbUEDtYnKaxWnpv8R9eYjOwy8SDniQc1ino+BkolIgCVXXvDmw==", + "license": "MIT", "dependencies": { - "@fluentui/set-version": "^8.2.14", + "@fluentui/set-version": "^8.2.23", "tslib": "^2.1.0" } }, "node_modules/@fluentui/example-data": { - "version": "8.4.15", - "resolved": "https://registry.npmjs.org/@fluentui/example-data/-/example-data-8.4.15.tgz", - "integrity": "sha512-NasmufMLRzJm8ACxunAuTKrgyv0aFhBu/hT1XTXZSVKrgyU+hPUTUF4v8r1L1ekUtrV185y6iZTA00eY2MqboA==", + "version": "8.4.24", + "resolved": "https://registry.npmjs.org/@fluentui/example-data/-/example-data-8.4.24.tgz", + "integrity": "sha512-eoEC6a8yzUdbaLflPiL8LDPLHo/U32EACHncUaEzoHrI/FilzlsztIQ9qY7AB5k8MIhbfEBm3QkQnn6/iVyt3w==", + "license": "MIT", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@fluentui/fluent2-theme": { - "version": "8.107.68", - "resolved": "https://registry.npmjs.org/@fluentui/fluent2-theme/-/fluent2-theme-8.107.68.tgz", - "integrity": "sha512-AwE1vDOm3IzVvG0pnL2DyOS1mLLGzktOlZIC2Q5BoNkYDbn91eFDN6jE11PuARvCPSRjEqumjkQU0egvF48Dsw==", + "version": "8.107.91", + "resolved": "https://registry.npmjs.org/@fluentui/fluent2-theme/-/fluent2-theme-8.107.91.tgz", + "integrity": "sha512-La9on84Q+A9kTH/qLgyCnwjMAC/iZo/rbkO77R5uhAaZRs6jtuusDf+JhbWI0hHBUHDdFKg8k403scDcnbg8Jg==", + "license": "MIT", "dependencies": { - "@fluentui/react": "^8.117.0", - "@fluentui/set-version": "^8.2.14", + "@fluentui/react": "^8.119.3", + "@fluentui/set-version": "^8.2.23", "tslib": "^2.1.0" } }, "node_modules/@fluentui/font-icons-mdl2": { - "version": "8.5.34", - "resolved": "https://registry.npmjs.org/@fluentui/font-icons-mdl2/-/font-icons-mdl2-8.5.34.tgz", - "integrity": "sha512-FRTtryqrU0ilzSATvfU3zG7x8+mnEIrio3Qd6LDsQ7cLm62BX2z25rBqTvmY2YmY/fHFx2tkVsTZcCKRT08Vww==", + "version": "8.5.47", + "resolved": "https://registry.npmjs.org/@fluentui/font-icons-mdl2/-/font-icons-mdl2-8.5.47.tgz", + "integrity": "sha512-99d/cjEMz0ik9LnVrEDhZB4CnQavwgBvZuNa/EAaeHZMlQ7eheCzU3PNG4goPC7o4yg7XCNyngA7hEx3RUPUDA==", + "license": "MIT", "dependencies": { - "@fluentui/set-version": "^8.2.14", - "@fluentui/style-utilities": "^8.10.5", - "@fluentui/utilities": "^8.15.0", + "@fluentui/set-version": "^8.2.23", + "@fluentui/style-utilities": "^8.10.18", + "@fluentui/utilities": "^8.15.13", "tslib": "^2.1.0" } }, "node_modules/@fluentui/foundation-legacy": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@fluentui/foundation-legacy/-/foundation-legacy-8.4.0.tgz", - "integrity": "sha512-RSOfVPLgCCru6RBYxqp754aeWZ+lYVI+CMffMrhg2/LGl0CcNGXZjK0LYH/anbVq1sEZ/D9e56FekzMOR3CScw==", + "version": "8.4.13", + "resolved": "https://registry.npmjs.org/@fluentui/foundation-legacy/-/foundation-legacy-8.4.13.tgz", + "integrity": "sha512-LIrqiDM0Fe45XLIx/XISwRfcaB5TfoMlkjic7K6goZtssi6VSNEAWjj+V2DOZNUaaFE3J3j61EspoZEKbqGazg==", + "license": "MIT", "dependencies": { - "@fluentui/merge-styles": "^8.6.0", - "@fluentui/set-version": "^8.2.14", - "@fluentui/style-utilities": "^8.10.5", - "@fluentui/utilities": "^8.15.0", + "@fluentui/merge-styles": "^8.6.12", + "@fluentui/set-version": "^8.2.23", + "@fluentui/style-utilities": "^8.10.18", + "@fluentui/utilities": "^8.15.13", "tslib": "^2.1.0" }, "peerDependencies": { @@ -302,9 +312,10 @@ } }, "node_modules/@fluentui/keyboard-key": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@fluentui/keyboard-key/-/keyboard-key-0.4.14.tgz", - "integrity": "sha512-XzZHcyFEM20H23h3i15UpkHi2AhRBriXPGAHq0Jm98TKFppXehedjjEFuUsh+CyU5JKBhDalWp8TAQ1ArpNzow==", + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/@fluentui/keyboard-key/-/keyboard-key-0.4.23.tgz", + "integrity": "sha512-9GXeyUqNJUdg5JiQUZeGPiKnRzMRi9YEUn1l9zq6X/imYdMhxHrxpVZS12129cBfgvPyxt9ceJpywSfmLWqlKA==", + "license": "MIT", "dependencies": { "tslib": "^2.1.0" } @@ -313,44 +324,48 @@ "version": "9.0.7", "resolved": "https://registry.npmjs.org/@fluentui/keyboard-keys/-/keyboard-keys-9.0.7.tgz", "integrity": "sha512-vaQ+lOveQTdoXJYqDQXWb30udSfTVcIuKk1rV0X0eGAgcHeSDeP1HxMy+OgHOQZH3OiBH4ZYeWxb+tmfiDiygQ==", + "license": "MIT", "dependencies": { "@swc/helpers": "^0.5.1" } }, "node_modules/@fluentui/merge-styles": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@fluentui/merge-styles/-/merge-styles-8.6.0.tgz", - "integrity": "sha512-Si54VVK/XZQMTPT6aKE/RmqsY7uy9hERreU143Fbqtg9cf+Hr4iJ7FOGC4dXCfrFIXs0KvIHXCh5mtfrEW2aRQ==", + "version": "8.6.12", + "resolved": "https://registry.npmjs.org/@fluentui/merge-styles/-/merge-styles-8.6.12.tgz", + "integrity": "sha512-v8njux9frUkoGGlBnQXKHaKCX2nLZVHPFMDMzibtAIt4vIkkv+oY2lFmJ2h96tSIkg4eVN7h5sSDTFVoAPwpYg==", + "license": "MIT", "dependencies": { - "@fluentui/set-version": "^8.2.14", + "@fluentui/set-version": "^8.2.23", "tslib": "^2.1.0" } }, "node_modules/@fluentui/priority-overflow": { - "version": "9.1.11", - "resolved": "https://registry.npmjs.org/@fluentui/priority-overflow/-/priority-overflow-9.1.11.tgz", - "integrity": "sha512-sdrpavvKX2kepQ1d6IaI3ObLq5SAQBPRHPGx2+wiMWL7cEx9vGGM0fmeicl3soqqmM5uwCmWnZk9QZv9XOY98w==", + "version": "9.1.13", + "resolved": "https://registry.npmjs.org/@fluentui/priority-overflow/-/priority-overflow-9.1.13.tgz", + "integrity": "sha512-yDojVpkhBZTXOYExrCgW1GXbw3x9pYIS617xlNJIc2t06Cd3H32y2p51QXFt94sBmlVyAvPu7UKBHaq1Yw7u+w==", + "license": "MIT", "dependencies": { "@swc/helpers": "^0.5.1" } }, "node_modules/@fluentui/react": { - "version": "8.117.0", - "resolved": "https://registry.npmjs.org/@fluentui/react/-/react-8.117.0.tgz", - "integrity": "sha512-7zPFyyhm6zZGUF5C7/L5XNIBNBYsGc2ZIVg+nuCd56hBgMh0smWDnbciFKpQ9jvAh6gvfKbsgUuVWrD/FwEkAg==", - "dependencies": { - "@fluentui/date-time-utilities": "^8.6.0", - "@fluentui/font-icons-mdl2": "^8.5.34", - "@fluentui/foundation-legacy": "^8.4.0", - "@fluentui/merge-styles": "^8.6.0", - "@fluentui/react-focus": "^8.8.42", - "@fluentui/react-hooks": "^8.7.0", - "@fluentui/react-portal-compat-context": "^9.0.11", - "@fluentui/react-window-provider": "^2.2.18", - "@fluentui/set-version": "^8.2.14", - "@fluentui/style-utilities": "^8.10.5", - "@fluentui/theme": "^2.6.43", - "@fluentui/utilities": "^8.15.0", + "version": "8.119.3", + "resolved": "https://registry.npmjs.org/@fluentui/react/-/react-8.119.3.tgz", + "integrity": "sha512-sJaFQU7sy8/kZR7ma9Ejqi6GnYFVzYcgSA2DVbvxGoH+edoztXQjro9qaIaUILhtWBUMMcG47DtykgubelhQFw==", + "license": "MIT", + "dependencies": { + "@fluentui/date-time-utilities": "^8.6.9", + "@fluentui/font-icons-mdl2": "^8.5.47", + "@fluentui/foundation-legacy": "^8.4.13", + "@fluentui/merge-styles": "^8.6.12", + "@fluentui/react-focus": "^8.9.10", + "@fluentui/react-hooks": "^8.8.10", + "@fluentui/react-portal-compat-context": "^9.0.12", + "@fluentui/react-window-provider": "^2.2.27", + "@fluentui/set-version": "^8.2.23", + "@fluentui/style-utilities": "^8.10.18", + "@fluentui/theme": "^2.6.56", + "@fluentui/utilities": "^8.15.13", "@microsoft/load-themed-styles": "^1.10.26", "tslib": "^2.1.0" }, @@ -362,19 +377,20 @@ } }, "node_modules/@fluentui/react-accordion": { - "version": "9.3.46", - "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.3.46.tgz", - "integrity": "sha512-bFOF/uoPYL4AUQEIKFTgx8WZgeC39Vw2FiL6A2A0km0Z9yBgWg7LLsF73/MbgoO0GjH8BvO/2ddpgdd433jIRw==", - "dependencies": { - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.4.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.4.4.tgz", + "integrity": "sha512-nDkzWhz9PID94rzg06CiuzSkFuAemT2mIOs5G9/IQqIaQYr2do/Ff7WH5gbB6vK901C1b4ZqxeNnPYNf/wLhpA==", + "license": "MIT", + "dependencies": { + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -385,18 +401,19 @@ } }, "node_modules/@fluentui/react-alert": { - "version": "9.0.0-beta.114", - "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.114.tgz", - "integrity": "sha512-ZA55Wf9ZNE2KfKnT9fDqvWqnAKgcrYwYIJoliG+pCLztCitwlv/XUKAWR/DkP02NpA2qEeaiY1D9k/Mwd1haIQ==", - "dependencies": { - "@fluentui/react-avatar": "^9.6.19", - "@fluentui/react-button": "^9.3.73", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.0.0-beta.124", + "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.124.tgz", + "integrity": "sha512-yFBo3B5H9hnoaXxlkuz8wRz04DEyQ+ElYA/p5p+Vojf19Zuta8DmFZZ6JtWdtxcdnnQ4LvAfC5OYYlzdReozPA==", + "license": "MIT", + "dependencies": { + "@fluentui/react-avatar": "^9.6.29", + "@fluentui/react-button": "^9.3.83", + "@fluentui/react-icons": "^2.0.239", + "@fluentui/react-jsx-runtime": "^9.0.39", + "@fluentui/react-tabster": "^9.21.5", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.10", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -407,15 +424,16 @@ } }, "node_modules/@fluentui/react-aria": { - "version": "9.10.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.10.2.tgz", - "integrity": "sha512-M8wzxPZlMOLr7SlZXlSi/zCbLSsXrJzpMjLkTOPPlMrMu8He38oM6Djc4dCac/cZn8ERpKUDaoAK5JF/kbtLzQ==", + "version": "9.13.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.13.2.tgz", + "integrity": "sha512-lb93r/FiE3bj1/lfixy/Hb+LW8MQ9HCqdDWLRo1gmP4f3QgIj/Gz7oTB+NilwzytiH4OBDXq0apdUHGLwGkotA==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", - "@fluentui/react-utilities": "^9.18.5", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", + "@fluentui/react-utilities": "^9.18.13", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -426,21 +444,22 @@ } }, "node_modules/@fluentui/react-avatar": { - "version": "9.6.19", - "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.6.19.tgz", - "integrity": "sha512-3/8BBoPXNGfcuNVN4+bpwpd124CEdFEm9VKD6hQ6VmIHM6phBWnQc6J7djuKlZTw7B5UEeqEOEZgMJeGUx27SA==", - "dependencies": { - "@fluentui/react-badge": "^9.2.29", - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-popover": "^9.9.2", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.6.33", + "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.6.33.tgz", + "integrity": "sha512-xikMYnjtBQRv1rHOhDEc/5GvG5F46MFhgu3jcBbxyVt512AfwVgDMPj18tg4y2RaZ587FLPFifK7VlNBDAaT4g==", + "license": "MIT", + "dependencies": { + "@fluentui/react-badge": "^9.2.41", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-popover": "^9.9.15", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-tooltip": "^9.4.21", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-tooltip": "^9.4.34", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -451,16 +470,17 @@ } }, "node_modules/@fluentui/react-badge": { - "version": "9.2.29", - "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.2.29.tgz", - "integrity": "sha512-k2CMMzBLPCNq5WAUfkCvWqCPeh8/NsfLxQBre8klxFZS5TT872ViLwmYHXpHWTfFymFrChaedOd7C8ZYqeT4tA==", + "version": "9.2.41", + "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.2.41.tgz", + "integrity": "sha512-/GBKotH68XrBix1mCJybYHw+5QKYoAbINqYPj2mEfcDiC2VfS4w4Drjokcp2O1KD2cX/YZ9PThptKmWkjT3UOw==", + "license": "MIT", "dependencies": { - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -471,20 +491,21 @@ } }, "node_modules/@fluentui/react-breadcrumb": { - "version": "9.0.19", - "resolved": "https://registry.npmjs.org/@fluentui/react-breadcrumb/-/react-breadcrumb-9.0.19.tgz", - "integrity": "sha512-12pqa0CAVDaBu16/E/aU9R+wJoBga/4Dm9UoyX4FG5TkoM28kiOGXZ8xhEdOrF4w1J9hFfEx2cyNGSdGFyJfcQ==", - "dependencies": { - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-button": "^9.3.73", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-link": "^9.2.15", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.0.33", + "resolved": "https://registry.npmjs.org/@fluentui/react-breadcrumb/-/react-breadcrumb-9.0.33.tgz", + "integrity": "sha512-VDnTsUPqmWRAuOwXwScItlaLzuMFlOXCRgrZuU3py8QTTjUU4jIBi2X7wI7DREpD0FRM7wbujCkN0tb4lRO4FQ==", + "license": "MIT", + "dependencies": { + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-button": "^9.3.87", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-link": "^9.2.28", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -495,19 +516,20 @@ } }, "node_modules/@fluentui/react-button": { - "version": "9.3.73", - "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.3.73.tgz", - "integrity": "sha512-VsCxj4pKWL1SVj0XlYBRs4kaFUfRVK3JqCWx9mlDuHYzeRzk4aBCBT5vBIzrrPTj3bR2yl/zOf6m5T43kyWZxw==", + "version": "9.3.87", + "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.3.87.tgz", + "integrity": "sha512-Di8RWjIswa1jriYfed6FH90fqmTwBkaILWxzJzChaBbUAOtxEYn3K57F+9PS9s05z7PhlDuVnfd2RV0dIrYHtg==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -518,16 +540,17 @@ } }, "node_modules/@fluentui/react-card": { - "version": "9.0.72", - "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.0.72.tgz", - "integrity": "sha512-sJQ0T0SOBZ8tTGMxmJhVYDaHsQe/+ECQwhPIb0irDnD3ojTbL/IjxONeBnxVJ5/xG6cA3rV6tfD8WrockIDXOg==", + "version": "9.0.87", + "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.0.87.tgz", + "integrity": "sha512-aH7tvf1XTtW5kVM2YzbM1OEVQ0dn9POBHEutmpSkHpxb/Wa4bAPm4Yrimt9PZqcFws1WdFapbZD0xaYGhf+9Ew==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -538,19 +561,20 @@ } }, "node_modules/@fluentui/react-checkbox": { - "version": "9.2.18", - "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.2.18.tgz", - "integrity": "sha512-m4UjLx5jMYj0WtPzwNRR0hbGX9NHZvvxf52Xka39DphAorB5ohuTfJe12cMKSwStaOQBa4gtGXntl7tqP02PHQ==", - "dependencies": { - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-label": "^9.1.66", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.2.32", + "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.2.32.tgz", + "integrity": "sha512-q75W+SaGxKHFNjInGq/TYARQHeP7x1H2N0681JFhvo6Ji0BbCTKpxMTsssHvR6OlqBPjcXfkxpXiVD/V8vVgNA==", + "license": "MIT", + "dependencies": { + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-label": "^9.1.74", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -561,23 +585,24 @@ } }, "node_modules/@fluentui/react-combobox": { - "version": "9.9.4", - "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.9.4.tgz", - "integrity": "sha512-3SmoCLyBa7+iuwrbVkjIVrOuTAeCYK7nvwWZfTf5eqeEsYmk+6orXy0kz1lR23M5Mtfa8l4FqvopUiuyAmXuCw==", + "version": "9.13.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.13.2.tgz", + "integrity": "sha512-unLJyLs0rq06cl81ka89JkvKo3iXXGHC5wbZ4KTAEF3ZoXjuw7EI19tLiR+FIEV60qhSo2jOXKCF8xpHOKWIXQ==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-portal": "^9.4.18", - "@fluentui/react-positioning": "^9.14.2", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-portal": "^9.4.31", + "@fluentui/react-positioning": "^9.15.6", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -588,62 +613,68 @@ } }, "node_modules/@fluentui/react-components": { - "version": "9.47.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.47.2.tgz", - "integrity": "sha512-2DHL03T6flpIqTWghQQ5ADmb2VXnfNAxz2mC9iL+RRHeTYeDf9PweOIiCowU2gioyGvV9VfKQbXP5WG5A7ijoQ==", - "dependencies": { - "@fluentui/react-accordion": "^9.3.46", - "@fluentui/react-alert": "9.0.0-beta.114", - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-avatar": "^9.6.19", - "@fluentui/react-badge": "^9.2.29", - "@fluentui/react-breadcrumb": "^9.0.19", - "@fluentui/react-button": "^9.3.73", - "@fluentui/react-card": "^9.0.72", - "@fluentui/react-checkbox": "^9.2.18", - "@fluentui/react-combobox": "^9.9.4", - "@fluentui/react-dialog": "^9.9.15", - "@fluentui/react-divider": "^9.2.65", - "@fluentui/react-drawer": "^9.1.9", - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-image": "^9.1.62", - "@fluentui/react-infobutton": "9.0.0-beta.98", - "@fluentui/react-infolabel": "^9.0.26", - "@fluentui/react-input": "^9.4.69", - "@fluentui/react-label": "^9.1.66", - "@fluentui/react-link": "^9.2.15", - "@fluentui/react-menu": "^9.13.5", - "@fluentui/react-message-bar": "^9.0.24", - "@fluentui/react-overflow": "^9.1.15", - "@fluentui/react-persona": "^9.2.78", - "@fluentui/react-popover": "^9.9.2", - "@fluentui/react-portal": "^9.4.18", - "@fluentui/react-positioning": "^9.14.2", - "@fluentui/react-progress": "^9.1.69", - "@fluentui/react-provider": "^9.13.16", - "@fluentui/react-radio": "^9.2.13", - "@fluentui/react-rating": "^9.0.1", - "@fluentui/react-select": "^9.1.69", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-skeleton": "^9.0.57", - "@fluentui/react-slider": "^9.1.75", - "@fluentui/react-spinbutton": "^9.2.69", - "@fluentui/react-spinner": "^9.4.2", - "@fluentui/react-switch": "^9.1.75", - "@fluentui/react-table": "^9.12.0", - "@fluentui/react-tabs": "^9.4.14", - "@fluentui/react-tabster": "^9.19.5", - "@fluentui/react-tags": "^9.2.0", - "@fluentui/react-text": "^9.4.14", - "@fluentui/react-textarea": "^9.3.69", + "version": "9.54.6", + "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.54.6.tgz", + "integrity": "sha512-ocL+VIdTZsyjrA8z7IWifoyH7YFAsLLn2FPFdLkQqPk/+XPcbuduRDBYfeVAqwsQLmNk44dC5RXZyziigLUd/A==", + "license": "MIT", + "dependencies": { + "@fluentui/react-accordion": "^9.4.4", + "@fluentui/react-alert": "9.0.0-beta.124", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-avatar": "^9.6.33", + "@fluentui/react-badge": "^9.2.41", + "@fluentui/react-breadcrumb": "^9.0.33", + "@fluentui/react-button": "^9.3.87", + "@fluentui/react-card": "^9.0.87", + "@fluentui/react-checkbox": "^9.2.32", + "@fluentui/react-combobox": "^9.13.2", + "@fluentui/react-dialog": "^9.11.6", + "@fluentui/react-divider": "^9.2.73", + "@fluentui/react-drawer": "^9.5.6", + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-image": "^9.1.71", + "@fluentui/react-infobutton": "9.0.0-beta.102", + "@fluentui/react-infolabel": "^9.0.40", + "@fluentui/react-input": "^9.4.83", + "@fluentui/react-label": "^9.1.74", + "@fluentui/react-link": "^9.2.28", + "@fluentui/react-menu": "^9.14.11", + "@fluentui/react-message-bar": "^9.2.6", + "@fluentui/react-motion": "^9.4.0", + "@fluentui/react-overflow": "^9.1.25", + "@fluentui/react-persona": "^9.2.92", + "@fluentui/react-popover": "^9.9.15", + "@fluentui/react-portal": "^9.4.31", + "@fluentui/react-positioning": "^9.15.6", + "@fluentui/react-progress": "^9.1.82", + "@fluentui/react-provider": "^9.17.0", + "@fluentui/react-radio": "^9.2.27", + "@fluentui/react-rating": "^9.0.15", + "@fluentui/react-search": "^9.0.12", + "@fluentui/react-select": "^9.1.82", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-skeleton": "^9.1.10", + "@fluentui/react-slider": "^9.1.89", + "@fluentui/react-spinbutton": "^9.2.83", + "@fluentui/react-spinner": "^9.4.12", + "@fluentui/react-swatch-picker": "^9.1.6", + "@fluentui/react-switch": "^9.1.89", + "@fluentui/react-table": "^9.15.11", + "@fluentui/react-tabs": "^9.4.27", + "@fluentui/react-tabster": "^9.22.3", + "@fluentui/react-tag-picker": "^9.2.3", + "@fluentui/react-tags": "^9.3.12", + "@fluentui/react-teaching-popover": "^9.1.11", + "@fluentui/react-text": "^9.4.23", + "@fluentui/react-textarea": "^9.3.83", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-toast": "^9.3.35", - "@fluentui/react-toolbar": "^9.1.76", - "@fluentui/react-tooltip": "^9.4.21", - "@fluentui/react-tree": "^9.4.36", - "@fluentui/react-utilities": "^9.18.5", - "@fluentui/react-virtualizer": "9.0.0-alpha.73", - "@griffel/react": "^1.5.14", + "@fluentui/react-toast": "^9.3.51", + "@fluentui/react-toolbar": "^9.1.90", + "@fluentui/react-tooltip": "^9.4.34", + "@fluentui/react-tree": "^9.7.5", + "@fluentui/react-utilities": "^9.18.13", + "@fluentui/react-virtualizer": "9.0.0-alpha.82", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -654,11 +685,12 @@ } }, "node_modules/@fluentui/react-context-selector": { - "version": "9.1.56", - "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.1.56.tgz", - "integrity": "sha512-TzDYTvHRuOB3qKiIBB0NU4mwX/fuxW41I1O9yK7C5Dt4RsexNInGLf5HMxYHWufevDSFhRLuAN+ikTHUMkcNzw==", + "version": "9.1.65", + "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.1.65.tgz", + "integrity": "sha512-hpluiP2NtK01Kx1RdKnJkQr7snbFuFJUwRho3NsuzuX/ea9OaVNEAxcvLMUcwd5nItf5Y5U8i07ib7YX5qchmQ==", + "license": "MIT", "dependencies": { - "@fluentui/react-utilities": "^9.18.5", + "@fluentui/react-utilities": "^9.18.13", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -670,23 +702,24 @@ } }, "node_modules/@fluentui/react-dialog": { - "version": "9.9.15", - "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.9.15.tgz", - "integrity": "sha512-UVjU7ZKq9117A80GQ/cv+YH/Pql4bN8FH3/GbJd8qwOxtlzOWpN8DOu1mwrj5ahxt3b+tpYsmp1QrqX9nujhMA==", + "version": "9.11.6", + "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.11.6.tgz", + "integrity": "sha512-a7KQZeRcaOM8PzEHFONIxjHyiZjLwA57+Bm2XdILJsVrNL9cCSz2ChN3zaIGGZ3gfZ+YkNvfcbXAz5sVIXyKVw==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-portal": "^9.4.18", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-motion": "^9.4.0", + "@fluentui/react-portal": "^9.4.31", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", - "@swc/helpers": "^0.5.1", - "react-transition-group": "^4.4.1" + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { "@types/react": ">=16.14.0 <19.0.0", @@ -696,15 +729,16 @@ } }, "node_modules/@fluentui/react-divider": { - "version": "9.2.65", - "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.2.65.tgz", - "integrity": "sha512-jjyvD+GnLACxHhV+eTdn0+X2Yar6NlzNK8q+xdZjuD+yJ5NcWiiD+Dkh5CJUFegkaBTUb2+Fp1pFEEMaCzrHkw==", + "version": "9.2.73", + "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.2.73.tgz", + "integrity": "sha512-AmkJPAFEszLbWh7vrV6vV+omnkQgfw1hhVBcTIlLD2b712Tk7GczZC2PXTq0fNKI3Aw8x4sNBbomozJp2y+X7w==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -715,18 +749,19 @@ } }, "node_modules/@fluentui/react-drawer": { - "version": "9.1.9", - "resolved": "https://registry.npmjs.org/@fluentui/react-drawer/-/react-drawer-9.1.9.tgz", - "integrity": "sha512-5KzOVxRPFJa0oDnp+kfCYJezA4JxsQzporNSmVw/i3/w/L9hCJyOuzrI+ps36Xb3tYymaKsAemC4+NAvs4HD+w==", - "dependencies": { - "@fluentui/react-dialog": "^9.9.15", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-motion-preview": "^0.5.17", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.5.6", + "resolved": "https://registry.npmjs.org/@fluentui/react-drawer/-/react-drawer-9.5.6.tgz", + "integrity": "sha512-vfn4G+gRpNETqBFQ3cnWJajKbCyMNeqInzDaeEh7eU+8/YANGIofMU8bPublVcSD5Ew9Ly++GEte4dIGvQiB8A==", + "license": "MIT", + "dependencies": { + "@fluentui/react-dialog": "^9.11.6", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-motion-preview": "^0.5.25", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -737,20 +772,21 @@ } }, "node_modules/@fluentui/react-experiments": { - "version": "8.14.137", - "resolved": "https://registry.npmjs.org/@fluentui/react-experiments/-/react-experiments-8.14.137.tgz", - "integrity": "sha512-2RhKX+J9xo8AtWpFATp2dUctNQtdQpJY8ndmSyvgLEvDOnHdTNpGC5j4PsIbGV5FmMIo28K67Ni9CM2mstuHlw==", - "dependencies": { - "@fluentui/example-data": "^8.4.15", - "@fluentui/font-icons-mdl2": "^8.5.34", - "@fluentui/foundation-legacy": "^8.4.0", - "@fluentui/merge-styles": "^8.6.0", - "@fluentui/react": "^8.117.0", - "@fluentui/react-hooks": "^8.7.0", - "@fluentui/set-version": "^8.2.14", - "@fluentui/style-utilities": "^8.10.5", - "@fluentui/theme": "^2.6.43", - "@fluentui/utilities": "^8.15.0", + "version": "8.14.160", + "resolved": "https://registry.npmjs.org/@fluentui/react-experiments/-/react-experiments-8.14.160.tgz", + "integrity": "sha512-LsthZCNwOtI8Dv+pTMhEaacBv8gm9I7fDq4Grw5MMAY5aQpCljcaBXCkHEq/4sOZtDTY7gnKh57c/g+GptCkUQ==", + "license": "MIT", + "dependencies": { + "@fluentui/example-data": "^8.4.24", + "@fluentui/font-icons-mdl2": "^8.5.47", + "@fluentui/foundation-legacy": "^8.4.13", + "@fluentui/merge-styles": "^8.6.12", + "@fluentui/react": "^8.119.3", + "@fluentui/react-hooks": "^8.8.10", + "@fluentui/set-version": "^8.2.23", + "@fluentui/style-utilities": "^8.10.18", + "@fluentui/theme": "^2.6.56", + "@fluentui/utilities": "^8.15.13", "@microsoft/load-themed-styles": "^1.10.26", "deep-assign": "^2.0.0", "prop-types": "^15.7.2", @@ -764,17 +800,18 @@ } }, "node_modules/@fluentui/react-field": { - "version": "9.1.59", - "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.1.59.tgz", - "integrity": "sha512-GrrWrGZes+qxE9JbAk3Z85wvFhM8CAXTu3amUxOHB+zt0QVcHXJHkg7OvEtXgSnFYJEau0aQgQg6ZjeFQkMpAg==", - "dependencies": { - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-label": "^9.1.66", + "version": "9.1.71", + "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.1.71.tgz", + "integrity": "sha512-DqvLa3ZPm+vhIvbQrZqV8d2Nr/+dJv3mOxlootqMVu4v1l8K6fux4qUzwXvSyydIx7U73R99sC/iOCic2SYDFw==", + "license": "MIT", + "dependencies": { + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-label": "^9.1.74", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -785,15 +822,16 @@ } }, "node_modules/@fluentui/react-focus": { - "version": "8.8.42", - "resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-8.8.42.tgz", - "integrity": "sha512-U9KRiBabHyVUfemArukjTH6TDthj/MnDbgAUa55CMdj061ZV/Ria+Fxb1QG+GW3Az6bSaAulJvj/fGuNrawWhA==", - "dependencies": { - "@fluentui/keyboard-key": "^0.4.14", - "@fluentui/merge-styles": "^8.6.0", - "@fluentui/set-version": "^8.2.14", - "@fluentui/style-utilities": "^8.10.5", - "@fluentui/utilities": "^8.15.0", + "version": "8.9.10", + "resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-8.9.10.tgz", + "integrity": "sha512-9kV15td8uuYhQS4bTLImxVo75dmbeOK0rZ4gQgOAY/0nKRYwiCLfH9SwQuEa+eCmjsBTNuDlXgghjQJyKFh5+A==", + "license": "MIT", + "dependencies": { + "@fluentui/keyboard-key": "^0.4.23", + "@fluentui/merge-styles": "^8.6.12", + "@fluentui/set-version": "^8.2.23", + "@fluentui/style-utilities": "^8.10.18", + "@fluentui/utilities": "^8.15.13", "tslib": "^2.1.0" }, "peerDependencies": { @@ -802,13 +840,14 @@ } }, "node_modules/@fluentui/react-hooks": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-hooks/-/react-hooks-8.7.0.tgz", - "integrity": "sha512-m1/2q+zF/dNj2dWqIl06G88dTEMmiaP40k16b1juyjHXYsVPooxPlUD1l9FLrB8mC3VkpCy/fgASaPqRH8mUGw==", + "version": "8.8.10", + "resolved": "https://registry.npmjs.org/@fluentui/react-hooks/-/react-hooks-8.8.10.tgz", + "integrity": "sha512-Xvnn6uKMsinMg/zo79KBNCDABnl0gpmArQYNQya9FCNRzvmHUCDvuQCqv4IKslvPvuC0Ya8mR2NORm2w0JoZiw==", + "license": "MIT", "dependencies": { - "@fluentui/react-window-provider": "^2.2.18", - "@fluentui/set-version": "^8.2.14", - "@fluentui/utilities": "^8.15.0", + "@fluentui/react-window-provider": "^2.2.27", + "@fluentui/set-version": "^8.2.23", + "@fluentui/utilities": "^8.15.13", "tslib": "^2.1.0" }, "peerDependencies": { @@ -817,9 +856,10 @@ } }, "node_modules/@fluentui/react-icons": { - "version": "2.0.225", - "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.225.tgz", - "integrity": "sha512-L9phN3bAMlZCa5+/ObGjIO+5GI8M50ym766sraSq92jaJwgAXrCJDLWuDGWZRGrC63DcagtR2culptj3q7gMMg==", + "version": "2.0.249", + "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.249.tgz", + "integrity": "sha512-VcOCbqv3MxzMZdH6jyqpzsfyNV0cG5F4TKXnnXcJ/QVQcWsN2BU6NrCiwkZHKEjbOYbxwBTdBHq1gnR5qz4baw==", + "license": "MIT", "dependencies": { "@griffel/react": "^1.0.0", "tslib": "^2.1.0" @@ -829,13 +869,14 @@ } }, "node_modules/@fluentui/react-icons-mdl2": { - "version": "1.3.59", - "resolved": "https://registry.npmjs.org/@fluentui/react-icons-mdl2/-/react-icons-mdl2-1.3.59.tgz", - "integrity": "sha512-cdvdvUXCrGHEob+3GWd8FJehbrxSXYliXkEwKVDOxC2+vBE6z1XanIRloGwdHBLnBsps46eYvvRVBHGlCUxmwg==", + "version": "1.3.72", + "resolved": "https://registry.npmjs.org/@fluentui/react-icons-mdl2/-/react-icons-mdl2-1.3.72.tgz", + "integrity": "sha512-uuBPsv1ep9EK92IwsmXPkalYQi0d5TNiReIbreHBeoHaGzyCRlXqwAW0XXqVP5/iCW1EyozwfccFovR6vyXoXw==", + "license": "MIT", "dependencies": { - "@fluentui/react-icon-provider": "^1.3.55", - "@fluentui/set-version": "^8.2.14", - "@fluentui/utilities": "^8.15.0", + "@fluentui/react-icon-provider": "^1.3.68", + "@fluentui/set-version": "^8.2.23", + "@fluentui/utilities": "^8.15.13", "@microsoft/load-themed-styles": "^1.10.26", "tslib": "^2.1.0" }, @@ -844,12 +885,13 @@ } }, "node_modules/@fluentui/react-icons-mdl2/node_modules/@fluentui/react-icon-provider": { - "version": "1.3.55", - "resolved": "https://registry.npmjs.org/@fluentui/react-icon-provider/-/react-icon-provider-1.3.55.tgz", - "integrity": "sha512-fa7AO7T+7+c5K6lIcsHbaC0apEf3LSQclK2F/PWMyn1r1mQp4eHIMxAPFxXrl/ay8QxRTaRhzIgxgar/XTXRjw==", + "version": "1.3.68", + "resolved": "https://registry.npmjs.org/@fluentui/react-icon-provider/-/react-icon-provider-1.3.68.tgz", + "integrity": "sha512-Mhxx8p+p0h0bN4gIoo+jGQ9jDBhAGc3HuRcS0CD9cld9eVGB/hr/RIiBj+39JQGJqzRB4rntLnLPFvjRAjPWiA==", + "license": "MIT", "dependencies": { - "@fluentui/set-version": "^8.2.14", - "@fluentui/style-utilities": "^8.10.5", + "@fluentui/set-version": "^8.2.23", + "@fluentui/style-utilities": "^8.10.18", "tslib": "^2.1.0" }, "peerDependencies": { @@ -860,15 +902,16 @@ } }, "node_modules/@fluentui/react-image": { - "version": "9.1.62", - "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.1.62.tgz", - "integrity": "sha512-j8V9XWdl9otn1kfBqo5EGBD7nvvaabb9H3Wz8I0pMfeC8fMwq6iR8KYO+MbFUSwmekMEoqsP8qPKHUOViMEhPw==", + "version": "9.1.71", + "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.1.71.tgz", + "integrity": "sha512-OKUbVsZLVe/kRP7KrweHDkztY8FUz6HzEPxZvJqIkwDf+KIJJxDV4R9Hpw8Fis6ceLbj/VI5JUVwGIp5YQlsjA==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -879,17 +922,18 @@ } }, "node_modules/@fluentui/react-infobutton": { - "version": "9.0.0-beta.98", - "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.98.tgz", - "integrity": "sha512-7IFrKpmv1PnTN7ZrisYE7qrsfY6bRTK5AVnsQVrBX9/6xkLe4ZE52cQtoAnTX1gMIgqDhgoOd/RTzTO07xxPiw==", - "dependencies": { - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-label": "^9.1.66", - "@fluentui/react-popover": "^9.9.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.0.0-beta.102", + "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.102.tgz", + "integrity": "sha512-3kA4F0Vga8Ds6JGlBajLCCDOo/LmPuS786Wg7ui4ZTDYVIMzy1yp2XuVcZniifBFvEp0HQCUoDPWUV0VI3FfzQ==", + "license": "MIT", + "dependencies": { + "@fluentui/react-icons": "^2.0.237", + "@fluentui/react-jsx-runtime": "^9.0.36", + "@fluentui/react-label": "^9.1.68", + "@fluentui/react-popover": "^9.9.6", + "@fluentui/react-tabster": "^9.21.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", + "@fluentui/react-utilities": "^9.18.7", "@griffel/react": "^1.5.14", "@swc/helpers": "^0.5.1" }, @@ -901,38 +945,40 @@ } }, "node_modules/@fluentui/react-infolabel": { - "version": "9.0.26", - "resolved": "https://registry.npmjs.org/@fluentui/react-infolabel/-/react-infolabel-9.0.26.tgz", - "integrity": "sha512-mvLRsiS0bP0mLokMmU8Aho8Wea4OE1vBvisuC2uwq584WyDyk8rxjyPNqFo0BrcgwHSB++bHcQpsF4keP1UVQQ==", - "dependencies": { - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-label": "^9.1.66", - "@fluentui/react-popover": "^9.9.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.0.40", + "resolved": "https://registry.npmjs.org/@fluentui/react-infolabel/-/react-infolabel-9.0.40.tgz", + "integrity": "sha512-3hXmmiuv5gEqZWTNK25tp/YdLoIgIZ64XgFXDgtaRjK94evzEIYR2jRhhfQUWZorMOhTqqSBMfKK/+M8dwfk2g==", + "license": "MIT", + "dependencies": { + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-label": "^9.1.74", + "@fluentui/react-popover": "^9.9.15", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { "@types/react": ">=16.8.0 <19.0.0", "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", "react-dom": ">=16.8.0 <19.0.0" } }, "node_modules/@fluentui/react-input": { - "version": "9.4.69", - "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.4.69.tgz", - "integrity": "sha512-pWpZYXZM0B/LbhpsboRdjm4hMRuoJMb6Kh2PcmNnPy1XGNkD4BASF5m9N8rgdZSgWyYxpCxO/ONGSqRY7A1O7Q==", + "version": "9.4.83", + "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.4.83.tgz", + "integrity": "sha512-mM2aU0Xsqfx7LKFs1X0VBCyXncxRQBRHwEh+1MTvkbhgOYLxD3f2qEy/XNk0vyJ2rya/A2zHE9vwDHKn7Ck44A==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -943,11 +989,12 @@ } }, "node_modules/@fluentui/react-jsx-runtime": { - "version": "9.0.34", - "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.0.34.tgz", - "integrity": "sha512-pJ/f/xZ6+19sD3kjyMp2NDmIwexdMbYHeqmr/AgbI+G3Fb2NKA0UA6XylAXlCiAx4nEXdOETJDrrDsdFAV+/Fw==", + "version": "9.0.42", + "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.0.42.tgz", + "integrity": "sha512-/iKhJx5htz+iBjWRjviM7cEAiG0y9oqVimmeWaZChi0M5abwvHkueYQ+n1BhzYOtsdeuXXcbrkx4VkaO5j5Efg==", + "license": "MIT", "dependencies": { - "@fluentui/react-utilities": "^9.18.5", + "@fluentui/react-utilities": "^9.18.13", "@swc/helpers": "^0.5.1", "react-is": "^17.0.2" }, @@ -959,18 +1006,20 @@ "node_modules/@fluentui/react-jsx-runtime/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" }, "node_modules/@fluentui/react-label": { - "version": "9.1.66", - "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.1.66.tgz", - "integrity": "sha512-N0HOD5Wd6NI3YG7nGIhRhrjNBfNpDyaWxNYGMVnQs0pa6CWXcT6sCVxXxxSYYEnVFIDX7JmzFc4mgombTwnmmg==", + "version": "9.1.74", + "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.1.74.tgz", + "integrity": "sha512-9EDwomVwcHJvI7QKIsBok3EQ5Ty5R3cDMnYZl7OIugffEvt+UWcmNyIOckYt80vsPYNbM9XqTt4rNAvCkFd1UQ==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -981,17 +1030,18 @@ } }, "node_modules/@fluentui/react-link": { - "version": "9.2.15", - "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.2.15.tgz", - "integrity": "sha512-wZzLz3od22wJhmEd5xwOULVAuXXEdBRDa01mojtnU25pBhIErvY2VXU5QNS+Yycjt52NvBElB6Ut+LOKJ9KD2g==", + "version": "9.2.28", + "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.2.28.tgz", + "integrity": "sha512-k1/i8ktTCbztK88YogIt2FYCpJJMFxC4IzXAvpKLioTw6N3ITmxo9KuNNMvOYckGgHyvJliWutu/rSozFXTDmg==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1002,22 +1052,23 @@ } }, "node_modules/@fluentui/react-menu": { - "version": "9.13.5", - "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.13.5.tgz", - "integrity": "sha512-P9y31r7g/YAlL6zPWTFM26rp1gP6jkIqaXVCB6OuV/ZMdAxGIUcILww4d5rGr6G/tUpA9fL9trpWCgQpHSOXKw==", + "version": "9.14.11", + "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.14.11.tgz", + "integrity": "sha512-E1LWDywVukrbmKN8GIbdmTxP3w3q9V7ig4xDJNIt3VQxNoHdDS/Dz00pT6SZT/zP9VqCnfhpuF0xu+q5sOh4Nw==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-portal": "^9.4.18", - "@fluentui/react-positioning": "^9.14.2", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-portal": "^9.4.31", + "@fluentui/react-positioning": "^9.15.6", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1028,60 +1079,81 @@ } }, "node_modules/@fluentui/react-message-bar": { - "version": "9.0.24", - "resolved": "https://registry.npmjs.org/@fluentui/react-message-bar/-/react-message-bar-9.0.24.tgz", - "integrity": "sha512-gcqXRMFDbPc23aDTovwVUepufUJjjtQlnfqkWEwjlV6k1UdAfIzqgSThm81ztFXop1StyOH8gVj7QBGpBDz7+g==", - "dependencies": { - "@fluentui/react-button": "^9.3.73", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/@fluentui/react-message-bar/-/react-message-bar-9.2.6.tgz", + "integrity": "sha512-A1OwuzCK9Rce4PHYyPnB56qVMj2bg9Qb9h2qpHrChhz6Giol5Ty45lmmVqEpd/w+lyMC73Sgqyfg2Lucy/p3vw==", + "license": "MIT", + "dependencies": { + "@fluentui/react-button": "^9.3.87", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1", "react-transition-group": "^4.4.1" }, "peerDependencies": { "@types/react": ">=16.8.0 <19.0.0", "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", "react-dom": ">=16.8.0 <19.0.0" } }, "node_modules/@fluentui/react-migration-v8-v9": { - "version": "9.6.3", - "resolved": "https://registry.npmjs.org/@fluentui/react-migration-v8-v9/-/react-migration-v8-v9-9.6.3.tgz", - "integrity": "sha512-JTyBPUh5uy9R1B/KVVZ5HSOJThodZxyO3nvNlzUWFE3RUWRDb/IHOw+FIyEEybtb4QAcqErSGhdokn9lxiNF3A==", + "version": "9.6.22", + "resolved": "https://registry.npmjs.org/@fluentui/react-migration-v8-v9/-/react-migration-v8-v9-9.6.22.tgz", + "integrity": "sha512-uq6hFIovsmUVQLcvkUxzoyJu4UXIN169rq+778Fl+AzoznVGgXDx3FoR8sDTtJB5fZvQBqQR7y2vilRQdA8Wxw==", + "license": "MIT", "dependencies": { "@ctrl/tinycolor": "3.3.4", - "@fluentui/fluent2-theme": "^8.107.68", - "@fluentui/react": "^8.117.0", - "@fluentui/react-components": "^9.47.2", - "@fluentui/react-hooks": "^8.7.0", - "@fluentui/react-icons": "^2.0.224", + "@fluentui/fluent2-theme": "^8.107.91", + "@fluentui/react": "^8.119.3", + "@fluentui/react-components": "^9.54.6", + "@fluentui/react-hooks": "^8.8.10", + "@fluentui/react-icons": "^2.0.245", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { "@types/react": ">=16.14.0 <19.0.0", "@types/react-dom": ">=16.9.0 <19.0.0", - "react": ">=16.14.0 <19.0.0", + "react": ">=16.8.0 <19.0.0", "react-dom": ">=16.14.0 <19.0.0" } }, + "node_modules/@fluentui/react-motion": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-motion/-/react-motion-9.4.0.tgz", + "integrity": "sha512-WeLA0/INSf74DKFjCxHjn16p0Pak7LnKlaxva8r5ZMNNQ2Mcl7dFGdY+2e+qejghR7+8fzeojr+nQfKXH94uVQ==", + "license": "MIT", + "dependencies": { + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-utilities": "^9.18.13", + "@swc/helpers": "^0.5.1", + "react-is": "^17.0.2" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "@types/react-dom": ">=16.8.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.8.0 <19.0.0" + } + }, "node_modules/@fluentui/react-motion-preview": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/@fluentui/react-motion-preview/-/react-motion-preview-0.5.17.tgz", - "integrity": "sha512-7hnFuCpF7el6eQq3xwMKOWUWhfY0/UjHhaKkJ3NWHQuM8H7mzYPTifpphSUvh4DYA5XEUh8n8YEvnNy1kFHsVg==", + "version": "0.5.25", + "resolved": "https://registry.npmjs.org/@fluentui/react-motion-preview/-/react-motion-preview-0.5.25.tgz", + "integrity": "sha512-TRmDFTuIEOeCs5HCyk5NCpMXBgY8L7tSkjAyZVdZtBY5KxFGlMys+7DnXTXJNDud5OvgDphU6XEvKEGFmaq/Uw==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1091,16 +1163,23 @@ "react-dom": ">=16.14.0 <19.0.0" } }, + "node_modules/@fluentui/react-motion/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, "node_modules/@fluentui/react-overflow": { - "version": "9.1.15", - "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.1.15.tgz", - "integrity": "sha512-oIHwP9jLP3vzUlPy2M8shzgwHSvIh3mhc2A5CPTyu+aU906NFV6EFEx03vy62Cof21Ux71KOpPTFTAX0tBQrAA==", + "version": "9.1.25", + "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.1.25.tgz", + "integrity": "sha512-NfZF6D+5xlaUN9bJ5sziE5VkO0SHmJeoUXu+K0wXTpexVQVc16xh9Ob9wF4FouQ6JnD86WWdEGkALKpyaNQieQ==", + "license": "MIT", "dependencies": { - "@fluentui/priority-overflow": "^9.1.11", - "@fluentui/react-context-selector": "^9.1.56", + "@fluentui/priority-overflow": "^9.1.13", + "@fluentui/react-context-selector": "^9.1.65", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1111,17 +1190,18 @@ } }, "node_modules/@fluentui/react-persona": { - "version": "9.2.78", - "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.2.78.tgz", - "integrity": "sha512-pWpyTYtoV7y1vHZv/MMc+h6kbIh9jB69FMXjkNX2uUiEBq0e+RQlkDhivZv58t9y6S8ZqdPZEelJgbH8HfHekw==", - "dependencies": { - "@fluentui/react-avatar": "^9.6.19", - "@fluentui/react-badge": "^9.2.29", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "version": "9.2.92", + "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.2.92.tgz", + "integrity": "sha512-TNbCR0NY4JIM217DZlSZBaCFkbFPzd6KRuVwC9XGLhHhTtA+Wr3J86OgWldtjTAUWcX6eJ94JsW0aYT4exCbYA==", + "license": "MIT", + "dependencies": { + "@fluentui/react-avatar": "^9.6.33", + "@fluentui/react-badge": "^9.2.41", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1132,21 +1212,22 @@ } }, "node_modules/@fluentui/react-popover": { - "version": "9.9.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.9.2.tgz", - "integrity": "sha512-F/7VTPZMVCY/dwqumzrp+wzRNTlsKJ9Gz1nmZPZuO7IMBC8XRIGkjqdjW7oW8SzIrRmOTkAvmsn4UfPL19spiw==", + "version": "9.9.15", + "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.9.15.tgz", + "integrity": "sha512-9KVRpKa1IDL6RGOJF7CYZvC+ayhye65fTshRYz17kiSXPHX3oshrPS+TwsrQq6ENmOuoirVva7AA6AqyooDrjQ==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-portal": "^9.4.18", - "@fluentui/react-positioning": "^9.14.2", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-portal": "^9.4.31", + "@fluentui/react-positioning": "^9.15.6", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1157,14 +1238,15 @@ } }, "node_modules/@fluentui/react-portal": { - "version": "9.4.18", - "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.4.18.tgz", - "integrity": "sha512-ShWpbZ2vjA/8yrk34e2n8+B+w034reYaxxfSq9N8csNsMbTInKdn44wTPp1ikcuqzZFJlkVFW4+LbKeQ/DvtZQ==", + "version": "9.4.31", + "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.4.31.tgz", + "integrity": "sha512-c/mrsn29MvBIxkyYrIAdI9E9JCMicF7mCxpWFbQQZMYKdu4/qLCtkmQfvQKEI9WFQzLS8IzTRM+NajNewUi/nA==", + "license": "MIT", "dependencies": { - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1", "use-disposable": "^1.0.1" }, @@ -1176,9 +1258,10 @@ } }, "node_modules/@fluentui/react-portal-compat-context": { - "version": "9.0.11", - "resolved": "https://registry.npmjs.org/@fluentui/react-portal-compat-context/-/react-portal-compat-context-9.0.11.tgz", - "integrity": "sha512-ubvW/ej0O+Pago9GH3mPaxzUgsNnBoqvghNamWjyKvZIViyaXUG6+sgcAl721R+qGAFac+A20akI5qDJz/xtdg==", + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/@fluentui/react-portal-compat-context/-/react-portal-compat-context-9.0.12.tgz", + "integrity": "sha512-5AVXWX9GnbvwnJZYUb4LSIF7BsI/N8oTI6+7Yn0w6B3yaWykA8Menlz757X5tgVBjouEj4Eom+AoVvA7u8gPDA==", + "license": "MIT", "dependencies": { "@swc/helpers": "^0.5.1" }, @@ -1188,16 +1271,17 @@ } }, "node_modules/@fluentui/react-positioning": { - "version": "9.14.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.14.2.tgz", - "integrity": "sha512-m0buzn3UI7j2WjCGL83YwC064Xe9N/dQJ8aSwhv/xXBgQkxHnHYAs3hLG4Tjb/tliEOobntFlSI7O1NYKiDrFw==", + "version": "9.15.6", + "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.15.6.tgz", + "integrity": "sha512-733OgnMAJt9OQ7yvjsshNR+mWtQE7+236HM6gf1SSL8D9j1W481b+jxnXbo6qiPDkAn1Me5wdGZoJmEN5jFO1w==", + "license": "MIT", "dependencies": { "@floating-ui/devtools": "0.2.1", "@floating-ui/dom": "^1.2.0", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1208,16 +1292,17 @@ } }, "node_modules/@fluentui/react-progress": { - "version": "9.1.69", - "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.1.69.tgz", - "integrity": "sha512-aoo9hAFPafO0by5Ibv9EaFyDZZSBH1Gy3udU3lKAJMTrny5kgzXhOnITvwUhM8Za1G2M5rX/y62ujcYAsQgLdw==", + "version": "9.1.82", + "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.1.82.tgz", + "integrity": "sha512-r4aZ57rEoReNZoIDG65OvXVk5/19HZGLFghBQ6J8ytLLnIYwqhOueUyv2HEcRXpK16ayhN37GpQE7eBLnMLGGg==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1228,18 +1313,19 @@ } }, "node_modules/@fluentui/react-provider": { - "version": "9.13.16", - "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.13.16.tgz", - "integrity": "sha512-LHiy/4wefxgx+dneWLCrvTgC3qP2kHm7M1tnx2jXKZsBwpXMhAWqxBN3xs1y+u0fyI3RqhJpJAOmKLtmHW2/Og==", - "dependencies": { - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.17.0.tgz", + "integrity": "sha512-z2nKk8MEDmDivxhcySLhD4xuEuSJgXjO14SjMcLnerAimm3Wftgoayga23cvwGgLmoeqAjG7ykEgLEfAzRDk7A==", + "license": "MIT", + "dependencies": { + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/core": "^1.14.1", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/core": "^1.16.0", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1250,18 +1336,19 @@ } }, "node_modules/@fluentui/react-radio": { - "version": "9.2.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.2.13.tgz", - "integrity": "sha512-tK26OntGs3FiUoMxCt4tnCf17am74KGXolRIDUDiyZKLICQq0xDlfokupCU9qGl59OUgMJGa/ZK4hijxZN3pyA==", - "dependencies": { - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-label": "^9.1.66", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.2.27", + "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.2.27.tgz", + "integrity": "sha512-CNGloT6Jc11I8fMpn9pqTgpN2gImgNuNY5YulOUQZ8Z4afT1P0YCWDTY6kRIUo3LFH4x4A1YsN3O05Sn2dImcA==", + "license": "MIT", + "dependencies": { + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-label": "^9.1.74", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1272,37 +1359,60 @@ } }, "node_modules/@fluentui/react-rating": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-rating/-/react-rating-9.0.1.tgz", - "integrity": "sha512-YNAv95ZnvJPI9Vt7OVmYfEqib4ijqVlXEz/cdVKwQG9s2Qek7jQwrH5lwQ0lFduLfli6Vu5ukxFPettMPp/mLQ==", + "version": "9.0.15", + "resolved": "https://registry.npmjs.org/@fluentui/react-rating/-/react-rating-9.0.15.tgz", + "integrity": "sha512-fa8rDyvxQplqL234IMThWRVfVj3U7y3LiJcjliZ1YrTNkTVRg/w7LK010625Ased2IOBIWS4YLP1UFBFdxIflw==", + "license": "MIT", "dependencies": { - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { "@types/react": ">=16.8.0 <19.0.0", "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", "react-dom": ">=16.8.0 <19.0.0" } }, + "node_modules/@fluentui/react-search": { + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/@fluentui/react-search/-/react-search-9.0.12.tgz", + "integrity": "sha512-63Yxkx0JeQ8ueSr37tc/OA+yYQFPQHAoVmvJyqhYngRLJUzuGT3ErvM6WjBtZjQ49ErRXjmwJw9Rcf3HowUZCg==", + "license": "MIT", + "dependencies": { + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-input": "^9.4.83", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-theme": "^9.1.19", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, "node_modules/@fluentui/react-select": { - "version": "9.1.69", - "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.1.69.tgz", - "integrity": "sha512-Ypmq0Ge6nlx2FmVaB1IKlWCjkTsaIAiLlKHoyjQg/QNvcE/RUA02ErSY4iliy7UOrIqZf2hX2tTh0lbDKb0Ufg==", - "dependencies": { - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "version": "9.1.82", + "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.1.82.tgz", + "integrity": "sha512-anu9A918H13HRRFdnmWk2XrjiVkefreUKsY5gA07qK94TJRH/drw1GPCOX5fOkQF60J7fqZShyNVTqE4fJ+9pQ==", + "license": "MIT", + "dependencies": { + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1313,9 +1423,10 @@ } }, "node_modules/@fluentui/react-shared-contexts": { - "version": "9.15.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-shared-contexts/-/react-shared-contexts-9.15.2.tgz", - "integrity": "sha512-0KEYEYGP4pjMrxZ5EytYqkUe56+tlr46ltxyKdcPcbfN+ptPffC9cevAR+4VIcb4xgmW+c7JT6nxDr5Rd5pvcw==", + "version": "9.20.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-shared-contexts/-/react-shared-contexts-9.20.0.tgz", + "integrity": "sha512-LOMgP51dC/dOQOopEhvRk9V/GlpkStMbXTsci+2raG+Zno3eIdS3TesWCango+r5rpBFCIZl4HOpGEErHGm03Q==", + "license": "MIT", "dependencies": { "@fluentui/react-theme": "^9.1.19", "@swc/helpers": "^0.5.1" @@ -1326,16 +1437,17 @@ } }, "node_modules/@fluentui/react-skeleton": { - "version": "9.0.57", - "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.0.57.tgz", - "integrity": "sha512-YBJBFX/RX4GBeMdP3jXzid50tFC+PSdfoBiwVTeSuZzjxxhLrUQpyFErhkZrnE+W53G70/7KbZpRqbOCVjW7YQ==", + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.1.10.tgz", + "integrity": "sha512-W0OkdaS7+5NkK32WTTP1sbBWu+NBL343YYU0R52LHfXBMJXlhJ/pNIcfIPrBSij6szmMiRZrPzYGtDzFx/S4qA==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1346,17 +1458,18 @@ } }, "node_modules/@fluentui/react-slider": { - "version": "9.1.75", - "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.1.75.tgz", - "integrity": "sha512-mLwPOFhsO2bgZZCSdBUXCd30fWp9bHvROZaiTrn+kslY2bqHAQQfWox4YTNoAQrWl0SBYY8UHca8YTcCWmMtXA==", - "dependencies": { - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.1.89", + "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.1.89.tgz", + "integrity": "sha512-cKCGAGVbKK6hYIQKfnveQehfCEr75gKPUSP9B7HdQX8CLiPUgUSrwXGouSYgJSLcpD3BN7boLj7DUfs3mhxMqQ==", + "license": "MIT", + "dependencies": { + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1367,18 +1480,19 @@ } }, "node_modules/@fluentui/react-spinbutton": { - "version": "9.2.69", - "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.2.69.tgz", - "integrity": "sha512-/KGoIEuVQmA/4groKY57rgBk+k2er3N7e/FljD6S2HzCW5WhBIkE4icYz0kJuA42c9bfYBd2phdkt2/6KlZCFw==", + "version": "9.2.83", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.2.83.tgz", + "integrity": "sha512-wWdggoxT0nUnbE8PqnUojnH0OznnkUvHHINwE0l3II8EDz0YXTPBZMoaRfB84+FykdDAfyNm2BWa+uEtRH47ZA==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1389,16 +1503,17 @@ } }, "node_modules/@fluentui/react-spinner": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.4.2.tgz", - "integrity": "sha512-fdxB+6FNM1qWNuzAEBGpF+u8esW7KyuVYujdVlIN/7uKRbwWe8sp4UMe7aHuvRtYleG9i1pMYnO3nwmrXYA6IQ==", + "version": "9.4.12", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.4.12.tgz", + "integrity": "sha512-pcIxhJtM0SFqDqL7/FUm9h2AbKn9D7WLjwXfE0Umx8T9cp8H/D1VgL9whCGqnvwa2BX2xWTmPbSz6QVRdwL7Jw==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-label": "^9.1.66", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-label": "^9.1.74", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1408,20 +1523,44 @@ "react-dom": ">=16.14.0 <19.0.0" } }, + "node_modules/@fluentui/react-swatch-picker": { + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@fluentui/react-swatch-picker/-/react-swatch-picker-9.1.6.tgz", + "integrity": "sha512-vLpmM2ENFPs+4qemjswfO5gEveUFIqSS/Gu1z7FiBbp/tUNS13rXYQBiUPFCS8xEsQG4gNcozBs9Lejdyean4g==", + "license": "MIT", + "dependencies": { + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", + "@fluentui/react-theme": "^9.1.19", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "@types/react-dom": ">=16.8.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.8.0 <19.0.0" + } + }, "node_modules/@fluentui/react-switch": { - "version": "9.1.75", - "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.1.75.tgz", - "integrity": "sha512-tK6SD6mCYHgXtnxFW64kkmMqD9jIdnk49g34E/OMyXi4DLezDv+PFmYaiFXeV6ASoz5OZlt/3J3w7zRC0RhBog==", - "dependencies": { - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-label": "^9.1.66", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.1.89", + "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.1.89.tgz", + "integrity": "sha512-9gYOhubFq5+4c2bnD6VJGfRCwl9X5RFp3AXztfrYELRTgwSsIeCAoa6VM3bu9nUi3V60GHCNHk38j8lVwDgy/w==", + "license": "MIT", + "dependencies": { + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-label": "^9.1.74", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1432,23 +1571,24 @@ } }, "node_modules/@fluentui/react-table": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.12.0.tgz", - "integrity": "sha512-8qvN2hrYYtVXkVrB5+DMWNTIJogzWr0KUkFuvUZ9f1ylmvR8NcRQpxlU5q0yLaNKecmTLDoADWYF6Ldoyt5e2Q==", + "version": "9.15.11", + "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.15.11.tgz", + "integrity": "sha512-6eK8v22lbZpMnBPVEwf7qaaueSrrVcLSMs9U4f3nNGo2pJVOnOcg9Vhvom/GL2D8FItpOOcTwxT7Asg/FGRIIA==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-avatar": "^9.6.19", - "@fluentui/react-checkbox": "^9.2.18", - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-radio": "^9.2.13", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-avatar": "^9.6.33", + "@fluentui/react-checkbox": "^9.2.32", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-radio": "^9.2.27", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1459,17 +1599,18 @@ } }, "node_modules/@fluentui/react-tabs": { - "version": "9.4.14", - "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.4.14.tgz", - "integrity": "sha512-hXcgzQCnmHym5ERlitE1gWU974TT644034FUXoc4x4EoduLQ1FEebHRFZKajGeR+/gGHvBXXnbvdw6dNZwwJkw==", - "dependencies": { - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.4.27", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.4.27.tgz", + "integrity": "sha512-aJmaTqXz77neyJpgffdKi9gpLtGQjRZcVcvhR/Ft0ZMC+u8XGkTlrtF0ntZZcnPwzeZ7P2qjMMrdvIyDsaSxMg==", + "license": "MIT", + "dependencies": { + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1480,17 +1621,48 @@ } }, "node_modules/@fluentui/react-tabster": { - "version": "9.19.5", - "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.19.5.tgz", - "integrity": "sha512-bazFB5naT7/I8Q1+cRNvGhhlCQlWvLmCUpj+7tgMrfdX0ghRNI+adygsqKFx1oKkRm5ZBgsVFyk3M6AuDGoAQw==", + "version": "9.22.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.22.3.tgz", + "integrity": "sha512-z/icX1sMTHVXJxq2tlNKGM9A9J7RYLgu03vVh+0z4N+Q4k5Oe0HvKFNyi447+R5UEHbWebMEpabbTIox3DuLQw==", + "license": "MIT", "dependencies": { - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1", - "keyborg": "^2.5.0", - "tabster": "^6.0.1" + "keyborg": "^2.6.0", + "tabster": "^8.0.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-tag-picker": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-tag-picker/-/react-tag-picker-9.2.3.tgz", + "integrity": "sha512-5VvdPcFUY1PrvlLFDCfx1oOiwViukZiI9fQDeX2606wj3g+1lFmzao+8DLxjQ/jX9rEiLFrCrF0RIg+xcjRtxA==", + "license": "MIT", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-combobox": "^9.13.2", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-portal": "^9.4.31", + "@fluentui/react-positioning": "^9.15.6", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", + "@fluentui/react-tags": "^9.3.12", + "@fluentui/react-theme": "^9.1.19", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { "@types/react": ">=16.14.0 <19.0.0", @@ -1500,20 +1672,21 @@ } }, "node_modules/@fluentui/react-tags": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-tags/-/react-tags-9.2.0.tgz", - "integrity": "sha512-eM5EQHeyCX+CI/mWQRIOE7U8t1L6eb77Ed2P90O+eP4rrk79HcZcsoUrPm8UcveYVGC4ebhLpF4k+qyDii27BQ==", + "version": "9.3.12", + "resolved": "https://registry.npmjs.org/@fluentui/react-tags/-/react-tags-9.3.12.tgz", + "integrity": "sha512-Qm77lq/lWoG0g7bOPZcvjJfyjqezI+uUTAYo1+5mugIhZ+7AyBzgsnCdrmdwn1yFgsSlNNes1+A78V/jHdUE0w==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-avatar": "^9.6.19", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-avatar": "^9.6.33", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1523,16 +1696,44 @@ "react-dom": ">=16.14.0 <19.0.0" } }, + "node_modules/@fluentui/react-teaching-popover": { + "version": "9.1.11", + "resolved": "https://registry.npmjs.org/@fluentui/react-teaching-popover/-/react-teaching-popover-9.1.11.tgz", + "integrity": "sha512-qjA764EpNLHgYg41KplqDpKc4OuA0zsEZmomO256Q5MdLpaj6A5tPcpWb/cHb3XsdKHoOysbW4V3Fd9Gn1XBIQ==", + "license": "MIT", + "dependencies": { + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-button": "^9.3.87", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-popover": "^9.9.15", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", + "@fluentui/react-theme": "^9.1.19", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", + "@swc/helpers": "^0.5.1", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "@types/react-dom": ">=16.8.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.8.0 <19.0.0" + } + }, "node_modules/@fluentui/react-text": { - "version": "9.4.14", - "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.4.14.tgz", - "integrity": "sha512-QoWtBYene1NhoDc8ZpZaS5t4CrgbXBrN8UsTNXJY2qVgLKctqx3nEP0ZNc9y3/oGOp1bSQ1rIY2SpVv9voMEaA==", + "version": "9.4.23", + "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.4.23.tgz", + "integrity": "sha512-ZQu7yBSULDIbCOvP9B1ViK4BFSb2T6VaWUbv5qfUEV4g24b812EspTYNdoicx7SqdaDt1tSdpy1wFl6QViC5/Q==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1543,16 +1744,17 @@ } }, "node_modules/@fluentui/react-textarea": { - "version": "9.3.69", - "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.3.69.tgz", - "integrity": "sha512-vBxYEDrmjUTlagPsLSqu8PSoCIyuoEn55TtpjVdQdueXeKv8o7Mx7zdkykHP82GJYHfRV7IPIqloEyn+b+ChWA==", + "version": "9.3.83", + "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.3.83.tgz", + "integrity": "sha512-Oiy5Ahkx44Gpm3g0rch1YyskW7xejiF5gWNR0LgoNJVSFeOS5eHz6GdHOva710IOGVQf71408uFZLancXxFz0A==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.59", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-field": "^9.1.71", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1572,22 +1774,23 @@ } }, "node_modules/@fluentui/react-toast": { - "version": "9.3.35", - "resolved": "https://registry.npmjs.org/@fluentui/react-toast/-/react-toast-9.3.35.tgz", - "integrity": "sha512-eBu3ixzcyvRhyLgtWxiYuCWKkeYUZpWqZkRY5m83rJFu+A4yXBpVrCQ/XYdeBe8GuhvxTK7U9AdvMvcY1EBTBg==", + "version": "9.3.51", + "resolved": "https://registry.npmjs.org/@fluentui/react-toast/-/react-toast-9.3.51.tgz", + "integrity": "sha512-msbIdN1x4XlifDDxaoV54aQ+dCjIVH7l9J37mG98ySrjP1F+QpDcaZ87xPb0Cpfg/oUkdvsK6FCeCl6HrWIGWA==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-portal": "^9.4.18", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-motion": "^9.4.0", + "@fluentui/react-portal": "^9.4.31", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", - "@swc/helpers": "^0.5.1", - "react-transition-group": "^4.4.1" + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { "@types/react": ">=16.14.0 <19.0.0", @@ -1597,20 +1800,21 @@ } }, "node_modules/@fluentui/react-toolbar": { - "version": "9.1.76", - "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.1.76.tgz", - "integrity": "sha512-Va0VCe5u1Y+jaf5c0I2YFCImiQLKpG/caEUu10vGmnKqHkeXUIC4o0rbj7IptmiOX7LPbzb/u8BtwFImKHHJJA==", - "dependencies": { - "@fluentui/react-button": "^9.3.73", - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-divider": "^9.2.65", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-radio": "^9.2.13", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "version": "9.1.90", + "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.1.90.tgz", + "integrity": "sha512-nN/18X/ef2uwJ6uDQOq1yv71RGuwOXUVXZHcMdp7OuePqb9G33S9p1s4dp8TFeBO2yzNOB3kh1hNswVVQ4PyFw==", + "license": "MIT", + "dependencies": { + "@fluentui/react-button": "^9.3.87", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-divider": "^9.2.73", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-radio": "^9.2.27", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1621,19 +1825,20 @@ } }, "node_modules/@fluentui/react-tooltip": { - "version": "9.4.21", - "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.4.21.tgz", - "integrity": "sha512-zGfhuOKDmmfFj9hssKAy00xGYzbxUZDQc4s8tNzP3NPRehuMPSY1ZaPIut3Gvrqn+i8kkKTxXsQBFBz3Qvzq6A==", + "version": "9.4.34", + "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.4.34.tgz", + "integrity": "sha512-mwyuCEiFrVGmyU/W/U2VVGT9i9uKKQMXNoy1NDGjARs7gzxXRvsFr0xME+7PhA8gyvK393rDn9d5aK3XqmuDVA==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-portal": "^9.4.18", - "@fluentui/react-positioning": "^9.14.2", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-portal": "^9.4.31", + "@fluentui/react-positioning": "^9.15.6", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1644,24 +1849,25 @@ } }, "node_modules/@fluentui/react-tree": { - "version": "9.4.36", - "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.4.36.tgz", - "integrity": "sha512-FEv4wG7lOrHDC3l6SFQDzwEz1rnPPeKlL4VR+/kP+R6clKdd2AjE1yeGfrM6j/Ax2iitilMoyqQaZKE/MZBUnQ==", + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.7.5.tgz", + "integrity": "sha512-RShNuaSJPKIUPtX7SQ0VXJgWTcSOMjrZQMUQDibqK+YoV1xQbtgs0k3ykU1OeqtwUAdOWjywqwtism4jFlZENg==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-aria": "^9.10.2", - "@fluentui/react-avatar": "^9.6.19", - "@fluentui/react-button": "^9.3.73", - "@fluentui/react-checkbox": "^9.2.18", - "@fluentui/react-context-selector": "^9.1.56", - "@fluentui/react-icons": "^2.0.224", - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-radio": "^9.2.13", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-tabster": "^9.19.5", + "@fluentui/react-aria": "^9.13.2", + "@fluentui/react-avatar": "^9.6.33", + "@fluentui/react-button": "^9.3.87", + "@fluentui/react-checkbox": "^9.2.32", + "@fluentui/react-context-selector": "^9.1.65", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-radio": "^9.2.27", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-tabster": "^9.22.3", "@fluentui/react-theme": "^9.1.19", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1672,12 +1878,13 @@ } }, "node_modules/@fluentui/react-utilities": { - "version": "9.18.5", - "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.18.5.tgz", - "integrity": "sha512-Q3WwuHY2YzZSOEg9KlwVKYUzYiWDAiyuuQHE4qZevoiNn2ly2gXgfbVUc27LPdWAOTLT9HjdddsdoaJuJ/S5Mw==", + "version": "9.18.13", + "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.18.13.tgz", + "integrity": "sha512-Qk9rL5tZI+az77+S2WKwLWu+WOSZZJSIthxp/ImjuiR6CS+LMrVdl0UC8lHpq03QU7hPgNxbbo0cVnCFazU3Lg==", + "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.7", - "@fluentui/react-shared-contexts": "^9.15.2", + "@fluentui/react-shared-contexts": "^9.20.0", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1686,14 +1893,15 @@ } }, "node_modules/@fluentui/react-virtualizer": { - "version": "9.0.0-alpha.73", - "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.73.tgz", - "integrity": "sha512-owoCcxzinQFZE4161c4V7rWn8PZR1eeO/2jg3taAUUa7nnyFti6u1wxv2fcRNNtn+hjWcaBtc6bOLVHsEZwoZg==", + "version": "9.0.0-alpha.82", + "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.82.tgz", + "integrity": "sha512-XvkDXua8Tn9If02RhLPzFMR7CivAZ+frCajQFKaWZjE7OJqYsJ+hKb5ZGz7SWdOPtFq6uxe3H96vG1aDcA0n+w==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.0.34", - "@fluentui/react-shared-contexts": "^9.15.2", - "@fluentui/react-utilities": "^9.18.5", - "@griffel/react": "^1.5.14", + "@fluentui/react-jsx-runtime": "^9.0.42", + "@fluentui/react-shared-contexts": "^9.20.0", + "@fluentui/react-utilities": "^9.18.13", + "@griffel/react": "^1.5.22", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1704,11 +1912,12 @@ } }, "node_modules/@fluentui/react-window-provider": { - "version": "2.2.18", - "resolved": "https://registry.npmjs.org/@fluentui/react-window-provider/-/react-window-provider-2.2.18.tgz", - "integrity": "sha512-nBKqxd0P8NmIR0qzFvka1urE2LVbUm6cse1I1T7TcOVNYa5jDf5BrO06+JRZfwbn00IJqOnIVoP0qONqceypWQ==", + "version": "2.2.27", + "resolved": "https://registry.npmjs.org/@fluentui/react-window-provider/-/react-window-provider-2.2.27.tgz", + "integrity": "sha512-Dg0G9bizjryV0Q/r0CPtCVTPa2II/EsT9E6JT3jPSALjQADDLlW4/+ZXbcEC7geZ/40+KpZDmhplvk/AJSFBKg==", + "license": "MIT", "dependencies": { - "@fluentui/set-version": "^8.2.14", + "@fluentui/set-version": "^8.2.23", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1717,34 +1926,37 @@ } }, "node_modules/@fluentui/set-version": { - "version": "8.2.14", - "resolved": "https://registry.npmjs.org/@fluentui/set-version/-/set-version-8.2.14.tgz", - "integrity": "sha512-f/QWJnSeyfAjGAqq57yjMb6a5ejPlwfzdExPmzFBuEOuupi8hHbV8Yno12XJcTW4I0KXEQGw+PUaM1aOf/j7jw==", + "version": "8.2.23", + "resolved": "https://registry.npmjs.org/@fluentui/set-version/-/set-version-8.2.23.tgz", + "integrity": "sha512-VPXaBsiaa3Xn/AY40nLU9bvDQ62lpMVnFzFTlQ8CbpdwrjxNlRxDUY5vRToNzp1+Zu5gD/+CgsXqIZGcry5L5w==", + "license": "MIT", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@fluentui/style-utilities": { - "version": "8.10.5", - "resolved": "https://registry.npmjs.org/@fluentui/style-utilities/-/style-utilities-8.10.5.tgz", - "integrity": "sha512-pATlzdNhkFghbjPqybq2vrIHnJZ6/bIoVk6tekMVucVedpfLr+TC/2EcRYhRSLyCOjE3qYPhFMZKe850FGDFqA==", - "dependencies": { - "@fluentui/merge-styles": "^8.6.0", - "@fluentui/set-version": "^8.2.14", - "@fluentui/theme": "^2.6.43", - "@fluentui/utilities": "^8.15.0", + "version": "8.10.18", + "resolved": "https://registry.npmjs.org/@fluentui/style-utilities/-/style-utilities-8.10.18.tgz", + "integrity": "sha512-nsXc6LI/UaPrJUh71WIqR19+mmfPl0b4qhaBUOzBGznGKU8jKlHT94pJbAIhWIjytdS8Zk8qtgStI+oYMxz9xg==", + "license": "MIT", + "dependencies": { + "@fluentui/merge-styles": "^8.6.12", + "@fluentui/set-version": "^8.2.23", + "@fluentui/theme": "^2.6.56", + "@fluentui/utilities": "^8.15.13", "@microsoft/load-themed-styles": "^1.10.26", "tslib": "^2.1.0" } }, "node_modules/@fluentui/theme": { - "version": "2.6.43", - "resolved": "https://registry.npmjs.org/@fluentui/theme/-/theme-2.6.43.tgz", - "integrity": "sha512-Z5M0L0xRASWBt13Uj4LiazMKxsWGdno2KeK5Rh+xrSYjAUIXxrJz5Y+VGmpObNsDemyfaYG2TGnTg/b0DDEXtQ==", + "version": "2.6.56", + "resolved": "https://registry.npmjs.org/@fluentui/theme/-/theme-2.6.56.tgz", + "integrity": "sha512-uUDfZpye7e+oXpmP0DOboBYKlyAxbLamnVdWs1a7l6fWEqTNfwDPIPZpMkdDmIBTjE6Q9eHP1u1PmQpMSlz0wA==", + "license": "MIT", "dependencies": { - "@fluentui/merge-styles": "^8.6.0", - "@fluentui/set-version": "^8.2.14", - "@fluentui/utilities": "^8.15.0", + "@fluentui/merge-styles": "^8.6.12", + "@fluentui/set-version": "^8.2.23", + "@fluentui/utilities": "^8.15.13", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1761,13 +1973,15 @@ } }, "node_modules/@fluentui/utilities": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@fluentui/utilities/-/utilities-8.15.0.tgz", - "integrity": "sha512-fj5/LBpt4JPQwx8OZPhHFPHYeCM+a1nnSSpPnVKj2cCZ3o3MoCenw23tgTGdQM5A+i9MKNTE8OuSfMcnTGlA0w==", + "version": "8.15.13", + "resolved": "https://registry.npmjs.org/@fluentui/utilities/-/utilities-8.15.13.tgz", + "integrity": "sha512-DrPv5baKHYtwB+OFqtGiOucdHFbqbnW7TSyxigADYkZQzJj1lnw5DoEGsVyMMVacD4vR21L3JfkMmfrhWm6hyw==", + "license": "MIT", "dependencies": { - "@fluentui/dom-utilities": "^2.2.14", - "@fluentui/merge-styles": "^8.6.0", - "@fluentui/set-version": "^8.2.14", + "@fluentui/dom-utilities": "^2.3.7", + "@fluentui/merge-styles": "^8.6.12", + "@fluentui/react-window-provider": "^2.2.27", + "@fluentui/set-version": "^8.2.23", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1776,24 +1990,26 @@ } }, "node_modules/@griffel/core": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.15.0.tgz", - "integrity": "sha512-+2Li2x6zqQdVBSMbvGSJRxbMbOrXhCEEzX0BK6OMfjdMPJLoR2aaHuAwHL3J9dOpHzFrjp9MMEo4Jzwfo4l6Xw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.17.1.tgz", + "integrity": "sha512-K3osVOktJ5nioY62idtkjLiIdVcazMwraNxkUMhLtoapDthnKVSC3+gYTuPCBZMdfLH5Hl5Y29YUClRlDjyb7g==", + "license": "MIT", "dependencies": { "@emotion/hash": "^0.9.0", - "@griffel/style-types": "^1.0.2", - "csstype": "^3.1.2", + "@griffel/style-types": "^1.2.0", + "csstype": "^3.1.3", "rtl-css-js": "^1.16.1", "stylis": "^4.2.0", "tslib": "^2.1.0" } }, "node_modules/@griffel/react": { - "version": "1.5.18", - "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.18.tgz", - "integrity": "sha512-Y5L2zvfE+quMPSQPtViMmuDXNCIyJaeeQc5m30VMELgXYN0uk4nbFqwKYXG0FmnHkEHy5MhiGy7q4zCR2+ubTg==", + "version": "1.5.24", + "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.24.tgz", + "integrity": "sha512-WDxWyg182kL/aFCViybARAm/ZFVZoJDiW52pguveZx6cJvvc51esZ2qYJhsbMoy8cqOfnfOrWhOibdb89kgXAQ==", + "license": "MIT", "dependencies": { - "@griffel/core": "^1.15.0", + "@griffel/core": "^1.17.1", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1801,11 +2017,12 @@ } }, "node_modules/@griffel/style-types": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.0.2.tgz", - "integrity": "sha512-ka/Tpl1WU8js88LObwB/4EvpgXzx/EEJfbHhAr4ZNt29hrQKgL93X1zSY6M/FRhMhWrGIawauWkZP6/y6w/WiQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.2.0.tgz", + "integrity": "sha512-x166MNw0vWe5l5qhinfNT4eyWOaP48iFzPyFOfIB0/BVidKTWsEe5PmqRJDDtrJFS3VHhd/tE0oM6tkEMh2tsg==", + "license": "MIT", "dependencies": { - "csstype": "^3.1.2" + "csstype": "^3.1.3" } }, "node_modules/@hpcc-js/api": { @@ -1862,13 +2079,12 @@ } }, "node_modules/@hpcc-js/comms": { - "version": "2.93.0", - "resolved": "https://registry.npmjs.org/@hpcc-js/comms/-/comms-2.93.0.tgz", - "integrity": "sha512-FZBiLiraUFGoSnYB6PUv5zMIHcDbdT2TOzRjHl8CF84UK9C9G6G5L19mYwvVOWKTeuSvwaOyOqeOZ6ELcQObrA==", - "license": "Apache-2.0", + "version": "2.94.0", + "resolved": "https://registry.npmjs.org/@hpcc-js/comms/-/comms-2.94.0.tgz", + "integrity": "sha512-+AfJsqj648638hTUeLYd0Thvu1QMHX9zLflrep2xVtz7Wo1OmOiI/mrjClMqK8A8drMa3AduKuQS1R2rL15wZw==", "dependencies": { - "@hpcc-js/ddl-shim": "^2.20.7", - "@hpcc-js/util": "^2.51.1", + "@hpcc-js/ddl-shim": "^2.21.0", + "@hpcc-js/util": "^2.52.0", "@xmldom/xmldom": "0.8.10", "abort-controller": "3.0.0", "node-fetch": "2.7.0", @@ -1877,6 +2093,14 @@ "undici": "5.28.4" } }, + "node_modules/@hpcc-js/comms/node_modules/@hpcc-js/util": { + "version": "2.52.0", + "resolved": "https://registry.npmjs.org/@hpcc-js/util/-/util-2.52.0.tgz", + "integrity": "sha512-WHm/0ApEdWktpPCUG+AFuMnnrDHOTqKXK2oVgyRUAAQJhSWMFxTJxbqIQG7SM9myK58tXzNJrKsP8huzt8X2dg==", + "dependencies": { + "tslib": "2.6.3" + } + }, "node_modules/@hpcc-js/comms/node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1896,6 +2120,11 @@ } ] }, + "node_modules/@hpcc-js/comms/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, "node_modules/@hpcc-js/dataflow": { "version": "8.1.7", "resolved": "https://registry.npmjs.org/@hpcc-js/dataflow/-/dataflow-8.1.7.tgz", @@ -1903,9 +2132,9 @@ "license": "Apache-2.0" }, "node_modules/@hpcc-js/ddl-shim": { - "version": "2.20.7", - "resolved": "https://registry.npmjs.org/@hpcc-js/ddl-shim/-/ddl-shim-2.20.7.tgz", - "integrity": "sha512-n+MQBW9zgfhN6zCTaZSiZfMAJfhR6bw4Fuo4fMhQdF2x17Yu/DbN8MReNvyq2OOBmxkwcp28/VxYnsJeppWMQw==", + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@hpcc-js/ddl-shim/-/ddl-shim-2.21.0.tgz", + "integrity": "sha512-Q66GJqvmTNysmgj/Du8/6+1xIhKgylNu8XVbx1ovNLcLoCxJIhtfWBhCYx0aY2aFHN+QnjC0BGXWyn3xCyxpnw==", "hasInstallScript": true, "dependencies": { "ajv": "6.12.6" @@ -4931,9 +5160,10 @@ } }, "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" }, "node_modules/current-module-paths": { "version": "1.1.1", @@ -5251,6 +5481,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" @@ -7486,9 +7717,10 @@ } }, "node_modules/keyborg": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.5.0.tgz", - "integrity": "sha512-nb4Ji1suqWqj6VXb61Jrs4ab/UWgtGph4wDch2NIZDfLBUObmLcZE0aiDjZY49ghtu03fvwxDNvS9ZB0XMz6/g==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.6.0.tgz", + "integrity": "sha512-o5kvLbuTF+o326CMVYpjlaykxqYP9DphFQZ2ZpgrvBouyvOxyEB7oqe8nOLFpiV5VCtz0D3pt8gXQYWpLpBnmA==", + "license": "MIT" }, "node_modules/keygrip": { "version": "1.1.0", @@ -8308,12 +8540,13 @@ } }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, "license": "ISC", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minizlib": { @@ -9575,6 +9808,7 @@ "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -9931,20 +10165,11 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/rtl-css-js": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.1.2" } @@ -10878,9 +11103,10 @@ } }, "node_modules/stylis": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", - "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==", + "license": "MIT" }, "node_modules/supports-color": { "version": "7.2.0", @@ -10940,11 +11166,12 @@ } }, "node_modules/tabster": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tabster/-/tabster-6.1.0.tgz", - "integrity": "sha512-wTPy2d6WVmU/YjT0ERY9jc+et1P/B8FoSQ4qhr1xi7liwTezRbRV6yA1pKx8kdPWmLdIOBA4fn07x9c0x/wnow==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/tabster/-/tabster-8.0.1.tgz", + "integrity": "sha512-Df8La4+IkdbHjupybEDv4rCPSOwx8L3Xh7UVbl0tzyrkiVTKvZg3IRID6KHd/tXbyerO4cXwhY9aOQ+mbEP04w==", + "license": "MIT", "dependencies": { - "keyborg": "2.5.0", + "keyborg": "2.6.0", "tslib": "^2.3.1" } }, @@ -10974,6 +11201,15 @@ "node": ">=10" } }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/terser": { "version": "5.27.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz", @@ -11416,6 +11652,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/use-disposable/-/use-disposable-1.0.2.tgz", "integrity": "sha512-UMaXVlV77dWOu4GqAFNjRzHzowYKUKbJBQfCexvahrYeIz4OkUYUjna4Tjjdf92NH8Nm8J7wEfFRgTIwYjO5jg==", + "license": "MIT", "peerDependencies": { "@types/react": ">=16.8.0 <19.0.0", "@types/react-dom": ">=16.8.0 <19.0.0", @@ -11423,6 +11660,15 @@ "react-dom": ">=16.8.0 <19.0.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/esp/src/package.json b/esp/src/package.json index bd8daf99417..a30728c2cf2 100644 --- a/esp/src/package.json +++ b/esp/src/package.json @@ -35,16 +35,16 @@ }, "main": "src/stub.js", "dependencies": { - "@fluentui/react": "8.117.0", - "@fluentui/react-components": "9.47.2", - "@fluentui/react-experiments": "8.14.137", - "@fluentui/react-hooks": "8.7.0", - "@fluentui/react-icons-mdl2": "1.3.59", - "@fluentui/react-migration-v8-v9": "9.6.3", + "@fluentui/react": "8.119.3", + "@fluentui/react-components": "9.54.6", + "@fluentui/react-experiments": "8.14.160", + "@fluentui/react-hooks": "8.8.10", + "@fluentui/react-icons-mdl2": "1.3.72", + "@fluentui/react-migration-v8-v9": "9.6.22", "@hpcc-js/chart": "2.83.4", "@hpcc-js/codemirror": "2.62.1", "@hpcc-js/common": "2.71.18", - "@hpcc-js/comms": "2.93.0", + "@hpcc-js/comms": "2.94.0", "@hpcc-js/dataflow": "8.1.7", "@hpcc-js/eclwatch": "2.74.8", "@hpcc-js/graph": "2.85.16", diff --git a/esp/src/src-react/components/EventScheduler.tsx b/esp/src/src-react/components/EventScheduler.tsx index 63b78fcbbcb..2512576b16d 100644 --- a/esp/src/src-react/components/EventScheduler.tsx +++ b/esp/src/src-react/components/EventScheduler.tsx @@ -123,7 +123,7 @@ export const EventScheduler: React.FunctionComponent = ({ const buttons = React.useMemo((): ICommandBarItemProps[] => [ { key: "refresh", text: nlsHPCC.Refresh, iconProps: { iconName: "Refresh" }, - onClick: () => refreshTable.call() + onClick: () => refreshData() }, { key: "divider_1", itemType: ContextualMenuItemType.Divider, onRender: () => }, { @@ -163,7 +163,7 @@ export const EventScheduler: React.FunctionComponent = ({ pushParams(filter); } }, - ], [currentUser, filter, hasFilter, refreshTable, selection, setShowDescheduleConfirm, store, total]); + ], [currentUser.username, filter, hasFilter, refreshData, selection, setShowDescheduleConfirm, store, total]); return } diff --git a/esp/src/src-react/components/IndexFileSummary.tsx b/esp/src/src-react/components/IndexFileSummary.tsx index 54f52605e97..72681e2f6cb 100644 --- a/esp/src/src-react/components/IndexFileSummary.tsx +++ b/esp/src/src-react/components/IndexFileSummary.tsx @@ -64,7 +64,7 @@ export const IndexFileSummary: React.FunctionComponent = React.useEffect(() => { setDescription(file?.Description || ""); - setProtected(file?.ProtectList?.DFUFileProtect?.length > 0 || false); + setProtected(isProtected); setRestricted(file?.IsRestricted || false); if ((file?.filePartsOnCluster() ?? []).length > 0) { @@ -78,7 +78,7 @@ export const IndexFileSummary: React.FunctionComponent = setReplicateFlag(_replicate); } - }, [file]); + }, [file, isProtected]); const canSave = React.useMemo(() => { return file && ( @@ -91,15 +91,11 @@ export const IndexFileSummary: React.FunctionComponent = const buttons = React.useMemo((): ICommandBarItemProps[] => [ { key: "refresh", text: nlsHPCC.Refresh, iconProps: { iconName: "Refresh" }, - onClick: () => { - refresh(); - } + onClick: () => refresh() }, { key: "copyFilename", text: nlsHPCC.CopyLogicalFilename, iconProps: { iconName: "Copy" }, - onClick: () => { - navigator?.clipboard?.writeText(logicalFile); - } + onClick: () => navigator?.clipboard?.writeText(logicalFile) }, { key: "divider_1", itemType: ContextualMenuItemType.Divider, onRender: () => }, { @@ -194,9 +190,15 @@ export const IndexFileSummary: React.FunctionComponent = break; case "isProtected": setProtected(value); + file?.update({ + Protect: value ? WsDfu.DFUChangeProtection.Protect : WsDfu.DFUChangeProtection.Unprotect, + }).catch(err => logger.error(err)); break; case "isRestricted": setRestricted(value); + file?.update({ + Restrict: value ? WsDfu.DFUChangeRestriction.Restrict : WsDfu.DFUChangeRestriction.Unrestricted, + }).catch(err => logger.error(err)); break; } }} /> diff --git a/esp/src/src-react/components/LogicalFileSummary.tsx b/esp/src/src-react/components/LogicalFileSummary.tsx index a2551783357..d412b1c4a28 100644 --- a/esp/src/src-react/components/LogicalFileSummary.tsx +++ b/esp/src/src-react/components/LogicalFileSummary.tsx @@ -69,7 +69,7 @@ export const LogicalFileSummary: React.FunctionComponent { setDescription(file?.Description || ""); - setProtected(file?.ProtectList?.DFUFileProtect?.length > 0 || false); + setProtected(isProtected); setRestricted(file?.IsRestricted || false); if ((file?.filePartsOnCluster() ?? []).length > 0) { @@ -83,7 +83,7 @@ export const LogicalFileSummary: React.FunctionComponent { return file && ( @@ -96,15 +96,11 @@ export const LogicalFileSummary: React.FunctionComponent [ { key: "refresh", text: nlsHPCC.Refresh, iconProps: { iconName: "Refresh" }, - onClick: () => { - refresh(); - } + onClick: () => refresh() }, { key: "copyFilename", text: nlsHPCC.CopyLogicalFilename, iconProps: { iconName: "Copy" }, - onClick: () => { - navigator?.clipboard?.writeText(logicalFile); - } + onClick: () => navigator?.clipboard?.writeText(logicalFile) }, { key: "divider_1", itemType: ContextualMenuItemType.Divider, onRender: () => }, { @@ -216,9 +212,15 @@ export const LogicalFileSummary: React.FunctionComponent logger.error(err)); break; case "isRestricted": setRestricted(value); + file?.update({ + Restrict: value ? WsDfu.DFUChangeRestriction.Restrict : WsDfu.DFUChangeRestriction.Unrestricted, + }).catch(err => logger.error(err)); break; } }} /> diff --git a/esp/src/src-react/components/SuperFileSummary.tsx b/esp/src/src-react/components/SuperFileSummary.tsx index ba5e16172e1..6c063de61e6 100644 --- a/esp/src/src-react/components/SuperFileSummary.tsx +++ b/esp/src/src-react/components/SuperFileSummary.tsx @@ -33,9 +33,9 @@ export const SuperFileSummary: React.FunctionComponent = React.useEffect(() => { setDescription(file?.Description || ""); - setProtected(file?.ProtectList?.DFUFileProtect?.length > 0 || false); + setProtected(isProtected); setRestricted(file?.IsRestricted || false); - }, [file]); + }, [file, isProtected]); const [DeleteConfirm, setShowDeleteConfirm] = useConfirm({ title: nlsHPCC.Delete, @@ -65,9 +65,7 @@ export const SuperFileSummary: React.FunctionComponent = const buttons = React.useMemo((): ICommandBarItemProps[] => [ { key: "refresh", text: nlsHPCC.Refresh, iconProps: { iconName: "Refresh" }, - onClick: () => { - refresh(); - } + onClick: () => refresh() }, { key: "divider_1", itemType: ContextualMenuItemType.Divider, onRender: () => }, { @@ -124,6 +122,9 @@ export const SuperFileSummary: React.FunctionComponent = break; case "isProtected": setProtected(value); + file?.update({ + Protect: value ? WsDfu.DFUChangeProtection.Protect : WsDfu.DFUChangeProtection.Unprotect, + }).catch(err => logger.error(err)); break; } }} /> diff --git a/esp/src/src-react/components/controls/Grid.tsx b/esp/src/src-react/components/controls/Grid.tsx index 634cb318627..f3cdd7a67f1 100644 --- a/esp/src/src-react/components/controls/Grid.tsx +++ b/esp/src/src-react/components/controls/Grid.tsx @@ -1,7 +1,7 @@ import * as React from "react"; -import { DetailsList, DetailsListLayoutMode, Dropdown, IColumn as _IColumn, ICommandBarItemProps, IDetailsHeaderProps, IDetailsListStyles, mergeStyleSets, Selection, Stack, TooltipHost, TooltipOverflowMode, IDetailsList, IRenderFunction, IDetailsRowProps, SelectionMode, ConstrainMode } from "@fluentui/react"; +import { DetailsList, DetailsListLayoutMode, Dropdown, IColumn as _IColumn, ICommandBarItemProps, IDetailsHeaderProps, IDetailsListStyles, mergeStyleSets, Selection, Stack, TooltipHost, TooltipOverflowMode, IRenderFunction, IDetailsRowProps, SelectionMode, ConstrainMode } from "@fluentui/react"; import { Pagination } from "@fluentui/react-experiments/lib/Pagination"; -import { useConst, useId, useMount, useOnEvent } from "@fluentui/react-hooks"; +import { useConst } from "@fluentui/react-hooks"; import { BaseStore, Memory, QueryRequest, QuerySortItem } from "src/store/Memory"; import nlsHPCC from "src/nlsHPCC"; import { createCopyDownloadSelection } from "../Common"; @@ -190,16 +190,6 @@ export function useFluentStoreState({ page }: FluentStoreStateProps): FluentStor return { selection, setSelection, pageNum, setPageNum, pageSize, setPageSize, total, setTotal, refreshTable }; } -interface IListEx { - _scrollElement?: HTMLElement; - _onScroll?: () => void; - _onAsyncScrollDebounced?: () => void; - -} -interface IDetailsListEx extends IDetailsList { - _list?: React.RefObject; -} - interface FluentStoreGridProps { store: any, query?: QueryRequest, @@ -308,30 +298,8 @@ const FluentStoreGrid: React.FunctionComponent = ({ columnWidths.set(column.key, newWidth); }, [columnWidths]); - /* Monitor Scroll Events (hack) - - Essentially we are setting the scrollElement of the DetailsList to the div that contains the DetailsList (rather than a scrollable pane host). - See: https://github.com/microsoft/fluentui/blob/55d3a31042e8972ea373841bef616c68e6ab69f9/packages/react/src/components/List/List.tsx#L355-L369 - - Note: Not sure if `_onScroll` call is needed, but excluding for now as it seems to work without it and is more performant. - */ - const id = useId("fluent-store-grid-"); - const detailListComponent = React.useRef(null); - const [detailListElement, setDetailListElement] = React.useState(null); - useMount(() => { - const detailListElement = document.querySelector(`#${id} .ms-DetailsList`); - setDetailListElement(detailListElement); - if (detailListComponent.current?._list?.current) { - detailListComponent.current._list.current._scrollElement = detailListElement; - } - }); - useOnEvent(detailListElement, "scroll", () => { - detailListComponent.current?._list?.current?._onAsyncScrollDebounced(); - }); - - return
+ return
= ({ const keys = selectedKey !== "" ? selectedKey.split(valueSeparator) : []; let items = [...selectedItems]; if (keys.length === items.length) return; - if (selectedKeys !== "" && selOptions.length && selectedKey === "") { + if (selectedKeys !== "" && selOptions.length && selectedKey === "" && selectedKeys === items.map(i => i.key).join("|")) { setSelectedItems([]); return; } @@ -833,7 +833,7 @@ export const CloudContainerNameField: React.FunctionComponent; @@ -1367,6 +1367,7 @@ export function createInputs(fields: Fields, onChange?: (id: string, newValue: a label: field.label, field: { onChange(fieldID, row.key); setDropzone(row.key as string); diff --git a/esp/src/src-react/hooks/file.ts b/esp/src/src-react/hooks/file.ts index 7ea78a2cc70..fc83c9853d0 100644 --- a/esp/src/src-react/hooks/file.ts +++ b/esp/src/src-react/hooks/file.ts @@ -19,13 +19,13 @@ export function useFile(cluster: string, name: string): [LogicalFile, boolean, n let handle; const fetchInfo = singletonDebounce(file, "fetchInfo"); fetchInfo() - .then(() => { + .then((response) => { if (active) { setFile(file); - setIsProtected(file.ProtectList?.DFUFileProtect?.length > 0 || false); + setIsProtected(response.ProtectList?.DFUFileProtect?.length > 0 || false); setLastUpdate(Date.now()); handle = file.watch(() => { - setIsProtected(file.ProtectList?.DFUFileProtect?.length > 0 || false); + setIsProtected(response.ProtectList?.DFUFileProtect?.length > 0 || false); setLastUpdate(Date.now()); }); } diff --git a/helm/hpcc/templates/issuers.yaml b/helm/hpcc/templates/issuers.yaml index 280c29198a7..9b52fb85800 100644 --- a/helm/hpcc/templates/issuers.yaml +++ b/helm/hpcc/templates/issuers.yaml @@ -136,7 +136,7 @@ spec: {{- range $k, $v := .Values.certificates.issuers }} {{- include "hpcc.addIssuer" (dict "root" $ "issuerKeyName" $k "me" $v ) }} {{- end }} - {{- $categories := list "system" "storage" "esp" "codeSign" "codeVerify" "authn" "eclUser" "ecl" "git" "jfrog" -}} + {{- $categories := list "authn" "codeSign" "codeVerify" "ecl" "eclUser" "esp" "git" "jfrog" "storage" "system" -}} {{- range $category := $categories }} {{ include "hpcc.addVaultClientCertificate" (dict "root" $ "category" $category) }} {{- end }} diff --git a/helm/hpcc/values.schema.json b/helm/hpcc/values.schema.json index f9be3740b9d..b2e1e742d85 100644 --- a/helm/hpcc/values.schema.json +++ b/helm/hpcc/values.schema.json @@ -69,10 +69,13 @@ "timeout": { "type": "integer" }, - "storage": { + "authn": { "$ref": "#/definitions/secrets" }, - "authn": { + "codeSign": { + "$ref": "#/definitions/secrets" + }, + "codeVerify": { "$ref": "#/definitions/secrets" }, "ecl": { @@ -81,20 +84,19 @@ "eclUser": { "$ref": "#/definitions/secrets" }, - "codeSign": { + "esp": { "$ref": "#/definitions/secrets" }, - "codeVerify": { + "git": { "$ref": "#/definitions/secrets" }, - "git": { + "jfrog": { "$ref": "#/definitions/secrets" }, - "system": { + "storage": { "$ref": "#/definitions/secrets" - } - , - "esp": { + }, + "system": { "$ref": "#/definitions/secrets" } }, @@ -107,13 +109,13 @@ "timeout": { "type": "integer" }, - "storage": { + "authn": { "$ref": "#/definitions/vaultCategory" }, - "authn": { + "codeSign": { "$ref": "#/definitions/vaultCategory" }, - "esp": { + "codeVerify": { "$ref": "#/definitions/vaultCategory" }, "ecl": { @@ -122,16 +124,20 @@ "eclUser": { "$ref": "#/definitions/vaultCategory" }, - "codeSign": { + "esp": { "$ref": "#/definitions/vaultCategory" }, - "codeVerify": { + "git": { "$ref": "#/definitions/vaultCategory" }, - "git": { + "jfrog": { + "$ref": "#/definitions/vaultCategory" + }, + "storage": { "$ref": "#/definitions/vaultCategory" } }, + "$comment": "The system secrets are used for vault configuration so cannot themselves be defined in a vault", "additionalProperties": false }, "bundles": { diff --git a/roxie/udplib/udptrr.cpp b/roxie/udplib/udptrr.cpp index 9a31fc0d287..984b5a164cc 100644 --- a/roxie/udplib/udptrr.cpp +++ b/roxie/udplib/udptrr.cpp @@ -22,6 +22,7 @@ #include "jthread.hpp" #include "jlog.hpp" +#include "jmisc.hpp" #include "jisem.hpp" #include "jsocket.hpp" #include "udplib.hpp" @@ -853,6 +854,31 @@ class CReceiveManager : implements IReceiveManager, public CInterface IpMapOf sendersTable; + class UdpRdTracker : public TimeDivisionTracker<6, false> + { + public: + enum + { + other, + waiting, + allocating, + processing, + pushing, + checkingPending + }; + + UdpRdTracker(const char *name, unsigned reportIntervalSeconds) : TimeDivisionTracker<6, false>(name, reportIntervalSeconds) + { + stateNames[other] = "other"; + stateNames[waiting] = "waiting"; + stateNames[allocating] = "allocating"; + stateNames[processing] = "processing"; + stateNames[pushing] = "pushing"; + stateNames[checkingPending] = "checking pending"; + } + + }; + class receive_receive_flow : public Thread { CReceiveManager &parent; @@ -863,7 +889,7 @@ class CReceiveManager : implements IReceiveManager, public CInterface std::atomic running = { false }; SenderList pendingRequests; // List of senders requesting permission to send PermitList pendingPermits; // List of active permits - + UdpRdTracker timeTracker; private: void noteRequest(UdpSenderEntry *requester, sequence_t flowSeq, sequence_t sendSeq) { @@ -966,7 +992,8 @@ class CReceiveManager : implements IReceiveManager, public CInterface public: receive_receive_flow(CReceiveManager &_parent, unsigned flow_p, unsigned _maxSlotsPerSender) - : Thread("UdpLib::receive_receive_flow"), parent(_parent), flow_port(flow_p), maxSlotsPerSender(_maxSlotsPerSender), maxPermits(_parent.input_queue_size) + : Thread("UdpLib::receive_receive_flow"), parent(_parent), flow_port(flow_p), maxSlotsPerSender(_maxSlotsPerSender), maxPermits(_parent.input_queue_size), + timeTracker("receive_receive_flow", 60) { } @@ -1210,6 +1237,7 @@ class CReceiveManager : implements IReceiveManager, public CInterface { DBGLOG("UdpReceiver: wait_read(%u)", timeout); } + UdpRdTracker::TimeDivision d(timeTracker, UdpRdTracker::waiting); bool dataAvail = flow_socket->wait_read(timeout); if (dataAvail) { @@ -1217,8 +1245,10 @@ class CReceiveManager : implements IReceiveManager, public CInterface unsigned int res ; flow_socket->readtms(&msg, l, l, res, 0); assert(res==l); + d.switchState(UdpRdTracker::processing); doFlowRequest(msg); } + d.switchState(UdpRdTracker::checkingPending); timeout = checkPendingRequests(); } catch (IException *e) @@ -1263,9 +1293,10 @@ class CReceiveManager : implements IReceiveManager, public CInterface ISocket *selfFlowSocket = nullptr; std::atomic running = { false }; Semaphore started; + UdpRdTracker timeTracker; public: - receive_data(CReceiveManager &_parent) : Thread("UdpLib::receive_data"), parent(_parent) + receive_data(CReceiveManager &_parent) : Thread("UdpLib::receive_data"), parent(_parent), timeTracker("receive_data", 60) { unsigned ip_buffer = parent.input_queue_size*DATA_PAYLOAD*2; if (ip_buffer < udpFlowSocketsSize) ip_buffer = udpFlowSocketsSize; @@ -1325,7 +1356,7 @@ class CReceiveManager : implements IReceiveManager, public CInterface adjustPriority(2); #endif started.signal(); - unsigned lastOOOReport = 0; + unsigned lastOOOReport = msTick(); unsigned lastPacketsOOO = 0; unsigned lastUnwantedDiscarded = 0; unsigned timeout = 5000; @@ -1342,8 +1373,10 @@ class CReceiveManager : implements IReceiveManager, public CInterface //Read at least the size of the smallest packet we can receive //static assert to check we are reading the smaller of the two possible packet types static_assert(sizeof(UdpRequestToSendMsg) <= sizeof(UdpPacketHeader)); - receive_socket->readtms(b->data, sizeof(UdpRequestToSendMsg), DATA_PAYLOAD, res, timeout); - + { + UdpRdTracker::TimeDivision d(timeTracker, UdpRdTracker::waiting); + receive_socket->readtms(b->data, sizeof(UdpRequestToSendMsg), DATA_PAYLOAD, res, timeout); + } //Even if a UDP packet is not split, very occasionally only some of the data may be present for the read. //Slightly horribly this packet could be one of two different formats(!) // a UdpRequestToSendMsg, which has a 2 byte command at the start of the header, with a maximum value of max_flow_cmd @@ -1372,27 +1405,30 @@ class CReceiveManager : implements IReceiveManager, public CInterface //Redirect them to the flow thread to process them. selfFlowSocket->write(b->data, res); } - - dataPacketsReceived++; - UdpSenderEntry *sender = &parent.sendersTable[hdr.node]; - if (sender->noteSeen(hdr)) - { - // We should perhaps track how often this happens, but it's not the same as unwantedDiscarded - hdr.node.clear(); // Used to indicate a duplicate that collate thread should discard. We don't discard on this thread as don't want to do anything that requires locks... - } - else { - //Decrease the number of active reservations to balance having received a new data packet (otherwise they will be double counted) - sender->decPermit(hdr.msgSeq); - if (udpTraceLevel > 5) // don't want to interrupt this thread if we can help it + UdpRdTracker::TimeDivision d(timeTracker, UdpRdTracker::processing); + dataPacketsReceived++; + UdpSenderEntry *sender = &parent.sendersTable[hdr.node]; + if (sender->noteSeen(hdr)) { - StringBuffer s; - DBGLOG("UdpReceiver: %u bytes received packet %" SEQF "u %x from %s", res, hdr.sendSeq, hdr.pktSeq, hdr.node.getTraceText(s).str()); + // We should perhaps track how often this happens, but it's not the same as unwantedDiscarded + hdr.node.clear(); // Used to indicate a duplicate that collate thread should discard. We don't discard on this thread as don't want to do anything that requires locks... + } + else + { + //Decrease the number of active reservations to balance having received a new data packet (otherwise they will be double counted) + sender->decPermit(hdr.msgSeq); + if (udpTraceLevel > 5) // don't want to interrupt this thread if we can help it + { + StringBuffer s; + DBGLOG("UdpReceiver: %u bytes received packet %" SEQF "u %x from %s", res, hdr.sendSeq, hdr.pktSeq, hdr.node.getTraceText(s).str()); + } } + d.switchState(UdpRdTracker::pushing); + parent.input_queue->pushOwn(b); + d.switchState(UdpRdTracker::allocating); + b = udpBufferManager->allocate(); } - parent.input_queue->pushOwn(b); - b = udpBufferManager->allocate(); - if (udpStatsReportInterval) { unsigned now = msTick(); @@ -1537,11 +1573,14 @@ class CReceiveManager : implements IReceiveManager, public CInterface void collatePackets() { + UdpRdTracker timeTracker("collatePackets", 60); while(running) { try { + UdpRdTracker::TimeDivision d(timeTracker, UdpRdTracker::waiting); DataBuffer *dataBuff = input_queue->pop(true); + d.switchState(UdpRdTracker::processing); dataBuff->changeState(roxiemem::DBState::queued, roxiemem::DBState::unowned, __func__); collatePacket(dataBuff); } diff --git a/roxie/udplib/udptrs.cpp b/roxie/udplib/udptrs.cpp index c223094c064..fe7c46ae868 100644 --- a/roxie/udplib/udptrs.cpp +++ b/roxie/udplib/udptrs.cpp @@ -80,7 +80,7 @@ RelaxedAtomic flowRequestsSent; RelaxedAtomic flowPermitsReceived; RelaxedAtomic dataPacketsSent; -static unsigned lastResentReport = 0; +static unsigned lastResentReport = msTick(); static unsigned lastOkToSendTimeouts = 0; static unsigned lastPacketsResent = 0; static unsigned lastFlowRequestsSent = 0; diff --git a/system/jlib/jmisc.hpp b/system/jlib/jmisc.hpp index bc3cdd07205..6e6fe9acafe 100644 --- a/system/jlib/jmisc.hpp +++ b/system/jlib/jmisc.hpp @@ -334,4 +334,107 @@ extern jlib_decl char **getSystemEnv(); extern jlib_decl char *getHPCCEnvVal(const char *name, const char *defaultValue); +// class TimeDivisionTracker is useful for working out what a thread spends its time doing. See udptrrr.cpp for an example +// of its usage + +template class TimeDivisionTracker +{ +protected: + unsigned __int64 totals[NUMSTATES] = {0}; + unsigned counts[NUMSTATES] = {0}; + const char *stateNames[NUMSTATES]; + unsigned __int64 lastTick = get_cycles_now(); + unsigned currentState = 0; + StringAttr name; + unsigned __int64 reportIntervalCycles = 0; + unsigned __int64 lastReport = 0; + + unsigned enterState(unsigned newState) + { + unsigned prevState = currentState; + unsigned __int64 now = get_cycles_now(); + if (reportIntervalCycles && now - lastReport >= reportIntervalCycles) + { + report(true); + now = get_cycles_now(); + } + if (newState != prevState) + { + totals[currentState] += now - lastTick; + currentState = newState; + counts[newState]++; + lastTick = now; + } + return prevState; + } + + void leaveState(unsigned backToState) + { + unsigned __int64 now = get_cycles_now(); + if (reportIntervalCycles && now - lastReport >= reportIntervalCycles) + report(true); + if (backToState != currentState) + { + totals[currentState] += now - lastTick; + lastTick = now; + currentState = backToState; + } + } + +public: + TimeDivisionTracker(const char *_name, unsigned reportIntervalSeconds) : name(_name) + { + if (reportIntervalSeconds) + reportIntervalCycles = millisec_to_cycle(reportIntervalSeconds * 1000); + } + + void report(bool reset) + { + VStringBuffer str("%s spent ", name.str()); + auto now = get_cycles_now(); + totals[currentState] += now - lastTick; + lastTick = now; + lastReport = now; + bool doneOne = false; + for (unsigned i = reportOther ? 0 : 1; i < NUMSTATES; i++) + { + if (counts[i]) + { + if (doneOne) + str.append(", "); + formatTime(str, cycle_to_nanosec(totals[i])); + str.appendf(" %s (%u times)", stateNames[i], counts[i]); + doneOne = true; + } + if (reset) + { + totals[i] = 0; + counts[i] = 0; + } + } + if (doneOne) + DBGLOG("%s", str.str()); + } + + class TimeDivision + { + unsigned prevState = 0; + TimeDivisionTracker &t; + public: + TimeDivision(TimeDivisionTracker &_t, unsigned newState) : t(_t) + { + prevState = t.enterState(newState); + } + ~TimeDivision() + { + t.leaveState(prevState); + } + void switchState(unsigned newState) + { + t.enterState(newState); + } + }; +}; + + #endif diff --git a/system/jlib/jqueue.tpp b/system/jlib/jqueue.tpp index 4f4ed610985..f334469c4dc 100644 --- a/system/jlib/jqueue.tpp +++ b/system/jlib/jqueue.tpp @@ -271,6 +271,8 @@ public: using PARENT::ensure; }; +//Sending signals once the critical section has been released generally gives better performance. +#define SIGNAL_OUTSIDE template class SimpleInterThreadQueueOf : protected SafeQueueOf @@ -358,18 +360,53 @@ public: bool enqueue(BASE *e,unsigned timeout=INFINITE) { - CriticalBlock b(SELF::crit); - if (limit) { - unsigned start=0; - while (limit<=SafeQueueOf::unsafeordinality()) - if (stopped||!qwait(deqwaitsem,deqwaiting,timeout,start)) - return false; + unsigned numToSignal = 0; + { + CriticalBlock b(SELF::crit); + if (limit) { + unsigned start=0; + while (limit<=SafeQueueOf::unsafeordinality()) + if (stopped||!qwait(deqwaitsem,deqwaiting,timeout,start)) + return false; + } + SafeQueueOf::unsafeenqueue(e); +#ifdef SIGNAL_OUTSIDE + numToSignal = enqwaiting; + enqwaiting = 0; +#else + if (enqwaiting) { + enqwaitsem.signal(enqwaiting); + enqwaiting = 0; + } +#endif } - SafeQueueOf::unsafeenqueue(e); - if (enqwaiting) { - enqwaitsem.signal(enqwaiting); + // Signal when critical section no longer held so the reader can actually remove the item + if (numToSignal) + enqwaitsem.signal(numToSignal); + return true; + } + + bool enqueueMany(unsigned num, BASE * *e,unsigned timeout=INFINITE) + { + assertex(!limit); + unsigned numToSignal = 0; + { + CriticalBlock b(SELF::crit); + for (unsigned i=0; i < num; i++) + SafeQueueOf::unsafeenqueue(e[i]); + +#ifdef SIGNAL_OUTSIDE + numToSignal = enqwaiting; enqwaiting = 0; +#else + if (enqwaiting) { + enqwaitsem.signal(enqwaiting); + enqwaiting = 0; + } +#endif } + if (numToSignal) + enqwaitsem.signal(numToSignal); return true; } @@ -409,21 +446,31 @@ public: BASE *dequeue(unsigned timeout=INFINITE) { - CriticalBlock b(SELF::crit); - unsigned start=0; - while (!stopped) { - BASE *ret; - if (get(ret,false)) { - if (deqwaiting) { - deqwaitsem.signal(deqwaiting); + BASE *ret = nullptr; + unsigned numToSignal = 0; + { + CriticalBlock b(SELF::crit); + unsigned start=0; + while (!stopped) { + if (get(ret,false)) { +#ifdef SIGNAL_OUTSIDE + numToSignal = deqwaiting; deqwaiting = 0; +#else + if (deqwaiting) { + deqwaitsem.signal(deqwaiting); + deqwaiting = 0; + } +#endif + break; } - return ret; + if (!qwait(enqwaitsem,enqwaiting,timeout,start)) + break; } - if (!qwait(enqwaitsem,enqwaiting,timeout,start)) - break; } - return NULL; + if (numToSignal) + deqwaitsem.signal(numToSignal); + return ret; } BASE *dequeueTail(unsigned timeout=INFINITE) diff --git a/system/jlib/jsocket.cpp b/system/jlib/jsocket.cpp index 51d4c0b7bd2..d109766bac6 100644 --- a/system/jlib/jsocket.cpp +++ b/system/jlib/jsocket.cpp @@ -399,35 +399,40 @@ enum SOCKETMODE { sm_tcp_server, sm_tcp, sm_udp_server, sm_udp, sm_multicast_ser # endif #endif -static CriticalSection queryKACS; +enum UseUDE { UNINIT, INITED }; +static std::atomic expertTCPSettings { UNINIT }; +static CriticalSection queryTCPCS; -enum UseKA { UNINIT, DISABLED, ENABLED }; -static std::atomic doKeepAlive { UNINIT }; +static bool hasKeepAlive = false; static int keepAliveTime = -1; static int keepAliveInterval = -1; static int keepAliveProbes = -1; +static bool disableDNSTimeout = false; +static int maxDNSThreads = 50; /* - + global: expert: + disableDNSTimeout: false + maxDNSThreads: 100 keepalive: time: 200 interval: 75 probes: 9 */ -extern jlib_decl bool queryKeepAlive(int &time, int &intvl, int &probes) +static void queryTCPSettings() { - UseKA state = doKeepAlive.load(); + UseUDE state = expertTCPSettings.load(); if (state == UNINIT) { - CriticalBlock block(queryKACS); - state = doKeepAlive.load(); + CriticalBlock block(queryTCPCS); + state = expertTCPSettings.load(); if (state == UNINIT) { #ifdef _CONTAINERIZED @@ -454,7 +459,6 @@ extern jlib_decl bool queryKeepAlive(int &time, int &intvl, int &probes) catch (...) { } - state = DISABLED; if (expert) { IPropertyTree *keepalive = expert->queryPropTree("keepalive"); @@ -463,22 +467,122 @@ extern jlib_decl bool queryKeepAlive(int &time, int &intvl, int &probes) keepAliveTime = keepalive->getPropInt("@time", keepAliveTime); keepAliveInterval = keepalive->getPropInt("@interval", keepAliveInterval); keepAliveProbes = keepalive->getPropInt("@probes", keepAliveProbes); - state = ENABLED; + hasKeepAlive = true; } + disableDNSTimeout = expert->getPropBool("@disableDNSTimeout", false); + maxDNSThreads = expert->getPropInt("@maxDNSThreads", maxDNSThreads); + // could also consider maxDNSThreads==0 as a way to disable DNS timeout ... + if (maxDNSThreads < 1) + maxDNSThreads = 1; } - doKeepAlive = state; + expertTCPSettings = INITED; } } +} - if (state == ENABLED) +extern jlib_decl bool queryKeepAlive(int &time, int &intvl, int &probes) +{ + queryTCPSettings(); + if (hasKeepAlive) { time = keepAliveTime; intvl = keepAliveInterval; probes = keepAliveProbes; + } + return hasKeepAlive; +} + +static int getAddressInfo(const char *name, unsigned *netaddr, bool okToLogErr); + +static CriticalSection queryDNSCS; + +class CAddrInfoThreadArgs : public CInterface +{ +public: + StringAttr name; + unsigned netaddr[4] = { 0, 0, 0, 0 }; + std::atomic retCode { EAI_SYSTEM }; + + CAddrInfoThreadArgs(const char *_name) : name(_name) { } +}; + +class CAddrPoolThread : public CInterface, implements IPooledThread +{ +public: + IMPLEMENT_IINTERFACE; + + Linked localAddrThreadInfo; + + virtual void init(void *param) override + { + localAddrThreadInfo.setown((CAddrInfoThreadArgs *)param); + } + + virtual void threadmain() override + { + localAddrThreadInfo->retCode = getAddressInfo(localAddrThreadInfo->name.get(), localAddrThreadInfo->netaddr, false); + } + + virtual bool stop() override + { return true; } - else - return false; + + virtual bool canReuse() const override + { + return true; + } +}; + +class CAddrInfoFactory : public CInterface, public IThreadFactory +{ +public: + IMPLEMENT_IINTERFACE; + IPooledThread *createNew() + { + return new CAddrPoolThread(); + } +}; + +static Owned addrInfoFactory; +static Owned addrInfoPool; +static std::atomic addrInfoPoolCreated { false }; + +static bool useDNSTimeout() +{ + queryTCPSettings(); + if (!disableDNSTimeout) + { + if (!addrInfoPoolCreated.load()) + { + CriticalBlock block(queryDNSCS); + if (!addrInfoPoolCreated.load()) + { + addrInfoFactory.setown(new CAddrInfoFactory); + addrInfoPool.setown(createThreadPool("AddrInfoPool", addrInfoFactory, true, nullptr, maxDNSThreads, 100000000)); + addrInfoPoolCreated = true; + } + } + return true; + } + return false; +} + +MODULE_INIT(INIT_PRIORITY_STANDARD) +{ + return true; +} + +MODULE_EXIT() +{ + // NB: this (and other MODULE_EXITs) are not called for Thor and Roxie because they are + // stopped via SIGTERM signal and thus exit() and the atexit handlers are not called + if (addrInfoPoolCreated.load()) + { + addrInfoPool->joinAll(true); + addrInfoPool.clear(); + addrInfoPoolCreated = false; + } } struct SocketStats @@ -3416,82 +3520,57 @@ static bool decodeNumericIP(const char *text,unsigned *netaddr) return false; } -static bool lookupHostAddress(const char *name,unsigned *netaddr) +static void RecursionSafeLogErr(int ret, int ref, const char *msg, unsigned lineno, const char *name) { - // if IP4only or using MS V6 can only resolve IPv4 using - static bool recursioncheck = false; // needed to stop error message recursing - unsigned retry=10; -#if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo) - if (IP4only) { -#else + static __thread bool recursioncheck = false; // needed to stop error message recursing + if (!recursioncheck) { + recursioncheck = true; + LogErr(ret, ref, msg, lineno, name); +#ifdef _DEBUG + PrintStackReport(); #endif - CriticalBlock c(hostnamesect); - hostent * entry = gethostbyname(name); - while (entry==NULL) { - if (retry--==0) { - if (!recursioncheck) { - recursioncheck = true; - LogErr(h_errno,1,"gethostbyname failed",__LINE__,name); - recursioncheck = false; - } - return false; - } - { - CriticalUnblock ub(hostnamesect); - Sleep((10-retry)*100); - } - entry = gethostbyname(name); - } - if (entry->h_addr_list[0]) { - unsigned ptr = 0; - if (!PreferredSubnet.isNull()) { - for (;;) { - ptr++; - if (entry->h_addr_list[ptr]==NULL) { - ptr = 0; - break; - } - IpAddress ip; - ip.setNetAddress(sizeof(unsigned),entry->h_addr_list[ptr]); - if (PreferredSubnet.test(ip)) - break; - } - } - memcpy(&netaddr[3], entry->h_addr_list[ptr], sizeof(netaddr[3])); - netaddr[2] = 0xffff0000; - netaddr[1] = 0; - netaddr[0] = 0; - return true; - } - return false; + recursioncheck = false; } -#if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo) +} + +int getAddressInfo(const char *name, unsigned *netaddr, bool okToLogErr) +{ struct addrinfo hints; - memset(&hints,0,sizeof(hints)); - struct addrinfo *addrInfo = NULL; - for (;;) { - memset(&hints,0,sizeof(hints)); + struct addrinfo *addrInfo = NULL; + int retry=10; + int retCode; + + // each retry could take up to several seconds, depending on how DNS resolver is configured + // should a few specific non-zero return codes break out early from retry loop (EAI_NONAME) ? + while (true) + { + memset(&hints, 0, sizeof(hints)); // dont wait for both A and AAAA records ... if (IP4only || (!IP6preferred)) hints.ai_family = AF_INET; - int ret = getaddrinfo(name, NULL , &hints, &addrInfo); - if (!ret) + // hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG | AI_V4MAPPED + retCode = getaddrinfo(name, NULL, &hints, &addrInfo); + if (0 == retCode) break; - if (retry--==0) { - if (!recursioncheck) { - recursioncheck = true; - LogErr(ret,1,"getaddrinfo failed",__LINE__,name); -#ifdef _DEBUG - PrintStackReport(); -#endif - recursioncheck = false; - } - return false; + if (--retry > 0) + Sleep((10-retry)*100); + else + { + // use gai_strerror(ret) to get meaningful error text ? + if (okToLogErr) + RecursionSafeLogErr(retCode, 1, "getaddrinfo failed", __LINE__, name); + return retCode; + } + if (EAI_NONAME == retCode) + { + // try one more time, but why ? + // MCK TODO: probably should only retry on EAI_AGAIN and possibly EAI_SYSTEM ... + retry = 1; } - Sleep((10-retry)*100); } - struct addrinfo *best = NULL; + + struct addrinfo *best = NULL; bool snm = !PreferredSubnet.isNull(); for (;;) { struct addrinfo *ai; @@ -3519,7 +3598,7 @@ static bool lookupHostAddress(const char *name,unsigned *netaddr) if ((best==NULL)||((best->ai_family==AF_INET)&&IP6preferred)) best = ai; break; - } + } } } if (best||!snm) @@ -3537,15 +3616,131 @@ static bool lookupHostAddress(const char *name,unsigned *netaddr) } } freeaddrinfo(addrInfo); - return best!=NULL; -#endif - return false; - + if (best!=NULL) + return 0; + else + return EAI_NONAME; // or EAI_NODATA ? } +static bool lookupHostAddress(const char *name, unsigned *netaddr, unsigned timeoutms=INFINITE) +{ + // if IP4only or using MS V6 can only resolve IPv4 using + int retry=10; + +#if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo) + if (IP4only) { +#else + { +#endif + CriticalBlock c(hostnamesect); + hostent * entry = gethostbyname(name); + while (entry==NULL) { + if (retry--==0) { + RecursionSafeLogErr(h_errno, 1, "gethostbyname failed", __LINE__, name); + return false; + } + { + CriticalUnblock ub(hostnamesect); + Sleep((10-retry)*100); + } + entry = gethostbyname(name); + } + if (entry->h_addr_list[0]) { + unsigned ptr = 0; + if (!PreferredSubnet.isNull()) { + for (;;) { + ptr++; + if (entry->h_addr_list[ptr]==NULL) { + ptr = 0; + break; + } + IpAddress ip; + ip.setNetAddress(sizeof(unsigned),entry->h_addr_list[ptr]); + if (PreferredSubnet.test(ip)) + break; + } + } + memcpy(&netaddr[3], entry->h_addr_list[ptr], sizeof(netaddr[3])); + netaddr[2] = 0xffff0000; + netaddr[1] = 0; + netaddr[0] = 0; + return true; + } + return false; + } + +#if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo) + int retCode = 0; + if ( (timeoutms != INFINITE) && (useDNSTimeout()) ) // could addrInfoPool be NULL ? + { + // getaddrinfo_a() offers an async getaddrinfo method, but has some limitations and a possible mem leak + // could implement timeout getaddrinfo functionality without threads by connecting with DNS servers and parsing response ... + // lookup performance may be significantly improved if system uses a DNS resolver cache + + PooledThreadHandle thrdHandle; + Owned addrThreadInfo = new CAddrInfoThreadArgs(name); + CTimeMon dnstimeout(timeoutms); + try + { + // wait up to timeoutms for an available thread from pool ... + thrdHandle = addrInfoPool->start((void *)addrThreadInfo.getLink(), "getaddrinfo-thread", timeoutms); + // MCK TODO: if have to create a new thread and at os/system/shell thread limit, create/start can take up to several seconds, can we control this ? + } + catch (IException *e) + { + addrThreadInfo->Release(); + StringBuffer excMsg; + StringBuffer emsg; + emsg.appendf("getaddrinfo failed (thread) (%d) (exc:%d) %s", timeoutms, e->errorCode(), e->errorMessage(excMsg).str()); + RecursionSafeLogErr(100, 1, emsg.str(), __LINE__, name); + e->Release(); + return false; + } + catch (...) + { + addrThreadInfo->Release(); + RecursionSafeLogErr(101, 1, "getaddrinfo failed (thread) (other exc)", __LINE__, name); + return false; + } -bool IpAddress::ipset(const char *text) + // take into account time already passed creating/starting thread above ... + unsigned remaining; + dnstimeout.timedout(&remaining); + if (addrInfoPool->join(thrdHandle, remaining)) + { + if (0 == addrThreadInfo->retCode) + { + memcpy(netaddr, addrThreadInfo->netaddr, sizeof(addrThreadInfo->netaddr)); + return true; + } + else + { + // use gai_strerror(ret) to get meaningful error text ? + StringBuffer emsg; + emsg.appendf("getaddrinfo failed (thread)"); + RecursionSafeLogErr(addrThreadInfo->retCode.load(), 1, emsg.str(), __LINE__, name); + return false; + } + } + // if join() returns false thread still running, but its detached, + // will terminate, release thread args and return to pool on its own ... + + StringBuffer emsg; + emsg.appendf("getaddrinfo timed out (thread) (%d)", timeoutms); + RecursionSafeLogErr(EAI_AGAIN, 1, emsg.str(), __LINE__, name); + return false; + } + + retCode = getAddressInfo(name, netaddr, true); + if (0 == retCode) + return true; + else + return false; +#endif +} + +bool IpAddress::ipset(const char *text, unsigned timeoutms) { if (text&&*text) { @@ -3565,7 +3760,7 @@ bool IpAddress::ipset(const char *text) break; if (!*s) return ipset(NULL); - if (lookupHostAddress(text,netaddr)) + if (lookupHostAddress(text, netaddr, timeoutms)) { hostname.set(text); return true; @@ -3772,7 +3967,7 @@ void SocketEndpoint::serialize(MemoryBuffer & out) const } -bool SocketEndpoint::set(const char *name,unsigned short _port) +bool SocketEndpoint::set(const char *name,unsigned short _port, unsigned timeoutms) { if (name) { if (*name=='[') { @@ -3802,7 +3997,7 @@ bool SocketEndpoint::set(const char *name,unsigned short _port) name = ips; _port = atoi(colon+1); } - if (ipset(name)) { + if (ipset(name, timeoutms)) { port = _port; return true; } @@ -6535,44 +6730,15 @@ bool SocketEndpointArray::fromName(const char *name, unsigned defport) return ordinality()>0; } #if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo) - struct addrinfo hints; - memset(&hints,0,sizeof(hints)); - struct addrinfo *addrInfo = NULL; - memset(&hints,0,sizeof(hints)); - int ret = getaddrinfo(name, NULL , &hints, &addrInfo); - if (ret == 0) + unsigned netaddr[4]; + int retCode = getAddressInfo(name, netaddr, true); + if (0 == retCode) { - struct addrinfo *ai; - for (ai = addrInfo; ai; ai = ai->ai_next) - { - // DBGLOG("flags=%d, family=%d, socktype=%d, protocol=%d, addrlen=%d, canonname=%s",ai->ai_flags,ai->ai_family,ai->ai_socktype,ai->ai_protocol,ai->ai_addrlen,ai->ai_canonname?ai->ai_canonname:"NULL"); - if (ai->ai_protocol == IPPROTO_IP) - { - switch (ai->ai_family) - { - case AF_INET: - { - SocketEndpoint ep; - ep.setNetAddress(sizeof(in_addr),&(((sockaddr_in *)ai->ai_addr)->sin_addr)); - ep.port = defport; - append(ep); - // StringBuffer s; - // DBGLOG("Lookup %s found %s", name, ep.getEndpointHostText(s).str()); - break; - } - case AF_INET6: - { - SocketEndpoint ep; - ep.setNetAddress(sizeof(in_addr6),&(((sockaddr_in6 *)ai->ai_addr)->sin6_addr)); - ep.port = defport; - append(ep); - break; - } - } - } - } + SocketEndpoint ep; + ep.setNetAddress(sizeof(netaddr),netaddr); + ep.port = defport; + append(ep); } - freeaddrinfo(addrInfo); #endif return ordinality()>0; } diff --git a/system/jlib/jsocket.hpp b/system/jlib/jsocket.hpp index 2ff0c0705ca..08524d55b72 100644 --- a/system/jlib/jsocket.hpp +++ b/system/jlib/jsocket.hpp @@ -95,7 +95,7 @@ class jlib_decl IpAddress IpAddress() = default; explicit IpAddress(const char *text) { ipset(text); } - bool ipset(const char *text); // sets to NULL if fails or text=NULL + bool ipset(const char *text, unsigned timeoutms=INFINITE); // sets to NULL if fails or text=NULL void ipset(const IpAddress& other) { *this = other; } bool ipequals(const IpAddress & other) const; int ipcompare(const IpAddress & other) const; // depreciated @@ -154,7 +154,7 @@ class jlib_decl SocketEndpoint : extends IpAddress { public: SocketEndpoint() = default; - SocketEndpoint(const char *name,unsigned short _port=0) { set(name,_port); }; + SocketEndpoint(const char *name,unsigned short _port=0, unsigned timeoutms=INFINITE) { set(name,_port,timeoutms); }; SocketEndpoint(unsigned short _port) { setLocalHost(_port); }; SocketEndpoint(unsigned short _port, const IpAddress & _ip) { set(_port,_ip); }; SocketEndpoint(const SocketEndpoint &other) = default; @@ -162,7 +162,7 @@ class jlib_decl SocketEndpoint : extends IpAddress void deserialize(MemoryBuffer & in); void serialize(MemoryBuffer & out) const; - bool set(const char *name,unsigned short _port=0); + bool set(const char *name,unsigned short _port=0, unsigned timeoutms=INFINITE); inline void set(const SocketEndpoint & value) { ipset(value); port = value.port; } inline void setLocalHost(unsigned short _port) { port = _port; GetHostIp(*this); } // NB *not* localhost(127.0.0.1) inline void set(unsigned short _port, const IpAddress & _ip) { ipset(_ip); port = _port; }; diff --git a/system/jlib/jstats.cpp b/system/jlib/jstats.cpp index ac6352ddc80..0dda1b137a5 100644 --- a/system/jlib/jstats.cpp +++ b/system/jlib/jstats.cpp @@ -197,7 +197,7 @@ const static unsigned __int64 oneMinute = I64C(60000000000); const static unsigned __int64 oneHour = I64C(3600000000000); const static unsigned __int64 oneDay = 24 * I64C(3600000000000); -static void formatTime(StringBuffer & out, unsigned __int64 value) +void formatTime(StringBuffer & out, unsigned __int64 value) { //Aim to display at least 3 significant digits in the result string if (value < oneMicroSecond) diff --git a/system/jlib/jstats.h b/system/jlib/jstats.h index 253d640c94d..14414235266 100644 --- a/system/jlib/jstats.h +++ b/system/jlib/jstats.h @@ -23,6 +23,7 @@ #include "jmutex.hpp" #include #include +#include #include "jstatcodes.h" @@ -44,6 +45,8 @@ inline constexpr stat_type statPercentageOf(stat_type value, stat_type per) { re inline StatisticKind queryStatsVariant(StatisticKind kind) { return (StatisticKind)(kind & ~StKindMask); } inline cost_type money2cost_type(double money) { return money * 1E6; } inline double cost_type2money(cost_type cost) { return ((double) cost) / 1E6; } + +extern jlib_decl void formatTime(StringBuffer & out, unsigned __int64 value); //--------------------------------------------------------------------------------------------------------------------- //Represents a single level of a scope @@ -838,6 +841,21 @@ void mergeStat(CRuntimeStatisticCollection & stats, INTERFACE * source, Statisti template void mergeStat(CRuntimeStatisticCollection & stats, const Shared & source, StatisticKind kind) { mergeStat(stats, source.get(), kind); } +// helper templates that add delta of previous vs current (from source) to tgtStats (and update prevStats) +template +void updateStatsDelta(CRuntimeStatisticCollection & tgtStats, CRuntimeStatisticCollection & prevStats, INTERFACE * source) +{ + CRuntimeStatisticCollection curStats(tgtStats.queryMapping()); + mergeStats(curStats, source); + prevStats.updateDelta(tgtStats, curStats); // NB: adds delta to tgtStats, and updates prevStats +} + +template +void updateStatsDelta(CRuntimeStatisticCollection & tgtStats, CRuntimeStatisticCollection & prevStats, const Shared & source) +{ + updateStatsDelta(tgtStats, prevStats, source.get()); +} + //Some template helper classes for overwriting/setting statistics from external sources. @@ -874,6 +892,55 @@ void setStat(CRuntimeStatisticCollection & stats, INTERFACE * source, StatisticK template void setStat(CRuntimeStatisticCollection & stats, const Shared & source, StatisticKind kind) { setStat(stats, source.get(), kind); } + +typedef std::map StatKindMap; + +template +void mergeRemappedStats(CRuntimeStatisticCollection & stats, INTERFACE * source, const StatisticsMapping & mapping, const StatKindMap & remaps) +{ + if (!source) + return; + unsigned max = mapping.numStatistics(); + for (unsigned i=0; i < max; i++) + { + StatisticKind kind = mapping.getKind(i); + if (remaps.find(kind) == remaps.end()) + stats.mergeStatistic(kind, source->getStatistic(kind)); + } + for (auto remap: remaps) + { + if (mapping.hasKind(remap.second)) + stats.mergeStatistic(remap.second, source->getStatistic(remap.first)); + } +} + +template +void mergeRemappedStats(CRuntimeStatisticCollection & stats, INTERFACE * source, const StatKindMap & remaps) +{ + mergeRemappedStats(stats, source, stats.queryMapping(), remaps); +} + +template +void mergeRemappedStats(CRuntimeStatisticCollection & stats, const Shared & source, const StatKindMap & remaps) +{ + mergeRemappedStats(stats, source.get(), stats.queryMapping(), remaps); +} + +template +void updateRemappedStatsDelta(CRuntimeStatisticCollection & tgtStats, CRuntimeStatisticCollection & prevStats, INTERFACE * source, const StatKindMap & remap) +{ + CRuntimeStatisticCollection curStats(tgtStats.queryMapping()); + ::mergeRemappedStats(curStats, source, remap); + prevStats.updateDelta(tgtStats, curStats); // NB: adds delta to tgtStats, and updates prevStats +} + +template +void updateRemappedStatsDelta(CRuntimeStatisticCollection & tgtStats, CRuntimeStatisticCollection & prevStats, const Shared & source, const StatKindMap & remap) +{ + updateRemappedStatsDelta(tgtStats, prevStats, source.get(), remap); +} + + //--------------------------------------------------------------------------------------------------------------------- //A class for minimizing the overhead of collecting timestamps. diff --git a/system/jlib/jtrace.hpp b/system/jlib/jtrace.hpp index c7b18595b22..85b6e3bb915 100644 --- a/system/jlib/jtrace.hpp +++ b/system/jlib/jtrace.hpp @@ -325,6 +325,7 @@ constexpr TraceFlags traceNone = TraceFlags::None; constexpr TraceFlags traceStandard = TraceFlags::Standard; constexpr TraceFlags traceDetailed = TraceFlags::Detailed; constexpr TraceFlags traceMax = TraceFlags::Max; +constexpr TraceFlags traceAll = (TraceFlags)(~TraceFlags::LevelMask); // i.e. all feature flags except for the detail level // Common to several engines constexpr TraceFlags traceHttp = TraceFlags::flag1; @@ -335,6 +336,7 @@ constexpr TraceFlags traceCouchbase = TraceFlags::flag5; constexpr TraceFlags traceFilters = TraceFlags::flag6; constexpr TraceFlags traceKafka = TraceFlags::flag7; constexpr TraceFlags traceJava = TraceFlags::flag8; +constexpr TraceFlags traceOptimizations = TraceFlags::flag9; // code generator, but IHqlExpressions also used by esp/engines // Specific to Roxie constexpr TraceFlags traceRoxieLock = TraceFlags::flag16; @@ -353,7 +355,8 @@ constexpr TraceFlags traceSmartStepping = TraceFlags::flag28; constexpr TraceFlags traceAborts = TraceFlags::flag29; constexpr TraceFlags traceAcknowledge = TraceFlags::flag30; - +//Specific to the code generator +// see traceOptimizations above. //========================================================================================= @@ -394,6 +397,16 @@ constexpr std::initializer_list roxieTraceOptions TRACEOPT(traceAcknowledge), }; +constexpr std::initializer_list eclccTraceOptions +{ + TRACEOPT(traceNone), + TRACEOPT(traceAll), // place before the other options so you can enable all and selectively disable + TRACEOPT(traceStandard), + TRACEOPT(traceDetailed), + TRACEOPT(traceMax), + TRACEOPT(traceOptimizations), +}; + interface IPropertyTree; extern jlib_decl bool doTrace(TraceFlags featureFlag, TraceFlags level=TraceFlags::Standard); diff --git a/system/security/LdapSecurity/ldapconnection.cpp b/system/security/LdapSecurity/ldapconnection.cpp index aaf426e8d67..14fe3b7d9d5 100644 --- a/system/security/LdapSecurity/ldapconnection.cpp +++ b/system/security/LdapSecurity/ldapconnection.cpp @@ -3226,20 +3226,23 @@ class CLdapClient : implements ILdapClient, public CInterface return true; } - virtual bool changePasswordSSL(const char* username, const char* newPassword) + virtual bool changePasswordSSL(const char* username, const char* newPassword, LDAP* ld) { Owned lconn; - try - { - lconn.setown(m_connections->getSSLConnection()); - } - catch(IException*) + if (ld == nullptr) { - throw MakeStringException(-1, "Failed to set user %s's password because of not being able to create an SSL connection to the ldap server. To set an Active Directory user's password from Linux, you need to enable SSL on the Active Directory ldap server", username); + try + { + lconn.setown(m_connections->getSSLConnection()); + } + catch (IException *e) + { + e->Release(); + throw MakeStringException(-1, "Failed to set user %s's password because of not being able to create an SSL connection to the ldap server. To set an Active Directory user's password from Linux, you need to enable SSL on the Active Directory ldap server", username); + } + ld = lconn.get()->getLd(); } - LDAP* ld = lconn.get()->getLd(); - char *attribute, **values = NULL; LDAPMessage *message; @@ -3347,7 +3350,7 @@ class CLdapClient : implements ILdapClient, public CInterface return false; } - virtual bool updateUserPassword(ISecUser& user, const char* newPassword, const char* currPassword) + virtual bool updateUserPassword(ISecUser& user, const char* newPassword, const char* currPassword, LDAP* ld) { const char* username = user.getName(); if(!username || !*username) @@ -3372,10 +3375,10 @@ class CLdapClient : implements ILdapClient, public CInterface throw MakeStringException(-1, "Password not changed, invalid credentials"); } - return updateUserPassword(username, newPassword); + return updateUserPassword(username, newPassword, ld); } - virtual bool updateUserPassword(const char* username, const char* newPassword) + virtual bool updateUserPassword(const char* username, const char* newPassword, LDAP* ld) { if(!username || !*username) { @@ -3472,7 +3475,7 @@ class CLdapClient : implements ILdapClient, public CInterface } DBGLOG("Trying changePasswordSSL to change password over regular SSL connection."); #endif - changePasswordSSL(username, newPassword); + changePasswordSSL(username, newPassword, ld); } else { @@ -3485,7 +3488,7 @@ class CLdapClient : implements ILdapClient, public CInterface TIMEVAL timeOut = {m_ldapconfig->getLdapTimeout(),0}; Owned lconn = m_connections->getConnection(); - LDAP* ld = lconn.get()->getLd(); + ld = lconn.get()->getLd(); char *attrs[] = {LDAP_NO_ATTRS, NULL}; CLDAPMessage searchResult; @@ -6032,7 +6035,7 @@ class CLdapClient : implements ILdapClient, public CInterface // set the password. Owned tmpuser = new CLdapSecUser(user->getName(), ""); - if (!updateUserPassword(*tmpuser, user->credentials().getPassword(), nullptr)) + if (!updateUserPassword(*tmpuser, user->credentials().getPassword(), nullptr, ld)) { DBGLOG("Error updating password for %s",username); throw MakeStringException(-1, "Error updating password for %s",username); @@ -6069,6 +6072,7 @@ class CLdapClient : implements ILdapClient, public CInterface virtual bool addUser(ISecUser& user) { + LdapServerType serverType = m_ldapconfig->getServerType(); const char* username = user.getName(); if(username == NULL || *username == '\0') { @@ -6111,7 +6115,7 @@ class CLdapClient : implements ILdapClient, public CInterface const char* employeeNumber = user.getEmployeeNumber(); StringBuffer dn; - if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY) + if(serverType == ACTIVE_DIRECTORY) { dn.append("cn=").append(fullname).append(","); } @@ -6123,7 +6127,7 @@ class CLdapClient : implements ILdapClient, public CInterface char* oc_name; char* act_fieldname; - if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY) + if(serverType == ACTIVE_DIRECTORY) { oc_name = "User"; act_fieldname = "sAMAccountName"; @@ -6223,7 +6227,7 @@ class CLdapClient : implements ILdapClient, public CInterface attrs[ind++] = &sn_attr; attrs[ind++] = &actname_attr; - if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY) + if(serverType == ACTIVE_DIRECTORY) { attrs[ind++] = &username_attr; attrs[ind++] = &dispname_attr; @@ -6239,7 +6243,19 @@ class CLdapClient : implements ILdapClient, public CInterface attrs[ind] = NULL; - Owned lconn = m_connections->getConnection(); + // + // If the server type is ACTIVE_DIRECTORY, an SSL connection will be needed later to + // set the new user password, otherwise a non SSL connection is used. + Owned lconn; + if(serverType == ACTIVE_DIRECTORY) + { + lconn.setown(m_connections->getSSLConnection()); + } + else + { + lconn.setown(m_connections->getConnection()); + } + LDAP* ld = lconn.get()->getLd(); int rc = ldap_add_ext_s(ld, (char*)dn.str(), attrs, NULL, NULL); if ( rc != LDAP_SUCCESS ) @@ -6256,7 +6272,7 @@ class CLdapClient : implements ILdapClient, public CInterface } } - if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY) + if(serverType == ACTIVE_DIRECTORY) { try { diff --git a/system/security/LdapSecurity/ldapconnection.hpp b/system/security/LdapSecurity/ldapconnection.hpp index 51d148e763d..ec198d412d8 100644 --- a/system/security/LdapSecurity/ldapconnection.hpp +++ b/system/security/LdapSecurity/ldapconnection.hpp @@ -287,9 +287,9 @@ interface ILdapClient : extends IInterface virtual void setResourceBasedn(const char* rbasedn, SecResourceType rtype = RT_DEFAULT) = 0; virtual ILdapConfig* getLdapConfig() = 0; virtual bool userInGroup(const char* userdn, const char* groupdn) = 0; - virtual bool updateUserPassword(ISecUser& user, const char* newPassword, const char* currPassword = 0) = 0; + virtual bool updateUserPassword(ISecUser& user, const char* newPassword, const char* currPassword = 0, LDAP* ld = nullptr) = 0; virtual bool updateUser(const char* type, ISecUser& user) = 0; - virtual bool updateUserPassword(const char* username, const char* newPassword) = 0; + virtual bool updateUserPassword(const char* username, const char* newPassword, LDAP* ld = nullptr) = 0; virtual bool getResources(SecResourceType rtype, const char * basedn, const char* prefix, const char* searchstr, IArrayOf& resources) = 0; virtual IPropertyTreeIterator* getResourceIterator(SecResourceType rtype, const char * basedn, const char* prefix, const char* resourceName, unsigned extraNameFilter) = 0; diff --git a/testing/unittests/jlibtests.cpp b/testing/unittests/jlibtests.cpp index d496ac2cd8d..2bf6f831ee4 100644 --- a/testing/unittests/jlibtests.cpp +++ b/testing/unittests/jlibtests.cpp @@ -4580,4 +4580,233 @@ class JLibStringTest : public CppUnit::TestFixture CPPUNIT_TEST_SUITE_REGISTRATION( JLibStringTest ); CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( JLibStringTest, "JLibStringTest" ); +// ======================================== + +class CAddrThreadArgs : public CInterface, implements IInterface +{ +public: + IMPLEMENT_IINTERFACE; + StringAttr name; + unsigned timeoutms; + bool logIt = true; + + CAddrThreadArgs(const char *_name, unsigned _timeoutms) : name(_name), timeoutms(_timeoutms) + { + } + + CAddrThreadArgs(const char *_name, unsigned _timeoutms, bool _logIt) : name(_name), timeoutms(_timeoutms), logIt(_logIt) + { + } +}; + +class CAddrPoolFactory : public CInterface, public IThreadFactory +{ + class CAddrPoolHandler : public CInterface, implements IPooledThread + { + public: + IMPLEMENT_IINTERFACE; + + CAddrThreadArgs *args; + + virtual void init(void *param) override + { + args = (CAddrThreadArgs *)param; + } + + virtual void threadmain() override + { + StringBuffer name(args->name); + unsigned timeoutms = args->timeoutms; + + SocketEndpoint ep; + CCycleTimer timer; + int srtn = ep.ipset(name.str(), timeoutms); + unsigned lookupTimeMS = timer.elapsedMs(); + + StringBuffer ipstr; + if (args->logIt && srtn) + ep.getIpText(ipstr); + else if (!srtn) + ipstr.append("failed"); + if ((args->logIt && srtn) || (!srtn)) + { + DBGLOG("%s (%d) -> %s (%u ms)", name.str(), (int)timeoutms, ipstr.str(), lookupTimeMS); + fflush(NULL); + } + } + + virtual bool stop() override + { + return true; + } + + virtual bool canReuse() const override + { + return true; + } + }; + +public: + IMPLEMENT_IINTERFACE; + + IPooledThread *createNew() + { + return new CAddrPoolHandler(); + } +}; + +class getaddrinfotest : public CppUnit::TestFixture +{ +public: + CPPUNIT_TEST_SUITE(getaddrinfotest); + CPPUNIT_TEST(testaddr); + CPPUNIT_TEST_SUITE_END(); + +/* + * can change settings with: + * + * + * + * + * global: + * expert: + * disableDNSTimeout: true + * maxDNSThreads: 100 + */ + + void testaddr1(const char *_name, unsigned timeoutms, bool logIt=true) + { + StringBuffer name(_name); + + SocketEndpoint ep; + CCycleTimer timer; + int srtn = ep.ipset(name.str(), timeoutms); + unsigned lookupTimeMS = timer.elapsedMs(); + + StringBuffer ipstr; + if (logIt && srtn) + ep.getIpText(ipstr); + else if (!srtn) + ipstr.append("failed"); + if ((logIt && srtn) || (!srtn)) + { + DBGLOG("%s (%d) -> %s (%u ms)", name.str(), (int)timeoutms, ipstr.str(), lookupTimeMS); + fflush(NULL); + } + } + + void testaddr() + { + fflush(NULL); + DBGLOG(" "); // to get past the "." ... + fflush(NULL); + + testaddr1("google.com", 3); + testaddr1("google.com", 500); + + Owned threadFactory = new CAddrPoolFactory(); + Owned threadPool = createThreadPool("GetAddrThreadPool", threadFactory, true, nullptr, 60); + + // ----------------- + + Owned t1a = new CAddrThreadArgs("mck1.com", 5); + Owned t2a = new CAddrThreadArgs("mck1.com", 5000); + Owned t3a = new CAddrThreadArgs("mck1.com", INFINITE); + + Owned t1b = new CAddrThreadArgs("mck101.com", 5); + Owned t2b = new CAddrThreadArgs("mck101.com", 5000); + Owned t3b = new CAddrThreadArgs("mck101.com", INFINITE); + + Owned t1c = new CAddrThreadArgs("google.com", 3); + Owned t2c = new CAddrThreadArgs("google.com", 500); + Owned t3c = new CAddrThreadArgs("google.com", 10000); + + Owned t1d = new CAddrThreadArgs("localhost", 3); + Owned t2d = new CAddrThreadArgs("localhost", 500); + Owned t3d = new CAddrThreadArgs("localhost", 1000); + + Owned t1e = new CAddrThreadArgs("127.0.0.1", 2000); + Owned t2e = new CAddrThreadArgs("1.2.3.4", 2000); + + Owned t1f = new CAddrThreadArgs("mck2.com", INFINITE); + + Owned t1g = new CAddrThreadArgs("mck103.com", INFINITE); + + Owned t1h = new CAddrThreadArgs("*bogus+", INFINITE); + + // ----------------- + + threadPool->startNoBlock(t1a); + threadPool->startNoBlock(t2a); + threadPool->startNoBlock(t3a); + + threadPool->startNoBlock(t1b); + threadPool->startNoBlock(t2b); + threadPool->startNoBlock(t3b); + + threadPool->startNoBlock(t1c); + threadPool->startNoBlock(t2c); + threadPool->startNoBlock(t3c); + + threadPool->startNoBlock(t1d); + threadPool->startNoBlock(t2d); + threadPool->startNoBlock(t3d); + + threadPool->startNoBlock(t1e); + threadPool->startNoBlock(t2e); + + threadPool->startNoBlock(t1f); + + threadPool->startNoBlock(t1g); + + threadPool->startNoBlock(t1h); + + threadPool->joinAll(); + + fflush(NULL); + + threadPool->startNoBlock(t1c); + threadPool->startNoBlock(t2c); + threadPool->startNoBlock(t3c); + + threadPool->joinAll(true); + + fflush(NULL); + + // --------------- + + CCycleTimer timer; + for (int i=0; i<10000; i++) + { + testaddr1("google.com", 500, false); + } + unsigned lookupTimeMS = timer.elapsedMs(); + DBGLOG("10k lookups (same thread) time = %u ms", lookupTimeMS); + fflush(NULL); + + Owned threadPool1 = createThreadPool("GetAddrThreadPool1", threadFactory, true, nullptr, 1); + + timer.reset(); + Owned t10a = new CAddrThreadArgs("google.com", 500, false); + for (int i=0; i<10000; i++) + { + threadPool1->start(t10a, "threadpool-test", 99999999); + } + + threadPool1->joinAll(true); + + lookupTimeMS = timer.elapsedMs(); + fflush(NULL); + DBGLOG("10k lookups (threadpool of 1) time = %u ms", lookupTimeMS); + + fflush(NULL); + DBGLOG("testaddr complete"); + fflush(NULL); + Sleep(7000); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( getaddrinfotest ); +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( getaddrinfotest, "getaddrinfotest" ); + #endif // _USE_CPPUNIT diff --git a/thorlcr/activities/funnel/thfunnelslave.cpp b/thorlcr/activities/funnel/thfunnelslave.cpp index 91deee8d18f..32962951c52 100644 --- a/thorlcr/activities/funnel/thfunnelslave.cpp +++ b/thorlcr/activities/funnel/thfunnelslave.cpp @@ -41,7 +41,7 @@ class CParallelFunnel : implements IRowStream, public CSimpleInterface StringAttr idStr; unsigned inputIndex; rowcount_t readThisInput; // purely for tracing - bool stopping; + std::atomic stopping{false}; public: CInputHandler(CParallelFunnel &_funnel, unsigned _inputIndex) : threaded("CInputHandler", this), funnel(_funnel), inputIndex(_inputIndex) @@ -63,8 +63,6 @@ class CParallelFunnel : implements IRowStream, public CSimpleInterface } void stop() { - CriticalBlock b(stopCrit); - if (stopping) return; stopping = true; } void join() @@ -77,6 +75,9 @@ class CParallelFunnel : implements IRowStream, public CSimpleInterface { bool started = false; IEngineRowStream *inputStream = nullptr; + constexpr unsigned chunkSize = 32; + const void * rows[chunkSize]; + unsigned numRows = 0; try { funnel.activity.startInput(inputIndex); @@ -84,20 +85,26 @@ class CParallelFunnel : implements IRowStream, public CSimpleInterface inputStream = funnel.activity.queryInputStream(inputIndex); while (!stopping) { - OwnedConstThorRow row = inputStream->ungroupedNextRow(); - if (!row) break; - + numRows = 0; + for (;numRows < chunkSize; numRows++) { - CriticalBlock b(stopCrit); - if (stopping) break; + const void * row = inputStream->ungroupedNextRow(); + if (!row) + break; + rows[numRows] = row; } - CriticalBlock b(funnel.crit); // will mean first 'push' could block on fullSem, others on this crit. - funnel.push(row.getClear()); - ++readThisInput; + + if (numRows == 0) break; + + funnel.pushMulti(numRows, rows); + readThisInput += numRows; + if (numRows != chunkSize) + break; } } catch (IException *e) { + roxiemem::ReleaseRoxieRowArray(numRows, rows); funnel.fireException(e); e->Release(); } @@ -124,27 +131,73 @@ class CParallelFunnel : implements IRowStream, public CSimpleInterface unsigned eoss; StringAttr idStr; - CriticalSection fullCrit, crit; + CriticalSection crit; + CriticalSection writerCrit; SimpleInterThreadQueueOf rows; Semaphore fullSem; size32_t totSize; - bool full, stopped; + unsigned waiting = 0; + bool stopped; Linked serializer; void push(const void *row) { - CriticalBlock b2(fullCrit); // exclusivity for totSize / full - if (stopped) + size32_t rowSize = thorRowMemoryFootprint(serializer, row); + + bool waitForSpace = false; + // only allow a single writer at a time, so only a single thread is waiting on the semaphore - otherwise signal() takes a very long time { - ReleaseThorRow(row); - return; + + CriticalBlock b(crit); // will mean first 'push' could block on fullSem, others on this crit. + if (stopped) + { + ReleaseThorRow(row); + return; + } + rows.enqueue(row); + totSize += rowSize; + if (totSize > FUNNEL_MIN_BUFF_SIZE) + { + waiting++; + waitForSpace = true; + } } - rows.enqueue(row); - totSize += thorRowMemoryFootprint(serializer, row); - while (totSize > FUNNEL_MIN_BUFF_SIZE) + + if (waitForSpace) { - full = true; - CriticalUnblock b(fullCrit); + CriticalBlock b(writerCrit); + fullSem.wait(); // block pushers on crit + } + } + + void pushMulti(unsigned numRows, const void * * newRows) + { + size32_t rowSizes = 0; + for (unsigned i=0; i < numRows; i++) + rowSizes += thorRowMemoryFootprint(serializer, newRows[i]); + + bool waitForSpace = false; + // only allow a single writer at a time, so only a single thread is waiting on the semaphore - otherwise signal() takes a very long time + { + CriticalBlock b(crit); // will mean first 'push' could block on fullSem, others on this crit. + if (stopped) + { + for (unsigned i=0; i < numRows; i++) + ReleaseThorRow(newRows[i]); + return; + } + rows.enqueueMany(numRows, newRows); + totSize += rowSizes; + if (totSize > FUNNEL_MIN_BUFF_SIZE) + { + waiting++; + waitForSpace = true; + } + } + + if (waitForSpace) + { + CriticalBlock b(writerCrit); fullSem.wait(); // block pushers on crit } } @@ -168,7 +221,8 @@ class CParallelFunnel : implements IRowStream, public CSimpleInterface { idStr.set(activityKindStr(activity.queryContainer().getKind())); - stopped = full = false; + stopped = false; + waiting = 0; totSize = 0; eoss = 0; serializer.set(activity.queryRowSerializer()); @@ -210,10 +264,11 @@ class CParallelFunnel : implements IRowStream, public CSimpleInterface CInputHandler &handler = inputHandlers.item(h); handler.stop(); } + { - CriticalBlock b(fullCrit); + CriticalBlock b(crit); stopped = true; // ensure any pending push()'s don't enqueue and if big row potentially block again. - if (full) + if (waiting) { for (;;) { @@ -222,7 +277,8 @@ class CParallelFunnel : implements IRowStream, public CSimpleInterface } rows.stop(); // I don't think really needed totSize = 0; - fullSem.signal(); + fullSem.signal(waiting); + waiting = 0; } } ForEachItemIn(h2, inputHandlers) @@ -243,16 +299,19 @@ class CParallelFunnel : implements IRowStream, public CSimpleInterface return NULL; } size32_t sz = thorRowMemoryFootprint(serializer, row.get()); + unsigned numToSignal = 0; { - CriticalBlock b(fullCrit); + CriticalBlock b(crit); assertex(totSize>=sz); totSize -= sz; - if (full) + if (waiting && (totSize <= FUNNEL_MIN_BUFF_SIZE)) { - full = false; - fullSem.signal(); + numToSignal = 1; + waiting--; } } + if (numToSignal) + fullSem.signal(numToSignal); return row.getClear(); } diff --git a/thorlcr/activities/hashdistrib/thhashdistribslave.cpp b/thorlcr/activities/hashdistrib/thhashdistribslave.cpp index 61a49ced9a9..da214c0f16a 100644 --- a/thorlcr/activities/hashdistrib/thhashdistribslave.cpp +++ b/thorlcr/activities/hashdistrib/thhashdistribslave.cpp @@ -2760,26 +2760,11 @@ class CSpill : implements IRowWriter, public CSimpleInterface ::Release(writer); writer = NULL; spillFileIO->flush(); - mergeStats(stats, this); - spillFile->noteSize(getStatistic(StSizeSpillFile)); + mergeRemappedStats(stats, spillFileIO, diskToTempStatsMap); + stats.addStatistic(StNumSpills, 1); + spillFile->noteSize(spillFileIO->getStatistic(StSizeDiskWrite)); spillFileIO.clear(); } - inline __int64 getStatistic(StatisticKind kind) const - { - switch (kind) - { - case StSizeSpillFile: - return spillFileIO->getStatistic(StSizeDiskWrite); - case StTimeSortElapsed: - return spillFileIO->getStatistic(StTimeDiskWriteIO); - case StSizeDiskWrite: - return 0; // Return file size as StSizeSpillFile kind. To avoid confusion, StSizeDiskWrite will not be returned - case StNumSpills: - return 1; - default: - return spillFileIO->getStatistic(kind); - } - } // IRowWriter virtual void putRow(const void *row) override { diff --git a/thorlcr/activities/loop/thloop.cpp b/thorlcr/activities/loop/thloop.cpp index b32da6e09ab..ebdde73be06 100644 --- a/thorlcr/activities/loop/thloop.cpp +++ b/thorlcr/activities/loop/thloop.cpp @@ -334,7 +334,7 @@ class CLocalResultActivityMasterBase : public CMasterActivity Owned inputRowIf; public: - CLocalResultActivityMasterBase(CMasterGraphElement *info) : CMasterActivity(info, spillingActivityStatistics) + CLocalResultActivityMasterBase(CMasterGraphElement *info) : CMasterActivity(info) { } virtual void init() override diff --git a/thorlcr/activities/loop/thloopslave.cpp b/thorlcr/activities/loop/thloopslave.cpp index ea7d149ff89..722358f0e4d 100644 --- a/thorlcr/activities/loop/thloopslave.cpp +++ b/thorlcr/activities/loop/thloopslave.cpp @@ -643,7 +643,7 @@ class CLocalResultSpillActivity : public CSlaveActivity } public: - CLocalResultSpillActivity(CGraphElementBase *_container) : CSlaveActivity(_container, spillingActivityStatistics) + CLocalResultSpillActivity(CGraphElementBase *_container) : CSlaveActivity(_container) { helper = (IHThorLocalResultSpillArg *)queryHelper(); appendOutputLinked(this); @@ -708,7 +708,7 @@ class CLocalResultSpillActivity : public CSlaveActivity class CLocalResultWriteActivityBase : public ProcessSlaveActivity { public: - CLocalResultWriteActivityBase(CGraphElementBase *_container) : ProcessSlaveActivity(_container, spillingActivityStatistics) + CLocalResultWriteActivityBase(CGraphElementBase *_container) : ProcessSlaveActivity(_container) { } virtual IThorResult *createResult() = 0; diff --git a/thorlcr/activities/nsplitter/thnsplitterslave.cpp b/thorlcr/activities/nsplitter/thnsplitterslave.cpp index 5331fedf845..ef47bcc27bf 100644 --- a/thorlcr/activities/nsplitter/thnsplitterslave.cpp +++ b/thorlcr/activities/nsplitter/thnsplitterslave.cpp @@ -152,7 +152,7 @@ class NSplitterSlaveActivity : public CSlaveActivity, implements ISharedSmartBuf } } public: - NSplitterSlaveActivity(CGraphElementBase *_container) : CSlaveActivity(_container, spillingActivityStatistics), writer(*this) + NSplitterSlaveActivity(CGraphElementBase *_container) : CSlaveActivity(_container), writer(*this) { numOutputs = container.getOutputs(); connectedOutputSet.setown(createBitSet()); diff --git a/thorlcr/master/thactivitymaster.cpp b/thorlcr/master/thactivitymaster.cpp index 86210a47c87..a99a0db2919 100644 --- a/thorlcr/master/thactivitymaster.cpp +++ b/thorlcr/master/thactivitymaster.cpp @@ -207,10 +207,8 @@ class CGenericMasterGraphElement : public CMasterGraphElement case TAKdistributed: case TAKtrace: case TAKemptyaction: - ret = new CMasterActivity(this); - break; case TAKsplit: - ret = new CMasterActivity(this, spillingActivityStatistics); + ret = new CMasterActivity(this); break; case TAKsoap_rowdataset: case TAKsoap_rowaction: diff --git a/thorlcr/thorutil/thbuf.cpp b/thorlcr/thorutil/thbuf.cpp index 42457777dae..2e45c7c78d8 100644 --- a/thorlcr/thorutil/thbuf.cpp +++ b/thorlcr/thorutil/thbuf.cpp @@ -668,7 +668,7 @@ static std::tuple createSerialOutputSt - Writer: - The writer to an in-memory queue, and when the queue is full, or a certain number of rows have been queued, it writes to starts writing to temp files. - The writer will always write to the queue if it can, even after it has started spilling. - - The writer commits to disk at LookAheadOptions::writeAheadSize granularity + - The writer commits to disk at LookAheadOptions::writeAheadSize granularity. NB: size is uncompressed, measured before data is written to disk. - The writer creates a new temp file when the current one reaches LookAheadOptions::tempFileGranularity - The writer pushes the current nextOutputRow to a queue when it creates the next output file (used by the reader to know when to move to next) - NB: writer implements ISmartRowBuffer::flush() which has slightly weird semantics (blocks until everything is read or stopped) @@ -706,7 +706,6 @@ class CCompressedSpillingRowStream: public CSimpleInterfaceOf, Owned outputStream; std::unique_ptr outputStreamSerializer; memsize_t pendingFlushToDiskSz = 0; - offset_t currentTempFileSize = 0; CFileOwner *currentOwnedOutputFile = nullptr; Owned currentOutputIFileIO; // keep for stats CriticalSection outputFilesQCS; @@ -876,15 +875,14 @@ class CCompressedSpillingRowStream: public CSimpleInterfaceOf, { if (pendingFlushToDiskSz <= threshold) return false; + pendingFlushToDiskSz = 0; rowcount_t currentNextOutputRow = nextOutputRow.load(); trace("WRITE: Flushed to disk. nextOutputRow = %" RCPF "u", currentNextOutputRow); outputStream->flush(); - currentTempFileSize += pendingFlushToDiskSz; + offset_t currentTempFileSize = currentOutputIFileIO->getStatistic(StSizeDiskWrite); currentOwnedOutputFile->noteSize(currentTempFileSize); - pendingFlushToDiskSz = 0; if (currentTempFileSize > options.tempFileGranularity) { - currentTempFileSize = 0; { CriticalBlock b(outputStreamCS); // set if reader isn't bounded yet, or queue next boundary @@ -899,7 +897,7 @@ class CCompressedSpillingRowStream: public CSimpleInterfaceOf, trace("WRITE: adding to tempFileEndRowMarker(size=%u): %" RCPF "u", (unsigned)outputFileEndRowMarkers.size(), currentNextOutputRow); } } - createNextOutputStream(); + createNextOutputStream(); // NB: creates new currentOwnedOutputFile/currentOutputIFileIO } committedRows = currentNextOutputRow; return true; @@ -2150,21 +2148,9 @@ class CSharedWriteAheadDisk : public CSharedWriteAheadBase } virtual unsigned __int64 getStatistic(StatisticKind kind) const override { - switch (kind) - { - case StSizeSpillFile: - return tempFileIO->getStatistic(StSizeDiskWrite); - case StCycleDiskWriteIOCycles: - case StTimeDiskWriteIO: - case StSizeDiskWrite: - return 0; - case StNumSpills: - return 1; - case StTimeSpillElapsed: - return tempFileIO->getStatistic(StCycleDiskWriteIOCycles); - default: - return tempFileIO->getStatistic(kind); - } + if (kind==StNumSpills) + return 1; + return tempFileIO->getStatistic(kind); } }; @@ -2464,6 +2450,7 @@ class CSharedFullSpillingWriteAhead : public CInterfaceOfflush(); tempFileOwner->noteSize(iFileIO->getStatistic(StSizeDiskWrite)); - ::mergeStats(inactiveStats, iFileIO); + updateRemappedStatsDelta(inactiveStats, previousFileStats, iFileIO, diskToTempStatsMap); // NB: also updates prev to current + previousFileStats.reset(); iFileIO.clear(); - outputStream.clear(); } } void createOutputStream() { + closeWriter(); // Ensure stats from closing files are preserved in inactiveStats // NB: Called once, when spilling starts. tempFileOwner.setown(activity.createOwnedTempFile(baseTmpFilename)); auto res = createSerialOutputStream(&(tempFileOwner->queryIFile()), compressHandler, options, numOutputs + 1); outputStream.setown(std::get<0>(res)); iFileIO.setown(std::get<1>(res)); totalInputRowsRead = inMemTotalRows; + inactiveStats.addStatistic(StNumSpills, 1); } void writeRowsFromInput() { @@ -2549,6 +2539,7 @@ class CSharedFullSpillingWriteAhead : public CInterfaceOfflush(); totalInputRowsRead.fetch_add(newRowsWritten); tempFileOwner->noteSize(iFileIO->getStatistic(StSizeDiskWrite)); + updateRemappedStatsDelta(inactiveStats, previousFileStats, iFileIO, diskToTempStatsMap); // NB: also updates prev to current // JCSMORE - could track size written, and start new file at this point (e.g. every 100MB), // and track their starting points (by row #) in a vector // We could then tell if/when the readers catch up, and remove consumed files as they do. @@ -2562,7 +2553,7 @@ class CSharedFullSpillingWriteAhead : public CInterfaceOfqueryRowMetaData()), serializer(rowIf->queryRowSerializer()), allocator(rowIf->queryRowAllocator()), deserializer(rowIf->queryRowDeserializer()), - inactiveStats(spillingWriteAheadStatistics) + inactiveStats(spillStatistics), previousFileStats(spillStatistics) { assertex(input); @@ -2726,29 +2717,7 @@ class CSharedFullSpillingWriteAhead : public CInterfaceOfgetStatistic(useKind); - v += inactiveStats.getStatisticValue(useKind); - return v; + return inactiveStats.getStatisticValue(kind); } }; diff --git a/thorlcr/thorutil/thormisc.cpp b/thorlcr/thorutil/thormisc.cpp index 0781cee53d4..fa2a6164204 100644 --- a/thorlcr/thorutil/thormisc.cpp +++ b/thorlcr/thorutil/thormisc.cpp @@ -74,8 +74,9 @@ static Owned ClusterMPAllocator; // stat. mappings shared between master and slave activities const StatisticsMapping spillStatistics({StTimeSpillElapsed, StTimeSortElapsed, StNumSpills, StSizeSpillFile, StSizePeakTempDisk}); +const StatisticsMapping executeStatistics({StTimeTotalExecute, StTimeLocalExecute, StTimeBlocked}); const StatisticsMapping soapcallStatistics({StTimeSoapcall}); -const StatisticsMapping basicActivityStatistics({StTimeTotalExecute, StTimeLocalExecute, StTimeBlocked, StNumParallelExecute}); +const StatisticsMapping basicActivityStatistics({StNumParallelExecute}, executeStatistics, spillStatistics); const StatisticsMapping groupActivityStatistics({StNumGroups, StNumGroupMax}, basicActivityStatistics); const StatisticsMapping indexReadFileStatistics({}, diskReadRemoteStatistics, jhtreeCacheStatistics); const StatisticsMapping indexReadActivityStatistics({StNumRowsProcessed}, indexReadFileStatistics, basicActivityStatistics); @@ -89,15 +90,18 @@ const StatisticsMapping joinActivityStatistics({StNumLeftRows, StNumRightRows}, const StatisticsMapping diskReadActivityStatistics({StNumDiskRowsRead, }, basicActivityStatistics, diskReadRemoteStatistics); const StatisticsMapping diskWriteActivityStatistics({StPerReplicated}, basicActivityStatistics, diskWriteRemoteStatistics); const StatisticsMapping sortActivityStatistics({}, basicActivityStatistics, spillStatistics); -const StatisticsMapping graphStatistics({StNumExecutions, StSizeSpillFile, StSizeGraphSpill, StSizePeakTempDisk, StSizePeakEphemeralDisk, StTimeUser, StTimeSystem, StNumContextSwitches, StSizeMemory, StSizePeakMemory, StSizeRowMemory, StSizePeakRowMemory}, basicActivityStatistics); const StatisticsMapping diskReadPartStatistics({StNumDiskRowsRead}, diskReadRemoteStatistics); const StatisticsMapping indexDistribActivityStatistics({}, basicActivityStatistics, jhtreeCacheStatistics); const StatisticsMapping soapcallActivityStatistics({}, basicActivityStatistics, soapcallStatistics); const StatisticsMapping hashDedupActivityStatistics({}, spillStatistics, diskWriteRemoteStatistics, basicActivityStatistics); const StatisticsMapping hashDistribActivityStatistics({StNumLocalRows, StNumRemoteRows, StSizeRemoteWrite}, basicActivityStatistics); -const StatisticsMapping spillingActivityStatistics({}, spillStatistics, basicActivityStatistics); -const StatisticsMapping spillingWriteAheadStatistics({}, spillStatistics); -const StatisticsMapping loopActivityStatistics({StNumIterations}, spillingActivityStatistics); +const StatisticsMapping loopActivityStatistics({StNumIterations}, basicActivityStatistics); +const StatisticsMapping graphStatistics({StNumExecutions, StSizeSpillFile, StSizeGraphSpill, StSizePeakTempDisk, StSizePeakEphemeralDisk, StTimeUser, StTimeSystem, StNumContextSwitches, StSizeMemory, StSizePeakMemory, StSizeRowMemory, StSizePeakRowMemory}, executeStatistics); + +const StatKindMap diskToTempStatsMap +={ {StSizeDiskWrite, StSizeSpillFile}, + {StTimeDiskWriteIO, StTimeSpillElapsed} + }; MODULE_INIT(INIT_PRIORITY_STANDARD) { diff --git a/thorlcr/thorutil/thormisc.hpp b/thorlcr/thorutil/thormisc.hpp index fc45b30e472..6c667ebd8e9 100644 --- a/thorlcr/thorutil/thormisc.hpp +++ b/thorlcr/thorutil/thormisc.hpp @@ -167,8 +167,9 @@ extern graph_decl const StatisticsMapping soapcallActivityStatistics; extern graph_decl const StatisticsMapping indexReadFileStatistics; extern graph_decl const StatisticsMapping hashDedupActivityStatistics; extern graph_decl const StatisticsMapping hashDistribActivityStatistics; -extern graph_decl const StatisticsMapping spillingActivityStatistics; -extern graph_decl const StatisticsMapping spillingWriteAheadStatistics; + +// Maps disk related stats to spill stats +extern graph_decl const std::map diskToTempStatsMap; class BooleanOnOff {