[BACK]Return to FilesystemCategory.c++ CVS log [TXT][DIR] Up to [Development] / failsafe / FailSafe-mgr / category / filesystem

File: [Development] / failsafe / FailSafe-mgr / category / filesystem / FilesystemCategory.c++ (download)

Revision 1.11, Mon Jul 24 22:36:22 2000 UTC (17 years, 3 months ago) by rusty
Branch: MAIN
CVS Tags: HEAD
Changes since 1.10: +28 -21 lines

Added GPL/LGPL copyright headers & documentation for open source release, and removed CXFS stuff

//
// FilesystemCategory.c++
//
//	Category for filesystems in clusters.
//
//
//  Copyright (c) 1998, 2000 Silicon Graphics, Inc.  All Rights Reserved.
//  
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of version 2.1 of the GNU Lesser General Public
//  License as published by the Free Software Foundation.
//  
//  This program is distributed in the hope that it would be useful, but
//  WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//  
//  Further, this software is distributed without any warranty that it is
//  free of the rightful claim of any third person regarding infringement
//  or the like.  Any license provided herein, whether implied or
//  otherwise, applies only to this software file.  Patent licenses, if
//  any, provided herein do not apply to combinations of this program
//  with other software, or any other product whatsoever.
//  
//  You should have received a copy of the GNU Lesser General Public
//  License along with this program; if not, write the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
//  USA.
//  
//  Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
//  Mountain View, CA 94043, or http://www.sgi.com/
//  
//  For further information regarding this notice, see:
//  http://oss.sgi.com/projects/GenInfo/NoticeExplan/
//

#ident "$Revision: 1.11 $"

#include <sys/types.h>
#include <stdio.h>
#include <ci_clikeys.h>
#include <ci_camvalues.h>
#include <ci_cdbvalues.h>

#include <sysadm/Command.h>
#include <sysadm/AppContext.h>
#include <sysadm/Log.h>

#include <fsmgr/FilesystemCategory.h>

namespace fsmgr {

SaCATEGORY_REF_DEF(FilesystemCategory);

const char* FilesystemCategory::NAME = "FilesystemCategory";
const char* FilesystemCategory::FS_DISABLED = "disabled";

    class FsClusterListener : public CategoryListener {
    private:
	FilesystemCategory* _fscat;
    public:
	FsClusterListener(FilesystemCategory* fscat)
	{
	    _fscat = fscat;
	}
	void itemAdded(const Item& item)
	{
	    Log::trace(_fscat->NAME,
		       "itemAdded: %s", (const char*) item.toString());
	    _fscat->buildItemListFromCluster(item);
	}

	void itemChanged(const Item&, const Item& newItem)
	{
	    Log::trace(_fscat->NAME,
		       "itemChanged: %s", (const char*) newItem.toString());
	    _fscat->buildItemListFromCluster(newItem);
	}

	void itemRemoved(const Item&)
	{
	    ItemList fsList;
	    _fscat->replaceItemList(fsList); // clear the list
	}
    };

//
// constructor

FilesystemCategory::FilesystemCategory()
: CamCategory("FilesystemCategory", cam_category_none)
{
    // Specifying cam_category_none above relies on a feature of
    // cam_register() which returns an error if the category is
    // cam_category_none.  We're specifying cam_category_none as the
    // CamCategory::_categories[0].  Since cam_register() fails for
    // cam_category_none, we know we won't get events for that
    // category, and thus we can spoof CamCategory by sticking the
    // items we receive from the FsClusterListener in
    // CamCategory::_itemCache[0].  Unfortunately we had to make
    // _itemCache[] protected instead of private.

    addCategory(cam_category_filesystem_status);

    _numFs = 0;
    _filesystems = new String[_numFs];
}

//
// destructor

FilesystemCategory::~FilesystemCategory()
{
    delete [] _filesystems;
    _clusterCategory->orphanCategoryListener(_handle);

}

// buildItemListFromCluster rips apart a CLUSTER item and converts it
// into a number of filesystems.  Note: required filesystem attributes
// are not checked for Attribute::NUL
//
void FilesystemCategory::buildItemListFromCluster(const Item& cluster)
{
    beginBlockChanges();

    Attribute aNumFs = cluster.getAttr(CICLI_CLUSTER_NUM_FILESYSTEMS);
    long long numFs(0L);
    if (aNumFs != Attribute::NUL)
	numFs = aNumFs.longValue();

    String* newFilesystems = new String[numFs];

    Log::debug(NAME, "cluster: %s", (const char*) cluster.toString());

    for (long long li = 0; li < numFs; ++li) {
	String idNum;
	idNum.fromNum((long) li);
	String attrId = String(CICLI_CLUSTER_FS_DEVNAME_) + idNum;
	Attribute aDevname = cluster.getAttr(attrId); // required

	// create item, use device name as selector
	//
	const String selector = aDevname.stringValue();
	Item* item = new Item(getSelector(), selector);

	// copy attributes
	//
	Attribute aCluster = cluster.getAttr(CICLI_CLUSTER); // required
	item->setAttr(aCluster);

	attrId = String(CICLI_CLUSTER_FS_STATUS_) + idNum;
	Attribute aMount = cluster.getAttr(attrId);
	item->setAttr(Attribute(CICLI_CLUSTER_FS_STATUS_,
				aMount.stringValue()));

	// mount     cam_status   status
	// enabled   active       mounted
	// disabled  active	  unmounted
	// enabled   inactive     mount-ready
	// enabled   error	  ERROR

	if (aMount.stringValue() == FS_DISABLED) {
	    item->setAttr(Attribute(STATUS_KEY, STATUS_INACTIVE));
	} else {
	    Attribute aStatus = cluster.getAttr(STATUS_KEY);
	    if (aStatus == Attribute::NUL ||
		aStatus.stringValue() == STATUS_INACTIVE ||
		aStatus.stringValue() == STATUS_UNKNOWN) {
		item->setAttr(Attribute(STATUS_KEY, STATUS_MOUNT_READY));
	    } else {		// if cluster is ERROR, cluster is ACTIVE
		item->setAttr(Attribute(STATUS_KEY, STATUS_MOUNTED));
	    }
	}

	item->setAttr(Attribute(CICLI_CLUSTER_FS_DEVNAME_,
				aDevname.stringValue()));

	attrId = String(CICLI_CLUSTER_FS_MOUNTPOINT_) + idNum;
	Attribute aMountPt = cluster.getAttr(attrId);
	item->setAttr(Attribute(CICLI_CLUSTER_FS_MOUNTPOINT_,
				aMountPt.stringValue()));

	// mount options are optional
	attrId = String(CICLI_CLUSTER_FS_MOUNTOPTIONS_) + idNum;
	Attribute aMountOpt = cluster.getAttr(attrId);
	if (aMountOpt != Attribute::NUL) {
	    item->setAttr(Attribute(CICLI_CLUSTER_FS_MOUNTOPTIONS_,
				    aMountOpt.stringValue()));
	}

	// force unmount
	attrId = String(CICLI_CLUSTER_FS_FORCE_) + idNum;
	Attribute aForce = cluster.getAttr(attrId);
	bool force = false;
	if (aForce != Attribute::NUL) {
	    force = aForce.booleanValue();
	}
	item->setAttr(Attribute(CICLI_CLUSTER_FS_FORCE_, force));

	// get server list
	//
	attrId = String(CICLI_CLUSTER_FS_NUM_SERVERS_) + idNum;
	Attribute aNumServers = cluster.getAttr(attrId);

	long long numServers(0L);
	if (aNumServers != Attribute::NUL)
	    numServers = aNumServers.longValue();
	item->setAttr(Attribute(CICLI_CLUSTER_FS_NUM_SERVERS_,
				numServers));
	Log::debug(NAME, "item %s", (const char*) item->toString());

	for (long long lj = 0; lj < numServers; ++lj) {
	    String serverId;
	    serverId.fromNum((long) lj);

	    attrId = String(CICLI_CLUSTER_FS_SERVER_NODE_) +
		idNum + "_" + serverId;
	    Attribute aNode = cluster.getAttr(attrId);
	    String newId = String(CICLI_CLUSTER_FS_SERVER_NODE_) + serverId;
	    item->setAttr(Attribute(newId, aNode.stringValue()));

	    attrId = String(CICLI_CLUSTER_FS_SERVER_RANK_) +
		idNum + "_" + serverId;
	    Attribute aRank = cluster.getAttr(attrId);
	    newId = String(CICLI_CLUSTER_FS_SERVER_RANK_) + serverId;
	    item->setAttr(Attribute(newId, aRank.stringValue()));
	}

	bool alreadyExisted = _itemCache[0].lookupByKey(selector);

	Item* cacheItem = new Item(*item);

	// this code copied from CamCategory::createItemFromObject()
	//
	for (int ii = 0; ii < _numCategories; ii++) {
	    if (_categories[ii] == cam_category_none) {	// spoof CamCategory
		delete _itemCache[ii].remove(selector);

		// Note that at this point _itemCache owns cacheItem, so
		// that we should not delete it here.
		_itemCache[ii].add(cacheItem, new String(selector));
	    } else {
		copyAttrs(_itemCache[ii].lookupByKey(selector), *item);
	    }
	}

	if (alreadyExisted) {
	    CamCategory::changeItem(*item);
	} else if (_itemCache[0].lookupByKey(selector)) {
	    CamCategory::addItem(*item);
	}
	delete item;

	newFilesystems[(int)li] = String(selector);
    }

    for (int oldFs = 0; oldFs < _numFs; ++oldFs) {
	bool found = false;
	for (int newFs = 0; newFs < numFs; ++newFs) {
	    if (newFilesystems[newFs] == _filesystems[oldFs]) {
		found = true;
		break;
	    }
	}
	if (! found) {
	    delete _itemCache[0].remove(_filesystems[oldFs]);
	    removeItem(_filesystems[oldFs]);
	}
    }

    delete [] _filesystems;
    _numFs = numFs;
    _filesystems = newFilesystems;

    endBlockChanges();
}

//
//  void FilesystemCategory::modifyItemOnCamEvent(Item* item)
//
//  Description:
//      Create CAM_STATUS attribute.
//
//  Parameters:
//      item	Item for which to derive any additional attributes
//
void FilesystemCategory::modifyItemOnCamEvent(Item* item)
{
    CamCategory::modifyItemOnCamEvent(item);

    Attribute status(item->getAttr(CICLI_CLUSTER_FS_STATUS_STRING));
    if (status != Attribute::NUL) {
	const char* val = STATUS_UNKNOWN;
	String statusStr = status.stringValue();
	if (statusStr == STATUS_DOWN) {
	    Attribute aStat = item->getAttr(STATUS_KEY);
	    if (aStat != Attribute::NUL) {
		statusStr = aStat.stringValue();
		if (statusStr == STATUS_MOUNT_READY)
		    val = STATUS_MOUNT_READY;
		else if (statusStr == STATUS_INACTIVE) {
		    Attribute aServer =
			item->getAttr(CICLI_CLUSTER_FS_SERVER_NODE_);
		    if (aServer != Attribute::NUL &&
			aServer.stringValue() != "")
			val = STATUS_ERROR;
		    else
			val = STATUS_INACTIVE;
		} else
		    val = STATUS_ERROR;
	    }
	} else if (statusStr == STATUS_INACTIVE) {
	    Attribute aMountStat = item->getAttr(CICLI_CLUSTER_FS_STATUS_);
	    if (aMountStat != Attribute::NUL) {
		statusStr = aMountStat.stringValue();
		if (statusStr == CDB_ENABLED)
		    val = STATUS_ERROR;
		else
		    val = STATUS_INACTIVE;
	    }
	} else if (statusStr == STATUS_UP) {
	    val = STATUS_MOUNTED;
	}
	assert(val != NULL);
	item->setAttr(Attribute(STATUS_KEY, val));
    }
}

void FilesystemCategory::startMonitor()
{
    Log::trace(NAME, "startMonitor");

    CamCategory::startMonitor();

    String errorString;
    _clusterCategory =
	CategoryFactory::getCategory("ClusterCategory",
				     errorString);
    _listener = new FsClusterListener(this);
    _filter.monitorAllItems();
    _handle = _clusterCategory->adoptCategoryListener(_listener, _filter);
    endExists();
}

} // namespace fsmgr