Someone (David Fetter?) mentioned long ago that contrib/userlock could
not be moved into core because it is GPLed, and the author couldn't be
contacted to ask about re-licensing.

Andrew(@supernews) wrote a specification for the userlock functionality,
and I implemented the attached code based on his specification, without
consulting the existing source.

It's available under a BSD license, if there's any use for it.

-- ams
/*
 * Abhijit Menon-Sen <[EMAIL PROTECTED]>
 * 2006-09-03
 */


#include "postgres.h"
#include "storage/lock.h"
#include "miscadmin.h"
#include "fmgr.h"


PG_MODULE_MAGIC;


static int lock(uint32, uint32, uint32);
static int unlock(uint32, uint32, uint32);

Datum user_lock(PG_FUNCTION_ARGS);
Datum user_unlock(PG_FUNCTION_ARGS);

Datum user_write_lock(PG_FUNCTION_ARGS);
Datum user_write_unlock(PG_FUNCTION_ARGS);
Datum user_write_lock_o(PG_FUNCTION_ARGS);
Datum user_write_unlock_o(PG_FUNCTION_ARGS);

Datum user_write_lock_oid(PG_FUNCTION_ARGS);
Datum user_write_unlock_oid(PG_FUNCTION_ARGS);
Datum user_write_lock_oid_i(PG_FUNCTION_ARGS);
Datum user_write_unlock_oid_i(PG_FUNCTION_ARGS);

Datum user_unlock_all(PG_FUNCTION_ARGS);


static int lock(uint32 group, uint32 id, uint32 lockmode)
{
    int r;
    LOCKTAG tag;

    tag.locktag_field1 = MyDatabaseId;
    tag.locktag_field2 = group;
    tag.locktag_field3 = id;
    tag.locktag_field4 = 0;
    tag.locktag_type = LOCKTAG_USERLOCK;
    tag.locktag_lockmethodid = USER_LOCKMETHOD;

    r = LockAcquire(&tag, lockmode, true, true);
    if ( r > 1 )
        r = 1;

    return r;
}


static int unlock(uint32 group, uint32 id, uint32 lockmode)
{
    int r;
    LOCKTAG tag;

    tag.locktag_field1 = MyDatabaseId;
    tag.locktag_field2 = group;
    tag.locktag_field3 = id;
    tag.locktag_field4 = 0;
    tag.locktag_type = LOCKTAG_USERLOCK;
    tag.locktag_lockmethodid = USER_LOCKMETHOD;

    if (LockRelease(&tag, lockmode, true))
        r = 1;
    else
        r = 0;

    return r;
}


PG_FUNCTION_INFO_V1(user_lock);

Datum user_lock(PG_FUNCTION_ARGS)
{
    int r;
    uint32 group = PG_GETARG_INT32(0);
    uint32 id = PG_GETARG_INT32(1);
    uint32 lockmode = PG_GETARG_INT32(2);

    r = lock(group, id, lockmode);

    PG_RETURN_INT32(r);
}


PG_FUNCTION_INFO_V1(user_unlock);

Datum user_unlock(PG_FUNCTION_ARGS)
{
    int r;
    uint32 group = PG_GETARG_INT32(0);
    uint32 id = PG_GETARG_INT32(1);
    uint32 lockmode = PG_GETARG_INT32(2);

    r = unlock(group, id, lockmode);

    PG_RETURN_INT32(r);
}


PG_FUNCTION_INFO_V1(user_write_lock);

Datum user_write_lock(PG_FUNCTION_ARGS)
{
    int r;
    uint32 group = PG_GETARG_INT32(0);
    uint32 id = PG_GETARG_INT32(1);

    r = lock(group, id, ExclusiveLock);

    PG_RETURN_INT32(r);
}


PG_FUNCTION_INFO_V1(user_write_unlock);

Datum user_write_unlock(PG_FUNCTION_ARGS)
{
    int r;
    uint32 group = PG_GETARG_INT32(0);
    uint32 id = PG_GETARG_INT32(1);

    r = unlock(group, id, ExclusiveLock);

    PG_RETURN_INT32(r);
}


PG_FUNCTION_INFO_V1(user_write_lock_o);

Datum user_write_lock_o(PG_FUNCTION_ARGS)
{
    int r;
    uint32 group = PG_GETARG_INT32(0);
    uint32 id = PG_GETARG_OID(1);

    r = lock(group, id, ExclusiveLock);

    PG_RETURN_INT32(r);
}


PG_FUNCTION_INFO_V1(user_write_unlock_o);

Datum user_write_unlock_o(PG_FUNCTION_ARGS)
{
    int r;
    uint32 group = PG_GETARG_INT32(0);
    uint32 id = PG_GETARG_OID(1);

    r = unlock(group, id, ExclusiveLock);

    PG_RETURN_INT32(r);
}


PG_FUNCTION_INFO_V1(user_write_lock_oid);

Datum user_write_lock_oid(PG_FUNCTION_ARGS)
{
    int r;
    uint32 id = PG_GETARG_OID(0);

    r = lock(0, id, ExclusiveLock);

    PG_RETURN_INT32(r);
}


PG_FUNCTION_INFO_V1(user_write_unlock_oid);

Datum user_write_unlock_oid(PG_FUNCTION_ARGS)
{
    int r;
    uint32 id = PG_GETARG_OID(0);

    r = unlock(0, id, ExclusiveLock);

    PG_RETURN_INT32(r);
}


PG_FUNCTION_INFO_V1(user_write_lock_oid_i);

Datum user_write_lock_oid_i(PG_FUNCTION_ARGS)
{
    int r;
    uint32 id = PG_GETARG_INT32(0);

    r = lock(0, id, ExclusiveLock);

    PG_RETURN_INT32(r);
}


PG_FUNCTION_INFO_V1(user_write_unlock_oid_i);

Datum user_write_unlock_oid_i(PG_FUNCTION_ARGS)
{
    int r;
    uint32 id = PG_GETARG_INT32(0);

    r = unlock(0, id, ExclusiveLock);

    PG_RETURN_INT32(r);
}


PG_FUNCTION_INFO_V1(user_unlock_all);

Datum user_unlock_all(PG_FUNCTION_ARGS)
{
    LockReleaseAll(USER_LOCKMETHOD, true);

    PG_RETURN_INT32(1);
}
CREATE FUNCTION user_lock(int4,int4,int4) returns int4
AS 'MODULE_PATHNAME', 'user_lock' LANGUAGE C VOLATILE STRICT;

CREATE FUNCTION user_unlock(int4,int4,int4) returns int4
AS 'MODULE_PATHNAME', 'user_unlock' LANGUAGE C VOLATILE STRICT;

CREATE FUNCTION user_write_lock(int4,int4) returns int4
AS 'MODULE_PATHNAME', 'user_write_lock' LANGUAGE C VOLATILE STRICT;

CREATE FUNCTION user_write_unlock(int4,int4) returns int4
AS 'MODULE_PATHNAME', 'user_write_unlock' LANGUAGE C VOLATILE STRICT;

CREATE FUNCTION user_write_lock(int4,oid) returns int4
AS 'MODULE_PATHNAME', 'user_write_lock_o' LANGUAGE C VOLATILE STRICT;

CREATE FUNCTION user_write_unlock(int4,oid) returns int4
AS 'MODULE_PATHNAME', 'user_write_unlock_o' LANGUAGE C VOLATILE STRICT;

CREATE FUNCTION user_write_lock_oid(oid) returns int4
AS 'MODULE_PATHNAME', 'user_write_lock_oid' LANGUAGE C VOLATILE STRICT;

CREATE FUNCTION user_write_unlock_oid(oid) returns int4
AS 'MODULE_PATHNAME', 'user_write_unlock_oid' LANGUAGE C VOLATILE STRICT;

CREATE FUNCTION user_write_lock_oid(int4) returns int4
AS 'MODULE_PATHNAME', 'user_write_lock_oid_i' LANGUAGE C VOLATILE STRICT;

CREATE FUNCTION user_write_unlock_oid(int4) returns int4
AS 'MODULE_PATHNAME', 'user_write_unlock_oid_i' LANGUAGE C VOLATILE STRICT;

CREATE FUNCTION user_unlock_all() returns int4
AS 'MODULE_PATHNAME', 'user_unlock_all' LANGUAGE C VOLATILE STRICT;
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to