[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     ! 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>