Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*LOCK TABLE*****************************************************************************/
- DROP TABLE GLOBAL_LOCKS;
- CREATE TABLE GLOBAL_LOCKS
- (
- lock_key VARCHAR2(100) NOT NULL,
- lock_info VARCHAR2(2000),
- token VARCHAR2(2000) NOT NULL
- );
- -- Add comments to the table
- COMMENT ON TABLE GLOBAL_LOCKS
- IS 'Таблица хранения глобальных блокировок';
- -- Add comments to the columns
- COMMENT ON column GLOBAL_LOCKS.lock_key
- IS 'Ключ блокировки';
- COMMENT ON column GLOBAL_LOCKS.lock_info
- IS 'Информация о блокировке';
- COMMENT ON column GLOBAL_LOCKS.token
- IS 'Токен для получения возможности снятия блокировки';
- -- Create/Recreate primary, unique and foreign key constraints
- ALTER TABLE GLOBAL_LOCKS
- add constraint GLOBAL_LOCKS_PK primary key (lock_key);
- /*PACKAGE*****************************************************************************/
- CREATE OR REPLACE PACKAGE C_MD_LOCK IS
- FUNCTION tryLock(p_lock_key IN VARCHAR2,
- p_lock_info IN OUT VARCHAR2) RETURN VARCHAR2;
- PROCEDURE unlock(p_token IN VARCHAR2,
- p_lock_key IN VARCHAR2);
- END C_MD_LOCK;
- /
- CREATE OR REPLACE PACKAGE BODY C_MD_LOCK IS
- /** Distributed lock PLSQL implementation**/
- /**
- Trying to acquire the lock.
- @p_lock_info - parameter is used to pass information about the lock being applied and to return information about the resulting holding lock,
- regardless of whether the session succeeded in acquiring the lock or not.
- Returns token if success and NULL if not.
- **/
- FUNCTION tryLock(p_lock_key IN VARCHAR2, p_lock_info IN OUT VARCHAR2)
- RETURN VARCHAR2 IS
- PRAGMA AUTONOMOUS_TRANSACTION;
- v_token VARCHAR2(2000);
- BEGIN
- --First check
- FOR rc IN (SELECT lock_info
- FROM GLOBAL_LOCKS
- WHERE lock_key = p_lock_key) LOOP
- p_lock_info := rc.lock_info;
- RETURN NULL;
- END LOOP;
- --Locks the table to provide atomicity of check and insert operations
- LOCK TABLE GLOBAL_LOCKS IN EXCLUSIVE MODE;
- --Second check
- FOR rc IN (SELECT lock_info
- FROM GLOBAL_LOCKS
- WHERE lock_key = p_lock_key) LOOP
- p_lock_info := rc.lock_info;
- RETURN NULL;
- END LOOP;
- v_token := SYS_GUID();
- INSERT INTO GLOBAL_LOCKS
- (lock_key, lock_info, token)
- VALUES
- (p_lock_key, p_lock_info, v_token);
- COMMIT;
- RETURN v_token;
- EXCEPTION
- WHEN OTHERS THEN
- ROLLBACK;
- RAISE_APPLICATION_ERROR(-20200,
- 'Error in function "C_MD_LOCK.tryLock" ' ||
- DBMS_UTILITY.format_error_backtrace || ' ' ||
- SQLERRM);
- END tryLock;
- /**
- Attempts to release this lock by token.
- **/
- PROCEDURE unlock(p_token IN VARCHAR2, p_lock_key IN VARCHAR2) IS
- PRAGMA AUTONOMOUS_TRANSACTION;
- BEGIN
- DELETE FROM GLOBAL_LOCKS
- WHERE lock_key = p_lock_key
- AND token = p_token;
- COMMIT;
- EXCEPTION
- WHEN OTHERS THEN
- ROLLBACK;
- RAISE_APPLICATION_ERROR(-20200,
- 'Error in function "C_MD_LOCK.unlock" ' ||
- DBMS_UTILITY.format_error_backtrace || ' ' ||
- SQLERRM);
- END unlock;
- END C_MD_LOCK;
- /
- /*TESTS*****************************************************************************/
- --lock
- DECLARE
- v_token VARCHAR2(2000);
- v_lock_key VARCHAR2(250) :='PROCESS_OKATO';
- v_lock_info VARCHAR2(250) :='Импорт OKATO';
- BEGIN
- -- Call the function
- v_token := C_MD_LOCK.tryLock(p_lock_key => v_lock_key,
- p_lock_info => v_lock_info);
- DBMS_OUTPUT.put_line('token='||v_token );
- END;
- /
- --unlock
- DECLARE
- v_token VARCHAR2(2000) := '<token>';
- v_lock_key VARCHAR2(250) :='PROCESS_OKATO';
- BEGIN
- -- Call the procedure
- C_MD_LOCK.unlock(p_token => v_token,
- p_lock_key => v_lock_key);
- END;
- /
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement