home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / po7_win / db / rdbms71 / prvtlock.sql < prev    next >
Text File  |  1994-08-07  |  9KB  |  315 lines

  1. rem 
  2. rem $Header: prvtlock.sql 7010300.2 94/04/04 02:35:37 snataraj Generic<base> $ 
  3. rem 
  4. Rem
  5. Rem    NAME
  6. Rem      prvtlock.sql - locking routines provided by Oracle
  7. Rem    DESCRIPTION
  8. Rem      These are private functions to be released in PL/SQL binary form.
  9. Rem      See below
  10. Rem    RETURNS
  11. Rem
  12. Rem    NOTES
  13. Rem     The procedural option is needed to use this facility.
  14. Rem
  15. Rem     Lockids from 2000000000 to 2147483647 are reserved for products
  16. Rem     supplied by Oracle:
  17. Rem
  18. Rem       Package                     Lock id range
  19. Rem       =================================================
  20. Rem       dbms_alert                  2000000000-2000002041
  21. Rem       dbms_alert                  2000002042-2000003063
  22. Rem
  23. Rem    MODIFIED   (MM/DD/YY)
  24. Rem     wmaimone   02/22/94 -  use create or replace
  25. Rem     adowning   02/04/94 -  Branch_for_patch
  26. Rem     adowning   02/04/94 -  Creation
  27. Rem     adowning   02/02/94 -  split file into public / private binary files
  28. Rem     rkooi      12/03/92 -  change comments 
  29. Rem     rkooi      11/25/92 -  return 5 instead of 6 per spec 
  30. Rem     rkooi      11/24/92 -  check for nulls 
  31. Rem     rkooi      11/18/92 -  add comments 
  32. Rem     rkooi      08/20/92 -  comments and cleanup 
  33. Rem     rkooi      06/29/92 -  add some comments 
  34. Rem     rkooi      05/30/92 -  fix timeout problems 
  35. Rem     rkooi      04/30/92 -  add some comments 
  36. Rem     rkooi      04/25/92 -  misc change 
  37. Rem     rkooi      04/12/92 -  Creation 
  38.  
  39. Rem This script must be run as user SYS
  40.  
  41. REM ************************************************************
  42. REM THIS PACKAGE MUST NOT BE MODIFIED BY THE CUSTOMER.  DOING SO
  43. REM COULD CAUSE INTERNAL ERRORS AND CORRUPTIONS IN THE RDBMS.
  44. REM FOR INSTANCE, THE PSD* ROUTINES MUST NOT BE CALLED DIRECTLY
  45. REM BY ANY CLIENT AND MUST REMAIN PRIVATE TO THIS PACKAGE.
  46. REM ************************************************************
  47.  
  48. drop table dbms_lock_allocated
  49. /
  50. create table dbms_lock_allocated(
  51.     name        varchar2(128) primary key,
  52.     lockid        integer,
  53.     expiration    date)
  54. /
  55. drop sequence dbms_lock_id
  56. /
  57.  
  58. create sequence dbms_lock_id start with 1073741824 maxvalue 1999999999
  59. /
  60.  
  61. create or replace package body dbms_lock is
  62.  
  63.   procedure psdlgt(id binary_integer, lockmode binary_integer, 
  64.                    maxholders binary_integer, timeout binary_integer, 
  65.                    release_on_commit binary_integer, 
  66.                    global_lock binary_integer, status in out binary_integer);
  67.     pragma interface (C, psdlgt);
  68.   procedure psdlcv(id binary_integer, lockmode binary_integer,
  69.              maxholders binary_integer, timeout binary_integer,
  70.            status in out binary_integer);
  71.     pragma interface (C, psdlcv);
  72.   procedure psdlrl(id binary_integer, status in out binary_integer);
  73.     pragma interface (C, psdlrl);
  74.   procedure psdwat(tens_of_millisecs binary_integer);
  75.     pragma interface (C, psdwat);
  76.  
  77.   procedure convertback(lockhandle varchar2,
  78.                         id out integer,
  79.                         status out integer) is
  80.     tmpid integer;
  81.   begin
  82.     begin
  83.       status := 0;
  84.       id := -1;
  85.       if length(lockhandle)=0 then
  86.         status := 5;
  87.       else
  88.         tmpid := to_number(substr(lockhandle,1,10));
  89.         if (tmpid <> to_number(substr(lockhandle,11,10))) then
  90.           status := 5;
  91.         elsif (tmpid mod 239) <> to_number(substr(lockhandle,21,10)) then
  92.           status := 5;
  93.         elsif tmpid<1073741824 or tmpid>1999999999 then
  94.           status := 3;
  95.         else
  96.           id := tmpid;
  97.         end if;
  98.       end if;
  99.     exception when others then
  100.       status := 5;
  101.     end;
  102.   end;
  103.  
  104.   function  internal_request(id integer,
  105.                     lockmode integer,
  106.                     timeout integer,
  107.                     release_on_commit boolean,
  108.                     global_lock boolean)
  109.             return integer is
  110.   arg1    binary_integer;
  111.   arg2    binary_integer;
  112.   arg3    binary_integer;
  113.   arg4    binary_integer;
  114.   arg5    binary_integer;
  115.   arg6    binary_integer;
  116.   status  binary_integer;
  117.   begin
  118.     if timeout<0 or lockmode<1 or lockmode>6 then
  119.       return 3;
  120.     end if;
  121.     if id is null or lockmode is null or timeout is null then
  122.       return 3;
  123.     end if;
  124.     arg1 := id;
  125.     arg2 := lockmode;
  126.     arg3 := 0;
  127.     if timeout>maxwait then
  128.       arg4 := maxwait;
  129.     else
  130.       arg4 := timeout;
  131.     end if;
  132.     if release_on_commit then
  133.       arg5 := 1;
  134.     else
  135.       arg5 := 0;
  136.     end if;
  137.     if global_lock then
  138.       arg6 := 1;
  139.     else
  140.       arg6 := 0;
  141.     end if;
  142.     psdlgt(arg1, arg2, arg3, arg4, arg5, arg6, status);
  143.     return status;
  144.   end;
  145.  
  146.   function  request(lockhandle varchar2,
  147.                     lockmode integer default x_mode, 
  148.                     timeout integer default maxwait,
  149.                     release_on_commit boolean default FALSE)
  150.             return integer is
  151.     id integer;
  152.     status integer;
  153.   begin
  154.     convertback(lockhandle, id, status);
  155.     if status <> 0 then
  156.       return status;
  157.     end if;
  158.     return internal_request(id, lockmode, timeout, release_on_commit, TRUE);
  159.   end;
  160.  
  161.   function  request(id integer,
  162.                     lockmode integer default x_mode, 
  163.                     timeout integer default maxwait,
  164.                     release_on_commit boolean default FALSE)
  165.             return integer is
  166.   begin
  167.     if id<0 or (id>1073741823 and id<2000000000) then
  168.       return 3;
  169.     end if;
  170.     return internal_request(id, lockmode, timeout, release_on_commit, TRUE);
  171.   end;
  172.  
  173.   function internal_convert(id integer, 
  174.                    lockmode integer, 
  175.                    timeout number)
  176.            return integer is
  177.     arg1   binary_integer;
  178.     arg2   binary_integer;
  179.     arg3   binary_integer;
  180.     arg4   binary_integer;
  181.     status binary_integer;
  182.   begin
  183.     if timeout<0 or lockmode<1 or lockmode>6 then
  184.       return 3;
  185.     end if;
  186.     if id is null or lockmode is null or timeout is null then
  187.       return 3;
  188.     end if;
  189.     arg1 := id;
  190.     arg2 := lockmode;
  191.     arg3 := 0;
  192.     if timeout>maxwait then
  193.       arg4 := maxwait;
  194.     else
  195.       arg4 := timeout;
  196.     end if;
  197.     psdlcv(arg1, arg2, arg3, arg4, status);
  198.     return status;
  199.   end;
  200.  
  201.   function convert(lockhandle varchar2,
  202.                    lockmode integer, 
  203.                    timeout number default maxwait)
  204.            return integer is
  205.     id integer;
  206.     status integer;
  207.   begin
  208.     convertback(lockhandle, id, status);
  209.     if status <> 0 then
  210.       return status;
  211.     end if;
  212.     return internal_convert(id, lockmode, timeout);
  213.   end;
  214.  
  215.   function convert(id integer, 
  216.                    lockmode integer, 
  217.                    timeout number default maxwait)
  218.            return integer is
  219.   begin
  220.     if id<0 or (id>1073741823 and id<2000000000) then
  221.       return 3;
  222.     end if;
  223.     return internal_convert(id, lockmode, timeout);
  224.   end;
  225.  
  226.   function internal_release(id integer) return integer is
  227.     arg1   binary_integer;
  228.     status binary_integer;
  229.   begin
  230.     if id is null then
  231.       return 3;
  232.     end if;
  233.     arg1 := id;
  234.     psdlrl(arg1, status);
  235.     return status;
  236.   end;
  237.  
  238.   function release(lockhandle varchar2) return integer is
  239.     id integer;
  240.     status integer;
  241.   begin
  242.     convertback(lockhandle, id, status);
  243.     if status <> 0 then
  244.       return status;
  245.     end if;
  246.     return internal_release(id);
  247.   end;
  248.  
  249.   function release(id integer) return integer is
  250.   begin
  251.     if id<0 or (id>1073741823 and id<2000000000) then
  252.       return 3;
  253.     end if;
  254.     return internal_release(id);
  255.   end;
  256.  
  257.   procedure sleep(seconds number) is
  258.     arg1   binary_integer;
  259.   begin
  260.     arg1 := seconds*100;
  261.     psdwat(arg1);
  262.   end;
  263.  
  264.   procedure allocate_unique(lockname in varchar2, 
  265.                 lockhandle out varchar2,
  266.                 expiration_secs in integer default 864000) is
  267.     lockid integer;
  268.     cursor c1(lname varchar2) is 
  269.       select lockid from dbms_lock_allocated where name = c1.lname for update;
  270.     trycount integer := 0;
  271.   begin
  272.     <<retryloop>>
  273.     loop
  274.       open c1(lockname);
  275.       fetch c1 into lockid;
  276.       if c1%notfound then
  277.         close c1;
  278.         if trycount >= 1 then
  279.           raise_application_error(-20000,
  280.            'ORU-10003: Unable to find or insert lock '''
  281.             || lockname || ''' into catalog dbms_lock_allocated.');
  282.         end if;
  283.         begin
  284.           -- we are first to try to allocate this lock.  So allocate
  285.           -- a lockid.
  286.           select dbms_lock_id.nextval into lockid from dual;
  287.           -- do periodic cleanout.
  288.           if (lockid mod 100) = 0 then
  289.             delete dbms_lock_allocated where expiration > sysdate;
  290.             commit;
  291.           end if;
  292.           insert into dbms_lock_allocated values (lockname, lockid, 
  293.             sysdate + (expiration_secs/86400));
  294.           exit retryloop;
  295.         exception when dup_val_on_index then
  296.           -- someone must have inserted this key into the table between the
  297.           -- the time we did the select and the time we tried to insert.
  298.           -- So retry.
  299.           trycount := trycount+1;
  300.         end;
  301.       else
  302.         update dbms_lock_allocated 
  303.           set expiration = sysdate + (expiration_secs/86400)
  304.           where current of c1;
  305.         close c1;
  306.         exit retryloop;
  307.       end if;
  308.     end loop;
  309.     lockhandle := to_char(lockid)||to_char(lockid)||to_char(lockid mod 239);
  310.     commit;
  311.   end;
  312.  
  313. end;
  314. /
  315.