Annotation of freem/src/locktab.c, revision 1.9

1.1       snw         1: /*
1.9     ! snw         2:  *   $Id: locktab.c,v 1.8 2025/05/14 15:28:55 snw Exp $
1.1       snw         3:  *    lock table implementation
                      4:  *
                      5:  *  
1.3       snw         6:  *   Author: Serena Willis <snw@coherent-logic.com>
1.1       snw         7:  *    Copyright (C) 1998 MUG Deutschland
1.4       snw         8:  *    Copyright (C) 2021, 2025 Coherent Logic Development LLC
1.1       snw         9:  *
                     10:  *
                     11:  *   This file is part of FreeM.
                     12:  *
                     13:  *   FreeM is free software: you can redistribute it and/or modify
                     14:  *   it under the terms of the GNU Affero Public License as published by
                     15:  *   the Free Software Foundation, either version 3 of the License, or
                     16:  *   (at your option) any later version.
                     17:  *
                     18:  *   FreeM is distributed in the hope that it will be useful,
                     19:  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
                     20:  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     21:  *   GNU Affero Public License for more details.
                     22:  *
                     23:  *   You should have received a copy of the GNU Affero Public License
                     24:  *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.
                     25:  *
1.5       snw        26:  *   $Log: locktab.c,v $
1.9     ! snw        27:  *   Revision 1.8  2025/05/14 15:28:55  snw
        !            28:  *   Get basic job table and lock table functionality working with new shared memory architecture
        !            29:  *
1.8       snw        30:  *   Revision 1.7  2025/05/01 21:02:31  snw
                     31:  *   Documentation updates
                     32:  *
1.7       snw        33:  *   Revision 1.6  2025/04/13 04:22:43  snw
                     34:  *   Fix snprintf calls
                     35:  *
1.6       snw        36:  *   Revision 1.5  2025/03/24 02:57:25  snw
                     37:  *   Shared memory compatibility fixes for OS/2
                     38:  *
1.5       snw        39:  *   Revision 1.4  2025/03/09 19:14:25  snw
                     40:  *   First phase of REUSE compliance and header reformat
                     41:  *
1.4       snw        42:  *
                     43:  * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
                     44:  * SPDX-License-Identifier: AGPL-3.0-or-later
1.1       snw        45:  **/
                     46: 
                     47: #include <stdio.h>
                     48: #include <stdlib.h>
                     49: #include <unistd.h>
                     50: #include <time.h>
                     51: #include <string.h>
1.9     ! snw        52: #include <errno.h>
1.1       snw        53: 
                     54: #include "mpsdef.h"
                     55: #include "locktab.h"
                     56: #include "shmmgr.h"
                     57: #include "mref.h"
                     58: #include "transact.h"
1.7       snw        59: #include "log.h"
1.1       snw        60: 
1.5       snw        61: #if !defined(__OpenBSD__) && !defined(__APPLE__) && !defined(__OS2__)
1.1       snw        62: union semun {
                     63:     int              val;    /* Value for SETVAL */
                     64:     struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
                     65:     unsigned short  *array;  /* Array for GETALL, SETALL */
                     66:     struct seminfo  *__buf;  /* Buffer for IPC_INFO
                     67:                                 (Linux-specific) */
                     68: };
                     69: #endif
                     70: 
                     71: int semid_locktab;
                     72: 
                     73: int locktab_list_count(char *key);
                     74: 
                     75: void locktab_init(void)
                     76: {
                     77:     union semun arg;
                     78:     key_t lt_sk;
                     79: 
                     80:     lt_sk = ftok (config_file, 3);
                     81:     
                     82:     if (first_process) {
                     83: 
                     84:         semid_locktab = semget (lt_sk, 1, 0666 | IPC_CREAT);
                     85:         if (semid_locktab == -1) {
1.8       snw        86:             logprintf (FM_LOG_FATAL, "locktab_init:  failed to create lock table semaphore");
1.1       snw        87:         }
                     88: 
                     89:         arg.val = 1;
                     90:         if (semctl (semid_locktab, 0, SETVAL, arg) == -1) {
1.8       snw        91:             logprintf (FM_LOG_FATAL, "locktab_init:  failed to initialize lock table semaphore");
1.1       snw        92:         }
                     93:         
                     94:     }
                     95:     else {
                     96: 
                     97:         semid_locktab = semget (lt_sk, 1, 0);
                     98:         if (semid_locktab == -1) {
1.8       snw        99:             logprintf (FM_LOG_FATAL, "locktab_init:  could not attach to lock table semaphore");
1.1       snw       100:         }
                    101:         
                    102:     }
                    103:     
                    104:     return;
                    105:     
                    106: }
                    107: 
                    108: short locktab_get_sem(void)
                    109: {
                    110:     int tries;
                    111:     struct sembuf s = {0, -1, 0};
                    112: 
1.8       snw       113:     logprintf (FM_LOG_DEBUG, "locktab_get_sem:  attempting to acquire lock table semaphore");
                    114:     
1.1       snw       115:     for (tries = 0; tries < 5; tries++) {
                    116: 
                    117:         if (semop (semid_locktab, &s, 1) != -1) {
1.8       snw       118:             logprintf (FM_LOG_DEBUG, "locktab_get_sem:  acquired semaphore by virtue of calling semop on it");
1.1       snw       119:             return TRUE;
                    120:         }
1.8       snw       121: 
                    122:         logprintf (FM_LOG_INFO, "locktab_get_sem:  sleeping for retry [tries = %d; errno = %d; error = %s]", tries, errno, strerror (errno));
1.1       snw       123:         sleep (1);
                    124: 
                    125:     }
1.8       snw       126:     logprintf (FM_LOG_ERROR, "locktab_get_sem:  failed to acquire job table semaphore");
1.1       snw       127:     
                    128:     return FALSE;
                    129: }
                    130: 
                    131: void locktab_release_sem(void)
                    132: {
                    133:     struct sembuf s = {0, 1, 0};
                    134: 
1.8       snw       135:     logprintf (FM_LOG_DEBUG, "locktab_release_sem:  trying to release lock table semaphore");
                    136:     if(semop (semid_locktab, &s, 1) != - 1) {
                    137:         logprintf (FM_LOG_DEBUG, "locktab_release_sem:  released lock table semaphore by means of semop");
                    138:     }
                    139:     else {
                    140:         logprintf (FM_LOG_FATAL, "locktab_release_sem:  failed to release lock table semaphore (error code %d [%s])", errno, strerror (errno));
                    141:     }
1.1       snw       142: 
                    143: }
                    144: 
                    145: void lock(char *lockarg, long time_out, char type)
                    146: {
                    147:     char *key = &(lockarg[1]);
                    148:     char a = lockarg[0];
                    149:     
                    150:     if (shm_config == NULL) {
                    151:         fprintf (stderr, "lock:  global LOCK operation attemped before shared memory available.\r\n");
                    152:         return;
                    153:     }
                    154: 
                    155:     switch (a) {
                    156: 
                    157:         case '+':
                    158:             locktab_increment (key, time_out, FALSE);
                    159:             break;
                    160:             
                    161:         case '-':
                    162:             locktab_decrement (key, time_out);
                    163:             break;
                    164:             
                    165:         case SP:
                    166:             locktab_unlock_all ();
                    167:             locktab_increment (key, time_out, TRUE);
                    168:             break;
                    169: 
                    170:         default:
                    171:             break;
                    172:             
                    173:     }
                    174: 
                    175:     return;
                    176:     
                    177: }
                    178: 
                    179: void locktab_increment(char *key, long lck_timeout, short old_lock)
                    180: {
                    181:     short lck_action;
                    182:     char chk_ns[256];
                    183:     int nref_ct = locktab_list_count (key);
                    184: 
                    185:     if (old_lock) {
                    186:         lck_action = lock_old;
                    187:     }
                    188:     else {
                    189:         lck_action = lock_inc;
                    190:     }
                    191: 
                    192:     strncpy (chk_ns, nsname, 256);
                    193:     
                    194:     switch (lck_timeout) {
                    195:             
                    196:         case -1: /* blocking lock (no timeout) */
                    197: 
                    198:             if (nref_ct > 1) {
                    199:                 /* this is a lock list */
                    200:                 char *nref;
                    201:                 char tmps[255];
                    202: 
                    203:                 int i;        
                    204:                 int successes = 0;
                    205:                 int attempts = 0;
                    206:                 int list_pos = 0;
                    207:                 
                    208:                 char *attempt_status = (char *) malloc (nref_ct * sizeof (char));
                    209:                 NULLPTRCHK(attempt_status,"locktab_increment");
                    210: 
                    211:                 for (i = 0; i < nref_ct; i++) attempt_status[i] = (char) FALSE;
                    212:                 
                    213:                 stcpy (tmps, key);
                    214:                 stcnv_m2c (tmps);                               
                    215:                 
                    216:                 nref = strtok (tmps, "\001\201");
                    217: 
                    218:                 do {
                    219:                     
                    220:                     list_pos = 0;                    
                    221:                     attempts = 0;
                    222:                     successes = 0;
                    223:                     
                    224:                     for (;;) {                    
                    225: 
                    226:                         attempts++;
                    227:                        
                    228:                         if (attempt_status[list_pos] == FALSE) {
                    229:                             
                    230:                             if (locktab_insert (nref) != NULL) {
                    231:                                 successes++;
                    232:                                 attempt_status[list_pos] = TRUE;
                    233:                             }
                    234:                             else {
                    235:                                 locktab_decrement (nref, -1L);
                    236:                                 attempt_status[list_pos] = FALSE;
                    237:                             }
                    238: 
                    239:                         }
                    240:                         
                    241:                         nref = strtok (NULL, "\001\201");                    
                    242:                         if (nref == NULL) break;
                    243: 
                    244:                         list_pos++;
                    245:                         
                    246:                     }                        
                    247: 
                    248:                 } while (successes < nref_ct);
                    249: 
                    250:                 free (attempt_status);
                    251:                 if (tp_level > 0) tp_add_op (TRUE, lck_action, key, chk_ns);
                    252:                 return;
                    253:                 
                    254:             }
                    255:             else {
1.7       snw       256:                 int sigint_ct = 0;
                    257:                 
1.1       snw       258:                 for (;;) {
                    259:                     
                    260:                     if (locktab_insert (key) != NULL) {
                    261:                         if (tp_level > 0) tp_add_op (TRUE, lck_action, key, chk_ns);
                    262:                         return;
                    263:                     }
                    264:                     else {
1.7       snw       265:                         if (merr () == INRPT) {
                    266:                             sigint_ct++;
                    267: 
                    268:                             if (sigint_ct == 1) {
                    269:                                 printf ("\r\nlocktab_insert:  got Ctrl-C in blocking LOCK; Ctrl-C again to force the process to halt\r\n");
                    270:                                 merr_clear ();
                    271:                             }
                    272:                             else {
                    273:                                 printf ("\r\n");
                    274:                                 logprintf (FM_LOG_FATAL, "locktab_insert:  blocking LOCK was interrupted; forcing halt");
                    275:                             }
                    276:                         }
1.1       snw       277:                         sleep (1);
                    278:                     }
                    279:                 
                    280:                 }
                    281:             }
                    282: 
                    283:             
                    284:         case 0: /* lock that returns immediately */
                    285: 
                    286:             if (nref_ct > 1) {
                    287:                 /* this is a lock list */
                    288:                 char *nref;
                    289:                 char tmps[255];
                    290:                 
                    291:                 int successes = 0;
                    292:                 int attempts = 0;
                    293:                 
                    294:                 stcpy (tmps, key);
                    295:                 stcnv_m2c (tmps);                               
                    296:                 
                    297:                 nref = strtok (tmps, "\001\201");
                    298: 
                    299:                 for (;;) {                    
                    300:                     attempts++;
                    301: 
                    302:                     if (locktab_insert (nref) != NULL) {
                    303:                         successes++;
                    304:                     }
                    305:                     else {
                    306:                         locktab_decrement (nref, 0L);
                    307:                         test = 0;
                    308:                         return;
                    309:                     }
                    310:                     
                    311:                     nref = strtok (NULL, "\001\201");                    
                    312:                     if (nref == NULL) break;
                    313:                 }                        
                    314: 
                    315:                 test = 1;
                    316:                 if (tp_level > 0) tp_add_op (TRUE, lck_action, key, chk_ns);      
                    317:                 return;
                    318:               
                    319:             }
                    320:             else {
                    321:             
                    322:                 if (locktab_insert (key) != NULL) {
                    323:                     test = 1;
                    324:                     if (tp_level > 0) tp_add_op (TRUE, lck_action, key, chk_ns);
                    325:                 }
                    326:                 else {
                    327:                     test = 0;
                    328:                 }
                    329: 
                    330:             }
                    331: 
                    332:             break;
                    333: 
                    334:         case 1: /* special case: lock with 1-second timeout */
                    335: 
                    336:             if (locktab_insert (key) != NULL) {
                    337:                 test = 1;            
                    338:             }
                    339:             else {
                    340:                 sleep (1);
                    341: 
                    342:                 if (locktab_insert (key) != NULL) {
                    343:                     test = 1;
                    344:                     if (tp_level > 0) tp_add_op (TRUE, lck_action, key, chk_ns);
                    345:                 }
                    346:                 else {
                    347:                     test = 0;
                    348:                 }
                    349:             }
                    350: 
                    351:             return;
                    352:             
                    353:         default: /* lock with timeout */
                    354:         {
                    355:             time_t start_secs;
                    356:             time_t end_secs;
                    357:             time_t elapsed;
                    358:             locktab_ent_t *lck = NULL;
                    359:             
                    360:             start_secs = time (NULL);
                    361: 
                    362:             if (nref_ct > 1) {
                    363:                 /* this is a lock-list */
                    364:                 printf ("lock-list with timeout\r\n");
                    365:             }
                    366:             else {
                    367:                 
                    368:             
                    369:                 for (;;) {
                    370:                     
                    371:                     
                    372:                     lck = locktab_insert (key);
                    373:                     
                    374:                     end_secs = time (NULL);
                    375:                     elapsed = end_secs - start_secs;
                    376:                     
                    377:                     if (lck != NULL) {
                    378:                         test = 1;
                    379:                         return;
                    380:                     }
                    381:                     
                    382:                     if (elapsed >= lck_timeout) {
                    383:                         
                    384:                         if (lck == NULL) {
                    385:                             test = 0;          
                    386:                         }
                    387:                         else {
                    388:                             if (tp_level > 0) tp_add_op (TRUE, lck_action, key, chk_ns);
                    389:                             test = 1;
                    390:                         }
                    391:                         
                    392:                         return;
                    393:                         
                    394:                     }
                    395: 
                    396:                     sleep (1); /* prevent CPU pegging */
                    397:                 
                    398:                 } /* timeout loop */
                    399: 
                    400:                 return;
                    401:             }
                    402:             
                    403:         } /* lock with timeout */
                    404:     } /* switch (timeout) */
                    405:             
                    406:             
                    407: }
                    408: 
                    409: void locktab_decrement(char *key, long lck_timeout)
                    410: {
                    411: 
                    412:     locktab_ent_t *lck = locktab_find (key);
                    413:     
                    414:     if (lck != NULL) {
                    415: 
                    416:         if (tp_level > lck->tp_level) {
                    417:             merr_raise (M41);
                    418:             return;
                    419:         }
                    420:         
                    421:         if (lck->ct > 0) lck->ct--;       
                    422:         
                    423:         if (lck->ct == 0) {
                    424:             lck->owner_job = 0;
                    425:             strcpy (lck->namespace, "<REUSABLE>");
                    426: 
                    427:             ssvn_lock_remove (lck->nref);
                    428:         }
                    429: 
                    430:         if (lck->owner_job != 0) {
                    431:             ssvn_lock_add (lck->nref, lck->owner_job, lck->ct);
                    432:         }
                    433:         
                    434:     }
                    435: 
                    436:     if (lck_timeout > -1) test = 1;
                    437:     
                    438: }
                    439: 
                    440: void locktab_unlock_all(void)
                    441: {
1.7       snw       442:     locktab_unlock_all_by_pid (pid);
                    443: }
                    444: 
                    445: void locktab_unlock_all_by_pid(const pid_t target_pid)
                    446: {
1.1       snw       447:     locktab_ent_t *lck;
1.7       snw       448:     int remove_ct;
                    449: 
                    450:     remove_ct = 0;
                    451:     if (target_pid != pid) {
                    452:         logprintf (FM_LOG_INFO, "locktab_unlock_all_by_pid:  removing all locks for pid %ld", target_pid);
                    453:     }
                    454: 
1.1       snw       455:     
1.8       snw       456:     for (lck = SOA(shm_config->hdr->locktab_head); lck != NULL; lck = SOA(lck->next)) {
1.1       snw       457: 
1.7       snw       458:         if (lck->owner_job == target_pid) {
                    459:             remove_ct++;
                    460:             
1.1       snw       461:             if (tp_level > lck->tp_level) {
                    462:                 merr_raise (M41);
                    463:                 return;
                    464:             }
                    465:             
                    466:             lck->ct = 0;
                    467:             lck->owner_job = 0;
                    468:             strcpy (lck->namespace, "<REUSABLE>");
                    469: 
                    470:             ssvn_lock_remove (lck->nref);
                    471:             
                    472:         }
                    473: 
1.7       snw       474:     }
                    475: 
                    476:     if (target_pid != pid) {
                    477:         logprintf (FM_LOG_INFO, "locktab_unlock_all_by_pid:  removed %ld lock(s) for pid %ld", remove_ct, target_pid);
                    478:     }
                    479: 
1.1       snw       480:     
                    481: }
                    482: 
                    483: locktab_ent_t *locktab_find(char *key)
                    484: {
                    485: 
                    486:     locktab_ent_t *lck;
                    487:     char chk_ns[255];
                    488: 
                    489:     if (key[1] == '%') {
1.6       snw       490:         snprintf (chk_ns, sizeof (chk_ns) - 1, "SYSTEM");
1.1       snw       491:     }
                    492:     else {
1.6       snw       493:         snprintf (chk_ns, sizeof (chk_ns) - 1, "%s", nsname);
1.1       snw       494:     }
                    495: 
1.8       snw       496:     for (lck = SOA(shm_config->hdr->locktab_head); lck != NULL; lck = SOA(lck->next)) {
1.1       snw       497: 
                    498:         if ((stcmp (lck->nref, key) == 0) && (strcmp (lck->namespace, chk_ns) == 0)) {
                    499: 
                    500:             if (lck->owner_job != pid) {
                    501:                 return (locktab_ent_t *) NULL;
                    502:             }
                    503:             else {
                    504:                 return lck;
                    505:             }
                    506:             
                    507:         }
                    508:         
                    509:     }
                    510: 
                    511:     return (locktab_ent_t *) NULL;
                    512:     
                    513: }
                    514: 
                    515: locktab_ent_t *locktab_insert(char *key)
                    516: {
                    517:     locktab_ent_t *l;
                    518:     char chk_ns[255];
                    519: 
                    520:     freem_ref_t *ik;
                    521:     freem_ref_t *ok;
                    522:     
                    523:     ik = malloc (sizeof (freem_ref_t));
                    524:     NULLPTRCHK(ik,"locktab_insert");
                    525: 
                    526:     ik = mref_init (ik, MREF_RT_GLOBAL, "");
                    527: 
                    528:     ok = malloc (sizeof (freem_ref_t));
                    529:     NULLPTRCHK(ok,"locktab_insert");    
                    530: 
                    531:     ik = internal_to_mref (ik, key);
                    532:     
                    533:     if (key[1] == '%') {
1.6       snw       534:         snprintf (chk_ns, sizeof (chk_ns) - 1, "SYSTEM");
1.1       snw       535:     }
                    536:     else {
1.6       snw       537:         snprintf (chk_ns, sizeof (chk_ns) - 1, "%s", nsname);
1.1       snw       538:     }
                    539:     
1.8       snw       540:     for (l = SOA(shm_config->hdr->locktab_head); l != NULL; l = SOA(l->next)) {
1.1       snw       541:         ok = mref_init (ok, MREF_RT_GLOBAL, "");
                    542:         ok = internal_to_mref (ok, l->nref);
                    543:         
                    544:         if (((stcmp (l->nref, key) == 0) || (mref_is_descendant (ok, ik) == TRUE)) && (strcmp (l->namespace, chk_ns) == 0)) {
                    545:             
                    546:             /* nref already owned by another job */
                    547:             if ((l->owner_job != pid) && (l->ct > 0)) {
                    548:                 free (ik);
                    549:                 free (ok);
                    550:                 return NULL;
                    551:             }
                    552:             else {
                    553:                 if ((mref_is_descendant (ok, ik)) && (pid == l->owner_job)) {
                    554:                     if (locktab_find (key) == NULL) goto new_insert;
                    555:                 }
                    556:                 
                    557:                 /* increment the lock and return */
                    558:                 l->ct++;
                    559: 
                    560:                 /* if this was a lock with a counter of zero belonging to another pid,
                    561:                  * re-use it and take ownership of it.
                    562:                  */
                    563:                 if (l->owner_job != pid) l->owner_job = pid;
                    564: 
                    565:                 l->tp_level = tp_level;
                    566:                 
                    567:                 ssvn_lock_add (l->nref, l->owner_job, l->ct);
                    568: 
                    569:                 free (ik);
                    570:                 free (ok);
                    571:                 
                    572:                 return l;
                    573:             }
                    574:             
                    575:         }
                    576: 
                    577:     }
                    578: 
                    579: new_insert:
                    580:     /* no lock exists for key: this is a new insert */            
                    581:     l = (locktab_ent_t *) shm_alloc (sizeof (locktab_ent_t));
                    582:     if (l == (locktab_ent_t *) NULL) {
                    583:         free (ik);
                    584:         free (ok);
                    585:         return (locktab_ent_t *) NULL;
                    586:     }
                    587: 
                    588:     stcpy (l->nref, key);
1.6       snw       589:     snprintf (l->namespace, sizeof (l->namespace) - 1, "%s", chk_ns);
1.1       snw       590:         
                    591:     l->owner_job = pid;
                    592:     l->ct = 1;
                    593:     
1.8       snw       594:     l->next = SBM(SOA(shm_config->hdr->locktab_head));
                    595:     shm_config->hdr->locktab_head = SBM(l);
1.1       snw       596: 
                    597:     ssvn_lock_add (l->nref, l->owner_job, l->ct);
                    598: 
                    599:     free (ik);
                    600:     free (ok);
                    601:     
                    602:     return l;
                    603: }
                    604: 
                    605: 
                    606: int locktab_count(char *key)
                    607: {
                    608:     locktab_ent_t *l;
                    609:     int ct = 0;
                    610: 
1.8       snw       611:     for (l = SOA(shm_config->hdr->locktab_head); l != NULL; l = SOA(l->next)) {
1.1       snw       612:         if (stcmp (l->nref, key) == 0) ct++;
                    613:     }
                    614: 
                    615:     return ct;
                    616: }
                    617: 
                    618: int locktab_list_count(char *key)
                    619: {
                    620:     int i;
                    621:     int lct = 0;
                    622:     
                    623:     for (i = 0; i < stlen (key); i++) {
                    624:         if (key[i] == '\001') lct++;        
                    625:     }
                    626: 
                    627:     return lct;
                    628: }
                    629: 
                    630: unsigned long locktab_pages(void)
                    631: {
                    632: 
                    633:     locktab_ent_t *l;
                    634:     unsigned long bytes = 0;
                    635:     unsigned long pages = 0;
                    636:     float extra;
                    637:     
1.8       snw       638:     for (l = SOA(shm_config->hdr->locktab_head); l != NULL; l = SOA(l->next)) {
1.1       snw       639:         bytes += sizeof (locktab_ent_t);
                    640:     }
                    641: 
                    642:     pages = bytes / PG_SIZE;
                    643:     extra = bytes % PG_SIZE;
                    644:     
                    645:     if (extra > 0) {
                    646:         pages++;
                    647:     }
                    648: 
                    649:     return pages;
                    650:   
                    651: }
                    652: 
                    653: unsigned long locktab_bytes(void)
                    654: {
                    655: 
                    656:     locktab_ent_t *l;
                    657:     unsigned int ct = 0;
                    658:     unsigned long bytes = 0;
                    659: 
1.8       snw       660:     for (l = SOA(shm_config->hdr->locktab_head); l != NULL; l = SOA(l->next)) {
1.1       snw       661:         ct++;
                    662:         bytes += sizeof (locktab_ent_t);
                    663:     }
                    664: 
                    665:     return bytes;
                    666: 
                    667: }
                    668: 
                    669: void locktab_dump(void)
                    670: {
                    671:     
                    672:     locktab_ent_t *l;
                    673:     unsigned long ct = 0;
                    674:     unsigned long tot = 0;
                    675:     freem_ref_t *r;
                    676:     char *ref_ext;
                    677:     
                    678:     r = (freem_ref_t *) malloc (sizeof (freem_ref_t));
                    679:     NULLPTRCHK(r,"locktab_dump");
                    680: 
                    681:     ref_ext = (char *) malloc (STRLEN * sizeof (char));
                    682:     NULLPTRCHK(ref_ext,"locktab_dump");
                    683:     
                    684:     printf ("%-20s%-20s%-20s%s\r\n", "NAMESPACE", "PID", "COUNT", "KEY");
                    685:     printf ("%-20s%-20s%-20s%s\r\n", "---------", "---", "-----", "---");
                    686: 
1.8       snw       687:     if (SOA(shm_config->hdr->locktab_head) == NULL) {
1.1       snw       688:         printf ("\r\n*** lock table empty ***\r\n");
                    689:         free (r);
                    690:         return;
                    691:     }
                    692: 
                    693:     
1.8       snw       694:     for (l = SOA(shm_config->hdr->locktab_head); l != NULL; l = SOA(l->next)) {
1.1       snw       695: 
                    696:         mref_init (r, MREF_RT_GLOBAL, "");
                    697:         internal_to_mref (r, l->nref);
                    698:         mref_to_external (r, ref_ext);
                    699: 
                    700:         if (l->owner_job) {
                    701:             printf ("%-20s%-20d%-20d%s\r\n", l->namespace, l->owner_job, l->ct, ref_ext);
                    702:             ct++;
                    703:         }
                    704:         
                    705:         tot++;
                    706:         
                    707:     }
                    708: 
                    709:     printf ("\r\n\tActive LOCK table entries:            %ld\r\n", ct);
                    710:     printf (    "\tReusable LOCK table entries:          %ld\r\n", tot - ct);
                    711:     printf (    "\tShared memory pages:                  %ld\r\n", locktab_pages ());
                    712:     printf (    "\tShared memory bytes:                  %ld\r\n", locktab_bytes ());
                    713: 
                    714:     free (r);
                    715:     free (ref_ext);
                    716:     
                    717:     return;
                    718:     
                    719: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>