2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
14 #include <afsconfig.h>
15 #include <afs/param.h>
19 #include <WINNT/afsclass.h>
24 * DEFINITIONS ________________________________________________________________
28 // Each CELL object maintains a list of servers; that list has
29 // hashtables placed across the (shortened) server name for
30 // faster lookup; it also maintains a hashtable across the
31 // servers' primary IP address (the first in the list; most
32 // servers will only have one anyway). The default table size
33 // in a HASHLIST is 1000 elements--that's too large for a list
34 // of servers-in-a-cell, as it's enough to handle up to 30,000
35 // servers before the table would need to resize iteself (see
36 // the documentation in hashlist.cpp for info). Instead, we
37 // choose a more reasonable default table size.
39 #define cKEYSERVERNAME_TABLESIZE 50
41 #define cKEYSERVERADDR_TABLESIZE 50
43 // Enable the definition below to do a better job of finding
44 // user entries in PTS which have no KAS entries (for instance,
45 // machine IP accounts).
47 #define FIND_PTS_DEBRIS
51 * VARIABLES __________________________________________________________________
55 LPHASHLIST
CELL::x_lCells
= NULL
;
59 * CONSTRUCTION _______________________________________________________________
63 void CELL::InitClass (void)
67 x_lCells
= New (HASHLIST
);
68 x_lCells
->SetCriticalSection (AfsClass_GetCriticalSection());
73 CELL::CELL (LPTSTR pszCellName
, PVOID hCreds
)
80 lstrcpy (m_szName
, pszCellName
);
85 m_fStatusOutOfDate
= TRUE
;
86 m_fVLDBOutOfDate
= TRUE
;
89 m_fServersOutOfDate
= TRUE
;
90 m_nServersUnmonitored
= 0;
92 m_lServers
= New (HASHLIST
);
93 m_lServers
->SetCriticalSection (AfsClass_GetCriticalSection());
94 m_lkServerName
= m_lServers
->CreateKey ("Server Name", CELL::KeyServerName_Compare
, CELL::KeyServerName_HashObject
, CELL::KeyServerName_HashData
, cKEYSERVERNAME_TABLESIZE
);
95 m_lkServerAddr
= m_lServers
->CreateKey ("Server Primary Address", CELL::KeyServerAddr_Compare
, CELL::KeyServerAddr_HashObject
, CELL::KeyServerAddr_HashData
, cKEYSERVERADDR_TABLESIZE
);
97 m_fUsersOutOfDate
= TRUE
;
98 m_lUsers
= New (HASHLIST
);
99 m_lUsers
->SetCriticalSection (AfsClass_GetCriticalSection());
100 m_lkUserName
= m_lUsers
->CreateKey ("User Name", CELL::KeyUserName_Compare
, CELL::KeyUserName_HashObject
, CELL::KeyUserName_HashData
);
101 m_lGroups
= New (HASHLIST
);
102 m_lGroups
->SetCriticalSection (AfsClass_GetCriticalSection());
103 m_lkGroupName
= m_lGroups
->CreateKey ("Group Name", CELL::KeyGroupName_Compare
, CELL::KeyGroupName_HashObject
, CELL::KeyGroupName_HashData
);
115 m_lpiThis
->m_cRef
--;
120 void CELL::FreeServers (BOOL fNotify
)
122 for (LPENUM pEnum
= m_lServers
->FindLast(); pEnum
; pEnum
= pEnum
->FindPrevious())
124 LPSERVER lpServer
= (LPSERVER
)(pEnum
->GetObject());
126 lpServer
->SendDeleteNotifications();
127 m_lServers
->Remove (lpServer
);
132 for (size_t ii
= 0; m_apszServers
[ii
]; ++ii
)
133 FreeString (m_apszServers
[ii
]);
134 Free (m_apszServers
);
135 m_apszServers
= NULL
;
140 void CELL::FreeUsers (BOOL fNotify
)
143 for (pEnum
= m_lGroups
->FindLast(); pEnum
; pEnum
= pEnum
->FindPrevious())
145 LPPTSGROUP lpGroup
= (LPPTSGROUP
)(pEnum
->GetObject());
147 lpGroup
->SendDeleteNotifications();
148 m_lGroups
->Remove (lpGroup
);
152 for (pEnum
= m_lUsers
->FindLast(); pEnum
; pEnum
= pEnum
->FindPrevious())
154 LPUSER lpUser
= (LPUSER
)(pEnum
->GetObject());
156 lpUser
->SendDeleteNotifications();
157 m_lUsers
->Remove (lpUser
);
164 * CELL-LIST MANAGEMENT _______________________________________________________
168 void CELL::Close (void)
174 BOOL
CELL::GetDefaultCell (LPTSTR pszName
, ULONG
*pStatus
)
177 wp
.wpClientLocalCellGet
.pszCell
= pszName
;
178 return Worker_DoTask (wtaskClientLocalCellGet
, &wp
, pStatus
);
182 LPIDENT
CELL::OpenCell (LPTSTR pszCell
, PVOID hCreds
, ULONG
*pStatus
)
184 LPIDENT lpiCell
= NULL
;
189 if ((lpCell
= ReopenCell (pszCell
, pStatus
)) != NULL
)
191 lpiCell
= lpCell
->GetIdentifier();
195 else // cell hasn't been opened before? see if we can reach the cell.
197 lpCell
= New2 (CELL
,(pszCell
, hCreds
));
198 if ((lpCell
->m_hCell
= lpCell
->GetCellObject (pStatus
)) == NULL
)
202 lpiCell
= lpCell
->GetIdentifier();
204 x_lCells
->Add (lpCell
);
205 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpiCell
);
214 void CELL::CloseCell (LPIDENT lpiCell
)
217 if ((lpCell
= lpiCell
->OpenCell()) != NULL
)
219 if (lpCell
->m_nReqs
> 1)
226 NOTIFYCALLBACK::SendNotificationToAll (evtDestroy
, lpiCell
);
227 lpCell
->CloseKasObject();
228 lpCell
->CloseCellObject();
230 x_lCells
->Remove (lpCell
);
237 LPCELL
CELL::ReopenCell (LPTSTR pszCell
, ULONG
*pStatus
)
239 LPCELL lpCell
= NULL
;
243 // Ordinarily we'd place a key on the cell name within the list of
244 // cells--however, the most likely case only has one cell anyway.
245 // So why expend the memory?
247 for (LPENUM pEnum
= x_lCells
->FindFirst(); pEnum
; pEnum
= pEnum
->FindNext())
249 LPCELL lpCellFound
= (LPCELL
)( pEnum
->GetObject() );
251 if (!lstrcmpi (lpCellFound
->m_szName
, pszCell
))
253 lpCell
= lpCellFound
;
263 *pStatus
= ERROR_FILE_NOT_FOUND
;
266 // AfsClass_Leave() has been called only if no cell was opened in the search.
271 PVOID
CELL::GetCurrentCredentials (void)
277 void CELL::SetCurrentCredentials (PVOID hCreds
)
288 * SERVER-LIST MANAGEMENT _____________________________________________________
292 LPSERVER
CELL::OpenServer (LPTSTR pszName
, ULONG
*pStatus
)
294 if (!RefreshServers (TRUE
, pStatus
))
298 if ((lpServer
= (LPSERVER
)(m_lkServerName
->GetFirstObject (pszName
))) != NULL
)
305 LPSERVER
CELL::OpenServer (LPSOCKADDR_IN pAddr
, ULONG
*pStatus
)
307 if (!RefreshServers (TRUE
, pStatus
))
310 // We'll try to use our lookup key first--since most machines only
311 // have one IP address anyway, our hashtable should make this lookup
312 // super fast. If it misses (i.e., if the server is multi-homed and
313 // for some reason VLDB refers to it by the second address), we'll
314 // have to do a brute-force search across each server in the cell.
315 // Again, we could have a better-designed lookup table here--but
316 // since multi-homing is the exception (by a vast majority), it's not
317 // worth the extra effort and memory. This technique is fast enough.
320 if ((lpServer
= (LPSERVER
)(m_lkServerAddr
->GetFirstObject (pAddr
))) != NULL
)
322 AfsClass_Enter(); // Aren't HashLists great? We found the server.
324 else // Try brute-force search
327 for (lpServer
= ServerFindFirst (&hEnum
, TRUE
, pStatus
); lpServer
; lpServer
= ServerFindNext (&hEnum
))
330 if (lpServer
->GetStatus (&ss
, TRUE
, pStatus
))
332 for (size_t iAddr
= 0; iAddr
< ss
.nAddresses
; ++iAddr
)
334 if (!memcmp (&ss
.aAddresses
[ iAddr
], pAddr
, sizeof(SOCKADDR_IN
)))
336 // don't close server! we're going to return this pointer.
343 ServerFindClose (&hEnum
);
349 LPSERVER
CELL::ServerFindFirst (HENUM
*phEnum
, BOOL fNotify
, ULONG
*pStatus
)
351 return ServerFindFirst (phEnum
, NULL
, fNotify
, pStatus
);
355 LPSERVER
CELL::ServerFindFirst (HENUM
*phEnum
, LPIDENT lpiFind
, BOOL fNotify
, ULONG
*pStatus
)
357 LPSERVER lpServer
= NULL
;
359 if (!RefreshServers (fNotify
, pStatus
))
364 lpServer
= lpiFind
->OpenServer();
367 else if ((*phEnum
= m_lServers
->FindFirst()) != NULL
)
369 lpServer
= (LPSERVER
)( (*phEnum
)->GetObject() );
373 if (!lpServer
&& pStatus
)
374 *pStatus
= ERROR_FILE_NOT_FOUND
;
379 LPSERVER
CELL::ServerFindNext (HENUM
*phEnum
)
381 LPSERVER lpServer
= NULL
;
385 if ((*phEnum
= (*phEnum
)->FindNext()) != NULL
)
387 lpServer
= (LPSERVER
)( (*phEnum
)->GetObject() );
396 void CELL::ServerFindClose (HENUM
*phEnum
)
406 BOOL
CELL::RefreshServers (BOOL fNotify
, ULONG
*pStatus
)
408 if (!m_fServersOutOfDate
)
411 return RefreshServerList (fNotify
, pStatus
);
415 BOOL
CELL::RefreshServerList (BOOL fNotify
, ULONG
*pStatus
)
419 BOOL fNotified
= FALSE
;
421 if (fNotify
&& m_fServersOutOfDate
)
423 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersBegin
, GetIdentifier());
427 BOOL fReplaceList
= m_fServersOutOfDate
;
428 m_fServersOutOfDate
= FALSE
;
430 // Ordinarily we'd just clear the list of servers and
431 // requery it from scratch; however, servers are an exception
432 // to that technique: occasionally we may get a request to
433 // just look for servers that have appeared or disappeared,
434 // without refreshing data for other servers. Thus the revised
437 // 1- if fReplaceList, empty the list of servers.
438 // otherwise, set each server's fDelete flag.
440 // 2- enumerate the servers in the cell: for each server,
441 // if fReplaceList, add the server to the list
442 // otherwise, if the server is in the list, clear its fDelete
444 // 3- if !fReplaceList, enumerate the list of servers: for each server,
445 // if the server's fDelete flag is set, remove the server
447 for (LPENUM pEnum
= m_lServers
->FindFirst(); pEnum
; pEnum
= pEnum
->FindNext())
449 LPSERVER lpServer
= (LPSERVER
)(pEnum
->GetObject());
453 lpServer
->SendDeleteNotifications();
454 m_lServers
->Remove (lpServer
);
457 else // the list of servers isn't invalidated, so just mark fDelete
459 lpServer
->m_fDelete
= TRUE
;
463 // Enumerate the servers in the cell.
466 if ((hCell
= GetCellObject (&status
)) == NULL
)
474 WORKERPACKET wpBegin
;
475 wpBegin
.wpClientAFSServerGetBegin
.hCell
= hCell
;
477 if (!Worker_DoTask (wtaskClientAFSServerGetBegin
, &wpBegin
, &status
))
486 wpNext
.wpClientAFSServerGetNext
.hEnum
= wpBegin
.wpClientAFSServerGetBegin
.hEnum
;
487 if (!Worker_DoTask (wtaskClientAFSServerGetNext
, &wpNext
, &status
))
489 if (status
== ADMITERATORDONE
)
496 afs_serverEntry_p pEntry
= &wpNext
.wpClientAFSServerGetNext
.Entry
;
498 TCHAR szServer
[ cchNAME
];
499 CopyAnsiToString (szServer
, pEntry
->serverName
);
502 int addrNetwork
= htonl (pEntry
->serverAddress
[0]);
503 lstrcpy (szServer
, inet_ntoa (*(struct in_addr
*)&addrNetwork
));
506 // The server identified by {pEntry} is in the cell. Now if we're
507 // building a list of SERVER objects from scratch, we can just
508 // add it--but if we're only touching up an existing list,
509 // first make sure there isn't such an animal in there now.
511 BOOL fNotifyAboutThisServer
= FALSE
;
513 LPSERVER lpServer
= NULL
;
516 if ((lpServer
= (LPSERVER
)(m_lkServerName
->GetFirstObject (szServer
))) != NULL
)
517 lpServer
->m_fDelete
= FALSE
;
520 if (lpServer
== NULL
)
522 // Okay, it's a new server. Create a SERVER object for it and
523 // add it to the list.
525 lpServer
= New2 (SERVER
,(this, szServer
));
526 lpServer
->m_wGhost
|= GHOST_HAS_SERVER_ENTRY
;
527 m_lServers
->Add (lpServer
);
528 fNotifyAboutThisServer
= TRUE
;
531 // Update the server's IP addresses
533 lpServer
->m_ss
.nAddresses
= 0;
535 for (size_t iAddr
= 0; iAddr
< AFS_MAX_SERVER_ADDRESS
; ++iAddr
)
537 if (pEntry
->serverAddress
[ iAddr
] == 0)
539 AfsClass_IntToAddress (&lpServer
->m_ss
.aAddresses
[ lpServer
->m_ss
.nAddresses
++ ], pEntry
->serverAddress
[ iAddr
]);
542 m_lServers
->Update (lpServer
); // That update affected a hashlistkey
544 // Tell our clients that we've found a server
546 if (fNotify
&& fNotifyAboutThisServer
)
550 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersBegin
, GetIdentifier());
553 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpServer
->GetIdentifier());
558 wpDone
.wpClientAFSServerGetDone
.hEnum
= wpBegin
.wpClientAFSServerGetBegin
.hEnum
;
559 Worker_DoTask (wtaskClientAFSServerGetDone
, &wpDone
);
563 // Finally, look through our list of servers: if any have fDelete set,
564 // then we didn't find them in the cell any longer. Remove those servers.
568 for (LPENUM pEnum
= m_lServers
->FindFirst(); pEnum
; pEnum
= pEnum
->FindNext())
570 LPSERVER lpServer
= (LPSERVER
)(pEnum
->GetObject());
571 if (lpServer
->m_fDelete
)
573 if (fNotify
&& !fNotified
)
575 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersBegin
, GetIdentifier());
578 lpServer
->SendDeleteNotifications();
579 m_lServers
->Remove (lpServer
);
585 // Fix m_apszServers if we did anything to the list of servers
591 for (size_t ii
= 0; m_apszServers
[ii
]; ++ii
)
592 FreeString (m_apszServers
[ii
]);
593 Free (m_apszServers
);
594 m_apszServers
= NULL
;
599 for (pEnum
= m_lServers
->FindFirst(); pEnum
; pEnum
= pEnum
->FindNext())
604 m_apszServers
= (char**)Allocate (sizeof(char*) * (1+cServers
));
605 memset (m_apszServers
, 0x00, sizeof(char*) * (1+cServers
));
608 for (pEnum
= m_lServers
->FindFirst(); pEnum
; pEnum
= pEnum
->FindNext())
610 LPSERVER lpServer
= (LPSERVER
)(pEnum
->GetObject());
611 m_apszServers
[ iServer
] = AllocateAnsi (cchNAME
+1);
612 CopyStringToAnsi (m_apszServers
[ iServer
], lpServer
->m_szName
);
619 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersEnd
, GetIdentifier(), ((rc
) ? 0 : status
));
628 * SERVER-LIST KEYS ___________________________________________________________
632 BOOL CALLBACK
CELL::KeyServerName_Compare (LPHASHLISTKEY pKey
, PVOID pObject
, PVOID pData
)
634 if (!lstrcmp (((LPSERVER
)pObject
)->m_szName
, (LPTSTR
)pData
))
637 TCHAR szShortName
[ cchNAME
];
638 SERVER::ShortenName (szShortName
, ((LPSERVER
)pObject
)->m_szName
);
639 if (!lstrcmp (szShortName
, (LPTSTR
)pData
))
645 HASHVALUE CALLBACK
CELL::KeyServerName_HashObject (LPHASHLISTKEY pKey
, PVOID pObject
)
647 return CELL::KeyServerName_HashData (pKey
, ((LPSERVER
)pObject
)->m_szName
);
650 HASHVALUE CALLBACK
CELL::KeyServerName_HashData (LPHASHLISTKEY pKey
, PVOID pData
)
652 TCHAR szShortName
[ cchNAME
];
653 SERVER::ShortenName (szShortName
, (LPTSTR
)pData
);
654 return HashString (szShortName
);
658 BOOL CALLBACK
CELL::KeyServerAddr_Compare (LPHASHLISTKEY pKey
, PVOID pObject
, PVOID pData
)
660 return !memcmp (&((LPSERVER
)pObject
)->m_ss
.aAddresses
[0], (LPSOCKADDR
)pData
, sizeof(SOCKADDR_IN
));
663 HASHVALUE CALLBACK
CELL::KeyServerAddr_HashObject (LPHASHLISTKEY pKey
, PVOID pObject
)
665 return CELL::KeyServerAddr_HashData (pKey
, &((LPSERVER
)pObject
)->m_ss
.aAddresses
[0]);
668 HASHVALUE CALLBACK
CELL::KeyServerAddr_HashData (LPHASHLISTKEY pKey
, PVOID pData
)
670 return *(DWORD
*)pData
;
674 BOOL CALLBACK
CELL::KeyUserName_Compare (LPHASHLISTKEY pKey
, PVOID pObject
, PVOID pData
)
676 return !lstrcmpi (((LPUSER
)pObject
)->m_szPrincipal
, (LPTSTR
)pData
);
679 HASHVALUE CALLBACK
CELL::KeyUserName_HashObject (LPHASHLISTKEY pKey
, PVOID pObject
)
681 return CELL::KeyUserName_HashData (pKey
, ((LPUSER
)pObject
)->m_szPrincipal
);
684 HASHVALUE CALLBACK
CELL::KeyUserName_HashData (LPHASHLISTKEY pKey
, PVOID pData
)
686 return HashString ((LPTSTR
)pData
);
690 BOOL CALLBACK
CELL::KeyGroupName_Compare (LPHASHLISTKEY pKey
, PVOID pObject
, PVOID pData
)
692 return !lstrcmpi (((LPPTSGROUP
)pObject
)->m_szName
, (LPTSTR
)pData
);
695 HASHVALUE CALLBACK
CELL::KeyGroupName_HashObject (LPHASHLISTKEY pKey
, PVOID pObject
)
697 return CELL::KeyGroupName_HashData (pKey
, ((LPPTSGROUP
)pObject
)->m_szName
);
700 HASHVALUE CALLBACK
CELL::KeyGroupName_HashData (LPHASHLISTKEY pKey
, PVOID pData
)
702 return HashString ((LPTSTR
)pData
);
707 * CELL OBJECT ________________________________________________________________
711 PVOID
CELL::GetCellObject (ULONG
*pStatus
)
716 NOTIFYCALLBACK::SendNotificationToAll (evtOpenCellBegin
, m_szName
);
719 wpOpen
.wpClientCellOpen
.pszCell
= m_szName
;
720 wpOpen
.wpClientCellOpen
.hCreds
= m_hCreds
;
722 if (Worker_DoTask (wtaskClientCellOpen
, &wpOpen
, &status
))
723 m_hCell
= wpOpen
.wpClientCellOpen
.hCell
;
727 NOTIFYCALLBACK::SendNotificationToAll (evtOpenCellEnd
, m_szName
, status
);
734 BOOL
CELL::CloseCellObject (ULONG
*pStatus
)
741 wp
.wpClientCellClose
.hCell
= m_hCell
;
742 rc
= Worker_DoTask (wtaskClientCellClose
, &wp
, pStatus
);
750 PVOID
CELL::GetKasObject (ULONG
*pStatus
)
752 // m_hKas is actually never set non-NULL;
753 // leaving it NULL indicates we will work happily with *any* server.
759 BOOL
CELL::CloseKasObject (ULONG
*pStatus
)
766 wp
.wpKasServerClose
.hServer
= m_hKas
;
767 rc
= Worker_DoTask (wtaskKasServerClose
, &wp
, pStatus
);
776 * CELL GENERAL _______________________________________________________________
780 LPIDENT
CELL::GetIdentifier (void)
782 if (m_lpiThis
== NULL
)
784 if ((m_lpiThis
= IDENT::FindIdent (this)) == NULL
)
785 m_lpiThis
= New2 (IDENT
,(this));
786 m_lpiThis
->m_cRef
++;
793 void CELL::GetName (LPTSTR pszName
)
795 lstrcpy (pszName
, m_szName
);
799 PVOID
CELL::GetUserParam (void)
801 return GetIdentifier()->GetUserParam();
805 void CELL::SetUserParam (PVOID pUserNew
)
807 GetIdentifier()->SetUserParam (pUserNew
);
811 BOOL
CELL::fAnyServersUnmonitored (void)
813 return (m_nServersUnmonitored
> 0) ? TRUE
: FALSE
;
818 * CELL STATUS ________________________________________________________________
822 void CELL::Invalidate (void)
824 if (!m_fServersOutOfDate
|| !m_fStatusOutOfDate
|| !m_fVLDBOutOfDate
|| !m_fUsersOutOfDate
)
828 m_fServersOutOfDate
= TRUE
;
829 m_fStatusOutOfDate
= TRUE
;
830 m_fVLDBOutOfDate
= TRUE
;
831 m_fUsersOutOfDate
= TRUE
;
832 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate
, GetIdentifier());
837 void CELL::InvalidateServers (void)
839 if (!m_fServersOutOfDate
|| !m_fVLDBOutOfDate
)
843 m_fServersOutOfDate
= TRUE
;
844 m_fVLDBOutOfDate
= TRUE
;
845 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate
, GetIdentifier());
850 void CELL::InvalidateUsers (void)
852 if (!m_fUsersOutOfDate
)
854 m_fUsersOutOfDate
= TRUE
;
855 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate
, GetIdentifier());
860 BOOL
CELL::RefreshStatus (BOOL fNotify
, ULONG
*pStatus
)
865 if (m_fStatusOutOfDate
)
868 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin
, GetIdentifier());
870 // Hmmm...well, actually, there's nothing for us to do here. I'm
871 // leaving this around, because the refreshed-cell-status notification
872 // may be useful as an appropriate hooking point.
877 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd
, GetIdentifier(), ((rc
) ? 0 : status
));
886 BOOL
CELL::RefreshVLDB (BOOL fNotify
, ULONG
*pStatus
)
890 if (m_fVLDBOutOfDate
)
892 if ((rc
= RefreshVLDB (GetIdentifier(), fNotify
, pStatus
)) == TRUE
)
894 m_fVLDBOutOfDate
= FALSE
;
902 BOOL
CELL::RefreshVLDB (LPIDENT lpiRef
, BOOL fNotify
, ULONG
*pStatus
, BOOL fAnythingRelatedToThisRWFileset
)
907 // What is the scope of this refresh operation? The entire cell,
908 // or the filesets on a particular server or aggregate?
910 LPIDENT lpiRefCell
= (lpiRef
== NULL
) ? GetIdentifier() : lpiRef
->GetCell();
911 LPIDENT lpiRefServer
= NULL
;
912 LPIDENT lpiRefAggregate
= NULL
;
913 LPIDENT lpiRefFileset
= NULL
;
914 VOLUMEID
*pvidRefFileset
= NULL
;
915 VOLUMEID vidRefFileset
;
917 if (fAnythingRelatedToThisRWFileset
)
919 pvidRefFileset
= &vidRefFileset
;
920 lpiRef
->GetFilesetID (pvidRefFileset
);
924 if (lpiRef
&& !lpiRef
->fIsCell())
926 lpiRefServer
= lpiRef
->GetServer();
928 if (lpiRef
&& (lpiRef
->fIsAggregate() || lpiRef
->fIsFileset()))
930 lpiRefAggregate
= lpiRef
->GetAggregate();
932 if (lpiRef
&& lpiRef
->fIsFileset())
934 lpiRefFileset
= lpiRef
;
938 // If we've been told to update only one server, aggregate or
939 // fileset, find out which IP addresses correspond with that
940 // server. We'll need this for comparisons later.
942 SERVERSTATUS ssRefServer
;
943 if (rc
&& lpiRefServer
)
946 if ((lpServer
= lpiRefServer
->OpenServer (&status
)) == NULL
)
950 rc
= lpServer
->GetStatus (&ssRefServer
, fNotify
, &status
);
955 // Likewise, if we've been told to update only one aggregate,
956 // find that aggregate's ID. We'll need it for comparisons later.
958 AGGREGATESTATUS asRefAggregate
;
959 int idPartition
= NO_PARTITION
;
960 if (rc
&& lpiRefAggregate
)
962 LPAGGREGATE lpAggregate
;
963 if ((lpAggregate
= lpiRefAggregate
->OpenAggregate (&status
)) == NULL
)
967 idPartition
= lpAggregate
->GetID();
968 rc
= lpAggregate
->GetStatus (&asRefAggregate
, fNotify
, &status
);
969 lpAggregate
->Close();
973 // Zip through the current list of objects that we're about to refresh.
974 // On each such object, remove the GHOST_HAS_VLDB_ENTRY flag,
975 // and delete objects entirely if that's the only ghost flag they have.
976 // (e.g., If we went through this routine earlier and created a ghost
977 // aggregate because VLDB referenced it and we couldn't find mention
978 // of it on the server, delete that aggregate. We'll recreate it here
979 // if necessary; otherwise, it needs to be gone.)
983 RefreshVLDB_RemoveReferences (lpiRefServer
, lpiRefAggregate
, lpiRefFileset
, pvidRefFileset
);
986 // We'll get a new list of filesets from VLDB, and to do that, we'll
987 // need the cell's object. If we're enumerating a specific server, we'll
988 // also need that server's object. Finally, if we're enumerating a
989 // specific aggregate, we'll also need that aggregate's name.
992 PVOID hServer
= NULL
;
998 if ((hCell
= GetCellObject (&status
)) == NULL
)
1001 else // get cell and server handles
1004 if ((lpServer
= lpiRefServer
->OpenServer()) == NULL
)
1008 if ((hServer
= lpServer
->OpenVosObject (&hCell
, &status
)) == NULL
)
1015 // Go get that list of filesets, and use it to update our knowledge
1016 // of the cell. Remember that, if {pvidRefFileset}, we only want
1024 wpGet
.wpVosVLDBGet
.hCell
= hCell
;
1025 wpGet
.wpVosVLDBGet
.idVolume
= *pvidRefFileset
;
1027 if (!Worker_DoTask (wtaskVosVLDBGet
, &wpGet
, &status
))
1030 RefreshVLDB_OneEntry (&wpGet
.wpVosVLDBGet
.Data
, lpiRefServer
, &ssRefServer
, lpiRefAggregate
, &asRefAggregate
, lpiRefFileset
, pvidRefFileset
, fNotify
);
1034 WORKERPACKET wpBegin
;
1035 wpBegin
.wpVosVLDBGetBegin
.hCell
= hCell
;
1036 wpBegin
.wpVosVLDBGetBegin
.hServer
= hServer
;
1037 wpBegin
.wpVosVLDBGetBegin
.idPartition
= idPartition
;
1039 if (!Worker_DoTask (wtaskVosVLDBGetBegin
, &wpBegin
, &status
))
1045 WORKERPACKET wpNext
;
1046 wpNext
.wpVosVLDBGetNext
.hEnum
= wpBegin
.wpVosVLDBGetBegin
.hEnum
;
1047 if (!Worker_DoTask (wtaskVosVLDBGetNext
, &wpNext
, &status
))
1049 if (status
== ADMITERATORDONE
)
1056 RefreshVLDB_OneEntry (&wpNext
.wpVosVLDBGetNext
.Data
, lpiRefServer
, &ssRefServer
, lpiRefAggregate
, &asRefAggregate
, lpiRefFileset
, pvidRefFileset
, fNotify
);
1059 WORKERPACKET wpDone
;
1060 wpDone
.wpVosVLDBGetDone
.hEnum
= wpBegin
.wpVosVLDBGetBegin
.hEnum
;
1061 Worker_DoTask (wtaskVosVLDBGetDone
, &wpDone
);
1066 // We've finished the update. If we were asked to send notifications
1067 // about our progress, do so.
1071 LPIDENT lpiNotify
= (lpiRef
) ? lpiRef
: GetIdentifier();
1073 if (!lpiNotify
->fIsFileset())
1075 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshFilesetsBegin
, lpiNotify
);
1076 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshFilesetsEnd
, lpiNotify
, status
);
1079 if (lpiNotify
->fIsCell() || lpiNotify
->fIsServer())
1081 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesBegin
, lpiNotify
);
1082 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesEnd
, lpiNotify
, status
);
1089 if ((lpServer
= lpiRefServer
->OpenServer()) != NULL
)
1091 lpServer
->CloseVosObject();
1102 void CELL::RefreshVLDB_RemoveReferences (LPIDENT lpiRefServer
, LPIDENT lpiRefAggregate
, LPIDENT lpiRefFileset
, LPVOLUMEID pvidRefFileset
)
1104 // Zip through the current list of objects that we're about to refresh.
1105 // On each such object, remove the GHOST_HAS_VLDB_ENTRY flag,
1106 // and delete objects entirely if that's the only ghost flag they have.
1107 // (e.g., If we went through this routine earlier and created a ghost
1108 // aggregate because VLDB referenced it and we couldn't find mention
1109 // of it on the server, delete that aggregate. We'll recreate it here
1110 // if necessary; otherwise, it needs to be gone.)
1112 // Note that by specifying {lpiRefServer} to start the enumeration,
1113 // we'll either enumerate only lpiRefServer, or all servers if it's NULL.
1116 for (LPSERVER lpServer
= ServerFindFirst (&heServer
, lpiRefServer
); lpServer
; lpServer
= ServerFindNext (&heServer
))
1119 if (!pvidRefFileset
)
1121 // Since we're about to check VLDB for references to this server,
1122 // remove the GHOST_HAS_VLDB_ENTRY flag from its SERVER object.
1123 // If that's the only thing keeping the object around, remove the
1126 if ((lpServer
->m_wGhost
&= (~GHOST_HAS_VLDB_ENTRY
)) == 0)
1129 lpServer
->SendDeleteNotifications();
1130 m_lServers
->Remove (lpServer
);
1136 // Check each of the server's aggregates, and deal with them the same
1140 for (LPAGGREGATE lpAggregate
= lpServer
->AggregateFindFirst (&heAggregate
, lpiRefAggregate
); lpAggregate
; lpAggregate
= lpServer
->AggregateFindNext (&heAggregate
))
1143 if (!pvidRefFileset
)
1145 // Since we're about to check VLDB for references to this aggregate,
1146 // remove the GHOST_HAS_VLDB_ENTRY flag from its AGGREGATE object.
1147 // If that's the only thing keeping the object around, remove the
1150 if ((lpAggregate
->m_wGhost
&= (~GHOST_HAS_VLDB_ENTRY
)) == 0)
1152 lpAggregate
->Close();
1153 lpAggregate
->SendDeleteNotifications();
1154 lpServer
->m_lAggregates
->Remove (lpAggregate
);
1155 Delete (lpAggregate
);
1160 // Check each of the aggregate's filesets, and deal with them the same
1164 for (LPFILESET lpFileset
= lpAggregate
->FilesetFindFirst (&heFileset
, lpiRefFileset
); lpFileset
; lpFileset
= lpAggregate
->FilesetFindNext (&heFileset
))
1166 if ((!pvidRefFileset
) || (*pvidRefFileset
== lpFileset
->m_fs
.idReadWrite
))
1168 // Since we're about to check VLDB for references to this fileset,
1169 // remove the GHOST_HAS_VLDB_ENTRY flag from its FILESET object.
1170 // If that's the only thing keeping the object around, remove the
1173 if ((lpFileset
->m_wGhost
&= (~GHOST_HAS_VLDB_ENTRY
)) == 0)
1176 lpFileset
->SendDeleteNotifications();
1177 lpAggregate
->m_lFilesets
->Remove (lpFileset
);
1186 lpAggregate
->Close();
1194 void CELL::RefreshVLDB_OneEntry (PVOID pp
, LPIDENT lpiRefServer
, LPSERVERSTATUS pssRefServer
, LPIDENT lpiRefAggregate
, LPAGGREGATESTATUS pasRefAggregate
, LPIDENT lpiRefFileset
, LPVOLUMEID pvidRefFileset
, BOOL fNotify
)
1196 vos_vldbEntry_p pEntry
= (vos_vldbEntry_p
)pp
;
1198 // If we were asked to update all the replicas of a particular
1199 // fileset, then we set {pvidRefFileset} above to that fileset's
1200 // ID. Check this VLDB entry to see if it refers to that fileset;
1201 // if not, we're not interested in it.
1205 if (memcmp (&pEntry
->volumeId
[ VOS_READ_WRITE_VOLUME
], pvidRefFileset
, sizeof(VOLUMEID
)))
1209 for (int iRepSite
= 0; iRepSite
< pEntry
->numServers
; ++iRepSite
)
1211 SOCKADDR_IN RepSiteAddr
;
1212 AfsClass_IntToAddress (&RepSiteAddr
, pEntry
->volumeSites
[ iRepSite
].serverAddress
);
1214 // Every fileset replication site which VLDB knows about
1215 // passes through this point, within {pEntry->volumeSites[ iRepSite ]}.
1217 // Are we going to be refreshing the server/aggregate on which
1218 // this repsite lives? If not, there's no need to process this
1219 // entry any further.
1223 BOOL fFilesetLivesOnThisServer
= FALSE
;
1225 for (size_t iAddress
= 0; !fFilesetLivesOnThisServer
&& (iAddress
< pssRefServer
->nAddresses
); ++iAddress
)
1227 if (!memcmp (&pssRefServer
->aAddresses
[ iAddress
], &RepSiteAddr
, sizeof(SOCKADDR_IN
)))
1229 if (lpiRefAggregate
)
1231 if (pasRefAggregate
->dwID
!= (DWORD
)(pEntry
->volumeSites
[ iRepSite
].serverPartition
))
1234 fFilesetLivesOnThisServer
= TRUE
;
1238 if (!fFilesetLivesOnThisServer
)
1242 // Do we know about the server mentioned by this replication
1246 if (lpiRefServer
!= NULL
)
1247 lpServer
= lpiRefServer
->OpenServer();
1249 lpServer
= OpenServer (&RepSiteAddr
);
1251 // If we found the server but aren't monitoring it,
1252 // forget about this fileset.
1254 if (lpServer
&& !lpServer
->fIsMonitored())
1261 // If we have no record of the server mentioned by this
1262 // replication site, we have to create a SERVER entry for
1263 // it before we can proceed. The server will appear as
1268 if (lpiRefAggregate
|| pvidRefFileset
)
1271 LPTSTR pszServer
= FormatString (TEXT("%1"), TEXT("%a"), &pEntry
->volumeSites
[ iRepSite
].serverAddress
);
1272 lpServer
= New2 (SERVER
,(this, pszServer
));
1274 FreeString (pszServer
);
1276 lpServer
->m_fStatusOutOfDate
= FALSE
;
1277 lpServer
->m_ss
.nAddresses
= 1;
1278 memcpy (&lpServer
->m_ss
.aAddresses
[0], &RepSiteAddr
, sizeof(SOCKADDR_IN
));
1280 m_lServers
->Add (lpServer
);
1283 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpServer
->GetIdentifier());
1286 lpServer
->m_wGhost
|= GHOST_HAS_VLDB_ENTRY
;
1288 // Great--we now have a replication site for a particular
1289 // fileset known to VLDB, and a pointer to the server
1290 // on which it resides. Does that server contain the
1291 // aggregate which VLDB expects to find?
1293 LPAGGREGATE lpAggregate
;
1294 if (lpiRefAggregate
!= NULL
)
1295 lpAggregate
= lpiRefAggregate
->OpenAggregate();
1297 lpAggregate
= lpServer
->OpenAggregate (pEntry
->volumeSites
[ iRepSite
].serverPartition
);
1299 // If the server has no record of the aggregate mentioned
1300 // by this replication site, we have to create an
1301 // AGGREGATE entry for it before we can proceed. The
1302 // aggregate will appear as a "ghost". Note that we
1303 // can't update the list of aggregates on a server if
1304 // we've been asked to update a particular fileset,
1305 // because someone clearly has a pointer to the list.
1309 if (lpiRefFileset
|| pvidRefFileset
)
1316 // Even if the partition doesn't exist, we can still figger out
1317 // its name given its ID--'cause there's a 1:1 mapping between
1318 // allowed IDs and allowed partition names. I guess there's
1319 // something to be said for forcing partitions to be named "vicep*"
1321 TCHAR szPartition
[ cchNAME
];
1323 wp
.wpVosPartitionIdToName
.idPartition
= pEntry
->volumeSites
[ iRepSite
].serverPartition
;
1324 wp
.wpVosPartitionIdToName
.pszPartition
= szPartition
;
1325 if (!Worker_DoTask (wtaskVosPartitionIdToName
, &wp
))
1326 wsprintf (szPartition
, TEXT("#%lu"), pEntry
->volumeSites
[ iRepSite
].serverPartition
);
1328 lpAggregate
= New2 (AGGREGATE
,(lpServer
, szPartition
, TEXT("")));
1331 lpAggregate
->m_fStatusOutOfDate
= FALSE
;
1332 lpAggregate
->m_as
.dwID
= pEntry
->volumeSites
[ iRepSite
].serverPartition
;
1333 lpAggregate
->m_as
.ckStorageTotal
= 0;
1334 lpAggregate
->m_as
.ckStorageFree
= 0;
1336 lpServer
->m_lAggregates
->Add (lpAggregate
);
1339 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpAggregate
->GetIdentifier());
1342 lpAggregate
->m_wGhost
|= GHOST_HAS_VLDB_ENTRY
;
1344 // Great--we now have a replication site for a particular
1345 // fileset known to VLDB, and a pointer to the server
1346 // and aggregate on which it resides. Does that aggregate
1347 // contain the fileset which VLDB expects to find?
1349 // Remember that each iRepSite can represent up to three
1350 // filesets on that aggregate--a RW, a RO, and a BAK.
1352 for (size_t iType
= 0; iType
< 3; ++iType
)
1355 // Does this repsite entry mention having this type
1356 // of fileset on this aggregate?
1358 if ((vos_volumeType_t
)iType
== VOS_READ_WRITE_VOLUME
)
1360 if (!((DWORD
)pEntry
->volumeSites
[ iRepSite
].serverFlags
& (DWORD
)VOS_VLDB_READ_WRITE
))
1363 else if ((vos_volumeType_t
)iType
== VOS_READ_ONLY_VOLUME
)
1365 if (!((DWORD
)pEntry
->volumeSites
[ iRepSite
].serverFlags
& (DWORD
)VOS_VLDB_READ_ONLY
))
1368 else if ((vos_volumeType_t
)iType
== VOS_BACKUP_VOLUME
)
1370 if (!((DWORD
)pEntry
->status
& (DWORD
)VOS_VLDB_ENTRY_BACKEXISTS
))
1373 // Only look for the backup where the R/W exists
1374 if (!((DWORD
)pEntry
->volumeSites
[ iRepSite
].serverFlags
& (DWORD
)VOS_VLDB_READ_WRITE
))
1378 LPFILESET lpFileset
= lpAggregate
->OpenFileset ((LPVOLUMEID
)&pEntry
->volumeId
[ iType
]);
1380 // If the aggregate has no record of the fileset mentioned
1381 // by this VLDB entry, we have to create a FILESET entry
1382 // for it. The fileset will appear as a "ghost".
1386 TCHAR szFilesetName
[ cchNAME
];
1387 CopyAnsiToString (szFilesetName
, pEntry
->name
);
1388 if ((vos_volumeType_t
)iType
== VOS_READ_ONLY_VOLUME
)
1389 lstrcat (szFilesetName
, TEXT(".readonly"));
1390 else if ((vos_volumeType_t
)iType
== VOS_BACKUP_VOLUME
)
1391 lstrcat (szFilesetName
, TEXT(".backup"));
1393 lpFileset
= New2 (FILESET
,(lpAggregate
, &pEntry
->volumeId
[ iType
], szFilesetName
));
1396 lpFileset
->m_fs
.id
= pEntry
->volumeId
[ iType
];
1397 lpFileset
->m_fs
.idReadWrite
= pEntry
->volumeId
[ VOS_READ_WRITE_VOLUME
];
1398 lpFileset
->m_fs
.idReplica
= pEntry
->volumeId
[ VOS_READ_ONLY_VOLUME
];
1399 AfsClass_UnixTimeToSystemTime (&lpFileset
->m_fs
.timeCreation
, 0);
1400 AfsClass_UnixTimeToSystemTime (&lpFileset
->m_fs
.timeLastUpdate
, 0);
1401 AfsClass_UnixTimeToSystemTime (&lpFileset
->m_fs
.timeLastAccess
, 0);
1402 AfsClass_UnixTimeToSystemTime (&lpFileset
->m_fs
.timeLastBackup
, 0);
1403 AfsClass_UnixTimeToSystemTime (&lpFileset
->m_fs
.timeCopyCreation
, 0);
1404 lpFileset
->m_fs
.nFiles
= 0;
1405 lpFileset
->m_fs
.ckQuota
= 0;
1406 lpFileset
->m_fs
.ckUsed
= 0;
1407 lpFileset
->m_fs
.Type
= (iType
== 0) ? ftREADWRITE
: (iType
== 1) ? ftREPLICA
: ftCLONE
;
1408 lpFileset
->m_fs
.State
= fsNORMAL
;
1410 lpAggregate
->m_lFilesets
->Add (lpFileset
);
1413 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpFileset
->GetIdentifier());
1417 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin
, lpFileset
->GetIdentifier());
1419 lpFileset
->m_wGhost
|= GHOST_HAS_VLDB_ENTRY
;
1420 lpFileset
->m_fStatusOutOfDate
= FALSE
;
1421 lpFileset
->m_fs
.idClone
= pEntry
->cloneId
;
1422 lpFileset
->m_fs
.State
&= ~fsMASK_VLDB
;
1424 if (pEntry
->status
& VOS_VLDB_ENTRY_LOCKED
)
1425 lpFileset
->m_fs
.State
|= fsLOCKED
;
1430 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd
, lpFileset
->GetIdentifier(), 0);
1433 if (lpServer
&& lpAggregate
)
1435 lpAggregate
->InvalidateAllocation();
1436 lpAggregate
->Close();
1448 BOOL
CELL::RefreshAll (ULONG
*pStatus
)
1453 BOOL fNotified
= FALSE
;
1455 if (m_fServersOutOfDate
&& (dwWant
& AFSCLASS_WANT_VOLUMES
))
1460 if ((++cRefreshAllReq
) == 1)
1462 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin
, GetIdentifier());
1466 ULONG nServersToRefresh
= 0;
1469 for (LPSERVER lpServer
= ServerFindFirst (&hEnum
); lpServer
; lpServer
= ServerFindNext (&hEnum
))
1471 if (lpServer
->fIsMonitored())
1472 ++nServersToRefresh
;
1476 if (nServersToRefresh
)
1479 for (LPSERVER lpServer
= ServerFindFirst (&hEnum
); lpServer
; lpServer
= ServerFindNext (&hEnum
))
1481 if (lpServer
->fIsMonitored())
1483 ULONG perComplete
= (ULONG
)iServer
* 100L / nServersToRefresh
;
1484 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate
, lpServer
->GetIdentifier(), NULL
, NULL
, NULL
, perComplete
, 0);
1486 // intentionally ignore errors in refreshing individual
1487 // servers--we only want to return an error code if
1488 // we couldn't refresh the *cell*.
1490 (void)lpServer
->RefreshAll (NULL
, ((double)iServer
/ (double)nServersToRefresh
), (1.0 / (double)nServersToRefresh
));
1496 rc
= RefreshVLDB (NULL
, TRUE
, &status
);
1500 if (rc
&& m_fUsersOutOfDate
&& (dwWant
& AFSCLASS_WANT_USERS
))
1505 if ((++cRefreshAllReq
) == 1)
1507 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin
, GetIdentifier(), NULL
, NULL
, NULL
, 0, 0);
1511 rc
= RefreshUsers (TRUE
, &status
);
1516 if ((--cRefreshAllReq
) == 0)
1518 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllEnd
, GetIdentifier(), NULL
, NULL
, NULL
, 100, status
);
1529 * USER/GROUP-LIST MANAGEMENT _________________________________________________
1533 LPUSER
CELL::OpenUser (LPTSTR pszName
, LPTSTR pszInstance
, ULONG
*pStatus
)
1537 // First off, do we have a USER object for this guy already?
1539 LPUSER lpUser
= NULL
;
1540 for (LPENUM pEnum
= m_lkUserName
->FindFirst (pszName
); pEnum
; pEnum
= pEnum
->FindNext())
1542 LPUSER lpTest
= (LPUSER
)( pEnum
->GetObject() );
1543 if (!pszInstance
|| !lstrcmpi (lpTest
->m_szInstance
, pszInstance
))
1552 // If not, see if we can create one...
1556 // See if there's a KAS or PTS entry for this user.
1558 BOOL fHasKAS
= FALSE
;
1559 BOOL fHasPTS
= FALSE
;
1562 wp
.wpKasPrincipalGet
.hCell
= GetCellObject (&status
);
1563 wp
.wpKasPrincipalGet
.hServer
= GetKasObject (&status
);
1564 wp
.wpKasPrincipalGet
.pszPrincipal
= pszName
;
1565 wp
.wpKasPrincipalGet
.pszInstance
= pszInstance
;
1566 if (Worker_DoTask (wtaskKasPrincipalGet
, &wp
, &status
))
1571 TCHAR szFullName
[ cchNAME
];
1572 AfsClass_GenFullUserName (szFullName
, pszName
, pszInstance
);
1575 wp
.wpPtsUserGet
.hCell
= GetCellObject();
1576 wp
.wpPtsUserGet
.pszUser
= szFullName
;
1577 if (Worker_DoTask (wtaskPtsUserGet
, &wp
, &status
))
1580 if (fHasKAS
|| fHasPTS
)
1582 lpUser
= New2 (USER
,(this, pszName
, pszInstance
));
1583 m_lUsers
->Add (lpUser
);
1584 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpUser
->GetIdentifier());
1589 if (!lpUser
&& pStatus
)
1595 LPUSER
CELL::UserFindFirst (HENUM
*phEnum
, BOOL fNotify
, ULONG
*pStatus
)
1597 return UserFindFirst (phEnum
, NULL
, fNotify
, pStatus
);
1601 LPUSER
CELL::UserFindFirst (HENUM
*phEnum
, LPIDENT lpiFind
, BOOL fNotify
, ULONG
*pStatus
)
1603 LPUSER lpUser
= NULL
;
1605 if (!RefreshUsers (fNotify
, pStatus
))
1608 if (lpiFind
!= NULL
)
1610 lpUser
= lpiFind
->OpenUser();
1613 else if ((*phEnum
= m_lUsers
->FindFirst()) != NULL
)
1615 lpUser
= (LPUSER
)( (*phEnum
)->GetObject() );
1619 if (!lpUser
&& pStatus
)
1620 *pStatus
= ERROR_FILE_NOT_FOUND
;
1625 LPUSER
CELL::UserFindNext (HENUM
*phEnum
)
1627 LPUSER lpUser
= NULL
;
1631 if ((*phEnum
= (*phEnum
)->FindNext()) != NULL
)
1633 lpUser
= (LPUSER
)( (*phEnum
)->GetObject() );
1642 void CELL::UserFindClose (HENUM
*phEnum
)
1653 LPPTSGROUP
CELL::OpenGroup (LPTSTR pszName
, ULONG
*pStatus
)
1657 // First off, do we have a USER object for this guy already?
1660 if ((lpGroup
= (LPPTSGROUP
)(m_lkGroupName
->GetFirstObject (pszName
))) != NULL
)
1663 // If not, see if we can create one...
1667 // See if there's a PTS entry for this group.
1670 wp
.wpPtsGroupGet
.hCell
= GetCellObject();
1671 wp
.wpPtsGroupGet
.pszGroup
= pszName
;
1672 if (Worker_DoTask (wtaskPtsGroupGet
, &wp
, &status
))
1674 lpGroup
= New2 (PTSGROUP
,(this, pszName
));
1675 m_lGroups
->Add (lpGroup
);
1676 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpGroup
->GetIdentifier());
1681 if (!lpGroup
&& pStatus
)
1687 LPPTSGROUP
CELL::GroupFindFirst (HENUM
*phEnum
, BOOL fNotify
, ULONG
*pStatus
)
1689 return GroupFindFirst (phEnum
, NULL
, fNotify
, pStatus
);
1693 LPPTSGROUP
CELL::GroupFindFirst (HENUM
*phEnum
, LPIDENT lpiFind
, BOOL fNotify
, ULONG
*pStatus
)
1695 LPPTSGROUP lpGroup
= NULL
;
1697 if (!RefreshUsers (fNotify
, pStatus
))
1700 if (lpiFind
!= NULL
)
1702 lpGroup
= lpiFind
->OpenGroup();
1705 else if ((*phEnum
= m_lGroups
->FindFirst()) != NULL
)
1707 lpGroup
= (LPPTSGROUP
)( (*phEnum
)->GetObject() );
1711 if (!lpGroup
&& pStatus
)
1712 *pStatus
= ERROR_FILE_NOT_FOUND
;
1717 LPPTSGROUP
CELL::GroupFindNext (HENUM
*phEnum
)
1719 LPPTSGROUP lpGroup
= NULL
;
1723 if ((*phEnum
= (*phEnum
)->FindNext()) != NULL
)
1725 lpGroup
= (LPPTSGROUP
)( (*phEnum
)->GetObject() );
1734 void CELL::GroupFindClose (HENUM
*phEnum
)
1744 BOOL
CELL::RefreshUsers (BOOL fNotify
, ULONG
*pStatus
)
1749 if (m_fUsersOutOfDate
)
1751 m_fUsersOutOfDate
= FALSE
;
1754 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshUsersBegin
, GetIdentifier());
1756 // First, forget everything we think we know about all users and groups;
1757 // we wouldn't be here if someone didn't think it was all out of date.
1761 // Then zip through KAS to build a list of all user entries;
1762 // we'll need hCell and hKAS for that.
1764 WORKERPACKET wpBegin
;
1765 wpBegin
.wpKasPrincipalGetBegin
.hCell
= GetCellObject();
1766 wpBegin
.wpKasPrincipalGetBegin
.hServer
= GetKasObject (&status
);
1768 if (!Worker_DoTask (wtaskKasPrincipalGetBegin
, &wpBegin
, &status
))
1774 TCHAR szPrincipal
[ cchNAME
];
1775 TCHAR szInstance
[ cchNAME
];
1777 WORKERPACKET wpNext
;
1778 wpNext
.wpKasPrincipalGetNext
.hEnum
= wpBegin
.wpKasPrincipalGetBegin
.hEnum
;
1779 wpNext
.wpKasPrincipalGetNext
.pszPrincipal
= szPrincipal
;
1780 wpNext
.wpKasPrincipalGetNext
.pszInstance
= szInstance
;
1781 if (!Worker_DoTask (wtaskKasPrincipalGetNext
, &wpNext
, &status
))
1783 if (status
== ADMITERATORDONE
)
1790 // Okay, we got a user from kas. Create a USER object for it.
1792 LPUSER lpUser
= New2 (USER
,(this, szPrincipal
, szInstance
));
1793 m_lUsers
->Add (lpUser
);
1795 // That was easy, wasn't it? Now check this user's groups,
1796 // both the ones it owns and the ones to which it belongs,
1797 // so we can build a full list-o-groups.
1800 if (lpUser
->GetMemberOf (&mszGroups
))
1802 BuildGroups (mszGroups
);
1803 FreeString (mszGroups
);
1806 if (lpUser
->GetOwnerOf (&mszGroups
))
1808 BuildGroups (mszGroups
);
1809 FreeString (mszGroups
);
1813 WORKERPACKET wpDone
;
1814 wpDone
.wpKasPrincipalGetDone
.hEnum
= wpBegin
.wpKasPrincipalGetBegin
.hEnum
;
1815 Worker_DoTask (wtaskKasPrincipalGetDone
, &wpDone
);
1818 #ifdef FIND_PTS_DEBRIS
1819 // Icky horrible painful part: to catch entries which exist on PTS
1820 // but not in KAS, we need to zip back through our list of groups
1821 // and check thier memberships.
1823 for (LPENUM pe
= m_lGroups
->FindFirst(); pe
; pe
= pe
->FindNext())
1825 LPPTSGROUP lpGroup
= (LPPTSGROUP
)(pe
->GetObject());
1828 if (lpGroup
->GetMembers (&mszMembers
))
1830 for (LPTSTR pszMember
= mszMembers
; pszMember
&& *pszMember
; pszMember
+= 1+lstrlen(pszMember
))
1832 // Make sure we have a user or group account for this guy.
1833 // Remember that the member name may have both a name and
1836 if (m_lkGroupName
->GetFirstObject (pszMember
))
1839 TCHAR szNameMatch
[ cchNAME
];
1840 TCHAR szInstanceMatch
[ cchNAME
];
1841 USER::SplitUserName (pszMember
, szNameMatch
, szInstanceMatch
);
1843 LPUSER lpFound
= NULL
;
1844 for (LPENUM pEnum
= m_lkUserName
->FindFirst (szNameMatch
); pEnum
; pEnum
= pEnum
->FindNext())
1846 LPUSER lpTest
= (LPUSER
)( pEnum
->GetObject() );
1847 if (!lstrcmpi (lpTest
->m_szInstance
, szInstanceMatch
))
1857 // Uh oh. Is this thing a user or a group? We're really only
1858 // interested in finding user-account debris here...
1861 wpGet
.wpPtsUserGet
.hCell
= GetCellObject();
1862 wpGet
.wpPtsUserGet
.pszUser
= pszMember
;
1863 if (Worker_DoTask (wtaskPtsUserGet
, &wpGet
))
1865 if (wpGet
.wpPtsUserGet
.Entry
.nameUid
> 0)
1867 LPUSER lpUser
= New2 (USER
,(this, pszMember
, TEXT("")));
1868 m_lUsers
->Add (lpUser
);
1876 // We've finally generated a complete list of the users and groups in
1877 // this cell. If we've been asked to, send out notifications for all
1878 // the things we found.
1883 for (pEnum
= m_lGroups
->FindFirst(); pEnum
; pEnum
= pEnum
->FindNext())
1885 LPPTSGROUP lpGroup
= (LPPTSGROUP
)(pEnum
->GetObject());
1886 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpGroup
->GetIdentifier());
1889 for (pEnum
= m_lUsers
->FindFirst(); pEnum
; pEnum
= pEnum
->FindNext())
1891 LPUSER lpUser
= (LPUSER
)(pEnum
->GetObject());
1892 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpUser
->GetIdentifier());
1895 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshUsersEnd
, GetIdentifier(), ((rc
) ? 0 : status
));
1905 void CELL::BuildGroups (LPTSTR mszGroups
)
1907 for (LPTSTR pszGroup
= mszGroups
; pszGroup
&& *pszGroup
; pszGroup
+= 1+lstrlen(pszGroup
))
1909 // Make sure we have this group in our list-of-groups
1912 if ((lpGroup
= (LPPTSGROUP
)m_lkGroupName
->GetFirstObject (pszGroup
)) == NULL
)
1914 lpGroup
= New2 (PTSGROUP
,(this, pszGroup
));
1915 m_lGroups
->Add (lpGroup
);
1921 BOOL
CELL::RefreshAccount (LPTSTR pszAccount
, LPTSTR pszInstance
, OP_CELL_REFRESH_ACCOUNT Op
, LPIDENT
*plpi
)
1925 // See if we can find this thing
1928 if ((lpi
= IDENT::FindUser (m_lpiThis
, pszAccount
, pszInstance
)) != NULL
)
1930 if (lpi
->m_cRef
== 0)
1935 if ((lpi
= IDENT::FindGroup (m_lpiThis
, pszAccount
)) != NULL
)
1936 if (lpi
->m_cRef
== 0)
1940 // If we couldn't find it, and Op is _CREATED_*, then make a new account
1942 if ((!lpi
) && (Op
== CELL_REFRESH_ACCOUNT_CREATED_USER
))
1944 LPUSER lpUser
= New2 (USER
,(this, pszAccount
, pszInstance
));
1945 m_lUsers
->Add (lpUser
);
1946 lpi
= lpUser
->GetIdentifier();
1947 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpi
);
1949 else if ((!lpi
) && (Op
== CELL_REFRESH_ACCOUNT_CREATED_GROUP
))
1951 LPPTSGROUP lpGroup
= New2 (PTSGROUP
,(this, pszAccount
));
1952 m_lGroups
->Add (lpGroup
);
1953 lpi
= lpGroup
->GetIdentifier();
1954 NOTIFYCALLBACK::SendNotificationToAll (evtCreate
, lpi
);
1957 // If we did find it, and Op is _DELETED, then remove the account
1959 if (lpi
&& (Op
== CELL_REFRESH_ACCOUNT_DELETED
))
1961 if (lpi
&& (lpi
->GetType() == itUSER
))
1964 if ((lpUser
= lpi
->OpenUser()) == NULL
)
1968 lpUser
->SendDeleteNotifications();
1970 m_lUsers
->Remove (lpUser
);
1975 else if (lpi
&& (lpi
->GetType() == itGROUP
))
1978 if ((lpGroup
= lpi
->OpenGroup()) == NULL
)
1982 lpGroup
->SendDeleteNotifications();
1984 m_lGroups
->Remove (lpGroup
);
1995 // If we still have an ident, refresh the account's properties
1997 if (lpi
&& (lpi
->GetType() == itUSER
))
2000 if ((lpUser
= lpi
->OpenUser()) == NULL
)
2004 lpUser
->Invalidate();
2005 lpUser
->RefreshStatus();
2009 else if (lpi
&& (lpi
->GetType() == itGROUP
))
2012 if ((lpGroup
= lpi
->OpenGroup()) == NULL
)
2016 lpGroup
->Invalidate();
2017 lpGroup
->RefreshStatus();
2028 BOOL
CELL::RefreshAccounts (LPTSTR mszAccounts
, OP_CELL_REFRESH_ACCOUNT Op
)
2031 for (LPTSTR psz
= mszAccounts
; psz
&& *psz
; psz
+= 1+lstrlen(psz
))
2033 if (!RefreshAccount (psz
, NULL
, Op
))