|
15 | 15 | # specific language governing permissions and limitations
|
16 | 16 | # under the License.
|
17 | 17 | import getpass
|
| 18 | +import socket |
18 | 19 | import time
|
19 | 20 | from types import TracebackType
|
20 | 21 | from typing import (
|
|
34 | 35 | AlreadyExistsException,
|
35 | 36 | FieldSchema,
|
36 | 37 | InvalidOperationException,
|
| 38 | + LockComponent, |
| 39 | + LockLevel, |
| 40 | + LockRequest, |
| 41 | + LockResponse, |
| 42 | + LockState, |
| 43 | + LockType, |
37 | 44 | MetaException,
|
38 | 45 | NoSuchObjectException,
|
39 | 46 | SerDeInfo,
|
40 | 47 | StorageDescriptor,
|
| 48 | + UnlockRequest, |
41 | 49 | )
|
42 | 50 | from hive_metastore.ttypes import Database as HiveDatabase
|
43 | 51 | from hive_metastore.ttypes import Table as HiveTable
|
|
56 | 64 | PropertiesUpdateSummary,
|
57 | 65 | )
|
58 | 66 | from pyiceberg.exceptions import (
|
| 67 | + CommitFailedException, |
59 | 68 | NamespaceAlreadyExistsError,
|
60 | 69 | NamespaceNotEmptyError,
|
61 | 70 | NoSuchIcebergTableError,
|
@@ -331,6 +340,15 @@ def register_table(self, identifier: Union[str, Identifier], metadata_location:
|
331 | 340 | """
|
332 | 341 | raise NotImplementedError
|
333 | 342 |
|
| 343 | + def _create_lock_request(self, database_name: str, table_name: str) -> LockRequest: |
| 344 | + lock_component: LockComponent = LockComponent( |
| 345 | + level=LockLevel.TABLE, type=LockType.EXCLUSIVE, dbname=database_name, tablename=table_name, isTransactional=True |
| 346 | + ) |
| 347 | + |
| 348 | + lock_request: LockRequest = LockRequest(component=[lock_component], user=getpass.getuser(), hostname=socket.gethostname()) |
| 349 | + |
| 350 | + return lock_request |
| 351 | + |
334 | 352 | def _commit_table(self, table_request: CommitTableRequest) -> CommitTableResponse:
|
335 | 353 | """Update the table.
|
336 | 354 |
|
@@ -363,15 +381,23 @@ def _commit_table(self, table_request: CommitTableRequest) -> CommitTableRespons
|
363 | 381 | self._write_metadata(updated_metadata, current_table.io, new_metadata_location)
|
364 | 382 |
|
365 | 383 | # commit to hive
|
366 |
| - try: |
367 |
| - with self._client as open_client: |
| 384 | + # https://github.com/apache/hive/blob/master/standalone-metastore/metastore-common/src/main/thrift/hive_metastore.thrift#L1232 |
| 385 | + with self._client as open_client: |
| 386 | + lock: LockResponse = open_client.lock(self._create_lock_request(database_name, table_name)) |
| 387 | + |
| 388 | + try: |
| 389 | + if lock.state != LockState.ACQUIRED: |
| 390 | + raise CommitFailedException(f"Failed to acquire lock for {table_request.identifier}, state: {lock.state}") |
| 391 | + |
368 | 392 | tbl = open_client.get_table(dbname=database_name, tbl_name=table_name)
|
369 | 393 | tbl.parameters = _construct_parameters(
|
370 | 394 | metadata_location=new_metadata_location, previous_metadata_location=current_table.metadata_location
|
371 | 395 | )
|
372 | 396 | open_client.alter_table(dbname=database_name, tbl_name=table_name, new_tbl=tbl)
|
373 |
| - except NoSuchObjectException as e: |
374 |
| - raise NoSuchTableError(f"Table does not exist: {table_name}") from e |
| 397 | + except NoSuchObjectException as e: |
| 398 | + raise NoSuchTableError(f"Table does not exist: {table_name}") from e |
| 399 | + finally: |
| 400 | + open_client.unlock(UnlockRequest(lockid=lock.lockid)) |
375 | 401 |
|
376 | 402 | return CommitTableResponse(metadata=updated_metadata, metadata_location=new_metadata_location)
|
377 | 403 |
|
|
0 commit comments