File indexing completed on 2026-04-10 08:39:06
0001
0002 split_rule_dict = {
0003 "allowEmptyInput": "AE",
0004 "allowIncompleteInDS": "AI",
0005 "addNthFieldToLFN": "AN",
0006 "allowPartialFinish": "AP",
0007 "altStageOut": "AT",
0008 "avoidVP": "AV",
0009 "maxCoreCount": "CC",
0010 "cloudAsVO": "CV",
0011 "ddmBackEnd": "DE",
0012 "disableAutoFinish": "DF",
0013 "disableReassign": "DI",
0014 "debugMode": "DM",
0015 "disableAutoRetry": "DR",
0016 "dynamicNumEvents": "DY",
0017 "nEsConsumers": "EC",
0018 "nEventsPerInput": "EI",
0019 "encJobParams": "EJ",
0020 "nEventsPerWorker": "ES",
0021 "firstContentsFeed": "FC",
0022 "failGoalUnreached": "FG",
0023 "fineGrainedProc": "FP",
0024 "firstEvent": "FT",
0025 "fullChain": "FU",
0026 "groupBoundaryID": "GB",
0027 "hpoWorkflow": "HO",
0028 "instantiateTmplSite": "IA",
0029 "inFilePosEvtNum": "IF",
0030 "ipStack": "IK",
0031 "allowInputLAN": "IL",
0032 "ignoreMissingInDS": "IM",
0033 "intermediateTask": "IN",
0034 "ipConnectivity": "IP",
0035 "inputPreStaging": "IS",
0036 "instantiateTmpl": "IT",
0037 "allowInputWAN": "IW",
0038 "noLoopingCheck": "LC",
0039 "useLocalIO": "LI",
0040 "limitedSites": "LS",
0041 "loadXML": "LX",
0042 "minCpuEfficiency": "MC",
0043 "messageDriven": "MD",
0044 "mergeEsOnOS": "ME",
0045 "nMaxFilesPerJob": "MF",
0046 "maxJumboPerSite": "MJ",
0047 "maxNumJobs": "MN",
0048 "mergeOutput": "MO",
0049 "multiStepExec": "MS",
0050 "maxWalltime": "MW",
0051 "maxEventsPerJob": "MX",
0052 "noExecStrCnv": "NC",
0053 "notDiscardEvents": "ND",
0054 "nEventsPerJob": "NE",
0055 "nFilesPerJob": "NF",
0056 "nGBPerJob": "NG",
0057 "noInputPooling": "NI",
0058 "nJumboJobs": "NJ",
0059 "noAutoPause": "NP",
0060 "nSitesPerJob": "NS",
0061 "nChunksToWait": "NT",
0062 "noWaitParent": "NW",
0063 "orderInputBy": "OI",
0064 "orderByLB": "OL",
0065 "onSiteMerging": "OM",
0066 "osMatching": "OS",
0067 "onlyTagsForFC": "OT",
0068 "pushStatusChanges": "PC",
0069 "pushJob": "PJ",
0070 "pfnList": "PL",
0071 "putLogToOS": "PO",
0072 "runUntilClosed": "RC",
0073 "registerDatasets": "RD",
0074 "registerEsFiles": "RE",
0075 "respectLB": "RL",
0076 "retryModuleRules": "RM",
0077 "reuseSecOnDemand": "RO",
0078 "releasePerLB": "RP",
0079 "respectSplitRule": "RR",
0080 "randomSeed": "RS",
0081 "retryRamOffset": "RX",
0082 "retryRamStep": "RY",
0083 "retryRamMax": "RZ",
0084 "resurrectConsumers": "SC",
0085 "switchEStoNormal": "SE",
0086 "stayOutputOnSite": "SO",
0087 "scoutSuccessRate": "SS",
0088 "useSecrets": "ST",
0089 "segmentedWork": "SW",
0090 "totNumJobs": "TJ",
0091 "tgtMaxOutputForNG": "TN",
0092 "t1Weight": "TW",
0093 "useBuild": "UB",
0094 "useJobCloning": "UC",
0095 "useRealNumEvents": "UE",
0096 "useFileAsSourceLFN": "UF",
0097 "usePrePro": "UP",
0098 "useScout": "US",
0099 "usePrefetcher": "UT",
0100 "useExhausted": "UX",
0101 "useZipToPin": "UZ",
0102 "writeInputToFile": "WF",
0103 "workflowHoldup": "WH",
0104 "waitInput": "WI",
0105 "maxAttemptES": "XA",
0106 "decAttOnFailedES": "XF",
0107 "maxAttemptEsJob": "XJ",
0108 "nEventsPerMergeJob": "ZE",
0109 "nFilesPerMergeJob": "ZF",
0110 "nGBPerMergeJob": "ZG",
0111 "nMaxFilesPerMergeJob": "ZM",
0112 }
0113
0114
0115
0116 enum_limitedSites = {"1": "with_allowlist", "2": "with_denylist", "3": "with_allow_and_denylist"}
0117 enum_ipConnectivity = {"1": "full", "2": "http"}
0118 enum_ipStack = {"4": "IPv4", "6": "IPv6"}
0119 enum_altStageOut = {"1": "on", "2": "off", "3": "force"}
0120 enum_inputLAN = {"1": "use", "2": "only"}
0121
0122
0123 enum_useScout = {"1": "no_use", "2": "will_update_requirements", "3": "updated_requirements"}
0124 enum_usePrePro = {"1": "toPreProcess", "2": "preProcessed", "3": "postPProcess"}
0125 enum_registerDatasets = {"1": "registering", "2": "registered"}
0126 enum_inputPreStaging = {"0": "notUse", "1": "use"}
0127 enum_firstContentsFeed = {"0": "False", "1": "True"}
0128 enum_fullChain = {"1": "only", "2": "require", "3": "capable"}
0129 enum_orderInputBy = {"1": "eventsAlignment"}
0130
0131
0132 split_rule_value_dict = {
0133 "US": enum_useScout,
0134 "LS": enum_limitedSites,
0135 "IP": enum_ipConnectivity,
0136 "IK": enum_ipStack,
0137 "AT": enum_altStageOut,
0138 "IL": enum_inputLAN,
0139 "UP": enum_usePrePro,
0140 "RD": enum_registerDatasets,
0141 "IS": enum_inputPreStaging,
0142 "FC": enum_firstContentsFeed,
0143 "FU": enum_fullChain,
0144 "OI": enum_orderInputBy,
0145 }
0146
0147
0148 changeable_split_rule_names = [
0149 "allowIncompleteInDS",
0150 "t1Weight",
0151 "nEsConsumers",
0152 "nMaxFilesPerJob",
0153 "nGBPerJob",
0154 "noInputPooling",
0155 "nFilesPerJob",
0156 "nEventsPerWorker",
0157 "nJumboJobs",
0158 "avoidVP",
0159 "allowInputLAN",
0160 "useLocalIO",
0161 "noLoopingCheck",
0162 "maxCoreCount",
0163 "onlyTagsForFC",
0164 "useZipToPin",
0165 "ignoreMissingInDS",
0166 "noAutoPause",
0167 ]
0168
0169 changeable_split_rule_tags = [split_rule_dict[tmp_name] for tmp_name in changeable_split_rule_names]
0170
0171
0172
0173 def extract_rule_values(split_rules: str, rule_names: list, is_sub_rule: bool = False) -> dict:
0174 """
0175 Extract rule values from split rule string
0176
0177 :param split_rules: a comma separated string
0178 :param rule_names: a list of rule names
0179 :param is_sub_rule: True to indicate the rule is a subrule
0180 :return: dict of rule names and values
0181 """
0182 if split_rules is None:
0183 split_rules = ""
0184 ret = {}
0185 if is_sub_rule:
0186 rule_separator = "|"
0187 key_value_separator = ":"
0188 else:
0189 rule_separator = ","
0190 key_value_separator = "="
0191 for tmp_rule in split_rules.split(rule_separator):
0192 for tmp_name in rule_names:
0193 if tmp_name in split_rule_dict and tmp_rule.startswith(split_rule_dict[tmp_name] + key_value_separator):
0194 ret[tmp_name] = tmp_rule.split(key_value_separator)[-1]
0195 break
0196 for tmp_name in rule_names:
0197 if tmp_name not in ret:
0198 ret[tmp_name] = None
0199 return ret
0200
0201
0202
0203 def replace_rule(split_rules: str, rule_name: str, rule_value: int | str, is_sub_rule=False):
0204 """
0205 Replace a rule in the split rule string
0206
0207 :param split_rules: s comma separated string
0208 :param rule_name: rule name
0209 :param rule_value: rule value
0210 :param is_sub_rule: True to indicate the rule is a subrule
0211 :return: string of split rules
0212 """
0213 if rule_name not in split_rule_dict:
0214 return split_rules
0215 if split_rules is None:
0216 split_rules = ""
0217 if is_sub_rule:
0218 rule_separator = "|"
0219 key_value_separator = ":"
0220 else:
0221 rule_separator = ","
0222 key_value_separator = "="
0223 tmp_str = ""
0224 for tmp_rule in split_rules.split(rule_separator):
0225 if tmp_rule.startswith(split_rule_dict[rule_name] + key_value_separator):
0226 continue
0227 if tmp_str != "":
0228 tmp_str += rule_separator
0229 tmp_str += tmp_rule
0230 if tmp_str != "":
0231 tmp_str += rule_separator
0232 tmp_str += split_rule_dict[rule_name] + key_value_separator + str(rule_value)
0233 return tmp_str
0234
0235
0236
0237 def remove_rule(split_rules: str, rule_token: str, is_sub_rule: bool = False):
0238 """
0239 Remove a rule from the split rule string
0240
0241 :param split_rules: s comma separated string
0242 :param rule_token: rule token
0243 :param is_sub_rule: TRue to indicate the rule is a subrule
0244 :return: string of split rules
0245 """
0246 if split_rules is None:
0247 split_rules = ""
0248 if is_sub_rule:
0249 rule_separator = "|"
0250 key_value_separator = ":"
0251 else:
0252 rule_separator = ","
0253 key_value_separator = "="
0254 tmp_str = ""
0255 for tmp_rule in split_rules.split(rule_separator):
0256 if tmp_rule.startswith(rule_token + key_value_separator):
0257 continue
0258 if tmp_str != "":
0259 tmp_str += rule_separator
0260 tmp_str += tmp_rule
0261 return tmp_str
0262
0263
0264
0265 def decode_split_rule(split_rules: str) -> str:
0266 """
0267 Convert a compact split-rule string into a human-readable one by replacing
0268 two-letter tags with their full names from split_rule_dict.
0269
0270 The input is a comma-separated string of ``TAG=value`` pairs, e.g.::
0271
0272 "AE=1,AN=1,2,3,AI=2"
0273
0274 Special case: ``AN`` (addNthFieldToLFN) may carry a comma-separated list
0275 as its value (e.g. ``AN=1,2,3``). All other tags treat ``=`` as the sole
0276 separator and never embed commas in their values.
0277
0278 :param split_rules: compact comma-separated split-rule string, or None/empty
0279 :return: human-readable comma-separated string, e.g.
0280 ``"allowEmptyInput=1,addNthFieldToLFN=1,2,3,allowIncompleteInDS=2"``
0281 Unknown tags are kept as-is.
0282 """
0283 if not split_rules:
0284 return split_rules or ""
0285
0286
0287 tag_to_name = {tag: name for name, tag in split_rule_dict.items()}
0288
0289
0290 an_tag = split_rule_dict["addNthFieldToLFN"]
0291
0292
0293
0294
0295 tokens = split_rules.split(",")
0296 rules = []
0297 for token in tokens:
0298
0299 eq_pos = token.find("=")
0300 if eq_pos == 2:
0301 candidate_tag = token[:2]
0302 if candidate_tag in tag_to_name or candidate_tag == an_tag:
0303
0304 rules.append([candidate_tag, token[3:]])
0305 continue
0306
0307
0308
0309 if rules and rules[-1][0] == an_tag:
0310 rules[-1].append(token)
0311 else:
0312
0313 rules.append([None, token])
0314
0315
0316 result_parts = []
0317 for parts in rules:
0318 tag = parts[0]
0319 if tag is None:
0320
0321 result_parts.append(parts[1])
0322 else:
0323 value = "_".join(parts[1:])
0324 name = tag_to_name.get(tag, tag)
0325 label = split_rule_value_dict.get(tag, {}).get(value, value)
0326 result_parts.append(f"{name}={label}")
0327
0328 return ",".join(result_parts)
0329
0330
0331
0332 def remove_rule_with_name(split_rules: str, rule_name: str, is_sub_rule: bool = False) -> str:
0333 """
0334 Remove a rule from the split rule string using the rule name
0335
0336 :param split_rules: a comma separated string
0337 :param rule_name: rule name
0338 :param is_sub_rule: True to indicate the rule is a subrule
0339 :return: string of split rules
0340 """
0341 split_rules = remove_rule(split_rules, split_rule_dict[rule_name], is_sub_rule)
0342 return split_rules