Set and automatically clear a lock, should be called from a context, for example: with self.gen_lock()
(self, lock_type="update", timeout=0, poll_interval=0.5)
| 1154 | |
| 1155 | @contextlib.contextmanager |
| 1156 | def gen_lock(self, lock_type="update", timeout=0, poll_interval=0.5): |
| 1157 | """ |
| 1158 | Set and automatically clear a lock, |
| 1159 | should be called from a context, for example: with self.gen_lock() |
| 1160 | """ |
| 1161 | if not isinstance(lock_type, str): |
| 1162 | raise GitLockError(errno.EINVAL, f"Invalid lock_type '{lock_type}'") |
| 1163 | |
| 1164 | # Make sure that we have a positive integer timeout, otherwise just set |
| 1165 | # it to zero. |
| 1166 | try: |
| 1167 | timeout = int(timeout) |
| 1168 | except ValueError: |
| 1169 | timeout = 0 |
| 1170 | else: |
| 1171 | if timeout < 0: |
| 1172 | timeout = 0 |
| 1173 | |
| 1174 | if not isinstance(poll_interval, ((int,), float)) or poll_interval < 0: |
| 1175 | poll_interval = 0.5 |
| 1176 | |
| 1177 | if poll_interval > timeout: |
| 1178 | poll_interval = timeout |
| 1179 | |
| 1180 | lock_set1 = False |
| 1181 | lock_set2 = False |
| 1182 | try: |
| 1183 | time_start = time.time() |
| 1184 | while True: |
| 1185 | try: |
| 1186 | self._lock(lock_type=lock_type, failhard=True) |
| 1187 | lock_set1 = True |
| 1188 | # docs state need to yield a single value, lock_set will do |
| 1189 | yield lock_set1 |
| 1190 | |
| 1191 | # Break out of his loop once we've yielded the lock, to |
| 1192 | # avoid continued attempts to iterate and establish lock |
| 1193 | # just ensuring lock_set is true (belts and braces) |
| 1194 | lock_set2 = True |
| 1195 | break |
| 1196 | |
| 1197 | except (OSError, GitLockError) as exc: |
| 1198 | if not timeout or time.time() - time_start > timeout: |
| 1199 | raise GitLockError(exc.errno, exc.strerror) |
| 1200 | else: |
| 1201 | log.debug( |
| 1202 | "A %s lock is already present for %s remote " |
| 1203 | "'%s', sleeping %f second(s)", |
| 1204 | lock_type, |
| 1205 | self.role, |
| 1206 | self.id, |
| 1207 | poll_interval, |
| 1208 | ) |
| 1209 | time.sleep(poll_interval) |
| 1210 | continue |
| 1211 | finally: |
| 1212 | if lock_set1 or lock_set2: |
| 1213 | msg = ( |
no test coverage detected