|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
protocol.hxx
Abstract:
This module deals with objects that make up the server and group entry items. This includes creatation/destruction and searching of the entries.
Author:
Steven Zeck (stevez) 07/01/90
--*/
#ifndef _PROTOCOL_
#define _PROTOCOL_
class QUERY_SERVER; class ENTRY_BASE_NODE; class ENTRY_BASE_ITEM; class ENTRY_SERVER_ITEM; class ENTRY_SERVER_NODE; class ENTRY_GROUP_ITEM; class ENTRY_GROUP_NODE;
DYN_ARRAY_TYPE(UUID_ARRAY, NS_UUID, LONG)
// The following enumeration is the the type of entry the object is.
typedef enum {
ServerEntryType = 1, GroupEntryType, ProfileEntryType, AnyEntryType, LastEntryType } TYPE_ENTRY_NODE ;
// The following are the type of base member entry the object is.
typedef enum { LocalItemType = 1, // local item
CacheItemType, // cached item, ie - remote
DeleteItemType, // delayed delete due
LastItemType // end marker
} TYPE_ENTRY_ITEM;
// The follwing is the return values by MatchItem virtual functions.
typedef enum { NoMatch, // Item didn't match
ItemMatch, // This item matched
SubItemMatch, // or a subitem under this object matched
}MATCH_RETURN;
// The following is the format for a query on the net with mailslots.
typedef struct {
NS_SYNTAX_ID Interface; // inteface that we are looking for
NS_UUID Object; // Object that we are interested in
UICHAR WkstaName[DOMAIN_MAX]; // buffer for machine name
UICHAR EntryName[ENTRY_MAX]; // buffer for entry name
} QueryPacket;
/*++
Class Definition:
ENTRY_KEY
Abstract:
This is the EntryName object. It is the name of the entries in the in memory object data base.
--*/
class ENTRY_KEY {
private: UNICODE_ARRAY EntryName; // and the string value of the entry
public:
ENTRY_KEY( IN PUZ Name, IN PUZ DomainName, OUT STATUS *Status );
ENTRY_KEY( IN PUZ Name, IN int fAllowGlobal, OUT STATUS *Status );
// Construct a new object by copying an existing one.
ENTRY_KEY( IN ENTRY_KEY *KeyNew, OUT STATUS *Status ) { EntryName = KeyNew->EntryName.Dup();
*Status = (!KeyNew->EntryName.pCur() || EntryName.pCur())? NSI_S_OK: NSI_S_OUT_OF_MEMORY; }
ACCESSOR(UNICODE_ARRAY, EntryName);
// Free the allocated objects referenced.
void Free( ) { EntryName.Free(); }
// Set the value of the EntryName
void SetEntryName( IN UNICODE_ARRAY &New, OUT UNICODE_ARRAY &Previous ) { Previous = EntryName; EntryName = New; }
int Equal( UNICODE_ARRAY& Entry1 );
// Compare two objects for identity
int Equal ( IN ENTRY_KEY &Entry1 ) { return(Equal(Entry1.EntryName)); }
// Determine if an entry name is empty.
int IsNil( ) { return(EntryName.cCur() == 0); }
// Return a Copy of the entry name.
UICHAR * CopyName( ) { return((UICHAR *)NewCopy(EntryName.pCur(), (int) EntryName.Size())); }
// Return the size to marshall this object.
int MarshallSize( ) { return(sizeof(ENTRY_KEY) + EntryName.Size()); }
char * Marshall( OUT char *Buffer );
PUZ MakeLocalName( OUT PUZ Buffer, OUT PUZ DomainBuffer, IN PUZ DefDomain );
friend char * KeyEntryUnMarshall( OUT ENTRY_KEY **Key, IN UICHAR * Domain, IN char *Buffer, OUT STATUS *Status );
friend ostream& operator << (ostream&, ENTRY_KEY&); };
/*++
Class Definition:
QUERY_REF_ITEM
Abstract:
This linked list is how replies are stored. Each found EntryItem is referenced by a pointer to the base case for EntryItems.
--*/
NEW_LINK_LIST(QUERY_REF,
ENTRY_BASE_ITEM *EntryItem; /* Reference to matched item */
QUERY_REF_ITEM ( IN ENTRY_BASE_ITEM *EntryItemNew ) { EntryItem = EntryItemNew; }
QUERY_REF_ITEM * Free( IN OUT QUERY_REF_LIST &ML );
friend ostream& operator << (ostream&, QUERY_REF_ITEM&); friend class QUERY; )
/*++
Class Definition:
QUERY
Abstract:
Base class for a query into the object data base. It contains the specification for the query and the resulting replay.
--*/
class QUERY {
protected: QUERY_REF_LIST ReplyList; // List which gets the reply from the query.
ENTRY_KEY Entry; // The entry, that we are searching on.
TYPE_ENTRY_NODE Type; // Type of entry we are interested in.
long ExpirationTime; // Cut off point for cached entries.
long Scope; // Flags which limit query.
int RecursionCount; // Keeps track of the recursion in searchs.
public: QUERY( IN TYPE_ENTRY_NODE TypeNew, IN ENTRY_KEY *KeyNew, IN long ScopeNew, OUT STATUS *Status ) : Entry(KeyNew, Status) { Type = TypeNew; ExpirationTime = maxCacheAge; Scope = ScopeNew; RecursionCount = 0; }
~QUERY() { Entry.Free(); }
ENTRY_BASE_ITEM * NextReply( );
QUERY_REF_ITEM * First( ) { return(ReplyList.First()); }
void FreeReply( IN QUERY_REF_ITEM * Item ) { Item->Free(ReplyList); }
ACCESSOR(long, ExpirationTime);
STATUS Search( );
STATUS SearchEntry( IN ENTRY_SERVER_NODE * &ENTRY_SERVER );
virtual STATUS QueryNet( );
STATUS BroadCast( IN QueryPacket& NetRequest, IN ENTRY_KEY &Entry );
virtual STATUS GetUpdatesFromMasterLocator( );
char * DetectMasterLocator( );
};
/*++
Class Definition:
QUERY_SERVER
Abstract:
Dervived class when searching only for a server entry object.
--*/
class QUERY_SERVER: public QUERY {
private:
// The following optional members are used to filter the search.
NS_SYNTAX_ID Interface; // Interface of interest.
NS_SYNTAX_ID TransferSyntax; // Stub transfer syntax of interest.
NS_UUID Object; // Object of interest
public:
QUERY_SERVER( IN ENTRY_KEY *KeyNew, IN NS_SYNTAX_ID *InterfaceNew, IN NS_SYNTAX_ID * TransferSyntaxNew, IN NS_UUID *ObjectNew, IN long ScopeNew, OUT STATUS *Status ) : QUERY (ServerEntryType, KeyNew, ScopeNew, Status) {
Interface = *InterfaceNew; TransferSyntax = *TransferSyntaxNew; Object = *ObjectNew; }
ACCESSOR(NS_UUID, Object);
virtual STATUS QueryNet( );
virtual STATUS GetUpdatesFromMasterLocator( );
friend class ENTRY_SERVER_ITEM; };
/*++
Class Definition:
QUERY_GROUP
Abstract:
Dervived class when searching only for a group entry object.
--*/ class QUERY_GROUP: public QUERY {
private:
public:
QUERY_GROUP( IN ENTRY_KEY *KeyNew, IN long ScopeNew, OUT STATUS *Status ) : QUERY (GroupEntryType, KeyNew, ScopeNew, Status) {
}
virtual STATUS QueryNet( );
virtual STATUS GetUpdatesFromMasterLocator( );
friend class ENTRY_GROUP_ITEM; };
/*++
Class Definition:
ENTRY_BASE_ITEM
Abstract:
Each type of entry object has a linked list of these objects. These items make up the member objects that belong to the entry. This is the base class for all member objects of a EntryNode (see next class).
--*/
NEW_LINK_LIST(ENTRY_BASE,
protected:
TYPE_ENTRY_ITEM Type; /* type of list item */ ENTRY_BASE_NODE *EntryNode; /* reference to which node I'm in */ ULONG Time; /* time arrived for cached PS */ ULONG UseCount; /* number of references to object */
public: ENTRY_BASE_ITEM( IN TYPE_ENTRY_ITEM TypeNew ) { Type = TypeNew; Time = CurrentTime(); EntryNode = NIL; UseCount = 1; }
ACCESSOR(ENTRY_BASE_NODE *, EntryNode)
// See if a this object is a queried type.
BOOL IsType( IN TYPE_ENTRY_ITEM qType ) { return(qType == Type); }
// Determine if a cached entry is stale and should be discarded.
BOOL IsStaleEntry( IN long Age ) { return(Type == CacheItemType && CurrentTime() > Time+Age); }
// Threads must Reserve and Release an node item to use it.
void MultiThreadReserve( ) { UseCount++; }
void MultiThreadRelease( ) { UseCount--; if (Type == DeleteItemType && UseCount == 0) delete this; }
virtual ~ENTRY_BASE_ITEM( );
virtual MATCH_RETURN MatchItem( IN QUERY *SearchSpec );
virtual int Marshall( OUT PB Buffer, IN OUT long UNALIGNED *cbBuffer );
virtual ostream& Format( IN OUT ostream& );
friend ostream& operator << (ostream&, ENTRY_BASE_ITEM&); )
/*++
Class Definition:
ENTRY_BASE_NODE
Abstract:
This is the base class for all entry objects. It contains the name of the entry and the type. All ENTRY_BASE_ITEM are belong to one of this objects. This object is the one keep in the dictionary for fast access.
--*/
class ENTRY_BASE_NODE {
protected: ENTRY_KEY Entry; // The entry name, must be first member.
TYPE_ENTRY_NODE Type; // Type of entry object.
ENTRY_BASE_LIST ItemList; // List of member objects of this node.
public:
unsigned long LastUpdateTime;
ENTRY_BASE_NODE( IN TYPE_ENTRY_NODE TypeNew, IN ENTRY_KEY *KeyNew, OUT STATUS *Status ): Entry (KeyNew, Status) { Type = TypeNew; LastUpdateTime = 0; }
ACCESSOR(ENTRY_KEY, Entry) ACCESSOR(ENTRY_BASE_LIST, ItemList)
// See if a this object is a queried type.
BOOL IsType( IN TYPE_ENTRY_NODE qType ) { return(qType == Type); }
virtual void DeleteAllObjects() { //do nothing - just keep compiler happy
} friend int ENTRY_BASE_NODECompare(ENTRY_KEY &E1, ENTRY_BASE_NODE &E2); friend ENTRY_KEY& ENTRY_BASE_NODEMyKey(ENTRY_BASE_NODE &E1); friend ostream& operator << (ostream&, ENTRY_BASE_NODE&); };
/*++
Class Definition:
ENTRY_SERVER_NODE
Abstract:
The is a server entry node. This class addes the object vector which all members of a server entry share.
--*/
class ENTRY_SERVER_NODE:public ENTRY_BASE_NODE {
private: UUID_ARRAY ObjectDA; // Commaon object vector.
public: ENTRY_SERVER_NODE( IN ENTRY_KEY *KeyNew, OUT STATUS *Status ): ENTRY_BASE_NODE (ServerEntryType, KeyNew, Status) {
}
ACCESSOR(UUID_ARRAY, ObjectDA)
STATUS MergeObjects( IN UUID_ARRAY *NewObject );
int DeleteObject( IN NS_UUID *Objects );
virtual void DeleteAllObjects( );
int SearchObject( IN NS_UUID *Object );
ENTRY_SERVER_ITEM * First( ) { return((ENTRY_SERVER_ITEM * ) TheItemList().First()); }
friend ostream& operator << (ostream&, ENTRY_SERVER_NODE&); friend class ENTRY_SERVER_ITEM; };
/*++
Class Definition:
ENTRY_SERVER_ITEM
Abstract:
This instance of a sever entry member object. It adds members which describe the interface the the binding.
--*/
class ENTRY_SERVER_ITEM: public ENTRY_BASE_ITEM {
private:
NS_SYNTAX_ID Interface; // The interface of the member.
NS_SYNTAX_ID TransferSyntax; // The stub transfer syntax of the member.
UNICODE_ARRAY StringBinding; // DCE string binding.
public:
ASSERT_CLASS;
ENTRY_SERVER_ITEM ( IN TYPE_ENTRY_ITEM TypeNew, IN NS_SYNTAX_ID *InterfaceNew, IN NS_SYNTAX_ID * Transfer, IN PUZ StringBinding, OUT STATUS *Status);
virtual ~ENTRY_SERVER_ITEM( );
int Compare( IN ENTRY_SERVER_ITEM * ServerItem );
// Memeber access/update functions
NS_UUID & TheInterfaceGID( ) { return(Interface.ThesyntaxGID()); } ENTRY_KEY & TheEntry( ) { return(EntryNode->TheEntry()); } UUID_ARRAY & TheObjectDA( ) { return(((ENTRY_SERVER_NODE *)EntryNode)->TheObjectDA()); }
ACCESSOR(NS_SYNTAX_ID, Interface); ACCESSOR(NS_SYNTAX_ID, TransferSyntax); ACCESSOR(UNICODE_ARRAY, StringBinding);
virtual MATCH_RETURN MatchItem( IN QUERY *SearchSpec );
virtual int Marshall( OUT PB Buffer, IN OUT long UNALIGNED *cbBuffer );
virtual ostream& Format( ostream& );
ENTRY_SERVER_ITEM * Next( ) { return((ENTRY_SERVER_ITEM * ) ENTRY_BASE_ITEM::Next()); }
friend ostream& operator << (ostream&, QUERY_REF_ITEM&); friend ostream& operator << (ostream&, ENTRY_SERVER_ITEM&); };
STATUS InsertServerEntry( IN ENTRY_KEY *Entry, IN ENTRY_SERVER_ITEM *ServerItem, IN UUID_ARRAY * ObjectDA );
/*++
Class Definition:
ENTRY_GROUP_NODE
Abstract:
This is a group entry node. No additional data members are added.
--*/
class ENTRY_GROUP_NODE:public ENTRY_BASE_NODE {
private:
public: ENTRY_GROUP_NODE( IN ENTRY_KEY *KeyNew, OUT STATUS *Status ): ENTRY_BASE_NODE (GroupEntryType, KeyNew, Status)
{
}
ENTRY_GROUP_ITEM * First( ) { return((ENTRY_GROUP_ITEM * ) TheItemList().First()); }
friend ostream& operator << (ostream&, ENTRY_GROUP_NODE&); friend class EnteryGroupItem; };
/*++
Class Definition:
ENTRY_GROUP_ITEM
Abstract:
This is a group entry member item. Group are simply a list of entry names that reference other entry objects. The links are symbolic references, not pointer values.
--*/
class ENTRY_GROUP_ITEM: public ENTRY_BASE_ITEM {
private:
UNICODE_ARRAY Member; // Entry Name of the member.
public:
ASSERT_CLASS;
ENTRY_GROUP_ITEM ( IN TYPE_ENTRY_ITEM TypeNew, IN PUZ MemberBinding, OUT STATUS *Status );
virtual ~ENTRY_GROUP_ITEM( );
// Compare this item with an other group member.
int Compare ( IN ENTRY_GROUP_ITEM * GroupItem ) { return (CmpUZ(Member.pCur(), GroupItem->Member.pCur())); }
// Compare this item with a unicode string for identity.
int Compare ( IN PUZ Name ) { return (CmpUZ(Member.pCur(), Name)); }
ACCESSOR(UNICODE_ARRAY, Member);
virtual MATCH_RETURN MatchItem( IN OUT QUERY *SearchSpec );
virtual int Marshall( OUT PB Buffer, IN OUT long UNALIGNED *cbBuffer );
virtual ostream& Format( IN OUT ostream& );
ENTRY_GROUP_ITEM * Next( ) { return((ENTRY_GROUP_ITEM * ) ENTRY_BASE_ITEM::Next()); }
friend ostream& operator << (ostream&, ENTRY_GROUP_ITEM&); };
STATUS InsertGroupEntry( IN ENTRY_KEY *Entry, IN ENTRY_GROUP_ITEM *GroupItem );
/*++
Class Definition:
REPLY_BASE_ITEM
Abstract:
All replies are kept in a LinkList. There is a base reply type which is used to derive several different kinds of replies in progress. Each derived REPLY_BASE must implement the virtual functions Free and Discard.
--*/
/* State of the Query in a lookup operation. */
typedef enum { InitialQuery, /* First query has been made */ FinialQuery, /* Finial query made, no more allowed */ ReRunQuery /* Rerun the query */ }REPLY_STATE;
NEW_LINK_LIST(REPLY_BASE,
protected:
long pidOwner; /* owner of the resource */ QUERY * aQuery; /* QUERY for lookup */ REPLY_STATE QueryMade; /* QUERY has been made */
public: REPLY_BASE_ITEM(); ~REPLY_BASE_ITEM();
BOOL AssertHandle( );
/* Set the cache discard age for a query. */
void SetExpiration( IN unsigned long Time ) { aQuery->TheExpirationTime() = Time;
/* If the "Next" operation hasn't been called, rerun the query. */
if (QueryMade == InitialQuery) { FreeQueryResult(); QueryMade = ReRunQuery; } }
/* Get the next item in the query reply. */
ENTRY_BASE_ITEM * NextBaseItem( ) { return(aQuery->NextReply()); }
STATUS PerformQueryIfNeeded( BOOL fFirstTime );
void FreeQueryResult( );
virtual BOOL Discard( IN ENTRY_BASE_ITEM *BaseItem );
virtual BOOL UpdateObject( IN ENTRY_SERVER_NODE *Entry, IN int Index ); )
extern REPLY_BASE_LIST RPRoot; // Global list of replies from this root.
inline REPLY_BASE_ITEM::REPLY_BASE_ITEM( ) /*++
Routine Description:
Construct a base REPLY_BASE_ITEM object. Link this object into the global list of replies.
--*/
{ QueryMade = InitialQuery; aQuery = NIL; pidOwner = (long) this; RPRoot.Append(this); }
/*++
Class Definition:
REPLY_SERVER_ITEM
Abstract:
This a reply object for a server entry based query. It contains additional state to interate through the replies formain the cross product of the reply list and object vector.
--*/
NEW_LINK_LIST_CLASS(REPLY_SERVER, REPLY_BASE,
private: unsigned int VectorSize; /* Vector size to return */ unsigned int fAllObjects; /* Include all objects in response */ UUID_ARRAY_ITER ObjectCur; /* Iterator for current object */
public: REPLY_SERVER_ITEM( IN QUERY_SERVER * aQueryNew, IN BOOL fAllObjectsNew = FALSE, IN int VectorSizeNew = 0 ) { aQuery = aQueryNew; /* BUGBUG glock c++: base should require this */ VectorSize = VectorSizeNew; fAllObjects = fAllObjectsNew; }
STATUS PerformQueryIfNeeded( BOOL fFirstTime );
ENTRY_SERVER_ITEM * NextBindingAndObject( OUT NS_UUID ** Object );
BOOL NextObject( OUT NS_UUID ** Object ) { return((!ObjectCur)? FALSE: (*Object = &*ObjectCur, ++ObjectCur, TRUE)); }
ACCESSOR(unsigned int, VectorSize);
virtual BOOL Discard( IN ENTRY_BASE_ITEM *BaseItem );
virtual BOOL UpdateObject( IN ENTRY_SERVER_NODE *Entry, IN int Index ); )
/*++
Class Definition:
REPLY_GROUP_ITEM
Abstract:
This a reply object for a group entry based query. Only group items will be in the reply list.
--*/
NEW_LINK_LIST_CLASS(REPLY_GROUP, REPLY_BASE,
public: REPLY_GROUP_ITEM( IN QUERY_GROUP * aQueryNew ) { aQuery = aQueryNew; /* BUGBUG glock c++: base should require this */ }
)
#endif // _PROTOCOL_
|