DBA Data[Home] [Help]

PACKAGE BODY: SYS.OJDS_CONTEXT

Source


1 package body ojds_context as
2   -- make a new context and return its node
3   function mkcontext (p number, c varchar2) return number is
4     inode number;
5   begin
6     select ojds$node_number$.nextval into inode from dual;
7     insert into ojds$inode$ (node, type, refcount, creation_ts,
8                                    last_modified, owner, is_context)
9       values (inode, 1, 0, sysdate, sysdate, c, 1);
10 
11     -- "." and ".." do not contribute to reference counting
12     -- that's why the links are inserted and deleted manually
13     -- bind ".." to the parent
14     insert into ojds$bindings$ (parent, child, id, binding_type)
15       values (inode, p, '..', 1);
16     -- bind "." to the parent
17     insert into ojds$bindings$ (parent, child, id, binding_type)
18       values (inode, inode, '.', 1);
19     return inode;
20   end;
21 
22   -- make a new reference and return its node
23   function mkreference (r varchar2) return number is
24     inode number;
25   begin
26     select ojds$node_number$.nextval into inode from dual;
27     insert into ojds$inode$ (node, type, refcount, creation_ts,
28                                    last_modified, owner, is_context)
29       values (inode, 2, 0, sysdate, sysdate, r, 0);
30     return inode;
31   end;
32 
33   -- bind a node to a parent
34   procedure link (p number, c number, i varchar2 , bt number) is
35   begin
36     -- update the refcount first, as we should be idempotent on
37     -- ref managment.
38     update ojds$inode$ set refcount = refcount + 1 where node = c;
39     insert into ojds$bindings$ (parent, child, id, binding_type)
40       values (p, c, i, bt);
41   end;
42 
43   -- remove a node from a parent
44   procedure unlink (p number, i varchar2) is
45     c number;
46     bt number;
47   begin
48     -- gets the child and lock the rows in bindings$ and inode$ tables
49     select b.child, b.binding_type into c, bt
50         from ojds$bindings$ b, ojds$inode$ n
51         where b.parent = p and b.id = i and
52               n.node = b.child for update;
53     -- delete "." and ".." if it's a context
54     if bt = 1 then
55       delete from ojds$bindings$ where parent = c and (id = '.' or id = '..');
56     end if;
57     -- delete the parent -> child link
58     delete from ojds$bindings$
59       where parent = p and id = i;
60     -- update the child ref count
61     update ojds$inode$ set refcount = refcount - 1 where node = c;
62     -- delete the child if refcount is 0
63     delete from ojds$inode$ where refcount = 0 and node = c;
64     -- if child was deleted also delete its entries in $permissions
65     if sql%rowcount > 0 then -- true if the node was deleted in $inode
66       delete from ojds$permissions$ where node = c;
67       delete from ojds$attributes$ where node = c;
68       delete from ojds$refaddr$ where node = c;
69     end if;
70   exception
71     when others then -- catches the case of deleting an unknown binding
72       if sql%notfound then
73         null;
74       end if;
75   end;
76 
77   -- remove unreferenced nodes
78   function rmUnrefNodes (junk number) return boolean is
79     cursor unrefNodes_cur is select node from ojds$inode$ where refcount = 0;
80     notEmpty boolean;
81   begin
82     notEmpty := FALSE;
83     for unrefNodes_rec in unrefNodes_cur
84     loop
85       notEmpty := TRUE;
86       -- delete the inode, permission, and attributes
87       delete from ojds$inode$ where node = unrefNodes_rec.node;
88       delete from ojds$permissions$ where node = unrefNodes_rec.node;
89       delete from ojds$attributes$ where node = unrefNodes_rec.node;
90       delete from ojds$refaddr$ where node = unrefNodes_rec.node;
91       -- delete child bindings and children's refcount
92       update ojds$inode$ set refcount = refcount - 1 where
93         node in (select i.node from ojds$inode$ i, ojds$bindings$ b
94           where i.node = b.child and b.parent = unrefNodes_rec.node and b.id <> '..' and b.id <> '.');
95       delete from ojds$bindings$ where parent = unrefNodes_rec.node;
96     end loop;
97     return notEmpty;
98   end;
99 
100   -- remove empty context; return 1 if it's NOT EMPTY; returns 0 : success.
101   function rmEmptyCtx (c number) return number is
102     cnt number;
103   begin
104     select count(*) into cnt from ojds$bindings$ where parent = c and id <> '.' and id <> '..';
105     if (cnt <> 0)
106       then
107         return 1;  -- not empty
108     end if;
109     -- delete its own "." and ".."
110     delete from ojds$bindings$ where parent = c;
111     -- delete all pointers to itself
112     delete from ojds$bindings$ where child = c;
113     -- delete the inode, permission, and attributes
114     delete from ojds$inode$ where node = c;
115     delete from ojds$permissions$ where node = c;
116     delete from ojds$attributes$ where node = c;
117     delete from ojds$refaddr$ where node = c;
118     return 0;
119   end;
120 
121   -- relink an entry
122   procedure relink (p number, i varchar2, nc number, nt number) is
123     c number;
124   begin
125     -- gets the child and lock the rows in bindings$ and inode$ tables
126     select b.child into c from ojds$bindings$ b, ojds$inode$ n
127       where b.parent = p and b.id = i and
128             n.node = b.child for update;
129     -- update the child ref count
130     update ojds$inode$ set refcount = refcount - 1 where node = c;
131     -- update the binding
132     update ojds$bindings$ set child = nc, binding_type = nt where parent = p and id = i;
133     -- ref managment.
134     update ojds$inode$ set refcount = refcount + 1 where node = nc;
135     -- delete the child if refcount is 0
136     delete from ojds$inode$ where refcount = 0 and node = c;
137     -- if child was deleted also delete its entries in $permissions
138     if sql%rowcount > 0 then -- true if the node was deleted in $inode
139       delete from ojds$permissions$ where node = c;
140       delete from ojds$attributes$ where node = c;
141       delete from ojds$refaddr$ where node = c;
142     end if;
143   exception
144     when others then -- catches the case of deleting an unknown binding
145       if sql%notfound then
146         link(p, nc, i, nt);
147       end if;
148   end;
149 
150   -- since permissions are lists, the java code that
151   -- manipulates this deletes all the permissions, and
152   -- adds the new ones since permissions are gc'd with their
153   -- associated inode, this should really be done with
154   -- some sort of constraint or procedure, but I don't know
155   -- how to pass arrays to sql from java.
156   -- helper function for building initial context
157   procedure addperm (i number, t number, s varchar2) is
158   begin
159     insert into ojds$permissions$ (node, type, schema) values (i, t, s);
160   end;
161 
162   -- drop user artifacts when a user is dropped.
163   procedure user_dropped (the_user varchar2) is
164   begin
165     drop_inode_s(the_user);
166     drop_permission_s(the_user);
167   end;
168 
169   procedure role_dropped (the_role varchar2) is
170   begin
171     drop_permission_s(the_role);
172   end;
173 
174   procedure drop_permission_s (the_dropped varchar2) is
175   begin
176     delete from ojds$permissions$ where schema=the_dropped;
177   end;
178 
179   procedure drop_inode_s (the_dropped varchar2) is
180     tmpp boolean;
181   begin
182     delete from ojds$permissions$ where schema=the_dropped;
183     -- check inode owner
184     loop
185       tmpp := drop_inode_slow(the_dropped);
186       exit when tmpp = FALSE;
187     end loop;
188   end;
189 
190   procedure drop_inode_node (inode_number NUMBER) is
191   begin
192     delete from ojds$inode$ where node = inode_number;
193     delete from ojds$permissions$ where node = inode_number;
194     delete from ojds$attributes$ where node = inode_number;
195     delete from ojds$refaddr$ where node = inode_number;
196     -- delete inward pointers.
197     delete from ojds$bindings$ where child = inode_number;
198   end;
199 
200   function is_this_a_context (inode_number NUMBER) return boolean is
201     tmp1 NUMBER;
202   begin
203     select is_context into tmp1 from ojds$inode$ where node = inode_number;
204     if (tmp1 = 0)
205     then
206       return FALSE;
207     else
208       return TRUE;
209     end if;
210   end;
211 
212   function drop_inode_slow (the_dropped varchar2) return boolean is
213     cursor drop_inode_cur is select node from ojds$inode$ where owner=the_dropped;
214     notEmpty boolean;
215     inode_number NUMBER;
216     is_context_ NUMBER;
217   begin
218     notEmpty := FALSE;
219     open drop_inode_cur;
220     fetch drop_inode_cur into inode_number;
221     if drop_inode_cur%NOTFOUND then
222       close drop_inode_cur;
223       return FALSE;
224     end if;
225     close drop_inode_cur;
226 
227     if (is_this_a_context(inode_number)) then
228       -- take care of '.' and '..'
229       delete from ojds$bindings$ where parent=inode_number and ((id = '.') or (id = '..'));
230       drop_all_child_links(inode_number);
231     end if;
232     drop_inode_node(inode_number);
233     return TRUE;
234   end;
235 
236   -- after deleting pointers to children and decrement children's reference count
237   -- we can use 'rmUnrefNode' to take care of the rest
238   procedure drop_all_child_links (inode_number NUMBER) is
239     cursor all_children_cur is select child from ojds$bindings$ where parent = inode_number and id <> '.' and id <> '..';
240     tmpp boolean;
241   begin
242     for children_rec in all_children_cur
243     loop
244       update ojds$inode$ set refcount = refcount - 1 where node = children_rec.child;
245     end loop;
246     delete from ojds$bindings$ where parent=inode_number and id <> '.' and id <> '..';
247     -- remove nodes with zero refcount cascadingly
248     loop
249       tmpp := rmUnrefNodes(1);
250       exit when tmpp = FALSE;
251     end loop;
252   end;
253 end ojds_context;