mirror of
https://github.com/postgres/postgres.git
synced 2025-08-08 06:02:22 +03:00
Update of contrib stuff from massimo.
This commit is contained in:
62
contrib/userlock/Makefile
Normal file
62
contrib/userlock/Makefile
Normal file
@@ -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
|
100
contrib/userlock/user_locks.c
Normal file
100
contrib/userlock/user_locks.c
Normal file
@@ -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 */
|
30
contrib/userlock/user_locks.doc
Normal file
30
contrib/userlock/user_locks.doc
Normal file
@@ -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.
|
12
contrib/userlock/user_locks.h
Normal file
12
contrib/userlock/user_locks.h
Normal file
@@ -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
|
69
contrib/userlock/user_locks.sql.in
Normal file
69
contrib/userlock/user_locks.sql.in
Normal file
@@ -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
|
Reference in New Issue
Block a user