Return unique directory with a number greater than the current maximum one. The number is assumed to start directly after prefix. if keep is true directories with a number less than (maxnum-keep) will be removed. If .lock files are used (lock_timeout non-zero), algor
(
cls, prefix="session-", rootdir=None, keep=3, lock_timeout=172800
)
| 1273 | |
| 1274 | @classmethod |
| 1275 | def make_numbered_dir( |
| 1276 | cls, prefix=class="st">"session-", rootdir=None, keep=3, lock_timeout=172800 |
| 1277 | ): class="cm"># two days |
| 1278 | class="st">"""Return unique directory with a number greater than the current |
| 1279 | maximum one. The number is assumed to start directly after prefix. |
| 1280 | if keep is true directories with a number less than (maxnum-keep) |
| 1281 | will be removed. If .lock files are used (lock_timeout non-zero), |
| 1282 | algorithm is multi-process safe. |
| 1283 | class="st">""" |
| 1284 | if rootdir is None: |
| 1285 | rootdir = cls.get_temproot() |
| 1286 | |
| 1287 | nprefix = prefix.lower() |
| 1288 | |
| 1289 | def parse_num(path): |
| 1290 | class="st">""class="st">"Parse the number out of a path (if it matches the prefix)"class="st">"" |
| 1291 | nbasename = path.basename.lower() |
| 1292 | if nbasename.startswith(nprefix): |
| 1293 | try: |
| 1294 | return int(nbasename[len(nprefix) :]) |
| 1295 | except ValueError: |
| 1296 | pass |
| 1297 | |
| 1298 | def create_lockfile(path): |
| 1299 | class="st">""class="st">"Exclusively create lockfile. Throws when failed"class="st">"" |
| 1300 | mypid = os.getpid() |
| 1301 | lockfile = path.join(class="st">".lock") |
| 1302 | if hasattr(lockfile, class="st">"mksymlinkto"): |
| 1303 | lockfile.mksymlinkto(str(mypid)) |
| 1304 | else: |
| 1305 | fd = error.checked_call( |
| 1306 | os.open, str(lockfile), os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644 |
| 1307 | ) |
| 1308 | with os.fdopen(fd, class="st">"w") as f: |
| 1309 | f.write(str(mypid)) |
| 1310 | return lockfile |
| 1311 | |
| 1312 | def atexit_remove_lockfile(lockfile): |
| 1313 | class="st">""class="st">"Ensure lockfile is removed at process exit"class="st">"" |
| 1314 | mypid = os.getpid() |
| 1315 | |
| 1316 | def try_remove_lockfile(): |
| 1317 | class="cm"># in a fork() situation, only the last process should |
| 1318 | class="cm"># remove the .lock, otherwise the other processes run the |
| 1319 | class="cm"># risk of seeing their temporary dir disappear. For now |
| 1320 | class="cm"># we remove the .lock in the parent only (i.e. we assume |
| 1321 | class="cm"># that the children finish before the parent). |
| 1322 | if os.getpid() != mypid: |
| 1323 | return |
| 1324 | try: |
| 1325 | lockfile.remove() |
| 1326 | except error.Error: |
| 1327 | pass |
| 1328 | |
| 1329 | atexit.register(try_remove_lockfile) |
| 1330 | |
| 1331 | class="cm"># compute the maximum number currently in use with the prefix |
| 1332 | lastmax = None |