home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ir / synonym.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-05  |  10.9 KB  |  378 lines

  1.  
  2. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  3.  
  4. /*
  5.  * 08/12/94  Changes to allow for caching of synonym tables in shared memory
  6.  *           segments made by Alberto Accomazzi (alberto@cfa.harvard.edu).
  7.  *           Two kinds of shared memory segments are used:
  8.  *           a "master" one containing an array of structures describing
  9.  *           what and how big the synonym tables cached in shared memory
  10.  *           are, and the synonym table data itself.  The first one is
  11.  *           created by the main server body, while the other tables are
  12.  *           created, if necessary, when a new synonym table is opened.
  13.  *           The synonym data as well as the synonym table (consisting
  14.  *           of pointers to the data area) are now both stored in contiguous
  15.  *           memory areas.  This allows us to copy them directly into 
  16.  *           shared memory by just changing offsets of the pointers in
  17.  *           the synonym table.
  18.  *           Since the master shared memory area is created only by the
  19.  *           server program, no caching takes place during indexing.
  20.  *           Beware that the shared memory areas may grow large depending
  21.  *           on the size of your synonym files.  The maximum number of
  22.  *           cached synonym files is defined in "synonym.h" as
  23.  *           MAX_SYN_CACHE.
  24.  */
  25.  
  26. #include "synonym.h"
  27. #include "cutil.h"
  28. #include <errno.h>
  29. #ifdef Mach
  30. extern int errno;
  31. #endif
  32.  
  33. char *syn_Buffer;
  34.  
  35. /* key to master shmem area */
  36. int cacheSynId;
  37.  
  38. #ifdef CACHE_SYN
  39. int synCached = 0;
  40. #define NAPTIME 1
  41. #define MAXNAPTIME 5
  42. #endif
  43.  
  44. int     syn_compare (arg1, arg2)
  45.         void * arg1, *arg2;
  46. {
  47.     t_Synonym * p1, *p2;
  48.     p1 = (t_Synonym *) arg1;
  49.     p2 = (t_Synonym *) arg2;
  50.     return strcasecmp (p1 -> key, p2 -> key);
  51. }
  52.  
  53. char   *lookup_Synonym (word, syn_Table, syn_Table_Size)
  54. char   *word;
  55. t_Synonym * syn_Table;
  56. int     syn_Table_Size;
  57. {
  58.     t_Synonym tmp;
  59.     t_Synonym * rec;
  60.     if (syn_Table_Size == 0)
  61.     return word;
  62.     if (syn_Table_Size==1) {
  63.       if (syn_Table->key == NULL) {
  64.         return(word);
  65.       } else {
  66.         if (strcasecmp(word,syn_Table->key)) {
  67.           return(word);
  68.         } else {
  69.           return(rec->root);
  70.         }
  71.       }
  72.     } else {
  73.       tmp.key = (char *) s_malloc (strlen (word) + 1);
  74.       strcpy (tmp.key, word);
  75.       rec = (t_Synonym *) bsearch (&tmp, syn_Table, 
  76.                                    syn_Table_Size, sizeof (t_Synonym), 
  77.                    syn_compare);
  78.       s_free (tmp.key);
  79.     }
  80.     if (rec)
  81.     return rec -> root;
  82.     return word;
  83. }
  84.  
  85.  
  86. void syn_ReadFile (fn, ptr, syn_Table_Size)
  87. char   *fn;
  88. t_Synonym ** ptr;
  89. int    *syn_Table_Size;
  90. {
  91.     int syn_Table_Max, syn_Buffer_Max, syn_Buffer_Size = 0, i = 0;
  92.     char   *key,
  93.            *datum,
  94.            *oldsynb,
  95.             inputLine[SYN_FILE_LINE_LENGTH];
  96.     FILE * fp;
  97.     long offset;
  98.     t_Synonym * syn_Table = NULL;
  99. #ifdef CACHE_SYN
  100.     t_cacheSyn *syn_Cache, *cs = NULL;
  101.     int TheId = 0, doshmem = 1;
  102.     key_t shm_key;
  103.     t_Synonym *tblptr;
  104.     char *shmptr, *pcs;
  105. #endif
  106.  
  107.     *syn_Table_Size = 0;
  108.     
  109. #ifdef CACHE_SYN
  110.     /* see if this synonym list is in shared memory */
  111.     if (cacheSynId && (pcs = (char *) shmat (cacheSynId, 0, 0)) !=
  112.     ((char *)-1)) {
  113.         syn_Cache = (t_cacheSyn *) pcs;
  114.     for (i = 0; i < MAX_SYN_CACHE; i++) {
  115.         cs = (t_cacheSyn *) pcs;
  116.         if (!strcmp(cs->synfile, fn) || !cs->id) {
  117.             /* found the synonym list */
  118.             TheId = cs->id;
  119.         break;
  120.         }
  121.         pcs += sizeof(t_cacheSyn);
  122.     }
  123.     if (TheId == -1) {
  124.         /* some other process is handling this shared memory segment;
  125.          * sleep for a while */
  126.         int naptime = 0;
  127.         waislog(WLOG_MEDIUM, WLOG_INFO,
  128.             "Another process is locking shared memory segment for file %s", cs->synfile);
  129.         while (cs->id == -1 && naptime < MAXNAPTIME) {
  130.             sleep(NAPTIME);
  131.         naptime += NAPTIME;
  132.         waislog(WLOG_MEDIUM, WLOG_INFO,
  133.             "Shared memory entry for synonym file %s locked, waiting since %d seconds", fn, naptime);
  134.         }
  135.         if (cs->id == -1) {
  136.             TheId = 0;
  137.         doshmem = 0;
  138.         waislog(WLOG_HIGH, WLOG_WARNING,
  139.             "Warning - shared memory lock for synonym file %s won't go away after %d seconds, disabling shared memory use for this search", fn, naptime); 
  140.         }
  141.         else 
  142.             TheId = cs->id;
  143.     } 
  144.     /* got the right Id, now attatch it */
  145.     if (TheId) {
  146.         if ((tblptr = (t_Synonym *) shmat (TheId, 0, 0)) != 
  147.          ((t_Synonym *) -1)) {
  148.             /* create pointers in syn_Table from offsets in shmem table */
  149.             *syn_Table_Size = cs->table_size;
  150.         syn_Buffer = (char *) (tblptr + 
  151.                        cs->table_size * sizeof (t_Synonym));
  152.             syn_Table = (t_Synonym *) tblptr;
  153.             for (i = 0; i < cs->table_size; i++) {
  154.             syn_Table[i].root += (long) tblptr;
  155.             syn_Table[i].key  += (long) tblptr;
  156.         }
  157.         (*ptr) = (t_Synonym *) syn_Table;
  158.         synCached = 1;
  159.         return;
  160.         }
  161.         else {
  162.             doshmem = 0;
  163.             waislog (WLOG_HIGH, WLOG_WARNING, "Warning, couldn't attatch shared memory segment for file %s", fn);
  164.         }
  165.     }
  166.     else if (doshmem) {
  167.         /* this slot is empty, lock it now */
  168.         cs->id = -1;
  169.         strcpy(cs->synfile, fn);
  170.         waislog(WLOG_MEDIUM, WLOG_INFO,
  171.             "Locking shared memory segment for file %s", fn);
  172.     }
  173.     }
  174.     else { 
  175.         if (cacheSynId)
  176.          waislog (WLOG_HIGH, WLOG_WARNING, "Warning, couldn't attatch master shared memory segment");
  177.     doshmem = 0;
  178.     }
  179. #endif /* CACHE_SYN */
  180.  
  181.     fp = fopen (fn, "rb");
  182.     if (!fp) {
  183.     waislog (WLOG_HIGH, WLOG_WARNING, "Warning: couldn't open %s - synonym translation disabled", fn);
  184.     return;
  185.     }
  186.     /* allocate first buffer for synonym table and strings */
  187.     syn_Table_Max = BUFSIZ / sizeof (t_Synonym);
  188.     syn_Table = (t_Synonym *) s_malloc (syn_Table_Max * sizeof (t_Synonym));
  189.     syn_Buffer_Max = 10 * BUFSIZ;
  190.     syn_Buffer = (char *) s_malloc (syn_Buffer_Max);
  191.     if (!syn_Table || !syn_Buffer) {
  192.     waislog (WLOG_HIGH, WLOG_WARNING, "Warning: error allocating space for %s - synonym translation disabled", fn);
  193.     goto wrapup;
  194.     }
  195.     
  196.  
  197.     /* read entries from file and write them into syn_Table */
  198.     while (!feof (fp)) {
  199.     fgets (inputLine, SYN_FILE_LINE_LENGTH - 1, fp);
  200.     datum = (char *) strtok (inputLine, " \n\r");
  201.     if (datum[0] != '#')    /* skip comment lines */
  202.         while ((key = (char *) strtok (NULL, " \n\r"))) {
  203.         (*syn_Table_Size)++;
  204.         if (*syn_Table_Size >= syn_Table_Max) {
  205.             syn_Table_Max += BUFSIZ / sizeof (t_Synonym);
  206.             syn_Table = (t_Synonym *) realloc (syn_Table, 
  207.                                (syn_Table_Max * 
  208.                             sizeof (t_Synonym)));
  209.             if (!syn_Table) {
  210.                 waislog (WLOG_HIGH, WLOG_WARNING, 
  211.                  "Warning: error allocating space for %s - synonym translation disabled", fn);
  212.             (*syn_Table_Size) = 0;
  213.             goto wrapup;
  214.             }
  215.         }
  216.         if (syn_Buffer_Size + strlen (datum) + strlen (key) + 2 >=
  217.             syn_Buffer_Max) {
  218.             syn_Buffer_Max += 10 * BUFSIZ;
  219.             /* save location of original pointer to buffer */
  220.             oldsynb = syn_Buffer;
  221.             syn_Buffer = (char *) realloc (syn_Buffer, syn_Buffer_Max);
  222.             if (!syn_Buffer) {
  223.                 waislog (WLOG_HIGH, WLOG_WARNING, 
  224.                  "Warning: error allocating space for %s - synonym translation disabled", fn);
  225.             (*syn_Table_Size) = 0;
  226.             goto wrapup;
  227.             }
  228.             if (oldsynb != syn_Buffer) {
  229.                 /* data area has moved; reset pointers */
  230.             offset = syn_Buffer - oldsynb;
  231.             for (i = 0; i < *syn_Table_Size - 1; i++) {
  232.                 syn_Table[i].root += offset;
  233.                 syn_Table[i].key  += offset;
  234.             }
  235.             }
  236.         }
  237.         synptr (root) = (char *) syn_Buffer + syn_Buffer_Size;
  238.         syn_Buffer_Size += strlen (datum) + 1;
  239.         strcpy (synptr (root), datum);
  240.         synptr (key) = (char *) syn_Buffer + syn_Buffer_Size;
  241.         syn_Buffer_Size += strlen (key) + 1;
  242.         strcpy (synptr (key), key);
  243.         }
  244.     }
  245.     fclose (fp);
  246.     qsort (syn_Table, (*syn_Table_Size), sizeof (t_Synonym), syn_compare);
  247.     (*ptr) = (t_Synonym *) syn_Table;
  248.  
  249. wrapup:
  250.  
  251. #ifdef CACHE_SYN
  252.  
  253.     if (!doshmem)
  254.         return;
  255.     /* try to put synonym table in a shared memory segment if a slot
  256.      * in the master table was locked */
  257.     if (cs->id != -1)
  258.         return;
  259.  
  260.     offset = *syn_Table_Size * sizeof (t_Synonym);
  261.     tblptr = (t_Synonym *) s_malloc (offset);
  262.     if (!tblptr) {
  263.         waislog (WLOG_HIGH, WLOG_WARNING, 
  264.          "Warning: cannot allocate memory for resetting synonym pointers");
  265.     cs->id = 0;
  266.     (cs->synfile)[0] = '\0';
  267.     return;
  268.     }
  269.     shm_key = 1;
  270.     TheId = -1;
  271.     while (TheId == (-1)) {
  272.         TheId = shmget (shm_key, offset + syn_Buffer_Size, 
  273.             0644 | IPC_CREAT | IPC_EXCL);
  274.     if (TheId == (-1) && errno != EEXIST) {
  275.         waislog (WLOG_HIGH, WLOG_WARNING, 
  276.              "Warning: cannot get shared memory for synonym file %s, caching disabled", fn);
  277.         break;
  278.     }
  279.     shm_key++;
  280.     }
  281.     if (TheId <= 0) {
  282.         s_free (tblptr);
  283.     cs->id = 0;
  284.     (cs->synfile)[0] = '\0';
  285.         return;
  286.     }
  287.     if ((shmptr = (char *) shmat (TheId, 0, 0)) == ((char *)-1)) {
  288.         waislog (WLOG_HIGH, WLOG_WARNING, 
  289.          "Warning: cannot attatch shared memory segment for synonym file %s, caching disabled", fn);
  290.         s_free (tblptr);
  291.     cs->id = 0;
  292.     (cs->synfile)[0] = '\0';
  293.     return;
  294.     }
  295.  
  296.     /* translate absolute pointer values to relative offsets (see description
  297.      * of data layout in the shared memory segment) */
  298.     for (i = 0; i < *syn_Table_Size; i++) {
  299.         tblptr[i].root = (char *) (offset + syn_Table[i].root - syn_Buffer);
  300.         tblptr[i].key  = (char *) (offset + syn_Table[i].key  - syn_Buffer);
  301.     }
  302.  
  303.     /* now just copy the two memory blocks in the shmem segment */
  304.     memcpy (shmptr, tblptr, offset);
  305.     memcpy (shmptr + offset, syn_Buffer, syn_Buffer_Size);
  306.  
  307.     /* fill entry in master shmem table */
  308.     cs->table_size = *syn_Table_Size;
  309.     cs->id = TheId;
  310.  
  311. #endif /* CACHE_SYN */
  312.  
  313.     return;
  314. }
  315.  
  316.  
  317. void syn_Free (syn_Table, syn_Table_Size)
  318. t_Synonym * syn_Table;
  319. int    *syn_Table_Size;
  320. {
  321. #ifdef CACHE_SYN
  322.     if (synCached) {
  323.         /* reset pointers in shared memory */
  324.         register int i;
  325.     long offset = *syn_Table_Size * sizeof (t_Synonym);
  326.     /* translate absolute pointer values to relative offsets
  327.      * (see description of data layout in the shared memory segment) */
  328.     for (i = 0; i < *syn_Table_Size; i++) {
  329.         syn_Table[i].root -= (long) syn_Table;
  330.         syn_Table[i].key  -= (long) syn_Table;
  331.     }
  332.     /* now forget all about shmem segments */
  333.     shmdt((char *)syn_Table);
  334.     syn_Buffer = NULL;
  335.     *syn_Table_Size = 0;
  336.     return;
  337.     }
  338. #endif        
  339.     if (syn_Table)
  340.         s_free (syn_Table);
  341.     syn_Table = NULL;
  342.     *syn_Table_Size = 0;
  343.     if (syn_Buffer)
  344.         s_free (syn_Buffer);
  345.     syn_Buffer = NULL;
  346.     return;
  347. }
  348.  
  349.  
  350.     
  351. /* 
  352.    test stub for synonym routines 
  353.  
  354. char* log_file_name=NULL;
  355. FILE* logfile;
  356. main( argc,argv )
  357. int argc;
  358. char* argv[];
  359. {
  360.   char word[256];  
  361.   t_Synonym* syn_Table;
  362.   int syn_Table_Size;
  363.   logfile=stderr;
  364.   log_file_name="/dev/null";
  365.   syn_ReadFile( "test.syn",&syn_Table,&syn_Table_Size );
  366.   printf("Enter synonyms at the prompt.  Hit CTRL-D when you're done.\nWord   : ");
  367. #ifndef _GETS_
  368.   while (fgets(word, 256, stdin))
  369. #else
  370.   while (gets(word))
  371. #endif
  372.       printf("Synonym: %s\nWord   : ", lookup_Synonym(word,syn_Table,syn_Table_Size));
  373.   syn_Free( syn_Table,&syn_Table_Size );
  374.  
  375.  
  376. */
  377.