[BACK]Return to DirectoryScanner.c++ CVS log [TXT][DIR] Up to [Development] / fam / fam

Annotation of fam/fam/DirectoryScanner.c++, Revision 1.1.1.1

1.1       trev        1: //  Copyright (C) 1999 Silicon Graphics, Inc.  All Rights Reserved.
                      2: //
                      3: //  This program is free software; you can redistribute it and/or modify it
                      4: //  under the terms of version 2 of the GNU General Public License as
                      5: //  published by the Free Software Foundation.
                      6: //
                      7: //  This program is distributed in the hope that it would be useful, but
                      8: //  WITHOUT ANY WARRANTY; without even the implied warranty of
                      9: //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  Further, any
                     10: //  license provided herein, whether implied or otherwise, is limited to
                     11: //  this program in accordance with the express provisions of the GNU
                     12: //  General Public License.  Patent licenses, if any, provided herein do not
                     13: //  apply to combinations of this program with other product or programs, or
                     14: //  any other product whatsoever.  This program is distributed without any
                     15: //  warranty that the program is delivered free of the rightful claim of any
                     16: //  third person by way of infringement or the like.  See the GNU General
                     17: //  Public License for more details.
                     18: //
                     19: //  You should have received a copy of the GNU General Public License along
                     20: //  with this program; if not, write the Free Software Foundation, Inc., 59
                     21: //  Temple Place - Suite 330, Boston MA 02111-1307, USA.
                     22:
                     23: #include "DirectoryScanner.h"
                     24:
                     25: #include <assert.h>
                     26: #include <string.h>
                     27: #include <errno.h>
                     28:
                     29: #include "Client.h"
                     30: #include "Directory.h"
                     31: #include "DirEntry.h"
                     32: #include "Log.h"
                     33:
                     34: //////////////////////////////////////////////////////////////////////////////
                     35:
                     36: DirectoryScanner::DirectoryScanner(Directory& d,
                     37: 				   const Event& e, bool b,
                     38: 				   DoneHandler dh, void *vp)
                     39:     : directory(d), done_handler(dh), closure(vp), new_event(e),
                     40:       scan_entries(b), dir(NULL), openErrno(0),
                     41:       epp(&d.entries), discard(NULL)
                     42:
                     43: {
                     44:     dir = opendir(d.name());
                     45:     if (dir == NULL) {
                     46: 	openErrno = errno;
                     47:     }
                     48: }
                     49:
                     50: DirectoryScanner::~DirectoryScanner()
                     51: {
                     52:     if (dir)
                     53: 	closedir(dir);
                     54: }
                     55:
                     56: //////////////////////////////////////////////////////////////////////////////
                     57:
                     58: // return address of ptr to entry matching name
                     59:
                     60: DirEntry **
                     61: DirectoryScanner::match_name(DirEntry **epp, const char *name)
                     62: {
                     63:     for (DirEntry *ep; ((ep = *epp) != NULL); epp = &ep->next)
                     64: 	if (!strcmp(ep->name(), name))
                     65: 	    return epp;
                     66:     return NULL;
                     67: }
                     68:
                     69: bool
                     70: DirectoryScanner::done()
                     71: {
                     72: #if HAVE_SGI_NOHANG
                     73:     if (openErrno == ETIMEDOUT) {
                     74:         // We got an nfs time out.  We'll want to try again later.
                     75: 	directory.unhang();
                     76: 	Log::debug("openErrno == ETIMEDOUT");
                     77: 	(*done_handler)(closure);
                     78: 	return true;
                     79:     }
                     80: #endif
                     81:     bool ready = directory.client()->ready_for_events();
                     82:
                     83:     directory.become_user();
                     84:     if (!directory.chdir()) {
                     85:         // Didn't have permission to read the directory.  Send Delete events
                     86:         // for its contents.
                     87:         while (*epp && ready)
                     88:         {   DirEntry *ep = *epp;
                     89: 	    *epp = ep->next;
                     90: 	    ep->post_event(Event::Deleted);
                     91: 	    ready = directory.client()->ready_for_events();
                     92: 	    delete ep;
                     93:         }
                     94:         if (*epp || !ready)
                     95: 	    return false;
                     96:
                     97:         (*done_handler)(closure);
                     98:         return true;
                     99:     }
                    100:
                    101:     while (dir && ready)
                    102:     {
                    103: 	struct direct *dp = readdir(dir);
                    104: 	if (dp == NULL)
                    105: 	{   closedir(dir);
                    106: 	    dir = NULL;
                    107: 	    break;
                    108: 	}
                    109:
                    110: 	//  Ignore "." and "..".
                    111:
                    112: 	if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
                    113: 	    continue;
                    114:
                    115: 	DirEntry *ep = *epp, **epp2;
                    116: 	if (ep && !strcmp(dp->d_name, ep->name()))
                    117: 	{
                    118: 	    //  Next entry in list matches. Do not change list.
                    119:
                    120: 	    // Log::debug("checkdir match %s", dp->d_name);
                    121: 	}
                    122: 	else if ((epp2 = match_name(&discard, dp->d_name)) != NULL)
                    123: 	{
                    124: 	    //  Found in discard.  Insert discarded entry before ep.
                    125:
                    126: 	    // Log::debug("checkdir fdisc %s", dp->d_name);
                    127: 	    ep = *epp2;
                    128: 	    *epp2 = ep->next;
                    129: 	    ep->next = *epp;
                    130: 	    *epp = ep;
                    131: 	}
                    132: 	else if (ep && (epp2 = match_name(&ep->next, dp->d_name)))
                    133: 	{
                    134: 	    //  Found further in list.  Prepend internode segment
                    135: 	    //  to discard.
                    136:
                    137: 	    // Log::debug("checkdir furth %s", dp->d_name);
                    138: 	    ep = *epp2;
                    139: 	    *epp2 = discard;
                    140: 	    discard = *epp;
                    141: 	    *epp = ep;
                    142: 	}
                    143: 	else
                    144: 	{
                    145: 	    // New entry. Insert.
                    146:
                    147: 	    ep = new DirEntry(dp->d_name, &directory, *epp);
                    148: 	    *epp = ep;
                    149: 	    ep->post_event(new_event);
                    150: 	    ready = directory.client()->ready_for_events();
                    151: 	    epp = &ep->next;
                    152: 	    continue;		// Do not scan newly created entry.
                    153: 	}
                    154: 	if (scan_entries)
                    155: 	{   ep->scan_no_chdir();
                    156: 	    ready = directory.client()->ready_for_events();
                    157: 	}
                    158: 	epp = &ep->next;
                    159:     }
                    160:
                    161:     directory.chdir_root();  // chdir back to "/"
                    162:
                    163:     while (*epp && ready)
                    164:     {   DirEntry *ep = *epp;
                    165: 	*epp = ep->next;
                    166: 	ep->post_event(Event::Deleted);
                    167: 	ready = directory.client()->ready_for_events();
                    168: 	delete ep;
                    169:     }
                    170:
                    171:     while (discard && ready)
                    172:     {   DirEntry *ep = discard;
                    173: 	discard = discard->next;
                    174: 	ep->post_event(Event::Deleted);
                    175: 	ready = directory.client()->ready_for_events();
                    176: 	delete ep;
                    177:     }
                    178:
                    179:     if (dir || *epp || discard || !ready)
                    180: 	return false;
                    181:
                    182:     (*done_handler)(closure);
                    183:     return true;
                    184: }
                    185:
                    186: //////////////////////////////////////////////////////////////////////////////
                    187: //  Memory management.  Maintain a cache of one DirectoryScanner to reduce
                    188: //  heap stirring.
                    189:
                    190: DirectoryScanner *DirectoryScanner::cache;
                    191:
                    192: void *
                    193: DirectoryScanner::operator new (size_t size)
                    194: {
                    195:     assert(size == sizeof (DirectoryScanner));
                    196:     DirectoryScanner *p = cache ? cache : (DirectoryScanner *) new char[size];
                    197:     if (cache)
                    198: 	cache = NULL;
                    199:     return p;
                    200: }
                    201:
                    202: void
                    203: DirectoryScanner::operator delete (void *p)
                    204: {
                    205:     assert(p != NULL);
                    206:     if (cache)
                    207: 	delete [] cache;
                    208:     cache = (DirectoryScanner *) p;
                    209: }

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