summaryrefslogblamecommitdiffstats
path: root/util/uhash_loader.c
blob: 8696b3c4ce85e5f39df08b591396a71e6b810c8b (plain) (tree)
1
2
3
4
5
6
7
8
9
          
                                        
                
                     
 

                                                         

                      
           
 

          







                       
                   
                                    
                  
                                
      
                                                
                

                                        
                  
                                    
      
                                         

                    


                         
                                         
                            


                        
                          
                                    

                                   
 





                                                                                                 
 
                                                         







                                               

 

                     
                                              

                   
                                                     
                                                        

                





                                                        
        


                                       


                          




                                             



                                  
    
                                           




                               
                                                                                    








                                              
                

                                                                          
                                                                       








                                      
                             

                                                                           
 
                                                          
 

                   










                                                                           
                                                
    
                             




                                                              


                                


                                            
                    



                                               
                                     


                                                                    
                                   
 
/* $Id$ */
/* standalone uhash loader -- jochang */
#include "bbs.h"
#include "fnv_hash.h"

void userec_add_to_uhash(int n, userec_t *id, int onfly);
void fill_uhash(int onfly);
void load_uhash(void);

SHM_t *SHM;

int main()
{
    setgid(BBSGID);
    setuid(BBSUID);
    chdir(BBSHOME);
    load_uhash();
    return 0;
}

void load_uhash(void) {
    int shmid, err;
    shmid = shmget(SHM_KEY, SHMSIZE,
#ifdef USE_HUGETLB
           SHM_HUGETLB |
#endif
           0600 | IPC_CREAT | IPC_EXCL);
    err = errno;
    if( err == EEXIST )
    shmid = shmget(SHM_KEY, SHMSIZE,
#ifdef USE_HUGETLB
               SHM_HUGETLB |
#endif
               0600 | IPC_CREAT);

    if( shmid < 0 ){
    perror("shmget");
    exit(1);
    }
    SHM = (void *) shmat(shmid, NULL, 0);
    if( SHM == (void *)-1 ){
    perror("shmat");
    exit(1);
    }
    if( err  != EEXIST ) {
    SHM->number=SHM->loaded = 0;
    SHM->version = SHM_VERSION;
    }

    if(SHM->version != SHM_VERSION) {
      fprintf(stderr, "Error: SHM->version(%d) != SHM_VERSION(%d)\n", SHM->version, SHM_VERSION);
      fprintf(stderr, "Please use the source code version corresponding to SHM,\n"
     "or use ipcrm(1) command to clean share memory.\n");
      exit(1);
    }

// in case it's not assumed zero, this becomes a race... 
    if( SHM->number == 0 && SHM->loaded == 0 ){
    SHM->loaded = 0;
    fill_uhash(0);
    SHM->loaded = 1;
    }
    else{
    fill_uhash(1);  
    }
}

void checkhash(int h)
{
    int *p = &(SHM->hash_head[h]), ch, deep=0;
    while(*p != -1)
    {
       if(*p <-1 || *p >= MAX_USERS) {*p=-1; return;}
       ch = StringHash( SHM->userid[*p])%(1<<HASH_BITS);
       if(ch!=h)
       {
           printf("remove %d %d!=%d %d [%s] next:%d\n", 
            deep, h, ch, *p, SHM->userid[*p],
            SHM->next_in_hash[*p]);
          *p = SHM->next_in_hash[*p]; //remove from link
          // *p=-1;  Ptt: cut it?
      //return;
       }
       else
          p = &(SHM->next_in_hash[*p]);
       deep++;
    }
}
void fill_uhash(int onfly)
{
    int fd, usernumber;
    usernumber = 0;

    for (fd = 0; fd < (1 << HASH_BITS); fd++)
      if(!onfly)
          SHM->hash_head[fd] = -1;
      else
      checkhash(fd);
    
    if ((fd = open(FN_PASSWD, O_RDWR)) > 0)
    {
    struct stat stbuf;
    caddr_t fimage, mimage;

    fstat(fd, &stbuf);
    fimage = mmap(NULL, stbuf.st_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
    if (fimage == (char *) -1)
    {
        perror("mmap");
        exit(1);
    }
    close(fd);
    fd = stbuf.st_size / sizeof(userec_t);
    if (fd > MAX_USERS)
        fd = MAX_USERS;
            
    for (mimage = fimage; usernumber < fd; mimage += sizeof(userec_t))
    {
        userec_add_to_uhash(usernumber, (userec_t *)mimage, onfly);
        usernumber++;
    }
    munmap(fimage, stbuf.st_size);
    }
    else
    {
    perror("open");
    exit(1);
    }
    SHM->number = usernumber;

    printf("total %d names %s.\n", usernumber, onfly ? "checked":"loaded");
}
void userec_add_to_uhash(int n, userec_t *user, int onfly)
{
    int *p, h, l=0;

    // uhash use userid="" to denote free slot for new register
    // However, such entries will have the same hash key.
    // So we skip most of invalid userid to prevent lots of hash collision.
    if (!is_validuserid(user->userid)) {
    // dirty hack, preserve few slot for new register
    static int count = 0;
    count++;
    if (count > 1000)
        return;
    }

    h = StringHash(user->userid)%(1<<HASH_BITS);
    
    p = &(SHM->hash_head[h]);
    if(!onfly || SHM->userid[n][0] != user->userid[0] || 
           strncmp(SHM->userid[n], user->userid, IDLEN-1))
    {
       strcpy(SHM->userid[n], user->userid);
       SHM->money[n] = user->money;
#ifdef USE_COOLDOWN
       SHM->cooldowntime[n] = 0;
#endif
       if(onfly)
           printf("add %s\n", user->userid);
    }
    while (*p != -1)
    {
    if(onfly && *p==n )  // already in hash
         return;
    l++;
    p = &(SHM->next_in_hash[*p]);
    }
    if(onfly)
       printf("add %d %d %d [%s] in hash\n", l, h, n, user->userid);
    SHM->next_in_hash[*p = n] = -1;
}