1
0
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:
Bruce Momjian
1997-11-05 21:38:25 +00:00
parent 5aaf00f3f3
commit 951986c550
33 changed files with 2547 additions and 578 deletions

62
contrib/userlock/Makefile Normal file
View 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

View 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 */

View 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.

View 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

View 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