home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / c / cbase.zoo / btree101.zoo / btdemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-20  |  14.5 KB  |  526 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "@(#)btdemo.c    1.4 - 90/06/20" */
  5.  
  6. #include <blkio.h>
  7. #include <errno.h>
  8. #include <btree.h>
  9. #include <ctype.h>
  10. #include <stdio.h>
  11. #ifdef AC_HDRS
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #else
  15. #ifndef EXIT_SUCCESS
  16. #define EXIT_SUCCESS    (0)
  17. #define EXIT_FAILURE    (1)
  18. void *memmove(t, s, n)
  19. void *t;
  20. void *s;
  21. size_t n;
  22. {
  23.     void *buf = NULL;
  24.     if ((buf = calloc((size_t)1, n)) == NULL) return NULL;
  25.     memcpy(buf, s, n);
  26.     memcpy(t, buf, n);
  27.     free(buf);
  28.     return t;
  29. }
  30. #endif
  31. #endif
  32.  
  33. #ifdef AC_PROTO
  34. int bdlock(btree_t *btp, int ltype);
  35. int putmenu(void);
  36. #else
  37. int bdlock();
  38. int putmenu();
  39. #endif
  40.  
  41. /* comparison function */
  42. int cmp(p1, p2, n)
  43. const void *p1;
  44. const void *p2;
  45. size_t n;
  46. {
  47.     return strncmp((char *)p1, (char *)p2, n);
  48. }
  49.  
  50. /* constants */
  51. #define LMAXTRIES    100        /* maximum lock tries */
  52. #define USAGE    ("Usage: btdemo filename keysize")
  53.  
  54. /* btdemo user requests */
  55. #define REQ_NEXT    ('N')    /* next */
  56. #define REQ_PREV    ('P')    /* previous */
  57. #define REQ_FIRST    ('F')    /* first */
  58. #define REQ_LAST    ('L')    /* last */
  59. #define REQ_INS        ('I')    /* insert */
  60. #define REQ_DEL        ('D')    /* delete */
  61. #define REQ_SRCH    ('S')    /* search */
  62. #define REQ_CUR        ('C')    /* current */
  63. #define REQ_ALL        ('A')    /* all */
  64. #define REQ_MENU    ('M')    /* help */
  65. #define REQ_QUIT    ('Q')    /* quit */
  66.  
  67. /*man---------------------------------------------------------------------------
  68. NAME
  69.      btdemo - btree demonstration program
  70.  
  71. SYNOPSIS
  72.      btdemo filename keysize
  73.  
  74. DESCRIPTION
  75.      btdemo is a demonstration program for the btree library.  It
  76.      allows interactive direct access to a btree with keys having a
  77.      single field of string data sorted by strncmp in ascending order.
  78.  
  79. SEE ALSO
  80.      btdump, btlist, btree.
  81.  
  82. WARNING
  83.      btdemo should be used only on btrees with keys having a single
  84.      field of string data sorted by strncmp in ascending order.  Use
  85.      on other btrees will produce unpredictable results and corrupt
  86.      the file if modifications are attempted.
  87.  
  88. ------------------------------------------------------------------------------*/
  89. int main(argc, argv)
  90. int argc;
  91. char *argv[];
  92. {
  93.     btree_t *    btp    = NULL;        /* btree pointer */
  94.     char        buf[256];        /* input buffer */
  95.     char *        endp    = NULL;        /* pointer for strtol fct */
  96.     char filename[FILENAME_MAX + 1];    /* btree file name */
  97.     int        fldc    = 1;        /* field count */
  98.     btfield_t    fldv[1];        /* field definition list */
  99.     int        found    = 0;        /* key found flag */
  100.     void *        key    = NULL;        /* key */
  101.     long        keylen    = 0;        /* strtol return */
  102.     size_t        keysize    = 0;        /* key size */
  103.     const int    m    = 4;        /* btree order */
  104.     int        rq    = 0;        /* user request */
  105.  
  106.     /* process command line options and arguments */
  107.     --argc;        /* filename argument */
  108.     ++argv;
  109.     if (argc < 1) {
  110.         puts(USAGE);
  111.         bexit(EXIT_FAILURE);
  112.     }
  113.     strncpy(filename, *argv, sizeof(filename));
  114.     filename[sizeof(filename) - 1] = NUL;
  115.     --argc;        /* key size argument */
  116.     ++argv;
  117.     if (argc < 1) {
  118.         puts(USAGE);
  119.         bexit(EXIT_FAILURE);
  120.     }
  121.     errno = 0;
  122.     keylen = strtol(*argv, &endp, 10);
  123.     if (errno == ERANGE) {
  124.         puts("btdemo: keysize argument out of range.");
  125.         puts(USAGE);
  126.         bexit(EXIT_FAILURE);
  127.     }
  128.     if (endp != NULL) {
  129.         if (endp[0] != NUL) {
  130.             puts(USAGE);
  131.             bexit(EXIT_FAILURE);
  132.         }
  133.     }
  134.     if (keylen < 1) {
  135.         puts(USAGE);
  136.         bexit(EXIT_FAILURE);
  137.     }
  138.     keysize = keylen;
  139.     if (argc != 1) {
  140.         puts(USAGE);
  141.         bexit(EXIT_FAILURE);
  142.     }
  143.  
  144.     /* open btree */
  145.     fldc = 1;
  146.     fldv[0].offset = 0;
  147.     fldv[0].len = keysize;
  148.     fldv[0].cmp = cmp;
  149.     fldv[0].flags = BT_FASC;
  150.     btp = btopen(filename, "r+", fldc, fldv);
  151.     if (btp == NULL) {
  152.         if (errno != ENOENT) {
  153.             fprintf(stderr, "*** Error %d opening btree.\n", errno);
  154.             bexit(EXIT_FAILURE);
  155.         }
  156.         printf("btree %s does not exist.  Creating.\n\n", filename);
  157.         if (btcreate(filename, m, keysize, fldc, fldv) == -1) {
  158.             fprintf(stderr, "*** Error %d creating btree.\n", errno);
  159.             bexit(EXIT_FAILURE);
  160.         }
  161.         btp = btopen(filename, "r+", fldc, fldv);
  162.         if (btp == NULL) {
  163.             fprintf(stderr, "*** Error %d opening btree.\n", errno);
  164.             bexit(EXIT_FAILURE);
  165.         }
  166.     }
  167.     if (keysize != btkeysize(btp)) {
  168.         printf("Incorrect keysize.  Keysize for this btree is %lu.\n", (unsigned long)btkeysize(btp));
  169.         bexit(EXIT_FAILURE);
  170.     }
  171.  
  172.     /* allocate key storage */
  173.     key = calloc(btkeysize(btp), (size_t)1);
  174.     if (key == NULL) {
  175.         fprintf(stderr, "Insufficient memory for key.\n");
  176.         bexit(EXIT_FAILURE);
  177.     }
  178.  
  179.     puts("\n--------------------------------------------------");
  180.     puts("|           btree Library Demo Program           |");
  181.     puts("--------------------------------------------------\n");
  182.     putmenu();
  183.  
  184.     /* main loop */
  185.     for (;;) {
  186.         fputs("Enter selection:  ", stdout);
  187.         fgets(buf, (int)sizeof(buf), stdin);
  188.         if (buf[strlen(buf) - 1] == '\n') {
  189.             buf[strlen(buf) - 1] = NUL;
  190.         }
  191.         /* add string library function to extract leading spaces */
  192.         rq = toupper(*buf);
  193.         if (rq == REQ_QUIT) {    /* quit btdemo */
  194.             break;
  195.         }
  196.         if (rq == NUL) {    /* default to next key */
  197.             rq = REQ_NEXT;
  198.         }
  199. if (rq == 'X') {
  200. if (bt_dgbtree(btp, btp->bthdr.root, stdout) == -1) {
  201. perror("bt_dgbtree");
  202. exit(1);
  203. }
  204. continue;
  205. }
  206.         switch (rq) {
  207.         case REQ_NEXT:    /* next key */
  208.             if (bdlock(btp, BT_RDLCK) == -1) {
  209.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  210.                 bexit(EXIT_FAILURE);
  211.             }
  212.             if (btkeycnt(btp) == 0) {
  213.                 printf("The btree is empty.\n\n");
  214.                 if (bdlock(btp, BT_UNLCK) == -1) {
  215.                     fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  216.                     bexit(EXIT_FAILURE);
  217.                 }
  218.                 break;
  219.             }
  220.             found = btsearch(btp, key);
  221.             if (found == -1) {
  222.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  223.                 bexit(EXIT_FAILURE);
  224.             }
  225.             if (found == 1) {
  226.                 if (btnext(btp) == -1) {
  227.                     fprintf(stderr, "*** Error %d finding next key.\n", errno);
  228.                     bexit(EXIT_FAILURE);
  229.                 }
  230.             }
  231.             if (btcursor(btp) == NULL) {
  232.                 puts("On last key.\n");
  233.             } else {
  234.                 if (btgetk(btp, key) == -1) {
  235.                     fprintf(stderr, "*** Error %d reading key.\n", errno);
  236.                     bexit(EXIT_FAILURE);
  237.                 }
  238.                 printf("The next key is %s.\n\n", (char *)key);
  239.             }
  240.             if (bdlock(btp, BT_UNLCK) == -1) {
  241.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  242.                 bexit(EXIT_FAILURE);
  243.             }
  244.             break;    /* case REQ_NEXT: */
  245.         case REQ_PREV:    /* previous key */
  246.             if (bdlock(btp, BT_RDLCK) == -1) {
  247.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  248.                 bexit(EXIT_FAILURE);
  249.             }
  250.             if (btkeycnt(btp) == 0) {
  251.                 puts("The btree is empty.\n");
  252.                 if (bdlock(btp, BT_UNLCK) == -1) {
  253.                     fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  254.                     bexit(EXIT_FAILURE);
  255.                 }
  256.                 break;
  257.             }
  258.             found = btsearch(btp, key);
  259.             if (found == -1) {
  260.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  261.                 bexit(EXIT_FAILURE);
  262.             }
  263.             if (found == 1) {
  264.                 if (btprev(btp) == -1) {
  265.                     fprintf(stderr, "*** Error %d finding previous key.\n", errno);
  266.                     bexit(EXIT_FAILURE);
  267.                 }
  268.             }
  269.             if (btcursor(btp) == NULL) {
  270.                 puts("On first key.\n");
  271.             } else {
  272.                 if (btgetk(btp, key) == -1) {
  273.                     fprintf(stderr, "*** Error %d reading key.\n", errno);
  274.                     bexit(EXIT_FAILURE);
  275.                 }
  276.                 printf("The previous key is %s.\n\n", (char *)key);
  277.             }
  278.             if (bdlock(btp, BT_UNLCK) == -1) {
  279.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  280.                 bexit(EXIT_FAILURE);
  281.             }
  282.             break;    /* case REQ_PREV: */
  283.         case REQ_FIRST:    /* first key */
  284.             if (bdlock(btp, BT_RDLCK) == -1) {
  285.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  286.                 bexit(EXIT_FAILURE);
  287.             }
  288.             if (btkeycnt(btp) == 0) {
  289.                 puts("The btree is empty.\n");
  290.                 if (bdlock(btp, BT_UNLCK) == -1) {
  291.                     fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  292.                     bexit(EXIT_FAILURE);
  293.                 }
  294.                 break;
  295.             }
  296.             if (btfirst(btp) == -1) {
  297.                 fprintf(stderr, "*** Error %d finding first key.\n", errno);
  298.                 bexit(EXIT_FAILURE);
  299.             }
  300.             if (btgetk(btp, key) == -1) {
  301.                 fprintf(stderr, "*** Error %d reading key.\n", errno);
  302.                 bexit(EXIT_FAILURE);
  303.             }
  304.             if (bdlock(btp, BT_UNLCK) == -1) {
  305.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  306.                 bexit(EXIT_FAILURE);
  307.             }
  308.             printf("The first key is %s.\n\n", (char *)key);
  309.             break;    /* case REQ_FIRST: */
  310.         case REQ_LAST:    /* last key */
  311.             if (bdlock(btp, BT_RDLCK) == -1) {
  312.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  313.                 bexit(EXIT_FAILURE);
  314.             }
  315.             if (btkeycnt(btp) == 0) {
  316.                 puts("The btree is empty.\n");
  317.                 if (bdlock(btp, BT_UNLCK) == -1) {
  318.                     fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  319.                     bexit(EXIT_FAILURE);
  320.                 }
  321.                 break;
  322.             }
  323.             if (btlast(btp) == -1) {
  324.                 fprintf(stderr, "*** Error %d finding last key.\n", errno);
  325.                 bexit(EXIT_FAILURE);
  326.             }
  327.             if (btgetk(btp, key) == -1) {
  328.                 fprintf(stderr, "*** Error %d reading key.\n", errno);
  329.                 bexit(EXIT_FAILURE);
  330.             }
  331.             if (bdlock(btp, BT_UNLCK) == -1) {
  332.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  333.                 bexit(EXIT_FAILURE);
  334.             }
  335.             printf("The last key is %s.\n", (char *)key);
  336.             break;    /* case REQ_LAST: */
  337.         case REQ_INS:    /* insert key */
  338.             printf("Enter key to insert:  ");
  339.             memset(key, 0, btkeysize(btp));
  340.             fgets(buf, (int)sizeof(buf), stdin);
  341.             if (buf[strlen(buf) - 1] == '\n') {
  342.                 buf[strlen(buf) - 1] = NUL;
  343.             }
  344.             strncpy((char *)key, buf, btkeysize(btp));
  345.             ((char *)key)[btkeysize(btp) - 1] = NUL;
  346.             if (bdlock(btp, BT_WRLCK) == -1) {
  347.                 fprintf(stderr, "*** Error %d write locking btree.\n", errno);
  348.                 bexit(EXIT_FAILURE);
  349.             }
  350.             if (btinsert(btp, key) == -1) {
  351.                 if (errno == BTEDUP) {
  352.                     printf("%s is already in the btree.\n\n", (char *)key);
  353.                 } else {
  354.                     fprintf(stderr, "*** Error %d inserting key into btree.\n", errno);
  355.                     bexit(EXIT_FAILURE);
  356.                 }
  357.             } else {
  358.                 printf("%s inserted in btree.\n\n", (char *)key);
  359.             }
  360.             if (bdlock(btp, BT_UNLCK) == -1) {
  361.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  362.                 bexit(EXIT_FAILURE);
  363.             }
  364.             break;    /* case REQ_INS: */
  365.         case REQ_DEL:    /* delete key */
  366.             fputs("Enter key to delete:  ", stdout);
  367.             memset(key, 0, btkeysize(btp));
  368.             fgets(buf, (int)sizeof(buf), stdin);
  369.             if (buf[strlen(buf) - 1] == '\n') {
  370.                 buf[strlen(buf) - 1] = NUL;
  371.             }
  372.             strncpy((char *)key, buf, btkeysize(btp));
  373.             ((char *)key)[btkeysize(btp) - 1] = NUL;
  374.             if (bdlock(btp, BT_WRLCK) == -1) {
  375.                 fprintf(stderr, "*** Error %d write locking btree.\n", errno);
  376.                 bexit(EXIT_FAILURE);
  377.             }
  378.             if (btdelete(btp, key) == -1) {
  379.                 if (errno == BTENKEY) {
  380.                     printf("%s not found.\n\n", (char *)key);
  381.                 } else {
  382.                     fprintf(stderr, "*** Error %d deleting key.\n", errno);
  383.                     bexit(EXIT_FAILURE);
  384.                 }
  385.             } else {
  386.                 printf("%s deleted from btree.\n\n", (char *)key);
  387.             }
  388.             if (bdlock(btp, BT_UNLCK) == -1) {
  389.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  390.                 bexit(EXIT_FAILURE);
  391.             }
  392.             break;    /* case REQ_DEL: */
  393.         case REQ_SRCH:    /* search for key */
  394.             fputs("Enter search key:  ", stdout);
  395.             memset(key, 0, btkeysize(btp));
  396.             fgets(buf, (int)sizeof(buf), stdin);
  397.             if (buf[strlen(buf) - 1] == '\n') {
  398.                 buf[strlen(buf) - 1] = NUL;
  399.             }
  400.             strncpy((char *)key, buf, btkeysize(btp));
  401.             ((char *)key)[btkeysize(btp) - 1] = NUL;
  402.             if (bdlock(btp, BT_RDLCK) == -1) {
  403.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  404.                 bexit(EXIT_FAILURE);
  405.             }
  406.             found = btsearch(btp, key);
  407.             if (found == -1) {
  408.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  409.                 bexit(EXIT_FAILURE);
  410.             }
  411.             if (found == 1) {
  412.                 printf("%s found.\n", (char *)key);
  413.             } else {
  414.                 printf("%s not found.\n", (char *)key);
  415.             }
  416.             if (bdlock(btp, BT_UNLCK) == -1) {
  417.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  418.                 bexit(EXIT_FAILURE);
  419.             }
  420.             break;    /* case REQ_SRCH: */
  421.         case REQ_CUR:    /* current key */
  422.             if (bdlock(btp, BT_RDLCK) == -1) {
  423.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  424.                 bexit(EXIT_FAILURE);
  425.             }
  426.             found = btsearch(btp, key);
  427.             if (found == -1) {
  428.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  429.                 bexit(EXIT_FAILURE);
  430.             }
  431.             if (found == 1) {
  432.                 printf("Current key: %s.\n", (char *)key);
  433.             } else {
  434.                 printf("No current key.\n");
  435.             }
  436.             if (bdlock(btp, BT_UNLCK) == -1) {
  437.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  438.                 bexit(EXIT_FAILURE);
  439.             }
  440.             break;    /* case REQ_CUR: */
  441.         case REQ_ALL:    /* list all keys */
  442.             if (bdlock(btp, BT_RDLCK) == -1) {
  443.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  444.                 bexit(EXIT_FAILURE);
  445.             }
  446.             printf("There are %lu keys in the btree.\n\n", btkeycnt(btp));
  447.             if (btsetcur(btp, NULL) == -1) {
  448.                 fprintf(stderr, "*** Error %d setting cursor.\n", errno);
  449.                 bexit(EXIT_FAILURE);
  450.             }
  451.             for (;;) {
  452.                 if (btnext(btp) == -1) {
  453.                     fprintf(stderr, "*** Error %d finding next key.\n", errno);
  454.                     bexit(EXIT_FAILURE);
  455.                 }
  456.                 if (btcursor(btp) == NULL) {
  457.                     break;
  458.                 }
  459.                 if (btgetk(btp, key) == -1) {
  460.                     fprintf(stderr, "*** Error %d reading key.\n", errno);
  461.                     bexit(EXIT_FAILURE);
  462.                 }
  463.                 puts((char *)key);
  464.             }
  465.             putchar((int)'\n');
  466.             if (bdlock(btp, BT_UNLCK) == -1) {
  467.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  468.                 bexit(EXIT_FAILURE);
  469.             }
  470.             break;    /* case REQ_ALL: */
  471.         case REQ_MENU:    /* menu */
  472.             putmenu();
  473.             break;    /* case REQ_MENU: */
  474.         default:
  475.             printf("Invalid selection.\a\n");
  476.             break;    /* default: */
  477.         }
  478.     }
  479.  
  480.     /* close btree */
  481.     if (btclose(btp) == -1) {
  482.         fprintf(stderr, "*** Error %d closing btree.\n", errno);
  483.         bexit(EXIT_FAILURE);
  484.     }
  485.  
  486.     bexit(EXIT_SUCCESS);
  487. }
  488.  
  489. /* bdlock:  btdemo lock */
  490. int bdlock(btp, ltype)
  491. btree_t *btp;
  492. int ltype;
  493. {
  494.     int i = 0;
  495.  
  496.     for (i = 0; i < LMAXTRIES; ++i) {
  497.         if (btlock(btp, ltype) == -1) {
  498.             if (errno == EAGAIN) {
  499.                 continue;
  500.             }
  501.             return -1;
  502.         } else {
  503.             errno = 0;
  504.             return 0;
  505.         }
  506.     }
  507.  
  508.     errno = EAGAIN;
  509.     return -1;
  510. }
  511.  
  512. /* putmenu:  display menu */
  513. int putmenu()
  514. {
  515.     puts("-----------------------MENU-----------------------");
  516.     puts("| N - Next key           P - Previous key        |");
  517.     puts("| F - First key          L - Last key            |");
  518.     puts("| I - Insert key         D - Delete key          |");
  519.     puts("| S - Search for key     C - Current key         |");
  520.     puts("| A - display All keys                           |");
  521.     puts("| M - Menu               Q - Quit                |");
  522.     puts("--------------------------------------------------");
  523.  
  524.     return 0;
  525. }
  526.