diff options
| author | Bruce Momjian | 1997-11-05 21:38:25 +0000 |
|---|---|---|
| committer | Bruce Momjian | 1997-11-05 21:38:25 +0000 |
| commit | 951986c550dccfdafffcf2eda30980c7310b41b4 (patch) | |
| tree | 9bd4eb75a2c8cdc96e72cd5675c0a398d9c3659c /contrib/userlock | |
| parent | 5aaf00f3f39848eb8fef768e3ec8c0e816a87172 (diff) | |
Update of contrib stuff from massimo.
Diffstat (limited to 'contrib/userlock')
| -rw-r--r-- | contrib/userlock/Makefile | 62 | ||||
| -rw-r--r-- | contrib/userlock/user_locks.c | 100 | ||||
| -rw-r--r-- | contrib/userlock/user_locks.doc | 30 | ||||
| -rw-r--r-- | contrib/userlock/user_locks.h | 12 | ||||
| -rw-r--r-- | contrib/userlock/user_locks.sql.in | 69 |
5 files changed, 273 insertions, 0 deletions
diff --git a/contrib/userlock/Makefile b/contrib/userlock/Makefile new file mode 100644 index 00000000000..0865bde7321 --- /dev/null +++ b/contrib/userlock/Makefile @@ -0,0 +1,62 @@ +#------------------------------------------------------------------------- +# +# Makefile-- +# Makefile for new string I/O functions. +# +#------------------------------------------------------------------------- + +PGDIR = ../.. +SRCDIR = $(PGDIR)/src + +include $(SRCDIR)/Makefile.global + +INCLUDE_OPT = -I ./ \ + -I $(SRCDIR)/ \ + -I $(SRCDIR)/include \ + -I $(SRCDIR)/port/$(PORTNAME) + +CFLAGS += $(INCLUDE_OPT) + +ifeq ($(PORTNAME), linux) + ifdef LINUX_ELF + ifeq ($(CC), gcc) + CFLAGS += -fPIC + endif + endif +endif + +ifeq ($(PORTNAME), i386_solaris) + CFLAGS+= -fPIC +endif + +MODNAME = user_locks + +MODULE = $(MODNAME)$(DLSUFFIX) + +all: module sql + +module: $(MODULE) + +sql: $(MODNAME).sql + +install: $(MODULE) + cp -p $(MODULE) $(LIBDIR) + cd $(LIBDIR); strip $(MODULE) + +%.sql: %.sql.in + sed "s|MODULE_PATHNAME|$(LIBDIR)/$(MODULE)|" < $< > $@ + +.SUFFIXES: $(DLSUFFIX) + +%$(DLSUFFIX): %.c + cc $(CFLAGS) -shared -o $@ $< + +depend dep: + $(CC) -MM $(INCLUDE_OPT) *.c >depend + +clean: + rm -f $(MODULE) $(MODNAME).sql + +ifeq (depend,$(wildcard depend)) +include depend +endif diff --git a/contrib/userlock/user_locks.c b/contrib/userlock/user_locks.c new file mode 100644 index 00000000000..efc9b0a4644 --- /dev/null +++ b/contrib/userlock/user_locks.c @@ -0,0 +1,100 @@ +/* + * user_locks.c -- + * + * This loadable module, together with my user-lock.patch applied to the + * backend, provides support for user-level long-term cooperative locks. + * + * Copyright (c) 1996, Massimo Dal Zotto <dz@cs.unitn.it> + */ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "postgres.h" +#include "miscadmin.h" +#include "storage/lock.h" +#include "storage/lmgr.h" +#include "storage/proc.h" +#include "storage/block.h" +#include "storage/multilev.h" +#include "utils/elog.h" + +#include "user_locks.h" + +#define USER_LOCKS_TABLE_ID 0 + +extern Oid MyDatabaseId; + +int +user_lock(unsigned int id1, unsigned int id2, LOCKT lockt) +{ + LOCKTAG tag; + + memset(&tag,0,sizeof(LOCKTAG)); + tag.relId = 0; + tag.dbId = MyDatabaseId; + tag.tupleId.ip_blkid.bi_hi = id2 >> 16; + tag.tupleId.ip_blkid.bi_lo = id2 & 0xffff; + tag.tupleId.ip_posid = (unsigned short) (id1 & 0xffff); + + return LockAcquire(USER_LOCKS_TABLE_ID, &tag, lockt); +} + +int +user_unlock(unsigned int id1, unsigned int id2, LOCKT lockt) +{ + LOCKTAG tag; + + memset(&tag, 0,sizeof(LOCKTAG)); + tag.relId = 0; + tag.dbId = MyDatabaseId; + tag.tupleId.ip_blkid.bi_hi = id2 >> 16; + tag.tupleId.ip_blkid.bi_lo = id2 & 0xffff; + tag.tupleId.ip_posid = (unsigned short) (id1 & 0xffff); + + return LockRelease(USER_LOCKS_TABLE_ID, &tag, lockt); +} + +int +user_write_lock(unsigned int id1, unsigned int id2) +{ + return user_lock(id1, id2, WRITE_LOCK); +} + + +int +user_write_unlock(unsigned int id1, unsigned int id2) +{ + return user_unlock(id1, id2, WRITE_LOCK); +} + +int +user_write_lock_oid(Oid oid) +{ + return user_lock(0, oid, WRITE_LOCK); +} + +int +user_write_unlock_oid(Oid oid) +{ + return user_unlock(0, oid, WRITE_LOCK); +} + +int +user_unlock_all() +{ + PROC *proc; + SHMEM_OFFSET location; + + ShmemPIDLookup(getpid(),&location); + if (location == INVALID_OFFSET) { + elog(NOTICE, "UserUnlockAll: unable to get proc ptr"); + return -1; + } + + proc = (PROC *) MAKE_PTR(location); + return LockReleaseAll(USER_LOCKS_TABLE_ID, &proc->lockQueue); +} + +/* end of file */ diff --git a/contrib/userlock/user_locks.doc b/contrib/userlock/user_locks.doc new file mode 100644 index 00000000000..15ffe48f13b --- /dev/null +++ b/contrib/userlock/user_locks.doc @@ -0,0 +1,30 @@ +User locks, by Massimo Dal Zotto <dz@cs.unitn.it> + +This loadable module, together with my user-lock.patch applied to the +backend, provides support for user-level long-term cooperative locks. + +For example one can write (this example is written in TclX): + + set rec [sql "select ...,user_write_lock_oid(oid) from table where id=$id"] + if {[keylget rec user_write_lock_oid] == 1} { + # the write lock has been acquired with the record, start + # a long editing session, then update the database and + # release the lock. + sql "update table set ... where id=$id" + sql "select user_write_unlock_oid([keylget rec oid])" + } else { + # the record has been read but the write lock couldn't be acquired, + # so it should not be modified by the application. + messageBox "This record is in use by another user, retry later" + } + +This could also be done by setting a flag in the record itself but in +this case you have the overhead of the updates to the record and there +may be some locks not released if the backend or the application crashes +before resetting the flag. +It could also be done with a begin/end block but in this case the entire +table would be locked by postgres and it is not acceptable to do this for +a long period because other transactions would block completely. +Note that this type of locks are handled cooperatively by the application +and do not interfere with the normal locks used by postgres. So an user +could still modify an user-locked record if he wanted to ignore the lock. diff --git a/contrib/userlock/user_locks.h b/contrib/userlock/user_locks.h new file mode 100644 index 00000000000..ab890483fa4 --- /dev/null +++ b/contrib/userlock/user_locks.h @@ -0,0 +1,12 @@ +#ifndef USER_LOCKS_H +#define USER_LOCKS_H + +int user_lock(unsigned int id1, unsigned int id2, LOCKT lockt); +int user_unlock(unsigned int id1, unsigned int id2, LOCKT lockt); +int user_write_lock(unsigned int id1, unsigned int id2); +int user_write_unlock(unsigned int id1, unsigned int id2); +int user_write_lock_oid(Oid oid); +int user_write_unlock_oid(Oid oid); +int user_unlock_all(void); + +#endif diff --git a/contrib/userlock/user_locks.sql.in b/contrib/userlock/user_locks.sql.in new file mode 100644 index 00000000000..da8d105de9c --- /dev/null +++ b/contrib/userlock/user_locks.sql.in @@ -0,0 +1,69 @@ +-- SQL code to define the user locks functions + +-- select user_lock(group,id,type); +-- +create function user_lock(int4,int4,int4) returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- select user_unlock(group,id,type); +-- +create function user_unlock(int4,int4,int4) returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- select user_write_lock(group,id); +-- +create function user_write_lock(int4,int4) returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- select user_write_unlock(group,id); +-- +create function user_write_unlock(int4,int4) returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- select user_write_lock(group,oid); +-- +create function user_write_lock(int4,oid) returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- select user_write_unlock(group,oid); +-- +create function user_write_unlock(int4,oid) returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- select user_write_lock_oid(oid); +-- +create function user_write_lock_oid(oid) returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- select user_write_unlock_oid(oid); +-- +create function user_write_unlock_oid(oid) returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- select user_write_lock_oid(int4); +-- +create function user_write_lock_oid(int4) returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- select user_write_unlock_oid(int4); +-- +create function user_write_unlock_oid(int4) returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- select user_unlock_all(); +-- +create function user_unlock_all() returns int4 + as 'MODULE_PATHNAME' + language 'c'; + +-- end of file |
