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
11 #include <afs/param.h>
15 #include <WINNT/afsclass.h>
20 * DEFINITIONS ________________________________________________________________
24 // Each CELL object maintains a list of servers; that list has
25 // hashtables placed across the (shortened) server name for
26 // faster lookup; it also maintains a hashtable across the
27 // servers' primary IP address (the first in the list; most
28 // servers will only have one anyway). The default table size
29 // in a HASHLIST is 1000 elements--that's too large for a list
30 // of servers-in-a-cell, as it's enough to handle up to 30,000
31 // servers before the table would need to resize iteself (see
32 // the documentation in hashlist.cpp for info). Instead, we
33 // choose a more reasonable default table size.
35 #define cKEYSERVERNAME_TABLESIZE 50
37 #define cKEYSERVERADDR_TABLESIZE 50
39 // Enable the definition below to do a better job of finding
40 // user entries in PTS which have no KAS entries (for instance,
41 // machine IP accounts).
43 #define FIND_PTS_DEBRIS
47 * VARIABLES __________________________________________________________________
51 LPHASHLIST CELL::x_lCells = NULL;
55 * CONSTRUCTION _______________________________________________________________
59 void CELL::InitClass (void)
63 x_lCells = New (HASHLIST);
64 x_lCells->SetCriticalSection (AfsClass_GetCriticalSection());
69 CELL::CELL (LPTSTR pszCellName, PVOID hCreds)
76 lstrcpy (m_szName, pszCellName);
81 m_fStatusOutOfDate = TRUE;
82 m_fVLDBOutOfDate = TRUE;
85 m_fServersOutOfDate = TRUE;
86 m_nServersUnmonitored = 0;
88 m_lServers = New (HASHLIST);
89 m_lServers->SetCriticalSection (AfsClass_GetCriticalSection());
90 m_lkServerName = m_lServers->CreateKey ("Server Name", CELL::KeyServerName_Compare, CELL::KeyServerName_HashObject, CELL::KeyServerName_HashData, cKEYSERVERNAME_TABLESIZE);
91 m_lkServerAddr = m_lServers->CreateKey ("Server Primary Address", CELL::KeyServerAddr_Compare, CELL::KeyServerAddr_HashObject, CELL::KeyServerAddr_HashData, cKEYSERVERADDR_TABLESIZE);
93 m_fUsersOutOfDate = TRUE;
94 m_lUsers = New (HASHLIST);
95 m_lUsers->SetCriticalSection (AfsClass_GetCriticalSection());
96 m_lkUserName = m_lUsers->CreateKey ("User Name", CELL::KeyUserName_Compare, CELL::KeyUserName_HashObject, CELL::KeyUserName_HashData);
97 m_lGroups = New (HASHLIST);
98 m_lGroups->SetCriticalSection (AfsClass_GetCriticalSection());
99 m_lkGroupName = m_lGroups->CreateKey ("Group Name", CELL::KeyGroupName_Compare, CELL::KeyGroupName_HashObject, CELL::KeyGroupName_HashData);
111 m_lpiThis->m_cRef --;
116 void CELL::FreeServers (BOOL fNotify)
118 for (LPENUM pEnum = m_lServers->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
120 LPSERVER lpServer = (LPSERVER)(pEnum->GetObject());
122 lpServer->SendDeleteNotifications();
123 m_lServers->Remove (lpServer);
128 for (size_t ii = 0; m_apszServers[ii]; ++ii)
129 FreeString (m_apszServers[ii]);
130 Free (m_apszServers);
131 m_apszServers = NULL;
136 void CELL::FreeUsers (BOOL fNotify)
138 for (LPENUM pEnum = m_lGroups->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
140 LPPTSGROUP lpGroup = (LPPTSGROUP)(pEnum->GetObject());
142 lpGroup->SendDeleteNotifications();
143 m_lGroups->Remove (lpGroup);
147 for (pEnum = m_lUsers->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
149 LPUSER lpUser = (LPUSER)(pEnum->GetObject());
151 lpUser->SendDeleteNotifications();
152 m_lUsers->Remove (lpUser);
159 * CELL-LIST MANAGEMENT _______________________________________________________
163 void CELL::Close (void)
169 BOOL CELL::GetDefaultCell (LPTSTR pszName, ULONG *pStatus)
172 wp.wpClientLocalCellGet.pszCell = pszName;
173 return Worker_DoTask (wtaskClientLocalCellGet, &wp, pStatus);
177 LPIDENT CELL::OpenCell (LPTSTR pszCell, PVOID hCreds, ULONG *pStatus)
179 LPIDENT lpiCell = NULL;
184 if ((lpCell = ReopenCell (pszCell, pStatus)) != NULL)
186 lpiCell = lpCell->GetIdentifier();
190 else // cell hasn't been opened before? see if we can reach the cell.
192 lpCell = New2 (CELL,(pszCell, hCreds));
193 if ((lpCell->m_hCell = lpCell->GetCellObject (pStatus)) == NULL)
197 lpiCell = lpCell->GetIdentifier();
199 x_lCells->Add (lpCell);
200 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpiCell);
209 void CELL::CloseCell (LPIDENT lpiCell)
212 if ((lpCell = lpiCell->OpenCell()) != NULL)
214 if (lpCell->m_nReqs > 1)
221 NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, lpiCell);
222 lpCell->CloseKasObject();
223 lpCell->CloseCellObject();
225 x_lCells->Remove (lpCell);
232 LPCELL CELL::ReopenCell (LPTSTR pszCell, ULONG *pStatus)
234 LPCELL lpCell = NULL;
238 // Ordinarily we'd place a key on the cell name within the list of
239 // cells--however, the most likely case only has one cell anyway.
240 // So why expend the memory?
242 for (LPENUM pEnum = x_lCells->FindFirst(); pEnum; pEnum = pEnum->FindNext())
244 LPCELL lpCellFound = (LPCELL)( pEnum->GetObject() );
246 if (!lstrcmpi (lpCellFound->m_szName, pszCell))
248 lpCell = lpCellFound;
258 *pStatus = ERROR_FILE_NOT_FOUND;
261 // AfsClass_Leave() has been called only if no cell was opened in the search.
266 PVOID CELL::GetCurrentCredentials (void)
272 void CELL::SetCurrentCredentials (PVOID hCreds)
283 * SERVER-LIST MANAGEMENT _____________________________________________________
287 LPSERVER CELL::OpenServer (LPTSTR pszName, ULONG *pStatus)
289 if (!RefreshServers (TRUE, pStatus))
293 if ((lpServer = (LPSERVER)(m_lkServerName->GetFirstObject (pszName))) != NULL)
300 LPSERVER CELL::OpenServer (LPSOCKADDR_IN pAddr, ULONG *pStatus)
302 if (!RefreshServers (TRUE, pStatus))
305 // We'll try to use our lookup key first--since most machines only
306 // have one IP address anyway, our hashtable should make this lookup
307 // super fast. If it misses (i.e., if the server is multi-homed and
308 // for some reason VLDB refers to it by the second address), we'll
309 // have to do a brute-force search across each server in the cell.
310 // Again, we could have a better-designed lookup table here--but
311 // since multi-homing is the exception (by a vast majority), it's not
312 // worth the extra effort and memory. This technique is fast enough.
315 if ((lpServer = (LPSERVER)(m_lkServerAddr->GetFirstObject (pAddr))) != NULL)
317 AfsClass_Enter(); // Aren't HashLists great? We found the server.
319 else // Try brute-force search
322 for (lpServer = ServerFindFirst (&hEnum, TRUE, pStatus); lpServer; lpServer = ServerFindNext (&hEnum))
325 if (lpServer->GetStatus (&ss, TRUE, pStatus))
327 for (size_t iAddr = 0; iAddr < ss.nAddresses; ++iAddr)
329 if (!memcmp (&ss.aAddresses[ iAddr ], pAddr, sizeof(SOCKADDR_IN)))
331 // don't close server! we're going to return this pointer.
338 ServerFindClose (&hEnum);
344 LPSERVER CELL::ServerFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
346 return ServerFindFirst (phEnum, NULL, fNotify, pStatus);
350 LPSERVER CELL::ServerFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
352 LPSERVER lpServer = NULL;
354 if (!RefreshServers (fNotify, pStatus))
359 lpServer = lpiFind->OpenServer();
362 else if ((*phEnum = m_lServers->FindFirst()) != NULL)
364 lpServer = (LPSERVER)( (*phEnum)->GetObject() );
368 if (!lpServer && pStatus)
369 *pStatus = ERROR_FILE_NOT_FOUND;
374 LPSERVER CELL::ServerFindNext (HENUM *phEnum)
376 LPSERVER lpServer = NULL;
380 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
382 lpServer = (LPSERVER)( (*phEnum)->GetObject() );
391 void CELL::ServerFindClose (HENUM *phEnum)
401 BOOL CELL::RefreshServers (BOOL fNotify, ULONG *pStatus)
403 if (!m_fServersOutOfDate)
406 return RefreshServerList (fNotify, pStatus);
410 BOOL CELL::RefreshServerList (BOOL fNotify, ULONG *pStatus)
414 BOOL fNotified = FALSE;
416 if (fNotify && m_fServersOutOfDate)
418 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersBegin, GetIdentifier());
422 BOOL fReplaceList = m_fServersOutOfDate;
423 m_fServersOutOfDate = FALSE;
425 // Ordinarily we'd just clear the list of servers and
426 // requery it from scratch; however, servers are an exception
427 // to that technique: occasionally we may get a request to
428 // just look for servers that have appeared or disappeared,
429 // without refreshing data for other servers. Thus the revised
432 // 1- if fReplaceList, empty the list of servers.
433 // otherwise, set each server's fDelete flag.
435 // 2- enumerate the servers in the cell: for each server,
436 // if fReplaceList, add the server to the list
437 // otherwise, if the server is in the list, clear its fDelete
439 // 3- if !fReplaceList, enumerate the list of servers: for each server,
440 // if the server's fDelete flag is set, remove the server
442 for (LPENUM pEnum = m_lServers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
444 LPSERVER lpServer = (LPSERVER)(pEnum->GetObject());
448 lpServer->SendDeleteNotifications();
449 m_lServers->Remove (lpServer);
452 else // the list of servers isn't invalidated, so just mark fDelete
454 lpServer->m_fDelete = TRUE;
458 // Enumerate the servers in the cell.
461 if ((hCell = GetCellObject (&status)) == NULL)
469 WORKERPACKET wpBegin;
470 wpBegin.wpClientAFSServerGetBegin.hCell = hCell;
472 if (!Worker_DoTask (wtaskClientAFSServerGetBegin, &wpBegin, &status))
481 wpNext.wpClientAFSServerGetNext.hEnum = wpBegin.wpClientAFSServerGetBegin.hEnum;
482 if (!Worker_DoTask (wtaskClientAFSServerGetNext, &wpNext, &status))
484 if (status == ADMITERATORDONE)
491 afs_serverEntry_p pEntry = &wpNext.wpClientAFSServerGetNext.Entry;
493 TCHAR szServer[ cchNAME ];
494 CopyAnsiToString (szServer, pEntry->serverName);
497 int addrNetwork = htonl (pEntry->serverAddress[0]);
498 lstrcpy (szServer, inet_ntoa (*(struct in_addr *)&addrNetwork));
501 // The server identified by {pEntry} is in the cell. Now if we're
502 // building a list of SERVER objects from scratch, we can just
503 // add it--but if we're only touching up an existing list,
504 // first make sure there isn't such an animal in there now.
506 BOOL fNotifyAboutThisServer = FALSE;
508 LPSERVER lpServer = NULL;
511 if ((lpServer = (LPSERVER)(m_lkServerName->GetFirstObject (szServer))) != NULL)
512 lpServer->m_fDelete = FALSE;
515 if (lpServer == NULL)
517 // Okay, it's a new server. Create a SERVER object for it and
518 // add it to the list.
520 lpServer = New2 (SERVER,(this, szServer));
521 lpServer->m_wGhost |= GHOST_HAS_SERVER_ENTRY;
522 m_lServers->Add (lpServer);
523 fNotifyAboutThisServer = TRUE;
526 // Update the server's IP addresses
528 lpServer->m_ss.nAddresses = 0;
530 for (size_t iAddr = 0; iAddr < AFS_MAX_SERVER_ADDRESS; ++iAddr)
532 if (pEntry->serverAddress[ iAddr ] == 0)
534 AfsClass_IntToAddress (&lpServer->m_ss.aAddresses[ lpServer->m_ss.nAddresses++ ], pEntry->serverAddress[ iAddr ]);
537 m_lServers->Update (lpServer); // That update affected a hashlistkey
539 // Tell our clients that we've found a server
541 if (fNotify && fNotifyAboutThisServer)
545 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersBegin, GetIdentifier());
548 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpServer->GetIdentifier());
553 wpDone.wpClientAFSServerGetDone.hEnum = wpBegin.wpClientAFSServerGetBegin.hEnum;
554 Worker_DoTask (wtaskClientAFSServerGetDone, &wpDone);
558 // Finally, look through our list of servers: if any have fDelete set,
559 // then we didn't find them in the cell any longer. Remove those servers.
563 for (LPENUM pEnum = m_lServers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
565 LPSERVER lpServer = (LPSERVER)(pEnum->GetObject());
566 if (lpServer->m_fDelete)
568 if (fNotify && !fNotified)
570 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersBegin, GetIdentifier());
573 lpServer->SendDeleteNotifications();
574 m_lServers->Remove (lpServer);
580 // Fix m_apszServers if we did anything to the list of servers
586 for (size_t ii = 0; m_apszServers[ii]; ++ii)
587 FreeString (m_apszServers[ii]);
588 Free (m_apszServers);
589 m_apszServers = NULL;
593 for (LPENUM pEnum = m_lServers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
598 m_apszServers = (char**)Allocate (sizeof(char*) * (1+cServers));
599 memset (m_apszServers, 0x00, sizeof(char*) * (1+cServers));
602 for (pEnum = m_lServers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
604 LPSERVER lpServer = (LPSERVER)(pEnum->GetObject());
605 m_apszServers[ iServer ] = AllocateAnsi (cchNAME+1);
606 CopyStringToAnsi (m_apszServers[ iServer ], lpServer->m_szName);
613 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersEnd, GetIdentifier(), ((rc) ? 0 : status));
622 * SERVER-LIST KEYS ___________________________________________________________
626 BOOL CALLBACK CELL::KeyServerName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
628 if (!lstrcmp (((LPSERVER)pObject)->m_szName, (LPTSTR)pData))
631 TCHAR szShortName[ cchNAME ];
632 SERVER::ShortenName (szShortName, ((LPSERVER)pObject)->m_szName);
633 if (!lstrcmp (szShortName, (LPTSTR)pData))
639 HASHVALUE CALLBACK CELL::KeyServerName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
641 return CELL::KeyServerName_HashData (pKey, ((LPSERVER)pObject)->m_szName);
644 HASHVALUE CALLBACK CELL::KeyServerName_HashData (LPHASHLISTKEY pKey, PVOID pData)
646 TCHAR szShortName[ cchNAME ];
647 SERVER::ShortenName (szShortName, (LPTSTR)pData);
648 return HashString (szShortName);
652 BOOL CALLBACK CELL::KeyServerAddr_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
654 return !memcmp (&((LPSERVER)pObject)->m_ss.aAddresses[0], (LPSOCKADDR)pData, sizeof(SOCKADDR_IN));
657 HASHVALUE CALLBACK CELL::KeyServerAddr_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
659 return CELL::KeyServerAddr_HashData (pKey, &((LPSERVER)pObject)->m_ss.aAddresses[0]);
662 HASHVALUE CALLBACK CELL::KeyServerAddr_HashData (LPHASHLISTKEY pKey, PVOID pData)
664 return *(DWORD*)pData;
668 BOOL CALLBACK CELL::KeyUserName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
670 return !lstrcmpi (((LPUSER)pObject)->m_szPrincipal, (LPTSTR)pData);
673 HASHVALUE CALLBACK CELL::KeyUserName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
675 return CELL::KeyUserName_HashData (pKey, ((LPUSER)pObject)->m_szPrincipal);
678 HASHVALUE CALLBACK CELL::KeyUserName_HashData (LPHASHLISTKEY pKey, PVOID pData)
680 return HashString ((LPTSTR)pData);
684 BOOL CALLBACK CELL::KeyGroupName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
686 return !lstrcmpi (((LPPTSGROUP)pObject)->m_szName, (LPTSTR)pData);
689 HASHVALUE CALLBACK CELL::KeyGroupName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
691 return CELL::KeyGroupName_HashData (pKey, ((LPPTSGROUP)pObject)->m_szName);
694 HASHVALUE CALLBACK CELL::KeyGroupName_HashData (LPHASHLISTKEY pKey, PVOID pData)
696 return HashString ((LPTSTR)pData);
701 * CELL OBJECT ________________________________________________________________
705 PVOID CELL::GetCellObject (ULONG *pStatus)
710 NOTIFYCALLBACK::SendNotificationToAll (evtOpenCellBegin, m_szName);
713 wpOpen.wpClientCellOpen.pszCell = m_szName;
714 wpOpen.wpClientCellOpen.hCreds = m_hCreds;
716 if (Worker_DoTask (wtaskClientCellOpen, &wpOpen, &status))
717 m_hCell = wpOpen.wpClientCellOpen.hCell;
721 NOTIFYCALLBACK::SendNotificationToAll (evtOpenCellEnd, m_szName, status);
728 BOOL CELL::CloseCellObject (ULONG *pStatus)
735 wp.wpClientCellClose.hCell = m_hCell;
736 rc = Worker_DoTask (wtaskClientCellClose, &wp, pStatus);
744 PVOID CELL::GetKasObject (ULONG *pStatus)
746 // m_hKas is actually never set non-NULL;
747 // leaving it NULL indicates we will work happily with *any* server.
753 BOOL CELL::CloseKasObject (ULONG *pStatus)
760 wp.wpKasServerClose.hServer = m_hKas;
761 rc = Worker_DoTask (wtaskKasServerClose, &wp, pStatus);
770 * CELL GENERAL _______________________________________________________________
774 LPIDENT CELL::GetIdentifier (void)
776 if (m_lpiThis == NULL)
778 if ((m_lpiThis = IDENT::FindIdent (this)) == NULL)
779 m_lpiThis = New2 (IDENT,(this));
780 m_lpiThis->m_cRef ++;
787 void CELL::GetName (LPTSTR pszName)
789 lstrcpy (pszName, m_szName);
793 PVOID CELL::GetUserParam (void)
795 return GetIdentifier()->GetUserParam();
799 void CELL::SetUserParam (PVOID pUserNew)
801 GetIdentifier()->SetUserParam (pUserNew);
805 BOOL CELL::fAnyServersUnmonitored (void)
807 return (m_nServersUnmonitored > 0) ? TRUE : FALSE;
812 * CELL STATUS ________________________________________________________________
816 void CELL::Invalidate (void)
818 if (!m_fServersOutOfDate || !m_fStatusOutOfDate || !m_fVLDBOutOfDate || !m_fUsersOutOfDate)
822 m_fServersOutOfDate = TRUE;
823 m_fStatusOutOfDate = TRUE;
824 m_fVLDBOutOfDate = TRUE;
825 m_fUsersOutOfDate = TRUE;
826 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
831 void CELL::InvalidateServers (void)
833 if (!m_fServersOutOfDate || !m_fVLDBOutOfDate)
837 m_fServersOutOfDate = TRUE;
838 m_fVLDBOutOfDate = TRUE;
839 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
844 void CELL::InvalidateUsers (void)
846 if (!m_fUsersOutOfDate)
848 m_fUsersOutOfDate = TRUE;
849 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
854 BOOL CELL::RefreshStatus (BOOL fNotify, ULONG *pStatus)
859 if (m_fStatusOutOfDate)
862 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
864 // Hmmm...well, actually, there's nothing for us to do here. I'm
865 // leaving this around, because the refreshed-cell-status notification
866 // may be useful as an appropriate hooking point.
871 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
880 BOOL CELL::RefreshVLDB (BOOL fNotify, ULONG *pStatus)
884 if (m_fVLDBOutOfDate)
886 if ((rc = RefreshVLDB (GetIdentifier(), fNotify, pStatus)) == TRUE)
888 m_fVLDBOutOfDate = FALSE;
896 BOOL CELL::RefreshVLDB (LPIDENT lpiRef, BOOL fNotify, ULONG *pStatus, BOOL fAnythingRelatedToThisRWFileset)
901 // What is the scope of this refresh operation? The entire cell,
902 // or the filesets on a particular server or aggregate?
904 LPIDENT lpiRefCell = (lpiRef == NULL) ? GetIdentifier() : lpiRef->GetCell();
905 LPIDENT lpiRefServer = NULL;
906 LPIDENT lpiRefAggregate = NULL;
907 LPIDENT lpiRefFileset = NULL;
908 VOLUMEID *pvidRefFileset = NULL;
909 VOLUMEID vidRefFileset;
911 if (fAnythingRelatedToThisRWFileset)
913 pvidRefFileset = &vidRefFileset;
914 lpiRef->GetFilesetID (pvidRefFileset);
918 if (lpiRef && !lpiRef->fIsCell())
920 lpiRefServer = lpiRef->GetServer();
922 if (lpiRef && (lpiRef->fIsAggregate() || lpiRef->fIsFileset()))
924 lpiRefAggregate = lpiRef->GetAggregate();
926 if (lpiRef && lpiRef->fIsFileset())
928 lpiRefFileset = lpiRef;
932 // If we've been told to update only one server, aggregate or
933 // fileset, find out which IP addresses correspond with that
934 // server. We'll need this for comparisons later.
936 SERVERSTATUS ssRefServer;
937 if (rc && lpiRefServer)
940 if ((lpServer = lpiRefServer->OpenServer (&status)) == NULL)
944 rc = lpServer->GetStatus (&ssRefServer, fNotify, &status);
949 // Likewise, if we've been told to update only one aggregate,
950 // find that aggregate's ID. We'll need it for comparisons later.
952 AGGREGATESTATUS asRefAggregate;
953 int idPartition = NO_PARTITION;
954 if (rc && lpiRefAggregate)
956 LPAGGREGATE lpAggregate;
957 if ((lpAggregate = lpiRefAggregate->OpenAggregate (&status)) == NULL)
961 idPartition = lpAggregate->GetID();
962 rc = lpAggregate->GetStatus (&asRefAggregate, fNotify, &status);
963 lpAggregate->Close();
967 // Zip through the current list of objects that we're about to refresh.
968 // On each such object, remove the GHOST_HAS_VLDB_ENTRY flag,
969 // and delete objects entirely if that's the only ghost flag they have.
970 // (e.g., If we went through this routine earlier and created a ghost
971 // aggregate because VLDB referenced it and we couldn't find mention
972 // of it on the server, delete that aggregate. We'll recreate it here
973 // if necessary; otherwise, it needs to be gone.)
977 RefreshVLDB_RemoveReferences (lpiRefServer, lpiRefAggregate, lpiRefFileset, pvidRefFileset);
980 // We'll get a new list of filesets from VLDB, and to do that, we'll
981 // need the cell's object. If we're enumerating a specific server, we'll
982 // also need that server's object. Finally, if we're enumerating a
983 // specific aggregate, we'll also need that aggregate's name.
986 PVOID hServer = NULL;
992 if ((hCell = GetCellObject (&status)) == NULL)
995 else // get cell and server handles
998 if ((lpServer = lpiRefServer->OpenServer()) == NULL)
1002 if ((hServer = lpServer->OpenVosObject (&hCell, &status)) == NULL)
1009 // Go get that list of filesets, and use it to update our knowledge
1010 // of the cell. Remember that, if {pvidRefFileset}, we only want
1018 wpGet.wpVosVLDBGet.hCell = hCell;
1019 wpGet.wpVosVLDBGet.idVolume = *pvidRefFileset;
1021 if (!Worker_DoTask (wtaskVosVLDBGet, &wpGet, &status))
1024 RefreshVLDB_OneEntry (&wpGet.wpVosVLDBGet.Data, lpiRefServer, &ssRefServer, lpiRefAggregate, &asRefAggregate, lpiRefFileset, pvidRefFileset, fNotify);
1028 WORKERPACKET wpBegin;
1029 wpBegin.wpVosVLDBGetBegin.hCell = hCell;
1030 wpBegin.wpVosVLDBGetBegin.hServer = hServer;
1031 wpBegin.wpVosVLDBGetBegin.idPartition = idPartition;
1033 if (!Worker_DoTask (wtaskVosVLDBGetBegin, &wpBegin, &status))
1039 WORKERPACKET wpNext;
1040 wpNext.wpVosVLDBGetNext.hEnum = wpBegin.wpVosVLDBGetBegin.hEnum;
1041 if (!Worker_DoTask (wtaskVosVLDBGetNext, &wpNext, &status))
1043 if (status == ADMITERATORDONE)
1050 RefreshVLDB_OneEntry (&wpNext.wpVosVLDBGetNext.Data, lpiRefServer, &ssRefServer, lpiRefAggregate, &asRefAggregate, lpiRefFileset, pvidRefFileset, fNotify);
1053 WORKERPACKET wpDone;
1054 wpDone.wpVosVLDBGetDone.hEnum = wpBegin.wpVosVLDBGetBegin.hEnum;
1055 Worker_DoTask (wtaskVosVLDBGetDone, &wpDone);
1060 // We've finished the update. If we were asked to send notifications
1061 // about our progress, do so.
1065 LPIDENT lpiNotify = (lpiRef) ? lpiRef : GetIdentifier();
1067 if (!lpiNotify->fIsFileset())
1069 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshFilesetsBegin, lpiNotify);
1070 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshFilesetsEnd, lpiNotify, status);
1073 if (lpiNotify->fIsCell() || lpiNotify->fIsServer())
1075 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesBegin, lpiNotify);
1076 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesEnd, lpiNotify, status);
1083 if ((lpServer = lpiRefServer->OpenServer()) != NULL)
1085 lpServer->CloseVosObject();
1096 void CELL::RefreshVLDB_RemoveReferences (LPIDENT lpiRefServer, LPIDENT lpiRefAggregate, LPIDENT lpiRefFileset, LPVOLUMEID pvidRefFileset)
1098 // Zip through the current list of objects that we're about to refresh.
1099 // On each such object, remove the GHOST_HAS_VLDB_ENTRY flag,
1100 // and delete objects entirely if that's the only ghost flag they have.
1101 // (e.g., If we went through this routine earlier and created a ghost
1102 // aggregate because VLDB referenced it and we couldn't find mention
1103 // of it on the server, delete that aggregate. We'll recreate it here
1104 // if necessary; otherwise, it needs to be gone.)
1106 // Note that by specifying {lpiRefServer} to start the enumeration,
1107 // we'll either enumerate only lpiRefServer, or all servers if it's NULL.
1110 for (LPSERVER lpServer = ServerFindFirst (&heServer, lpiRefServer); lpServer; lpServer = ServerFindNext (&heServer))
1113 if (!pvidRefFileset)
1115 // Since we're about to check VLDB for references to this server,
1116 // remove the GHOST_HAS_VLDB_ENTRY flag from its SERVER object.
1117 // If that's the only thing keeping the object around, remove the
1120 if ((lpServer->m_wGhost &= (~GHOST_HAS_VLDB_ENTRY)) == 0)
1123 lpServer->SendDeleteNotifications();
1124 m_lServers->Remove (lpServer);
1130 // Check each of the server's aggregates, and deal with them the same
1134 for (LPAGGREGATE lpAggregate = lpServer->AggregateFindFirst (&heAggregate, lpiRefAggregate); lpAggregate; lpAggregate = lpServer->AggregateFindNext (&heAggregate))
1137 if (!pvidRefFileset)
1139 // Since we're about to check VLDB for references to this aggregate,
1140 // remove the GHOST_HAS_VLDB_ENTRY flag from its AGGREGATE object.
1141 // If that's the only thing keeping the object around, remove the
1144 if ((lpAggregate->m_wGhost &= (~GHOST_HAS_VLDB_ENTRY)) == 0)
1146 lpAggregate->Close();
1147 lpAggregate->SendDeleteNotifications();
1148 lpServer->m_lAggregates->Remove (lpAggregate);
1149 Delete (lpAggregate);
1154 // Check each of the aggregate's filesets, and deal with them the same
1158 for (LPFILESET lpFileset = lpAggregate->FilesetFindFirst (&heFileset, lpiRefFileset); lpFileset; lpFileset = lpAggregate->FilesetFindNext (&heFileset))
1160 if ((!pvidRefFileset) || (*pvidRefFileset == lpFileset->m_fs.idReadWrite))
1162 // Since we're about to check VLDB for references to this fileset,
1163 // remove the GHOST_HAS_VLDB_ENTRY flag from its FILESET object.
1164 // If that's the only thing keeping the object around, remove the
1167 if ((lpFileset->m_wGhost &= (~GHOST_HAS_VLDB_ENTRY)) == 0)
1170 lpFileset->SendDeleteNotifications();
1171 lpAggregate->m_lFilesets->Remove (lpFileset);
1180 lpAggregate->Close();
1188 void CELL::RefreshVLDB_OneEntry (PVOID pp, LPIDENT lpiRefServer, LPSERVERSTATUS pssRefServer, LPIDENT lpiRefAggregate, LPAGGREGATESTATUS pasRefAggregate, LPIDENT lpiRefFileset, LPVOLUMEID pvidRefFileset, BOOL fNotify)
1190 vos_vldbEntry_p pEntry = (vos_vldbEntry_p)pp;
1192 // If we were asked to update all the replicas of a particular
1193 // fileset, then we set {pvidRefFileset} above to that fileset's
1194 // ID. Check this VLDB entry to see if it refers to that fileset;
1195 // if not, we're not interested in it.
1199 if (memcmp (&pEntry->volumeId[ VOS_READ_WRITE_VOLUME ], pvidRefFileset, sizeof(VOLUMEID)))
1203 for (int iRepSite = 0; iRepSite < pEntry->numServers; ++iRepSite)
1205 SOCKADDR_IN RepSiteAddr;
1206 AfsClass_IntToAddress (&RepSiteAddr, pEntry->volumeSites[ iRepSite ].serverAddress);
1208 // Every fileset replication site which VLDB knows about
1209 // passes through this point, within {pEntry->volumeSites[ iRepSite ]}.
1211 // Are we going to be refreshing the server/aggregate on which
1212 // this repsite lives? If not, there's no need to process this
1213 // entry any further.
1217 BOOL fFilesetLivesOnThisServer = FALSE;
1219 for (size_t iAddress = 0; !fFilesetLivesOnThisServer && (iAddress < pssRefServer->nAddresses); ++iAddress)
1221 if (!memcmp (&pssRefServer->aAddresses[ iAddress ], &RepSiteAddr, sizeof(SOCKADDR_IN)))
1223 if (lpiRefAggregate)
1225 if (pasRefAggregate->dwID != (DWORD)(pEntry->volumeSites[ iRepSite ].serverPartition))
1228 fFilesetLivesOnThisServer = TRUE;
1232 if (!fFilesetLivesOnThisServer)
1236 // Do we know about the server mentioned by this replication
1240 if (lpiRefServer != NULL)
1241 lpServer = lpiRefServer->OpenServer();
1243 lpServer = OpenServer (&RepSiteAddr);
1245 // If we found the server but aren't monitoring it,
1246 // forget about this fileset.
1248 if (lpServer && !lpServer->fIsMonitored())
1255 // If we have no record of the server mentioned by this
1256 // replication site, we have to create a SERVER entry for
1257 // it before we can proceed. The server will appear as
1262 if (lpiRefAggregate || pvidRefFileset)
1265 LPTSTR pszServer = FormatString (TEXT("%1"), TEXT("%a"), &pEntry->volumeSites[ iRepSite ].serverAddress);
1266 lpServer = New2 (SERVER,(this, pszServer));
1268 FreeString (pszServer);
1270 lpServer->m_fStatusOutOfDate = FALSE;
1271 lpServer->m_ss.nAddresses = 1;
1272 memcpy (&lpServer->m_ss.aAddresses[0], &RepSiteAddr, sizeof(SOCKADDR_IN));
1274 m_lServers->Add (lpServer);
1277 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpServer->GetIdentifier());
1280 lpServer->m_wGhost |= GHOST_HAS_VLDB_ENTRY;
1282 // Great--we now have a replication site for a particular
1283 // fileset known to VLDB, and a pointer to the server
1284 // on which it resides. Does that server contain the
1285 // aggregate which VLDB expects to find?
1287 LPAGGREGATE lpAggregate;
1288 if (lpiRefAggregate != NULL)
1289 lpAggregate = lpiRefAggregate->OpenAggregate();
1291 lpAggregate = lpServer->OpenAggregate (pEntry->volumeSites[ iRepSite ].serverPartition);
1293 // If the server has no record of the aggregate mentioned
1294 // by this replication site, we have to create an
1295 // AGGREGATE entry for it before we can proceed. The
1296 // aggregate will appear as a "ghost". Note that we
1297 // can't update the list of aggregates on a server if
1298 // we've been asked to update a particular fileset,
1299 // because someone clearly has a pointer to the list.
1303 if (lpiRefFileset || pvidRefFileset)
1310 // Even if the partition doesn't exist, we can still figger out
1311 // its name given its ID--'cause there's a 1:1 mapping between
1312 // allowed IDs and allowed partition names. I guess there's
1313 // something to be said for forcing partitions to be named "vicep*"
1315 TCHAR szPartition[ cchNAME ];
1317 wp.wpVosPartitionIdToName.idPartition = pEntry->volumeSites[ iRepSite ].serverPartition;
1318 wp.wpVosPartitionIdToName.pszPartition = szPartition;
1319 if (!Worker_DoTask (wtaskVosPartitionIdToName, &wp))
1320 wsprintf (szPartition, TEXT("#%lu"), pEntry->volumeSites[ iRepSite ].serverPartition);
1322 lpAggregate = New2 (AGGREGATE,(lpServer, szPartition, TEXT("")));
1325 lpAggregate->m_fStatusOutOfDate = FALSE;
1326 lpAggregate->m_as.dwID = pEntry->volumeSites[ iRepSite ].serverPartition;
1327 lpAggregate->m_as.ckStorageTotal = 0;
1328 lpAggregate->m_as.ckStorageFree = 0;
1330 lpServer->m_lAggregates->Add (lpAggregate);
1333 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpAggregate->GetIdentifier());
1336 lpAggregate->m_wGhost |= GHOST_HAS_VLDB_ENTRY;
1338 // Great--we now have a replication site for a particular
1339 // fileset known to VLDB, and a pointer to the server
1340 // and aggregate on which it resides. Does that aggregate
1341 // contain the fileset which VLDB expects to find?
1343 // Remember that each iRepSite can represent up to three
1344 // filesets on that aggregate--a RW, a RO, and a BAK.
1346 for (size_t iType = 0; iType < 3; ++iType)
1349 // Does this repsite entry mention having this type
1350 // of fileset on this aggregate?
1352 if ((vos_volumeType_t)iType == VOS_READ_WRITE_VOLUME)
1354 if (!((DWORD)pEntry->volumeSites[ iRepSite ].serverFlags & (DWORD)VOS_VLDB_READ_WRITE))
1357 else if ((vos_volumeType_t)iType == VOS_READ_ONLY_VOLUME)
1359 if (!((DWORD)pEntry->volumeSites[ iRepSite ].serverFlags & (DWORD)VOS_VLDB_READ_ONLY))
1362 else if ((vos_volumeType_t)iType == VOS_BACKUP_VOLUME)
1364 if (!((DWORD)pEntry->status & (DWORD)VOS_VLDB_ENTRY_BACKEXISTS))
1367 // Only look for the backup where the R/W exists
1368 if (!((DWORD)pEntry->volumeSites[ iRepSite ].serverFlags & (DWORD)VOS_VLDB_READ_WRITE))
1372 LPFILESET lpFileset = lpAggregate->OpenFileset ((LPVOLUMEID)&pEntry->volumeId[ iType ]);
1374 // If the aggregate has no record of the fileset mentioned
1375 // by this VLDB entry, we have to create a FILESET entry
1376 // for it. The fileset will appear as a "ghost".
1380 TCHAR szFilesetName[ cchNAME ];
1381 CopyAnsiToString (szFilesetName, pEntry->name);
1382 if ((vos_volumeType_t)iType == VOS_READ_ONLY_VOLUME)
1383 lstrcat (szFilesetName, TEXT(".readonly"));
1384 else if ((vos_volumeType_t)iType == VOS_BACKUP_VOLUME)
1385 lstrcat (szFilesetName, TEXT(".backup"));
1387 lpFileset = New2 (FILESET,(lpAggregate, &pEntry->volumeId[ iType ], szFilesetName));
1390 lpFileset->m_fs.id = pEntry->volumeId[ iType ];
1391 lpFileset->m_fs.idReadWrite = pEntry->volumeId[ VOS_READ_WRITE_VOLUME ];
1392 lpFileset->m_fs.idReplica = pEntry->volumeId[ VOS_READ_ONLY_VOLUME ];
1393 AfsClass_UnixTimeToSystemTime (&lpFileset->m_fs.timeCreation, 0);
1394 AfsClass_UnixTimeToSystemTime (&lpFileset->m_fs.timeLastUpdate, 0);
1395 AfsClass_UnixTimeToSystemTime (&lpFileset->m_fs.timeLastAccess, 0);
1396 AfsClass_UnixTimeToSystemTime (&lpFileset->m_fs.timeLastBackup, 0);
1397 AfsClass_UnixTimeToSystemTime (&lpFileset->m_fs.timeCopyCreation, 0);
1398 lpFileset->m_fs.nFiles = 0;
1399 lpFileset->m_fs.ckQuota = 0;
1400 lpFileset->m_fs.ckUsed = 0;
1401 lpFileset->m_fs.Type = (iType == 0) ? ftREADWRITE : (iType == 1) ? ftREPLICA : ftCLONE;
1402 lpFileset->m_fs.State = fsNORMAL;
1404 lpAggregate->m_lFilesets->Add (lpFileset);
1407 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpFileset->GetIdentifier());
1411 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, lpFileset->GetIdentifier());
1413 lpFileset->m_wGhost |= GHOST_HAS_VLDB_ENTRY;
1414 lpFileset->m_fStatusOutOfDate = FALSE;
1415 lpFileset->m_fs.idClone = pEntry->cloneId;
1416 lpFileset->m_fs.State &= ~fsMASK_VLDB;
1418 if (pEntry->status & VOS_VLDB_ENTRY_LOCKED)
1419 lpFileset->m_fs.State |= fsLOCKED;
1424 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, lpFileset->GetIdentifier(), 0);
1427 if (lpServer && lpAggregate)
1429 lpAggregate->InvalidateAllocation();
1430 lpAggregate->Close();
1442 BOOL CELL::RefreshAll (ULONG *pStatus)
1447 BOOL fNotified = FALSE;
1449 if (m_fServersOutOfDate && (dwWant & AFSCLASS_WANT_VOLUMES))
1454 if ((++cRefreshAllReq) == 1)
1456 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin, GetIdentifier());
1460 size_t nServersToRefresh = 0;
1463 for (LPSERVER lpServer = ServerFindFirst (&hEnum); lpServer; lpServer = ServerFindNext (&hEnum))
1465 if (lpServer->fIsMonitored())
1466 ++nServersToRefresh;
1470 if (nServersToRefresh)
1473 for (LPSERVER lpServer = ServerFindFirst (&hEnum); lpServer; lpServer = ServerFindNext (&hEnum))
1475 if (lpServer->fIsMonitored())
1477 ULONG perComplete = (ULONG)iServer * 100L / nServersToRefresh;
1478 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpServer->GetIdentifier(), NULL, NULL, NULL, perComplete, 0);
1480 // intentionally ignore errors in refreshing individual
1481 // servers--we only want to return an error code if
1482 // we couldn't refresh the *cell*.
1484 (void)lpServer->RefreshAll (NULL, ((double)iServer / (double)nServersToRefresh), (1.0 / (double)nServersToRefresh));
1490 rc = RefreshVLDB (NULL, TRUE, &status);
1494 if (rc && m_fUsersOutOfDate && (dwWant & AFSCLASS_WANT_USERS))
1499 if ((++cRefreshAllReq) == 1)
1501 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin, GetIdentifier(), NULL, NULL, NULL, 0, 0);
1505 rc = RefreshUsers (TRUE, &status);
1510 if ((--cRefreshAllReq) == 0)
1512 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllEnd, GetIdentifier(), NULL, NULL, NULL, 100, status);
1523 * USER/GROUP-LIST MANAGEMENT _________________________________________________
1527 LPUSER CELL::OpenUser (LPTSTR pszName, LPTSTR pszInstance, ULONG *pStatus)
1531 // First off, do we have a USER object for this guy already?
1533 LPUSER lpUser = NULL;
1534 for (LPENUM pEnum = m_lkUserName->FindFirst (pszName); pEnum; pEnum = pEnum->FindNext())
1536 LPUSER lpTest = (LPUSER)( pEnum->GetObject() );
1537 if (!pszInstance || !lstrcmpi (lpTest->m_szInstance, pszInstance))
1546 // If not, see if we can create one...
1550 // See if there's a KAS or PTS entry for this user.
1552 BOOL fHasKAS = FALSE;
1553 BOOL fHasPTS = FALSE;
1556 wp.wpKasPrincipalGet.hCell = GetCellObject (&status);
1557 wp.wpKasPrincipalGet.hServer = GetKasObject (&status);
1558 wp.wpKasPrincipalGet.pszPrincipal = pszName;
1559 wp.wpKasPrincipalGet.pszInstance = pszInstance;
1560 if (Worker_DoTask (wtaskKasPrincipalGet, &wp, &status))
1565 TCHAR szFullName[ cchNAME ];
1566 AfsClass_GenFullUserName (szFullName, pszName, pszInstance);
1569 wp.wpPtsUserGet.hCell = GetCellObject();
1570 wp.wpPtsUserGet.pszUser = szFullName;
1571 if (Worker_DoTask (wtaskPtsUserGet, &wp, &status))
1574 if (fHasKAS || fHasPTS)
1576 lpUser = New2 (USER,(this, pszName, pszInstance));
1577 m_lUsers->Add (lpUser);
1578 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpUser->GetIdentifier());
1583 if (!lpUser && pStatus)
1589 LPUSER CELL::UserFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1591 return UserFindFirst (phEnum, NULL, fNotify, pStatus);
1595 LPUSER CELL::UserFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1597 LPUSER lpUser = NULL;
1599 if (!RefreshUsers (fNotify, pStatus))
1602 if (lpiFind != NULL)
1604 lpUser = lpiFind->OpenUser();
1607 else if ((*phEnum = m_lUsers->FindFirst()) != NULL)
1609 lpUser = (LPUSER)( (*phEnum)->GetObject() );
1613 if (!lpUser && pStatus)
1614 *pStatus = ERROR_FILE_NOT_FOUND;
1619 LPUSER CELL::UserFindNext (HENUM *phEnum)
1621 LPUSER lpUser = NULL;
1625 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1627 lpUser = (LPUSER)( (*phEnum)->GetObject() );
1636 void CELL::UserFindClose (HENUM *phEnum)
1647 LPPTSGROUP CELL::OpenGroup (LPTSTR pszName, ULONG *pStatus)
1651 // First off, do we have a USER object for this guy already?
1654 if ((lpGroup = (LPPTSGROUP)(m_lkGroupName->GetFirstObject (pszName))) != NULL)
1657 // If not, see if we can create one...
1661 // See if there's a PTS entry for this group.
1664 wp.wpPtsGroupGet.hCell = GetCellObject();
1665 wp.wpPtsGroupGet.pszGroup = pszName;
1666 if (Worker_DoTask (wtaskPtsGroupGet, &wp, &status))
1668 lpGroup = New2 (PTSGROUP,(this, pszName));
1669 m_lGroups->Add (lpGroup);
1670 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpGroup->GetIdentifier());
1675 if (!lpGroup && pStatus)
1681 LPPTSGROUP CELL::GroupFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1683 return GroupFindFirst (phEnum, NULL, fNotify, pStatus);
1687 LPPTSGROUP CELL::GroupFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1689 LPPTSGROUP lpGroup = NULL;
1691 if (!RefreshUsers (fNotify, pStatus))
1694 if (lpiFind != NULL)
1696 lpGroup = lpiFind->OpenGroup();
1699 else if ((*phEnum = m_lGroups->FindFirst()) != NULL)
1701 lpGroup = (LPPTSGROUP)( (*phEnum)->GetObject() );
1705 if (!lpGroup && pStatus)
1706 *pStatus = ERROR_FILE_NOT_FOUND;
1711 LPPTSGROUP CELL::GroupFindNext (HENUM *phEnum)
1713 LPPTSGROUP lpGroup = NULL;
1717 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1719 lpGroup = (LPPTSGROUP)( (*phEnum)->GetObject() );
1728 void CELL::GroupFindClose (HENUM *phEnum)
1738 BOOL CELL::RefreshUsers (BOOL fNotify, ULONG *pStatus)
1743 if (m_fUsersOutOfDate)
1745 m_fUsersOutOfDate = FALSE;
1748 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshUsersBegin, GetIdentifier());
1750 // First, forget everything we think we know about all users and groups;
1751 // we wouldn't be here if someone didn't think it was all out of date.
1755 // Then zip through KAS to build a list of all user entries;
1756 // we'll need hCell and hKAS for that.
1758 WORKERPACKET wpBegin;
1759 wpBegin.wpKasPrincipalGetBegin.hCell = GetCellObject();
1760 wpBegin.wpKasPrincipalGetBegin.hServer = GetKasObject (&status);
1762 if (!Worker_DoTask (wtaskKasPrincipalGetBegin, &wpBegin, &status))
1768 TCHAR szPrincipal[ cchNAME ];
1769 TCHAR szInstance[ cchNAME ];
1771 WORKERPACKET wpNext;
1772 wpNext.wpKasPrincipalGetNext.hEnum = wpBegin.wpKasPrincipalGetBegin.hEnum;
1773 wpNext.wpKasPrincipalGetNext.pszPrincipal = szPrincipal;
1774 wpNext.wpKasPrincipalGetNext.pszInstance = szInstance;
1775 if (!Worker_DoTask (wtaskKasPrincipalGetNext, &wpNext, &status))
1777 if (status == ADMITERATORDONE)
1784 // Okay, we got a user from kas. Create a USER object for it.
1786 LPUSER lpUser = New2 (USER,(this, szPrincipal, szInstance));
1787 m_lUsers->Add (lpUser);
1789 // That was easy, wasn't it? Now check this user's groups,
1790 // both the ones it owns and the ones to which it belongs,
1791 // so we can build a full list-o-groups.
1794 if (lpUser->GetMemberOf (&mszGroups))
1796 BuildGroups (mszGroups);
1797 FreeString (mszGroups);
1800 if (lpUser->GetOwnerOf (&mszGroups))
1802 BuildGroups (mszGroups);
1803 FreeString (mszGroups);
1807 WORKERPACKET wpDone;
1808 wpDone.wpKasPrincipalGetDone.hEnum = wpBegin.wpKasPrincipalGetBegin.hEnum;
1809 Worker_DoTask (wtaskKasPrincipalGetDone, &wpDone);
1812 #ifdef FIND_PTS_DEBRIS
1813 // Icky horrible painful part: to catch entries which exist on PTS
1814 // but not in KAS, we need to zip back through our list of groups
1815 // and check thier memberships.
1817 for (LPENUM pe = m_lGroups->FindFirst(); pe; pe = pe->FindNext())
1819 LPPTSGROUP lpGroup = (LPPTSGROUP)(pe->GetObject());
1822 if (lpGroup->GetMembers (&mszMembers))
1824 for (LPTSTR pszMember = mszMembers; pszMember && *pszMember; pszMember += 1+lstrlen(pszMember))
1826 // Make sure we have a user or group account for this guy.
1827 // Remember that the member name may have both a name and
1830 if (m_lkGroupName->GetFirstObject (pszMember))
1833 TCHAR szNameMatch[ cchNAME ];
1834 TCHAR szInstanceMatch[ cchNAME ];
1835 USER::SplitUserName (pszMember, szNameMatch, szInstanceMatch);
1837 LPUSER lpFound = NULL;
1838 for (LPENUM pEnum = m_lkUserName->FindFirst (szNameMatch); pEnum; pEnum = pEnum->FindNext())
1840 LPUSER lpTest = (LPUSER)( pEnum->GetObject() );
1841 if (!lstrcmpi (lpTest->m_szInstance, szInstanceMatch))
1851 // Uh oh. Is this thing a user or a group? We're really only
1852 // interested in finding user-account debris here...
1855 wpGet.wpPtsUserGet.hCell = GetCellObject();
1856 wpGet.wpPtsUserGet.pszUser = pszMember;
1857 if (Worker_DoTask (wtaskPtsUserGet, &wpGet))
1859 if (wpGet.wpPtsUserGet.Entry.nameUid > 0)
1861 LPUSER lpUser = New2 (USER,(this, pszMember, TEXT("")));
1862 m_lUsers->Add (lpUser);
1870 // We've finally generated a complete list of the users and groups in
1871 // this cell. If we've been asked to, send out notifications for all
1872 // the things we found.
1876 for (LPENUM pEnum = m_lGroups->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1878 LPPTSGROUP lpGroup = (LPPTSGROUP)(pEnum->GetObject());
1879 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpGroup->GetIdentifier());
1882 for (pEnum = m_lUsers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1884 LPUSER lpUser = (LPUSER)(pEnum->GetObject());
1885 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpUser->GetIdentifier());
1888 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshUsersEnd, GetIdentifier(), ((rc) ? 0 : status));
1898 void CELL::BuildGroups (LPTSTR mszGroups)
1900 for (LPTSTR pszGroup = mszGroups; pszGroup && *pszGroup; pszGroup += 1+lstrlen(pszGroup))
1902 // Make sure we have this group in our list-of-groups
1905 if ((lpGroup = (LPPTSGROUP)m_lkGroupName->GetFirstObject (pszGroup)) == NULL)
1907 lpGroup = New2 (PTSGROUP,(this, pszGroup));
1908 m_lGroups->Add (lpGroup);
1914 BOOL CELL::RefreshAccount (LPTSTR pszAccount, LPTSTR pszInstance, OP_CELL_REFRESH_ACCOUNT Op, LPIDENT *plpi)
1918 // See if we can find this thing
1921 if ((lpi = IDENT::FindUser (m_lpiThis, pszAccount, pszInstance)) != NULL)
1923 if (lpi->m_cRef == 0)
1928 if ((lpi = IDENT::FindGroup (m_lpiThis, pszAccount)) != NULL)
1929 if (lpi->m_cRef == 0)
1933 // If we couldn't find it, and Op is _CREATED_*, then make a new account
1935 if ((!lpi) && (Op == CELL_REFRESH_ACCOUNT_CREATED_USER))
1937 LPUSER lpUser = New2 (USER,(this, pszAccount, pszInstance));
1938 m_lUsers->Add (lpUser);
1939 lpi = lpUser->GetIdentifier();
1940 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpi);
1942 else if ((!lpi) && (Op == CELL_REFRESH_ACCOUNT_CREATED_GROUP))
1944 LPPTSGROUP lpGroup = New2 (PTSGROUP,(this, pszAccount));
1945 m_lGroups->Add (lpGroup);
1946 lpi = lpGroup->GetIdentifier();
1947 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpi);
1950 // If we did find it, and Op is _DELETED, then remove the account
1952 if (lpi && (Op == CELL_REFRESH_ACCOUNT_DELETED))
1954 if (lpi && (lpi->GetType() == itUSER))
1957 if ((lpUser = lpi->OpenUser()) == NULL)
1961 lpUser->SendDeleteNotifications();
1963 m_lUsers->Remove (lpUser);
1968 else if (lpi && (lpi->GetType() == itGROUP))
1971 if ((lpGroup = lpi->OpenGroup()) == NULL)
1975 lpGroup->SendDeleteNotifications();
1977 m_lGroups->Remove (lpGroup);
1988 // If we still have an ident, refresh the account's properties
1990 if (lpi && (lpi->GetType() == itUSER))
1993 if ((lpUser = lpi->OpenUser()) == NULL)
1997 lpUser->Invalidate();
1998 lpUser->RefreshStatus();
2002 else if (lpi && (lpi->GetType() == itGROUP))
2005 if ((lpGroup = lpi->OpenGroup()) == NULL)
2009 lpGroup->Invalidate();
2010 lpGroup->RefreshStatus();
2021 BOOL CELL::RefreshAccounts (LPTSTR mszAccounts, OP_CELL_REFRESH_ACCOUNT Op)
2024 for (LPTSTR psz = mszAccounts; psz && *psz; psz += 1+lstrlen(psz))
2026 if (!RefreshAccount (psz, NULL, Op))