Changeset 364 for trunk/src/sh_inotify.c


Ignore:
Timestamp:
Oct 21, 2011, 10:30:44 PM (13 years ago)
Author:
katerina
Message:

Change inotify watch list to a tree with unlimited members, lookup by integer watch.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/sh_inotify.c

    r269 r364  
    3939#include "sh_inotify.h"
    4040#include "sh_mem.h"
     41#include "sh_utils.h"
    4142#include "slib.h"
    4243
     
    115116/*--- nothing thread-related below this point --- */
    116117
     118#include "zAVLTree.h"
     119
     120typedef struct
     121{
     122  int    watch;
     123  int    flag;
     124  char * file;
     125} sh_watch;
    117126
    118127/**************************************************
     
    181190#define SH_INOTIFY_MODIFY 1
    182191
     192static void sh_inotify_init(sh_watches * watches)
     193{
     194  watches->list_of_watches = NULL;
     195  watches->count           = 0;
     196  watches->max_count       = 0;
     197  return;
     198}
     199
     200static void sh_inotify_free_watch(void * item)
     201{
     202  sh_watch * this = (sh_watch *) item;
     203
     204  if (this->file)
     205    SH_FREE(this->file);
     206  SH_FREE(this);
     207  return;
     208}
     209
     210static sh_watch * sh_inotify_create_watch(char * file, int nwatch, int flag)
     211{
     212  sh_watch * this = SH_ALLOC(sizeof(sh_watch));
     213
     214  this->file  = sh_util_strdup(file);
     215  this->watch = nwatch;
     216  this->flag  = flag;
     217  return this;
     218}
     219
     220/********** List Handling ******************/
     221
     222struct sh_inotify_litem
     223{
     224  sh_watch * watch;
     225  struct sh_inotify_litem * next;
     226};
     227
     228typedef struct {
     229  struct sh_inotify_litem *prenode;
     230  struct sh_inotify_litem *curnode;
     231} sh_inotify_listCursor;
     232
     233static sh_watch * sh_inotify_list_first(sh_inotify_listCursor * listcursor, sh_watches * watches)
     234{
     235  listcursor->prenode = watches->dormant_watches;
     236  listcursor->curnode = watches->dormant_watches;
     237
     238  return listcursor->curnode->watch;
     239}
     240
     241static sh_watch * sh_inotify_list_next(sh_inotify_listCursor * listcursor, sh_watches * watches)
     242{
     243  (void) watches;
     244
     245  listcursor->prenode = listcursor->curnode;
     246  listcursor->curnode = listcursor->curnode->next;
     247
     248  if (listcursor->curnode)
     249    return listcursor->curnode->watch;
     250  return NULL;
     251}
     252
     253static void sh_inotify_listitem_destroy(struct sh_inotify_litem * this)
     254{
     255  SH_FREE(this);
     256  return;
     257}
     258
     259static sh_watch * sh_inotify_list_del_current(sh_inotify_listCursor * listcursor, sh_watches * watches)
     260{
     261  sh_watch * ret = NULL;
     262
     263  if (listcursor->curnode)
     264    {
     265      struct sh_inotify_litem * this = listcursor->curnode;
     266
     267      if (listcursor->prenode == this)
     268        {
     269          watches->dormant_watches = this->next;
     270
     271          listcursor->prenode = watches->dormant_watches;
     272          listcursor->curnode = watches->dormant_watches;
     273        }
     274      else
     275        {
     276          listcursor->prenode->next = this->next;
     277          listcursor->curnode       = this->next;
     278        }
     279      ret = listcursor->curnode->watch;
     280      sh_inotify_listitem_destroy(this);
     281    }
     282  return ret;
     283}
     284
     285static int sh_inotify_add_dormant(sh_watches * watches, sh_watch * item)
     286{
     287  struct sh_inotify_litem * this = SH_ALLOC(sizeof(struct sh_inotify_litem));
     288
     289  this->watch = item;
     290  this->next  = (struct sh_inotify_litem *) watches->dormant_watches;
     291 
     292  watches->dormant_watches = this;
     293  return 0;
     294}
     295
     296/********** End List Handling **************/
     297
     298static zAVLKey sh_inotify_getkey(void const *item)
     299{
     300  return (&((sh_watch *)item)->watch);
     301}
     302
     303
     304/* This function removes all watches from the list,
     305 * and closes the inode file descriptor in this thread.
     306 */
    183307void sh_inotify_remove(sh_watches * watches)
    184308{
    185   int     i;
    186309  int     ifd = sh_inotify_getfd();
    187 
    188   for (i = 0; i < watches->count; ++i)
    189     {
    190       if (watches->file[i])
    191         {
    192           SH_FREE (watches->file[i]);
    193           watches->file[i] = 0;
    194         }
    195       watches->watch[i] = 0;
    196       watches->flag[i] = 0;
    197     }
    198   watches->count = 0;
     310  zAVLTree   * all_watches = (zAVLTree *)(watches->list_of_watches);
     311
     312  if (all_watches)
     313    zAVLFreeTree(all_watches, sh_inotify_free_watch);
     314
     315  sh_inotify_init(watches);
     316
    199317  if (ifd >= 0)
    200318    close(ifd);
    201319  sh_set_inotify_fd(-1);
    202320
     321  watches->count = 0;
     322
    203323  return;
    204324}
     
    206326static int index_watched_file(char * filename, sh_watches * watches)
    207327{
    208   int i;
    209 
    210   for (i = 0; i < watches->count; ++i)
    211     {
    212       if (0 == strcmp(filename, watches->file[i]))
    213         return i;
     328  sh_watch   * item;
     329  zAVLCursor   avlcursor;
     330  zAVLTree   * all_watches = (zAVLTree *)(watches->list_of_watches);
     331
     332  if (all_watches)
     333    {
     334      for (item = (sh_watch *) zAVLFirst(&avlcursor, all_watches); item;
     335           item = (sh_watch *) zAVLNext(&avlcursor))
     336        {
     337          if (item->file)
     338            {
     339              if (0 == strcmp(filename, item->file))
     340                return item->watch;
     341            }
     342        }
    214343    }
    215344  return -1;
     
    220349int sh_inotify_add_watch(char * filename, sh_watches * watches, int  * errnum)
    221350{
    222   size_t len;
    223351  *errnum = 0;
    224352
     
    226354    {
    227355      int nwatch;
     356      sh_watch   * item;
    228357      int index = index_watched_file(filename, watches);
    229358     
     
    231360        {
    232361          int     ifd = sh_inotify_getfd();
     362
     363          /*************************************
    233364
    234365          if (watches->count == SH_INOTIFY_MAX)
     
    241372              return -1;
    242373            }
     374          **************************************/
    243375
    244376          nwatch = inotify_add_watch (ifd, filename,
     
    249381              return -1;
    250382            }
     383
     384          item = sh_inotify_create_watch(filename, nwatch, /* flag */ 0);
    251385         
    252           watches->watch[watches->count] = nwatch;
    253           watches->flag[watches->count]  = 0;
    254 
    255           len = strlen(filename) + 1;
    256           watches->file[watches->count] = SH_ALLOC(len);
    257           sl_strlcpy(watches->file[watches->count], filename, len);
     386          if (NULL == watches->list_of_watches)
     387            watches->list_of_watches = zAVLAllocTree (sh_inotify_getkey, zAVL_KEY_INT);
     388 
     389          if (watches->list_of_watches)
     390            {
     391              *errnum =  zAVLInsert((zAVLTree *)(watches->list_of_watches), item);
     392              if (*errnum != 0)
     393                {
     394                  sh_inotify_free_watch(item);
     395                  return -1;
     396                }
     397            }
     398          else
     399            {
     400              *errnum = -1;
     401              return -1;
     402            }
    258403
    259404          ++(watches->count);
     
    266411                               int  * errnum, int waitsec)
    267412{
    268   int     ifd = sh_inotify_getfd();
     413  sh_watch   * item;
     414  zAVLTree   * all_watches = (zAVLTree *)(watches->list_of_watches);
     415  int          ifd = sh_inotify_getfd();
    269416 
    270417  *errnum = 0;
     
    279426      char buffer[1024];
    280427
     428      sh_inotify_listCursor listcursor;
     429
    281430      /* -- Add watch if required
    282431       */
     
    290439        }
    291440
    292       for (i = 0; i < watches->count; ++i)
    293         {
    294           if (watches->watch[i] == -1)
    295             watches->watch[i] = inotify_add_watch (ifd, watches->file[i],
    296                                          IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT);
     441      /* -- Check dormant watches for reopening.
     442       */
     443      for (item = sh_inotify_list_first(&listcursor, watches); item;
     444           item = sh_inotify_list_next(&listcursor, watches))
     445        {
     446        have_next:
     447          if (item->file && item->watch == -1)
     448            {
     449              item->watch = inotify_add_watch (ifd, item->file,
     450                                               IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT);
     451              if (item->watch >= 0)
     452                {
     453                  zAVLInsert(all_watches, item);
     454                  item = sh_inotify_list_del_current(&listcursor, watches);
     455                  goto have_next;
     456                }
     457            }
    297458        }
    298459
     
    306467      if (len > 0)
    307468        {
    308           int j;
    309469          struct inotify_event *event;
    310470
     
    315475            event = (struct inotify_event *) &buffer[i];
    316476
    317             for (j = 0; j < watches->count; ++j)
     477            item = zAVLSearch(all_watches, &(event->wd));
     478
     479            if (item)
    318480              {
    319                 if (watches->watch[j] == event->wd)
     481                if (event->mask & IN_MODIFY)
    320482                  {
    321                     if (event->mask & IN_MODIFY)
    322                       {
    323                         watches->flag[j] |= SH_INOTIFY_MODIFY;
    324                         flag |= SH_INOTIFY_MODIFY;
    325                       }
    326                     else if (event->mask & IN_DELETE_SELF ||
    327                         event->mask & IN_UNMOUNT     ||
    328                         event->mask & IN_MOVE_SELF   )
    329                       {
    330                         watches->flag[j] |= SH_INOTIFY_REOPEN;
    331                         (void) inotify_rm_watch(ifd, watches->watch[j]);
    332                         watches->watch[j] = -1;
    333                         flag |= SH_INOTIFY_REOPEN;
    334                       }
     483                    item->flag |= SH_INOTIFY_MODIFY;
     484                    flag |= SH_INOTIFY_MODIFY;
     485                  }
     486                else if (event->mask & IN_DELETE_SELF ||
     487                         event->mask & IN_UNMOUNT     ||
     488                         event->mask & IN_MOVE_SELF   )
     489                  {
     490                    item->flag |= SH_INOTIFY_REOPEN;
     491                    (void) inotify_rm_watch(ifd, item->watch);
     492                    zAVLDelete(all_watches, item);
     493                    sh_inotify_add_dormant(watches, item);
     494                    item->watch    = -1;
     495                    flag |= SH_INOTIFY_REOPEN;
    335496                  }
    336497              }
     498           
    337499            i += sizeof (struct inotify_event) + event->len;
    338500          }
Note: See TracChangeset for help on using the changeset viewer.