version 1.1.1.1, 2025/01/19 02:04:04
|
version 1.9, 2025/05/15 02:49:11
|
Line 1
|
Line 1
|
/* |
/* |
* * |
* $Id$ |
* * * |
|
* * * |
|
* *************** |
|
* * * * * |
|
* * MUMPS * |
|
* * * * * |
|
* *************** |
|
* * * |
|
* * * |
|
* * |
|
* |
|
* locktab.c |
|
* lock table implementation |
* lock table implementation |
* |
* |
* |
* |
* Author: Serena Willis <jpw@coherent-logic.com> |
* Author: Serena Willis <snw@coherent-logic.com> |
* Copyright (C) 1998 MUG Deutschland |
* Copyright (C) 1998 MUG Deutschland |
* Copyright (C) 2021 Coherent Logic Development LLC |
* Copyright (C) 2021, 2025 Coherent Logic Development LLC |
* |
* |
* |
* |
* This file is part of FreeM. |
* This file is part of FreeM. |
Line 35
|
Line 23
|
* You should have received a copy of the GNU Affero Public License |
* You should have received a copy of the GNU Affero Public License |
* along with FreeM. If not, see <https://www.gnu.org/licenses/>. |
* along with FreeM. If not, see <https://www.gnu.org/licenses/>. |
* |
* |
|
* $Log$ |
|
* Revision 1.9 2025/05/15 02:49:11 snw |
|
* Fix linker error on errno symbol in locktab.c |
|
* |
|
* Revision 1.8 2025/05/14 15:28:55 snw |
|
* Get basic job table and lock table functionality working with new shared memory architecture |
|
* |
|
* Revision 1.7 2025/05/01 21:02:31 snw |
|
* Documentation updates |
|
* |
|
* Revision 1.6 2025/04/13 04:22:43 snw |
|
* Fix snprintf calls |
|
* |
|
* Revision 1.5 2025/03/24 02:57:25 snw |
|
* Shared memory compatibility fixes for OS/2 |
|
* |
|
* Revision 1.4 2025/03/09 19:14:25 snw |
|
* First phase of REUSE compliance and header reformat |
|
* |
|
* |
|
* SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC |
|
* SPDX-License-Identifier: AGPL-3.0-or-later |
**/ |
**/ |
|
|
#include <stdio.h> |
#include <stdio.h> |
Line 42
|
Line 52
|
#include <unistd.h> |
#include <unistd.h> |
#include <time.h> |
#include <time.h> |
#include <string.h> |
#include <string.h> |
|
#include <errno.h> |
|
|
#include "mpsdef.h" |
#include "mpsdef.h" |
#include "locktab.h" |
#include "locktab.h" |
#include "shmmgr.h" |
#include "shmmgr.h" |
#include "mref.h" |
#include "mref.h" |
#include "transact.h" |
#include "transact.h" |
|
#include "log.h" |
|
|
#if !defined(__OpenBSD__) && !defined(__APPLE__) |
#if !defined(__OpenBSD__) && !defined(__APPLE__) && !defined(__OS2__) |
union semun { |
union semun { |
int val; /* Value for SETVAL */ |
int val; /* Value for SETVAL */ |
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ |
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ |
Line 74 void locktab_init(void)
|
Line 86 void locktab_init(void)
|
|
|
semid_locktab = semget (lt_sk, 1, 0666 | IPC_CREAT); |
semid_locktab = semget (lt_sk, 1, 0666 | IPC_CREAT); |
if (semid_locktab == -1) { |
if (semid_locktab == -1) { |
fprintf (stderr, "locktab_init: failed to create lock table semaphore\r\n"); |
logprintf (FM_LOG_FATAL, "locktab_init: failed to create lock table semaphore"); |
exit (1); |
|
} |
} |
|
|
arg.val = 1; |
arg.val = 1; |
if (semctl (semid_locktab, 0, SETVAL, arg) == -1) { |
if (semctl (semid_locktab, 0, SETVAL, arg) == -1) { |
fprintf (stderr, "locktab_init: failed to initialize lock table semaphore\r\n"); |
logprintf (FM_LOG_FATAL, "locktab_init: failed to initialize lock table semaphore"); |
exit (1); |
|
} |
} |
|
|
} |
} |
Line 89 void locktab_init(void)
|
Line 99 void locktab_init(void)
|
|
|
semid_locktab = semget (lt_sk, 1, 0); |
semid_locktab = semget (lt_sk, 1, 0); |
if (semid_locktab == -1) { |
if (semid_locktab == -1) { |
fprintf (stderr, "locktab_init: could not attach to lock table semaphore\r\n"); |
logprintf (FM_LOG_FATAL, "locktab_init: could not attach to lock table semaphore"); |
exit (1); |
|
} |
} |
|
|
} |
} |
Line 104 short locktab_get_sem(void)
|
Line 113 short locktab_get_sem(void)
|
int tries; |
int tries; |
struct sembuf s = {0, -1, 0}; |
struct sembuf s = {0, -1, 0}; |
|
|
|
logprintf (FM_LOG_DEBUG, "locktab_get_sem: attempting to acquire lock table semaphore"); |
|
|
for (tries = 0; tries < 5; tries++) { |
for (tries = 0; tries < 5; tries++) { |
|
|
if (semop (semid_locktab, &s, 1) != -1) { |
if (semop (semid_locktab, &s, 1) != -1) { |
|
logprintf (FM_LOG_DEBUG, "locktab_get_sem: acquired semaphore by virtue of calling semop on it"); |
return TRUE; |
return TRUE; |
} |
} |
|
|
|
logprintf (FM_LOG_INFO, "locktab_get_sem: sleeping for retry [tries = %d; errno = %d; error = %s]", tries, errno, strerror (errno)); |
sleep (1); |
sleep (1); |
|
|
} |
} |
|
logprintf (FM_LOG_ERROR, "locktab_get_sem: failed to acquire job table semaphore"); |
|
|
return FALSE; |
return FALSE; |
} |
} |
Line 121 void locktab_release_sem(void)
|
Line 135 void locktab_release_sem(void)
|
{ |
{ |
struct sembuf s = {0, 1, 0}; |
struct sembuf s = {0, 1, 0}; |
|
|
semop (semid_locktab, &s, 1); |
logprintf (FM_LOG_DEBUG, "locktab_release_sem: trying to release lock table semaphore"); |
|
if(semop (semid_locktab, &s, 1) != - 1) { |
|
logprintf (FM_LOG_DEBUG, "locktab_release_sem: released lock table semaphore by means of semop"); |
|
} |
|
else { |
|
logprintf (FM_LOG_FATAL, "locktab_release_sem: failed to release lock table semaphore (error code %d [%s])", errno, strerror (errno)); |
|
} |
|
|
} |
} |
|
|
Line 236 void locktab_increment(char *key, long l
|
Line 256 void locktab_increment(char *key, long l
|
|
|
} |
} |
else { |
else { |
|
int sigint_ct = 0; |
|
|
for (;;) { |
for (;;) { |
|
|
if (locktab_insert (key) != NULL) { |
if (locktab_insert (key) != NULL) { |
Line 243 void locktab_increment(char *key, long l
|
Line 265 void locktab_increment(char *key, long l
|
return; |
return; |
} |
} |
else { |
else { |
|
if (merr () == INRPT) { |
|
sigint_ct++; |
|
|
|
if (sigint_ct == 1) { |
|
printf ("\r\nlocktab_insert: got Ctrl-C in blocking LOCK; Ctrl-C again to force the process to halt\r\n"); |
|
merr_clear (); |
|
} |
|
else { |
|
printf ("\r\n"); |
|
logprintf (FM_LOG_FATAL, "locktab_insert: blocking LOCK was interrupted; forcing halt"); |
|
} |
|
} |
sleep (1); |
sleep (1); |
} |
} |
|
|
Line 408 void locktab_decrement(char *key, long l
|
Line 442 void locktab_decrement(char *key, long l
|
|
|
void locktab_unlock_all(void) |
void locktab_unlock_all(void) |
{ |
{ |
|
locktab_unlock_all_by_pid (pid); |
|
} |
|
|
|
void locktab_unlock_all_by_pid(const pid_t target_pid) |
|
{ |
locktab_ent_t *lck; |
locktab_ent_t *lck; |
|
int remove_ct; |
for (lck = shm_config->hdr->locktab_head; lck != NULL; lck = lck->next) { |
|
|
|
if (lck->owner_job == pid) { |
remove_ct = 0; |
|
if (target_pid != pid) { |
|
logprintf (FM_LOG_INFO, "locktab_unlock_all_by_pid: removing all locks for pid %ld", target_pid); |
|
} |
|
|
|
|
|
for (lck = SOA(shm_config->hdr->locktab_head); lck != NULL; lck = SOA(lck->next)) { |
|
|
|
if (lck->owner_job == target_pid) { |
|
remove_ct++; |
|
|
if (tp_level > lck->tp_level) { |
if (tp_level > lck->tp_level) { |
merr_raise (M41); |
merr_raise (M41); |
return; |
return; |
Line 427 void locktab_unlock_all(void)
|
Line 474 void locktab_unlock_all(void)
|
|
|
} |
} |
|
|
} |
} |
|
|
|
if (target_pid != pid) { |
|
logprintf (FM_LOG_INFO, "locktab_unlock_all_by_pid: removed %ld lock(s) for pid %ld", remove_ct, target_pid); |
|
} |
|
|
|
|
} |
} |
|
|
Line 438 locktab_ent_t *locktab_find(char *key)
|
Line 490 locktab_ent_t *locktab_find(char *key)
|
char chk_ns[255]; |
char chk_ns[255]; |
|
|
if (key[1] == '%') { |
if (key[1] == '%') { |
snprintf (chk_ns, 255, "SYSTEM"); |
snprintf (chk_ns, sizeof (chk_ns) - 1, "SYSTEM"); |
} |
} |
else { |
else { |
snprintf (chk_ns, 255, nsname); |
snprintf (chk_ns, sizeof (chk_ns) - 1, "%s", nsname); |
} |
} |
|
|
for (lck = shm_config->hdr->locktab_head; lck != NULL; lck = lck->next) { |
for (lck = SOA(shm_config->hdr->locktab_head); lck != NULL; lck = SOA(lck->next)) { |
|
|
if ((stcmp (lck->nref, key) == 0) && (strcmp (lck->namespace, chk_ns) == 0)) { |
if ((stcmp (lck->nref, key) == 0) && (strcmp (lck->namespace, chk_ns) == 0)) { |
|
|
Line 482 locktab_ent_t *locktab_insert(char *key)
|
Line 534 locktab_ent_t *locktab_insert(char *key)
|
ik = internal_to_mref (ik, key); |
ik = internal_to_mref (ik, key); |
|
|
if (key[1] == '%') { |
if (key[1] == '%') { |
snprintf (chk_ns, 255, "SYSTEM"); |
snprintf (chk_ns, sizeof (chk_ns) - 1, "SYSTEM"); |
} |
} |
else { |
else { |
snprintf (chk_ns, 255, "%s", nsname); |
snprintf (chk_ns, sizeof (chk_ns) - 1, "%s", nsname); |
} |
} |
|
|
for (l = shm_config->hdr->locktab_head; l != NULL; l = l->next) { |
for (l = SOA(shm_config->hdr->locktab_head); l != NULL; l = SOA(l->next)) { |
ok = mref_init (ok, MREF_RT_GLOBAL, ""); |
ok = mref_init (ok, MREF_RT_GLOBAL, ""); |
ok = internal_to_mref (ok, l->nref); |
ok = internal_to_mref (ok, l->nref); |
|
|
Line 537 new_insert:
|
Line 589 new_insert:
|
} |
} |
|
|
stcpy (l->nref, key); |
stcpy (l->nref, key); |
snprintf (l->namespace, 255, "%s", chk_ns); |
snprintf (l->namespace, sizeof (l->namespace) - 1, "%s", chk_ns); |
|
|
l->owner_job = pid; |
l->owner_job = pid; |
l->ct = 1; |
l->ct = 1; |
|
|
l->next = shm_config->hdr->locktab_head; |
l->next = SBM(SOA(shm_config->hdr->locktab_head)); |
shm_config->hdr->locktab_head = l; |
shm_config->hdr->locktab_head = SBM(l); |
|
|
ssvn_lock_add (l->nref, l->owner_job, l->ct); |
ssvn_lock_add (l->nref, l->owner_job, l->ct); |
|
|
Line 559 int locktab_count(char *key)
|
Line 611 int locktab_count(char *key)
|
locktab_ent_t *l; |
locktab_ent_t *l; |
int ct = 0; |
int ct = 0; |
|
|
for (l = shm_config->hdr->locktab_head; l != NULL; l = l->next) { |
for (l = SOA(shm_config->hdr->locktab_head); l != NULL; l = SOA(l->next)) { |
if (stcmp (l->nref, key) == 0) ct++; |
if (stcmp (l->nref, key) == 0) ct++; |
} |
} |
|
|
Line 586 unsigned long locktab_pages(void)
|
Line 638 unsigned long locktab_pages(void)
|
unsigned long pages = 0; |
unsigned long pages = 0; |
float extra; |
float extra; |
|
|
for (l = shm_config->hdr->locktab_head; l != NULL; l = l->next) { |
for (l = SOA(shm_config->hdr->locktab_head); l != NULL; l = SOA(l->next)) { |
bytes += sizeof (locktab_ent_t); |
bytes += sizeof (locktab_ent_t); |
} |
} |
|
|
Line 608 unsigned long locktab_bytes(void)
|
Line 660 unsigned long locktab_bytes(void)
|
unsigned int ct = 0; |
unsigned int ct = 0; |
unsigned long bytes = 0; |
unsigned long bytes = 0; |
|
|
for (l = shm_config->hdr->locktab_head; l != NULL; l = l->next) { |
for (l = SOA(shm_config->hdr->locktab_head); l != NULL; l = SOA(l->next)) { |
ct++; |
ct++; |
bytes += sizeof (locktab_ent_t); |
bytes += sizeof (locktab_ent_t); |
} |
} |
Line 635 void locktab_dump(void)
|
Line 687 void locktab_dump(void)
|
printf ("%-20s%-20s%-20s%s\r\n", "NAMESPACE", "PID", "COUNT", "KEY"); |
printf ("%-20s%-20s%-20s%s\r\n", "NAMESPACE", "PID", "COUNT", "KEY"); |
printf ("%-20s%-20s%-20s%s\r\n", "---------", "---", "-----", "---"); |
printf ("%-20s%-20s%-20s%s\r\n", "---------", "---", "-----", "---"); |
|
|
if (shm_config->hdr->locktab_head == NULL) { |
if (SOA(shm_config->hdr->locktab_head) == NULL) { |
printf ("\r\n*** lock table empty ***\r\n"); |
printf ("\r\n*** lock table empty ***\r\n"); |
free (r); |
free (r); |
return; |
return; |
} |
} |
|
|
|
|
for (l = shm_config->hdr->locktab_head; l != NULL; l = l->next) { |
for (l = SOA(shm_config->hdr->locktab_head); l != NULL; l = SOA(l->next)) { |
|
|
mref_init (r, MREF_RT_GLOBAL, ""); |
mref_init (r, MREF_RT_GLOBAL, ""); |
internal_to_mref (r, l->nref); |
internal_to_mref (r, l->nref); |