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

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

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