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)
139 for (pEnum = m_lGroups->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
141 LPPTSGROUP lpGroup = (LPPTSGROUP)(pEnum->GetObject());
143 lpGroup->SendDeleteNotifications();
144 m_lGroups->Remove (lpGroup);
148 for (pEnum = m_lUsers->FindLast(); pEnum; pEnum = pEnum->FindPrevious())
150 LPUSER lpUser = (LPUSER)(pEnum->GetObject());
152 lpUser->SendDeleteNotifications();
153 m_lUsers->Remove (lpUser);
160 * CELL-LIST MANAGEMENT _______________________________________________________
164 void CELL::Close (void)
170 BOOL CELL::GetDefaultCell (LPTSTR pszName, ULONG *pStatus)
173 wp.wpClientLocalCellGet.pszCell = pszName;
174 return Worker_DoTask (wtaskClientLocalCellGet, &wp, pStatus);
178 LPIDENT CELL::OpenCell (LPTSTR pszCell, PVOID hCreds, ULONG *pStatus)
180 LPIDENT lpiCell = NULL;
185 if ((lpCell = ReopenCell (pszCell, pStatus)) != NULL)
187 lpiCell = lpCell->GetIdentifier();
191 else // cell hasn't been opened before? see if we can reach the cell.
193 lpCell = New2 (CELL,(pszCell, hCreds));
194 if ((lpCell->m_hCell = lpCell->GetCellObject (pStatus)) == NULL)
198 lpiCell = lpCell->GetIdentifier();
200 x_lCells->Add (lpCell);
201 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpiCell);
210 void CELL::CloseCell (LPIDENT lpiCell)
213 if ((lpCell = lpiCell->OpenCell()) != NULL)
215 if (lpCell->m_nReqs > 1)
222 NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, lpiCell);
223 lpCell->CloseKasObject();
224 lpCell->CloseCellObject();
226 x_lCells->Remove (lpCell);
233 LPCELL CELL::ReopenCell (LPTSTR pszCell, ULONG *pStatus)
235 LPCELL lpCell = NULL;
239 // Ordinarily we'd place a key on the cell name within the list of
240 // cells--however, the most likely case only has one cell anyway.
241 // So why expend the memory?
243 for (LPENUM pEnum = x_lCells->FindFirst(); pEnum; pEnum = pEnum->FindNext())
245 LPCELL lpCellFound = (LPCELL)( pEnum->GetObject() );
247 if (!lstrcmpi (lpCellFound->m_szName, pszCell))
249 lpCell = lpCellFound;
259 *pStatus = ERROR_FILE_NOT_FOUND;
262 // AfsClass_Leave() has been called only if no cell was opened in the search.
267 PVOID CELL::GetCurrentCredentials (void)
273 void CELL::SetCurrentCredentials (PVOID hCreds)
284 * SERVER-LIST MANAGEMENT _____________________________________________________
288 LPSERVER CELL::OpenServer (LPTSTR pszName, ULONG *pStatus)
290 if (!RefreshServers (TRUE, pStatus))
294 if ((lpServer = (LPSERVER)(m_lkServerName->GetFirstObject (pszName))) != NULL)
301 LPSERVER CELL::OpenServer (LPSOCKADDR_IN pAddr, ULONG *pStatus)
303 if (!RefreshServers (TRUE, pStatus))
306 // We'll try to use our lookup key first--since most machines only
307 // have one IP address anyway, our hashtable should make this lookup
308 // super fast. If it misses (i.e., if the server is multi-homed and
309 // for some reason VLDB refers to it by the second address), we'll
310 // have to do a brute-force search across each server in the cell.
311 // Again, we could have a better-designed lookup table here--but
312 // since multi-homing is the exception (by a vast majority), it's not
313 // worth the extra effort and memory. This technique is fast enough.
316 if ((lpServer = (LPSERVER)(m_lkServerAddr->GetFirstObject (pAddr))) != NULL)
318 AfsClass_Enter(); // Aren't HashLists great? We found the server.
320 else // Try brute-force search
323 for (lpServer = ServerFindFirst (&hEnum, TRUE, pStatus); lpServer; lpServer = ServerFindNext (&hEnum))
326 if (lpServer->GetStatus (&ss, TRUE, pStatus))
328 for (size_t iAddr = 0; iAddr < ss.nAddresses; ++iAddr)
330 if (!memcmp (&ss.aAddresses[ iAddr ], pAddr, sizeof(SOCKADDR_IN)))
332 // don't close server! we're going to return this pointer.
339 ServerFindClose (&hEnum);
345 LPSERVER CELL::ServerFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
347 return ServerFindFirst (phEnum, NULL, fNotify, pStatus);
351 LPSERVER CELL::ServerFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
353 LPSERVER lpServer = NULL;
355 if (!RefreshServers (fNotify, pStatus))
360 lpServer = lpiFind->OpenServer();
363 else if ((*phEnum = m_lServers->FindFirst()) != NULL)
365 lpServer = (LPSERVER)( (*phEnum)->GetObject() );
369 if (!lpServer && pStatus)
370 *pStatus = ERROR_FILE_NOT_FOUND;
375 LPSERVER CELL::ServerFindNext (HENUM *phEnum)
377 LPSERVER lpServer = NULL;
381 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
383 lpServer = (LPSERVER)( (*phEnum)->GetObject() );
392 void CELL::ServerFindClose (HENUM *phEnum)
402 BOOL CELL::RefreshServers (BOOL fNotify, ULONG *pStatus)
404 if (!m_fServersOutOfDate)
407 return RefreshServerList (fNotify, pStatus);
411 BOOL CELL::RefreshServerList (BOOL fNotify, ULONG *pStatus)
415 BOOL fNotified = FALSE;
417 if (fNotify && m_fServersOutOfDate)
419 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersBegin, GetIdentifier());
423 BOOL fReplaceList = m_fServersOutOfDate;
424 m_fServersOutOfDate = FALSE;
426 // Ordinarily we'd just clear the list of servers and
427 // requery it from scratch; however, servers are an exception
428 // to that technique: occasionally we may get a request to
429 // just look for servers that have appeared or disappeared,
430 // without refreshing data for other servers. Thus the revised
433 // 1- if fReplaceList, empty the list of servers.
434 // otherwise, set each server's fDelete flag.
436 // 2- enumerate the servers in the cell: for each server,
437 // if fReplaceList, add the server to the list
438 // otherwise, if the server is in the list, clear its fDelete
440 // 3- if !fReplaceList, enumerate the list of servers: for each server,
441 // if the server's fDelete flag is set, remove the server
443 for (LPENUM pEnum = m_lServers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
445 LPSERVER lpServer = (LPSERVER)(pEnum->GetObject());
449 lpServer->SendDeleteNotifications();
450 m_lServers->Remove (lpServer);
453 else // the list of servers isn't invalidated, so just mark fDelete
455 lpServer->m_fDelete = TRUE;
459 // Enumerate the servers in the cell.
462 if ((hCell = GetCellObject (&status)) == NULL)
470 WORKERPACKET wpBegin;
471 wpBegin.wpClientAFSServerGetBegin.hCell = hCell;
473 if (!Worker_DoTask (wtaskClientAFSServerGetBegin, &wpBegin, &status))
482 wpNext.wpClientAFSServerGetNext.hEnum = wpBegin.wpClientAFSServerGetBegin.hEnum;
483 if (!Worker_DoTask (wtaskClientAFSServerGetNext, &wpNext, &status))
485 if (status == ADMITERATORDONE)
492 afs_serverEntry_p pEntry = &wpNext.wpClientAFSServerGetNext.Entry;
494 TCHAR szServer[ cchNAME ];
495 CopyAnsiToString (szServer, pEntry->serverName);
498 int addrNetwork = htonl (pEntry->serverAddress[0]);
499 lstrcpy (szServer, inet_ntoa (*(struct in_addr *)&addrNetwork));
502 // The server identified by {pEntry} is in the cell. Now if we're
503 // building a list of SERVER objects from scratch, we can just
504 // add it--but if we're only touching up an existing list,
505 // first make sure there isn't such an animal in there now.
507 BOOL fNotifyAboutThisServer = FALSE;
509 LPSERVER lpServer = NULL;
512 if ((lpServer = (LPSERVER)(m_lkServerName->GetFirstObject (szServer))) != NULL)
513 lpServer->m_fDelete = FALSE;
516 if (lpServer == NULL)
518 // Okay, it's a new server. Create a SERVER object for it and
519 // add it to the list.
521 lpServer = New2 (SERVER,(this, szServer));
522 lpServer->m_wGhost |= GHOST_HAS_SERVER_ENTRY;
523 m_lServers->Add (lpServer);
524 fNotifyAboutThisServer = TRUE;
527 // Update the server's IP addresses
529 lpServer->m_ss.nAddresses = 0;
531 for (size_t iAddr = 0; iAddr < AFS_MAX_SERVER_ADDRESS; ++iAddr)
533 if (pEntry->serverAddress[ iAddr ] == 0)
535 AfsClass_IntToAddress (&lpServer->m_ss.aAddresses[ lpServer->m_ss.nAddresses++ ], pEntry->serverAddress[ iAddr ]);
538 m_lServers->Update (lpServer); // That update affected a hashlistkey
540 // Tell our clients that we've found a server
542 if (fNotify && fNotifyAboutThisServer)
546 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersBegin, GetIdentifier());
549 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpServer->GetIdentifier());
554 wpDone.wpClientAFSServerGetDone.hEnum = wpBegin.wpClientAFSServerGetBegin.hEnum;
555 Worker_DoTask (wtaskClientAFSServerGetDone, &wpDone);
559 // Finally, look through our list of servers: if any have fDelete set,
560 // then we didn't find them in the cell any longer. Remove those servers.
564 for (LPENUM pEnum = m_lServers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
566 LPSERVER lpServer = (LPSERVER)(pEnum->GetObject());
567 if (lpServer->m_fDelete)
569 if (fNotify && !fNotified)
571 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersBegin, GetIdentifier());
574 lpServer->SendDeleteNotifications();
575 m_lServers->Remove (lpServer);
581 // Fix m_apszServers if we did anything to the list of servers
587 for (size_t ii = 0; m_apszServers[ii]; ++ii)
588 FreeString (m_apszServers[ii]);
589 Free (m_apszServers);
590 m_apszServers = NULL;
595 for (pEnum = m_lServers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
600 m_apszServers = (char**)Allocate (sizeof(char*) * (1+cServers));
601 memset (m_apszServers, 0x00, sizeof(char*) * (1+cServers));
604 for (pEnum = m_lServers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
606 LPSERVER lpServer = (LPSERVER)(pEnum->GetObject());
607 m_apszServers[ iServer ] = AllocateAnsi (cchNAME+1);
608 CopyStringToAnsi (m_apszServers[ iServer ], lpServer->m_szName);
615 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshServersEnd, GetIdentifier(), ((rc) ? 0 : status));
624 * SERVER-LIST KEYS ___________________________________________________________
628 BOOL CALLBACK CELL::KeyServerName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
630 if (!lstrcmp (((LPSERVER)pObject)->m_szName, (LPTSTR)pData))
633 TCHAR szShortName[ cchNAME ];
634 SERVER::ShortenName (szShortName, ((LPSERVER)pObject)->m_szName);
635 if (!lstrcmp (szShortName, (LPTSTR)pData))
641 HASHVALUE CALLBACK CELL::KeyServerName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
643 return CELL::KeyServerName_HashData (pKey, ((LPSERVER)pObject)->m_szName);
646 HASHVALUE CALLBACK CELL::KeyServerName_HashData (LPHASHLISTKEY pKey, PVOID pData)
648 TCHAR szShortName[ cchNAME ];
649 SERVER::ShortenName (szShortName, (LPTSTR)pData);
650 return HashString (szShortName);
654 BOOL CALLBACK CELL::KeyServerAddr_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
656 return !memcmp (&((LPSERVER)pObject)->m_ss.aAddresses[0], (LPSOCKADDR)pData, sizeof(SOCKADDR_IN));
659 HASHVALUE CALLBACK CELL::KeyServerAddr_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
661 return CELL::KeyServerAddr_HashData (pKey, &((LPSERVER)pObject)->m_ss.aAddresses[0]);
664 HASHVALUE CALLBACK CELL::KeyServerAddr_HashData (LPHASHLISTKEY pKey, PVOID pData)
666 return *(DWORD*)pData;
670 BOOL CALLBACK CELL::KeyUserName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
672 return !lstrcmpi (((LPUSER)pObject)->m_szPrincipal, (LPTSTR)pData);
675 HASHVALUE CALLBACK CELL::KeyUserName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
677 return CELL::KeyUserName_HashData (pKey, ((LPUSER)pObject)->m_szPrincipal);
680 HASHVALUE CALLBACK CELL::KeyUserName_HashData (LPHASHLISTKEY pKey, PVOID pData)
682 return HashString ((LPTSTR)pData);
686 BOOL CALLBACK CELL::KeyGroupName_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
688 return !lstrcmpi (((LPPTSGROUP)pObject)->m_szName, (LPTSTR)pData);
691 HASHVALUE CALLBACK CELL::KeyGroupName_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
693 return CELL::KeyGroupName_HashData (pKey, ((LPPTSGROUP)pObject)->m_szName);
696 HASHVALUE CALLBACK CELL::KeyGroupName_HashData (LPHASHLISTKEY pKey, PVOID pData)
698 return HashString ((LPTSTR)pData);
703 * CELL OBJECT ________________________________________________________________
707 PVOID CELL::GetCellObject (ULONG *pStatus)
712 NOTIFYCALLBACK::SendNotificationToAll (evtOpenCellBegin, m_szName);
715 wpOpen.wpClientCellOpen.pszCell = m_szName;
716 wpOpen.wpClientCellOpen.hCreds = m_hCreds;
718 if (Worker_DoTask (wtaskClientCellOpen, &wpOpen, &status))
719 m_hCell = wpOpen.wpClientCellOpen.hCell;
723 NOTIFYCALLBACK::SendNotificationToAll (evtOpenCellEnd, m_szName, status);
730 BOOL CELL::CloseCellObject (ULONG *pStatus)
737 wp.wpClientCellClose.hCell = m_hCell;
738 rc = Worker_DoTask (wtaskClientCellClose, &wp, pStatus);
746 PVOID CELL::GetKasObject (ULONG *pStatus)
748 // m_hKas is actually never set non-NULL;
749 // leaving it NULL indicates we will work happily with *any* server.
755 BOOL CELL::CloseKasObject (ULONG *pStatus)
762 wp.wpKasServerClose.hServer = m_hKas;
763 rc = Worker_DoTask (wtaskKasServerClose, &wp, pStatus);
772 * CELL GENERAL _______________________________________________________________
776 LPIDENT CELL::GetIdentifier (void)
778 if (m_lpiThis == NULL)
780 if ((m_lpiThis = IDENT::FindIdent (this)) == NULL)
781 m_lpiThis = New2 (IDENT,(this));
782 m_lpiThis->m_cRef ++;
789 void CELL::GetName (LPTSTR pszName)
791 lstrcpy (pszName, m_szName);
795 PVOID CELL::GetUserParam (void)
797 return GetIdentifier()->GetUserParam();
801 void CELL::SetUserParam (PVOID pUserNew)
803 GetIdentifier()->SetUserParam (pUserNew);
807 BOOL CELL::fAnyServersUnmonitored (void)
809 return (m_nServersUnmonitored > 0) ? TRUE : FALSE;
814 * CELL STATUS ________________________________________________________________
818 void CELL::Invalidate (void)
820 if (!m_fServersOutOfDate || !m_fStatusOutOfDate || !m_fVLDBOutOfDate || !m_fUsersOutOfDate)
824 m_fServersOutOfDate = TRUE;
825 m_fStatusOutOfDate = TRUE;
826 m_fVLDBOutOfDate = TRUE;
827 m_fUsersOutOfDate = TRUE;
828 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
833 void CELL::InvalidateServers (void)
835 if (!m_fServersOutOfDate || !m_fVLDBOutOfDate)
839 m_fServersOutOfDate = TRUE;
840 m_fVLDBOutOfDate = TRUE;
841 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
846 void CELL::InvalidateUsers (void)
848 if (!m_fUsersOutOfDate)
850 m_fUsersOutOfDate = TRUE;
851 NOTIFYCALLBACK::SendNotificationToAll (evtInvalidate, GetIdentifier());
856 BOOL CELL::RefreshStatus (BOOL fNotify, ULONG *pStatus)
861 if (m_fStatusOutOfDate)
864 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
866 // Hmmm...well, actually, there's nothing for us to do here. I'm
867 // leaving this around, because the refreshed-cell-status notification
868 // may be useful as an appropriate hooking point.
873 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
882 BOOL CELL::RefreshVLDB (BOOL fNotify, ULONG *pStatus)
886 if (m_fVLDBOutOfDate)
888 if ((rc = RefreshVLDB (GetIdentifier(), fNotify, pStatus)) == TRUE)
890 m_fVLDBOutOfDate = FALSE;
898 BOOL CELL::RefreshVLDB (LPIDENT lpiRef, BOOL fNotify, ULONG *pStatus, BOOL fAnythingRelatedToThisRWFileset)
903 // What is the scope of this refresh operation? The entire cell,
904 // or the filesets on a particular server or aggregate?
906 LPIDENT lpiRefCell = (lpiRef == NULL) ? GetIdentifier() : lpiRef->GetCell();
907 LPIDENT lpiRefServer = NULL;
908 LPIDENT lpiRefAggregate = NULL;
909 LPIDENT lpiRefFileset = NULL;
910 VOLUMEID *pvidRefFileset = NULL;
911 VOLUMEID vidRefFileset;
913 if (fAnythingRelatedToThisRWFileset)
915 pvidRefFileset = &vidRefFileset;
916 lpiRef->GetFilesetID (pvidRefFileset);
920 if (lpiRef && !lpiRef->fIsCell())
922 lpiRefServer = lpiRef->GetServer();
924 if (lpiRef && (lpiRef->fIsAggregate() || lpiRef->fIsFileset()))
926 lpiRefAggregate = lpiRef->GetAggregate();
928 if (lpiRef && lpiRef->fIsFileset())
930 lpiRefFileset = lpiRef;
934 // If we've been told to update only one server, aggregate or
935 // fileset, find out which IP addresses correspond with that
936 // server. We'll need this for comparisons later.
938 SERVERSTATUS ssRefServer;
939 if (rc && lpiRefServer)
942 if ((lpServer = lpiRefServer->OpenServer (&status)) == NULL)
946 rc = lpServer->GetStatus (&ssRefServer, fNotify, &status);
951 // Likewise, if we've been told to update only one aggregate,
952 // find that aggregate's ID. We'll need it for comparisons later.
954 AGGREGATESTATUS asRefAggregate;
955 int idPartition = NO_PARTITION;
956 if (rc && lpiRefAggregate)
958 LPAGGREGATE lpAggregate;
959 if ((lpAggregate = lpiRefAggregate->OpenAggregate (&status)) == NULL)
963 idPartition = lpAggregate->GetID();
964 rc = lpAggregate->GetStatus (&asRefAggregate, fNotify, &status);
965 lpAggregate->Close();
969 // Zip through the current list of objects that we're about to refresh.
970 // On each such object, remove the GHOST_HAS_VLDB_ENTRY flag,
971 // and delete objects entirely if that's the only ghost flag they have.
972 // (e.g., If we went through this routine earlier and created a ghost
973 // aggregate because VLDB referenced it and we couldn't find mention
974 // of it on the server, delete that aggregate. We'll recreate it here
975 // if necessary; otherwise, it needs to be gone.)
979 RefreshVLDB_RemoveReferences (lpiRefServer, lpiRefAggregate, lpiRefFileset, pvidRefFileset);
982 // We'll get a new list of filesets from VLDB, and to do that, we'll
983 // need the cell's object. If we're enumerating a specific server, we'll
984 // also need that server's object. Finally, if we're enumerating a
985 // specific aggregate, we'll also need that aggregate's name.
988 PVOID hServer = NULL;
994 if ((hCell = GetCellObject (&status)) == NULL)
997 else // get cell and server handles
1000 if ((lpServer = lpiRefServer->OpenServer()) == NULL)
1004 if ((hServer = lpServer->OpenVosObject (&hCell, &status)) == NULL)
1011 // Go get that list of filesets, and use it to update our knowledge
1012 // of the cell. Remember that, if {pvidRefFileset}, we only want
1020 wpGet.wpVosVLDBGet.hCell = hCell;
1021 wpGet.wpVosVLDBGet.idVolume = *pvidRefFileset;
1023 if (!Worker_DoTask (wtaskVosVLDBGet, &wpGet, &status))
1026 RefreshVLDB_OneEntry (&wpGet.wpVosVLDBGet.Data, lpiRefServer, &ssRefServer, lpiRefAggregate, &asRefAggregate, lpiRefFileset, pvidRefFileset, fNotify);
1030 WORKERPACKET wpBegin;
1031 wpBegin.wpVosVLDBGetBegin.hCell = hCell;
1032 wpBegin.wpVosVLDBGetBegin.hServer = hServer;
1033 wpBegin.wpVosVLDBGetBegin.idPartition = idPartition;
1035 if (!Worker_DoTask (wtaskVosVLDBGetBegin, &wpBegin, &status))
1041 WORKERPACKET wpNext;
1042 wpNext.wpVosVLDBGetNext.hEnum = wpBegin.wpVosVLDBGetBegin.hEnum;
1043 if (!Worker_DoTask (wtaskVosVLDBGetNext, &wpNext, &status))
1045 if (status == ADMITERATORDONE)
1052 RefreshVLDB_OneEntry (&wpNext.wpVosVLDBGetNext.Data, lpiRefServer, &ssRefServer, lpiRefAggregate, &asRefAggregate, lpiRefFileset, pvidRefFileset, fNotify);
1055 WORKERPACKET wpDone;
1056 wpDone.wpVosVLDBGetDone.hEnum = wpBegin.wpVosVLDBGetBegin.hEnum;
1057 Worker_DoTask (wtaskVosVLDBGetDone, &wpDone);
1062 // We've finished the update. If we were asked to send notifications
1063 // about our progress, do so.
1067 LPIDENT lpiNotify = (lpiRef) ? lpiRef : GetIdentifier();
1069 if (!lpiNotify->fIsFileset())
1071 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshFilesetsBegin, lpiNotify);
1072 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshFilesetsEnd, lpiNotify, status);
1075 if (lpiNotify->fIsCell() || lpiNotify->fIsServer())
1077 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesBegin, lpiNotify);
1078 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAggregatesEnd, lpiNotify, status);
1085 if ((lpServer = lpiRefServer->OpenServer()) != NULL)
1087 lpServer->CloseVosObject();
1098 void CELL::RefreshVLDB_RemoveReferences (LPIDENT lpiRefServer, LPIDENT lpiRefAggregate, LPIDENT lpiRefFileset, LPVOLUMEID pvidRefFileset)
1100 // Zip through the current list of objects that we're about to refresh.
1101 // On each such object, remove the GHOST_HAS_VLDB_ENTRY flag,
1102 // and delete objects entirely if that's the only ghost flag they have.
1103 // (e.g., If we went through this routine earlier and created a ghost
1104 // aggregate because VLDB referenced it and we couldn't find mention
1105 // of it on the server, delete that aggregate. We'll recreate it here
1106 // if necessary; otherwise, it needs to be gone.)
1108 // Note that by specifying {lpiRefServer} to start the enumeration,
1109 // we'll either enumerate only lpiRefServer, or all servers if it's NULL.
1112 for (LPSERVER lpServer = ServerFindFirst (&heServer, lpiRefServer); lpServer; lpServer = ServerFindNext (&heServer))
1115 if (!pvidRefFileset)
1117 // Since we're about to check VLDB for references to this server,
1118 // remove the GHOST_HAS_VLDB_ENTRY flag from its SERVER object.
1119 // If that's the only thing keeping the object around, remove the
1122 if ((lpServer->m_wGhost &= (~GHOST_HAS_VLDB_ENTRY)) == 0)
1125 lpServer->SendDeleteNotifications();
1126 m_lServers->Remove (lpServer);
1132 // Check each of the server's aggregates, and deal with them the same
1136 for (LPAGGREGATE lpAggregate = lpServer->AggregateFindFirst (&heAggregate, lpiRefAggregate); lpAggregate; lpAggregate = lpServer->AggregateFindNext (&heAggregate))
1139 if (!pvidRefFileset)
1141 // Since we're about to check VLDB for references to this aggregate,
1142 // remove the GHOST_HAS_VLDB_ENTRY flag from its AGGREGATE object.
1143 // If that's the only thing keeping the object around, remove the
1146 if ((lpAggregate->m_wGhost &= (~GHOST_HAS_VLDB_ENTRY)) == 0)
1148 lpAggregate->Close();
1149 lpAggregate->SendDeleteNotifications();
1150 lpServer->m_lAggregates->Remove (lpAggregate);
1151 Delete (lpAggregate);
1156 // Check each of the aggregate's filesets, and deal with them the same
1160 for (LPFILESET lpFileset = lpAggregate->FilesetFindFirst (&heFileset, lpiRefFileset); lpFileset; lpFileset = lpAggregate->FilesetFindNext (&heFileset))
1162 if ((!pvidRefFileset) || (*pvidRefFileset == lpFileset->m_fs.idReadWrite))
1164 // Since we're about to check VLDB for references to this fileset,
1165 // remove the GHOST_HAS_VLDB_ENTRY flag from its FILESET object.
1166 // If that's the only thing keeping the object around, remove the
1169 if ((lpFileset->m_wGhost &= (~GHOST_HAS_VLDB_ENTRY)) == 0)
1172 lpFileset->SendDeleteNotifications();
1173 lpAggregate->m_lFilesets->Remove (lpFileset);
1182 lpAggregate->Close();
1190 void CELL::RefreshVLDB_OneEntry (PVOID pp, LPIDENT lpiRefServer, LPSERVERSTATUS pssRefServer, LPIDENT lpiRefAggregate, LPAGGREGATESTATUS pasRefAggregate, LPIDENT lpiRefFileset, LPVOLUMEID pvidRefFileset, BOOL fNotify)
1192 vos_vldbEntry_p pEntry = (vos_vldbEntry_p)pp;
1194 // If we were asked to update all the replicas of a particular
1195 // fileset, then we set {pvidRefFileset} above to that fileset's
1196 // ID. Check this VLDB entry to see if it refers to that fileset;
1197 // if not, we're not interested in it.
1201 if (memcmp (&pEntry->volumeId[ VOS_READ_WRITE_VOLUME ], pvidRefFileset, sizeof(VOLUMEID)))
1205 for (int iRepSite = 0; iRepSite < pEntry->numServers; ++iRepSite)
1207 SOCKADDR_IN RepSiteAddr;
1208 AfsClass_IntToAddress (&RepSiteAddr, pEntry->volumeSites[ iRepSite ].serverAddress);
1210 // Every fileset replication site which VLDB knows about
1211 // passes through this point, within {pEntry->volumeSites[ iRepSite ]}.
1213 // Are we going to be refreshing the server/aggregate on which
1214 // this repsite lives? If not, there's no need to process this
1215 // entry any further.
1219 BOOL fFilesetLivesOnThisServer = FALSE;
1221 for (size_t iAddress = 0; !fFilesetLivesOnThisServer && (iAddress < pssRefServer->nAddresses); ++iAddress)
1223 if (!memcmp (&pssRefServer->aAddresses[ iAddress ], &RepSiteAddr, sizeof(SOCKADDR_IN)))
1225 if (lpiRefAggregate)
1227 if (pasRefAggregate->dwID != (DWORD)(pEntry->volumeSites[ iRepSite ].serverPartition))
1230 fFilesetLivesOnThisServer = TRUE;
1234 if (!fFilesetLivesOnThisServer)
1238 // Do we know about the server mentioned by this replication
1242 if (lpiRefServer != NULL)
1243 lpServer = lpiRefServer->OpenServer();
1245 lpServer = OpenServer (&RepSiteAddr);
1247 // If we found the server but aren't monitoring it,
1248 // forget about this fileset.
1250 if (lpServer && !lpServer->fIsMonitored())
1257 // If we have no record of the server mentioned by this
1258 // replication site, we have to create a SERVER entry for
1259 // it before we can proceed. The server will appear as
1264 if (lpiRefAggregate || pvidRefFileset)
1267 LPTSTR pszServer = FormatString (TEXT("%1"), TEXT("%a"), &pEntry->volumeSites[ iRepSite ].serverAddress);
1268 lpServer = New2 (SERVER,(this, pszServer));
1270 FreeString (pszServer);
1272 lpServer->m_fStatusOutOfDate = FALSE;
1273 lpServer->m_ss.nAddresses = 1;
1274 memcpy (&lpServer->m_ss.aAddresses[0], &RepSiteAddr, sizeof(SOCKADDR_IN));
1276 m_lServers->Add (lpServer);
1279 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpServer->GetIdentifier());
1282 lpServer->m_wGhost |= GHOST_HAS_VLDB_ENTRY;
1284 // Great--we now have a replication site for a particular
1285 // fileset known to VLDB, and a pointer to the server
1286 // on which it resides. Does that server contain the
1287 // aggregate which VLDB expects to find?
1289 LPAGGREGATE lpAggregate;
1290 if (lpiRefAggregate != NULL)
1291 lpAggregate = lpiRefAggregate->OpenAggregate();
1293 lpAggregate = lpServer->OpenAggregate (pEntry->volumeSites[ iRepSite ].serverPartition);
1295 // If the server has no record of the aggregate mentioned
1296 // by this replication site, we have to create an
1297 // AGGREGATE entry for it before we can proceed. The
1298 // aggregate will appear as a "ghost". Note that we
1299 // can't update the list of aggregates on a server if
1300 // we've been asked to update a particular fileset,
1301 // because someone clearly has a pointer to the list.
1305 if (lpiRefFileset || pvidRefFileset)
1312 // Even if the partition doesn't exist, we can still figger out
1313 // its name given its ID--'cause there's a 1:1 mapping between
1314 // allowed IDs and allowed partition names. I guess there's
1315 // something to be said for forcing partitions to be named "vicep*"
1317 TCHAR szPartition[ cchNAME ];
1319 wp.wpVosPartitionIdToName.idPartition = pEntry->volumeSites[ iRepSite ].serverPartition;
1320 wp.wpVosPartitionIdToName.pszPartition = szPartition;
1321 if (!Worker_DoTask (wtaskVosPartitionIdToName, &wp))
1322 wsprintf (szPartition, TEXT("#%lu"), pEntry->volumeSites[ iRepSite ].serverPartition);
1324 lpAggregate = New2 (AGGREGATE,(lpServer, szPartition, TEXT("")));
1327 lpAggregate->m_fStatusOutOfDate = FALSE;
1328 lpAggregate->m_as.dwID = pEntry->volumeSites[ iRepSite ].serverPartition;
1329 lpAggregate->m_as.ckStorageTotal = 0;
1330 lpAggregate->m_as.ckStorageFree = 0;
1332 lpServer->m_lAggregates->Add (lpAggregate);
1335 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpAggregate->GetIdentifier());
1338 lpAggregate->m_wGhost |= GHOST_HAS_VLDB_ENTRY;
1340 // Great--we now have a replication site for a particular
1341 // fileset known to VLDB, and a pointer to the server
1342 // and aggregate on which it resides. Does that aggregate
1343 // contain the fileset which VLDB expects to find?
1345 // Remember that each iRepSite can represent up to three
1346 // filesets on that aggregate--a RW, a RO, and a BAK.
1348 for (size_t iType = 0; iType < 3; ++iType)
1351 // Does this repsite entry mention having this type
1352 // of fileset on this aggregate?
1354 if ((vos_volumeType_t)iType == VOS_READ_WRITE_VOLUME)
1356 if (!((DWORD)pEntry->volumeSites[ iRepSite ].serverFlags & (DWORD)VOS_VLDB_READ_WRITE))
1359 else if ((vos_volumeType_t)iType == VOS_READ_ONLY_VOLUME)
1361 if (!((DWORD)pEntry->volumeSites[ iRepSite ].serverFlags & (DWORD)VOS_VLDB_READ_ONLY))
1364 else if ((vos_volumeType_t)iType == VOS_BACKUP_VOLUME)
1366 if (!((DWORD)pEntry->status & (DWORD)VOS_VLDB_ENTRY_BACKEXISTS))
1369 // Only look for the backup where the R/W exists
1370 if (!((DWORD)pEntry->volumeSites[ iRepSite ].serverFlags & (DWORD)VOS_VLDB_READ_WRITE))
1374 LPFILESET lpFileset = lpAggregate->OpenFileset ((LPVOLUMEID)&pEntry->volumeId[ iType ]);
1376 // If the aggregate has no record of the fileset mentioned
1377 // by this VLDB entry, we have to create a FILESET entry
1378 // for it. The fileset will appear as a "ghost".
1382 TCHAR szFilesetName[ cchNAME ];
1383 CopyAnsiToString (szFilesetName, pEntry->name);
1384 if ((vos_volumeType_t)iType == VOS_READ_ONLY_VOLUME)
1385 lstrcat (szFilesetName, TEXT(".readonly"));
1386 else if ((vos_volumeType_t)iType == VOS_BACKUP_VOLUME)
1387 lstrcat (szFilesetName, TEXT(".backup"));
1389 lpFileset = New2 (FILESET,(lpAggregate, &pEntry->volumeId[ iType ], szFilesetName));
1392 lpFileset->m_fs.id = pEntry->volumeId[ iType ];
1393 lpFileset->m_fs.idReadWrite = pEntry->volumeId[ VOS_READ_WRITE_VOLUME ];
1394 lpFileset->m_fs.idReplica = pEntry->volumeId[ VOS_READ_ONLY_VOLUME ];
1395 AfsClass_UnixTimeToSystemTime (&lpFileset->m_fs.timeCreation, 0);
1396 AfsClass_UnixTimeToSystemTime (&lpFileset->m_fs.timeLastUpdate, 0);
1397 AfsClass_UnixTimeToSystemTime (&lpFileset->m_fs.timeLastAccess, 0);
1398 AfsClass_UnixTimeToSystemTime (&lpFileset->m_fs.timeLastBackup, 0);
1399 AfsClass_UnixTimeToSystemTime (&lpFileset->m_fs.timeCopyCreation, 0);
1400 lpFileset->m_fs.nFiles = 0;
1401 lpFileset->m_fs.ckQuota = 0;
1402 lpFileset->m_fs.ckUsed = 0;
1403 lpFileset->m_fs.Type = (iType == 0) ? ftREADWRITE : (iType == 1) ? ftREPLICA : ftCLONE;
1404 lpFileset->m_fs.State = fsNORMAL;
1406 lpAggregate->m_lFilesets->Add (lpFileset);
1409 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpFileset->GetIdentifier());
1413 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, lpFileset->GetIdentifier());
1415 lpFileset->m_wGhost |= GHOST_HAS_VLDB_ENTRY;
1416 lpFileset->m_fStatusOutOfDate = FALSE;
1417 lpFileset->m_fs.idClone = pEntry->cloneId;
1418 lpFileset->m_fs.State &= ~fsMASK_VLDB;
1420 if (pEntry->status & VOS_VLDB_ENTRY_LOCKED)
1421 lpFileset->m_fs.State |= fsLOCKED;
1426 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, lpFileset->GetIdentifier(), 0);
1429 if (lpServer && lpAggregate)
1431 lpAggregate->InvalidateAllocation();
1432 lpAggregate->Close();
1444 BOOL CELL::RefreshAll (ULONG *pStatus)
1449 BOOL fNotified = FALSE;
1451 if (m_fServersOutOfDate && (dwWant & AFSCLASS_WANT_VOLUMES))
1456 if ((++cRefreshAllReq) == 1)
1458 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin, GetIdentifier());
1462 size_t nServersToRefresh = 0;
1465 for (LPSERVER lpServer = ServerFindFirst (&hEnum); lpServer; lpServer = ServerFindNext (&hEnum))
1467 if (lpServer->fIsMonitored())
1468 ++nServersToRefresh;
1472 if (nServersToRefresh)
1475 for (LPSERVER lpServer = ServerFindFirst (&hEnum); lpServer; lpServer = ServerFindNext (&hEnum))
1477 if (lpServer->fIsMonitored())
1479 ULONG perComplete = (ULONG)iServer * 100L / nServersToRefresh;
1480 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllUpdate, lpServer->GetIdentifier(), NULL, NULL, NULL, perComplete, 0);
1482 // intentionally ignore errors in refreshing individual
1483 // servers--we only want to return an error code if
1484 // we couldn't refresh the *cell*.
1486 (void)lpServer->RefreshAll (NULL, ((double)iServer / (double)nServersToRefresh), (1.0 / (double)nServersToRefresh));
1492 rc = RefreshVLDB (NULL, TRUE, &status);
1496 if (rc && m_fUsersOutOfDate && (dwWant & AFSCLASS_WANT_USERS))
1501 if ((++cRefreshAllReq) == 1)
1503 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllBegin, GetIdentifier(), NULL, NULL, NULL, 0, 0);
1507 rc = RefreshUsers (TRUE, &status);
1512 if ((--cRefreshAllReq) == 0)
1514 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshAllEnd, GetIdentifier(), NULL, NULL, NULL, 100, status);
1525 * USER/GROUP-LIST MANAGEMENT _________________________________________________
1529 LPUSER CELL::OpenUser (LPTSTR pszName, LPTSTR pszInstance, ULONG *pStatus)
1533 // First off, do we have a USER object for this guy already?
1535 LPUSER lpUser = NULL;
1536 for (LPENUM pEnum = m_lkUserName->FindFirst (pszName); pEnum; pEnum = pEnum->FindNext())
1538 LPUSER lpTest = (LPUSER)( pEnum->GetObject() );
1539 if (!pszInstance || !lstrcmpi (lpTest->m_szInstance, pszInstance))
1548 // If not, see if we can create one...
1552 // See if there's a KAS or PTS entry for this user.
1554 BOOL fHasKAS = FALSE;
1555 BOOL fHasPTS = FALSE;
1558 wp.wpKasPrincipalGet.hCell = GetCellObject (&status);
1559 wp.wpKasPrincipalGet.hServer = GetKasObject (&status);
1560 wp.wpKasPrincipalGet.pszPrincipal = pszName;
1561 wp.wpKasPrincipalGet.pszInstance = pszInstance;
1562 if (Worker_DoTask (wtaskKasPrincipalGet, &wp, &status))
1567 TCHAR szFullName[ cchNAME ];
1568 AfsClass_GenFullUserName (szFullName, pszName, pszInstance);
1571 wp.wpPtsUserGet.hCell = GetCellObject();
1572 wp.wpPtsUserGet.pszUser = szFullName;
1573 if (Worker_DoTask (wtaskPtsUserGet, &wp, &status))
1576 if (fHasKAS || fHasPTS)
1578 lpUser = New2 (USER,(this, pszName, pszInstance));
1579 m_lUsers->Add (lpUser);
1580 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpUser->GetIdentifier());
1585 if (!lpUser && pStatus)
1591 LPUSER CELL::UserFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1593 return UserFindFirst (phEnum, NULL, fNotify, pStatus);
1597 LPUSER CELL::UserFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1599 LPUSER lpUser = NULL;
1601 if (!RefreshUsers (fNotify, pStatus))
1604 if (lpiFind != NULL)
1606 lpUser = lpiFind->OpenUser();
1609 else if ((*phEnum = m_lUsers->FindFirst()) != NULL)
1611 lpUser = (LPUSER)( (*phEnum)->GetObject() );
1615 if (!lpUser && pStatus)
1616 *pStatus = ERROR_FILE_NOT_FOUND;
1621 LPUSER CELL::UserFindNext (HENUM *phEnum)
1623 LPUSER lpUser = NULL;
1627 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1629 lpUser = (LPUSER)( (*phEnum)->GetObject() );
1638 void CELL::UserFindClose (HENUM *phEnum)
1649 LPPTSGROUP CELL::OpenGroup (LPTSTR pszName, ULONG *pStatus)
1653 // First off, do we have a USER object for this guy already?
1656 if ((lpGroup = (LPPTSGROUP)(m_lkGroupName->GetFirstObject (pszName))) != NULL)
1659 // If not, see if we can create one...
1663 // See if there's a PTS entry for this group.
1666 wp.wpPtsGroupGet.hCell = GetCellObject();
1667 wp.wpPtsGroupGet.pszGroup = pszName;
1668 if (Worker_DoTask (wtaskPtsGroupGet, &wp, &status))
1670 lpGroup = New2 (PTSGROUP,(this, pszName));
1671 m_lGroups->Add (lpGroup);
1672 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpGroup->GetIdentifier());
1677 if (!lpGroup && pStatus)
1683 LPPTSGROUP CELL::GroupFindFirst (HENUM *phEnum, BOOL fNotify, ULONG *pStatus)
1685 return GroupFindFirst (phEnum, NULL, fNotify, pStatus);
1689 LPPTSGROUP CELL::GroupFindFirst (HENUM *phEnum, LPIDENT lpiFind, BOOL fNotify, ULONG *pStatus)
1691 LPPTSGROUP lpGroup = NULL;
1693 if (!RefreshUsers (fNotify, pStatus))
1696 if (lpiFind != NULL)
1698 lpGroup = lpiFind->OpenGroup();
1701 else if ((*phEnum = m_lGroups->FindFirst()) != NULL)
1703 lpGroup = (LPPTSGROUP)( (*phEnum)->GetObject() );
1707 if (!lpGroup && pStatus)
1708 *pStatus = ERROR_FILE_NOT_FOUND;
1713 LPPTSGROUP CELL::GroupFindNext (HENUM *phEnum)
1715 LPPTSGROUP lpGroup = NULL;
1719 if ((*phEnum = (*phEnum)->FindNext()) != NULL)
1721 lpGroup = (LPPTSGROUP)( (*phEnum)->GetObject() );
1730 void CELL::GroupFindClose (HENUM *phEnum)
1740 BOOL CELL::RefreshUsers (BOOL fNotify, ULONG *pStatus)
1745 if (m_fUsersOutOfDate)
1747 m_fUsersOutOfDate = FALSE;
1750 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshUsersBegin, GetIdentifier());
1752 // First, forget everything we think we know about all users and groups;
1753 // we wouldn't be here if someone didn't think it was all out of date.
1757 // Then zip through KAS to build a list of all user entries;
1758 // we'll need hCell and hKAS for that.
1760 WORKERPACKET wpBegin;
1761 wpBegin.wpKasPrincipalGetBegin.hCell = GetCellObject();
1762 wpBegin.wpKasPrincipalGetBegin.hServer = GetKasObject (&status);
1764 if (!Worker_DoTask (wtaskKasPrincipalGetBegin, &wpBegin, &status))
1770 TCHAR szPrincipal[ cchNAME ];
1771 TCHAR szInstance[ cchNAME ];
1773 WORKERPACKET wpNext;
1774 wpNext.wpKasPrincipalGetNext.hEnum = wpBegin.wpKasPrincipalGetBegin.hEnum;
1775 wpNext.wpKasPrincipalGetNext.pszPrincipal = szPrincipal;
1776 wpNext.wpKasPrincipalGetNext.pszInstance = szInstance;
1777 if (!Worker_DoTask (wtaskKasPrincipalGetNext, &wpNext, &status))
1779 if (status == ADMITERATORDONE)
1786 // Okay, we got a user from kas. Create a USER object for it.
1788 LPUSER lpUser = New2 (USER,(this, szPrincipal, szInstance));
1789 m_lUsers->Add (lpUser);
1791 // That was easy, wasn't it? Now check this user's groups,
1792 // both the ones it owns and the ones to which it belongs,
1793 // so we can build a full list-o-groups.
1796 if (lpUser->GetMemberOf (&mszGroups))
1798 BuildGroups (mszGroups);
1799 FreeString (mszGroups);
1802 if (lpUser->GetOwnerOf (&mszGroups))
1804 BuildGroups (mszGroups);
1805 FreeString (mszGroups);
1809 WORKERPACKET wpDone;
1810 wpDone.wpKasPrincipalGetDone.hEnum = wpBegin.wpKasPrincipalGetBegin.hEnum;
1811 Worker_DoTask (wtaskKasPrincipalGetDone, &wpDone);
1814 #ifdef FIND_PTS_DEBRIS
1815 // Icky horrible painful part: to catch entries which exist on PTS
1816 // but not in KAS, we need to zip back through our list of groups
1817 // and check thier memberships.
1819 for (LPENUM pe = m_lGroups->FindFirst(); pe; pe = pe->FindNext())
1821 LPPTSGROUP lpGroup = (LPPTSGROUP)(pe->GetObject());
1824 if (lpGroup->GetMembers (&mszMembers))
1826 for (LPTSTR pszMember = mszMembers; pszMember && *pszMember; pszMember += 1+lstrlen(pszMember))
1828 // Make sure we have a user or group account for this guy.
1829 // Remember that the member name may have both a name and
1832 if (m_lkGroupName->GetFirstObject (pszMember))
1835 TCHAR szNameMatch[ cchNAME ];
1836 TCHAR szInstanceMatch[ cchNAME ];
1837 USER::SplitUserName (pszMember, szNameMatch, szInstanceMatch);
1839 LPUSER lpFound = NULL;
1840 for (LPENUM pEnum = m_lkUserName->FindFirst (szNameMatch); pEnum; pEnum = pEnum->FindNext())
1842 LPUSER lpTest = (LPUSER)( pEnum->GetObject() );
1843 if (!lstrcmpi (lpTest->m_szInstance, szInstanceMatch))
1853 // Uh oh. Is this thing a user or a group? We're really only
1854 // interested in finding user-account debris here...
1857 wpGet.wpPtsUserGet.hCell = GetCellObject();
1858 wpGet.wpPtsUserGet.pszUser = pszMember;
1859 if (Worker_DoTask (wtaskPtsUserGet, &wpGet))
1861 if (wpGet.wpPtsUserGet.Entry.nameUid > 0)
1863 LPUSER lpUser = New2 (USER,(this, pszMember, TEXT("")));
1864 m_lUsers->Add (lpUser);
1872 // We've finally generated a complete list of the users and groups in
1873 // this cell. If we've been asked to, send out notifications for all
1874 // the things we found.
1879 for (pEnum = m_lGroups->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1881 LPPTSGROUP lpGroup = (LPPTSGROUP)(pEnum->GetObject());
1882 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpGroup->GetIdentifier());
1885 for (pEnum = m_lUsers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1887 LPUSER lpUser = (LPUSER)(pEnum->GetObject());
1888 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpUser->GetIdentifier());
1891 NOTIFYCALLBACK::SendNotificationToAll (evtRefreshUsersEnd, GetIdentifier(), ((rc) ? 0 : status));
1901 void CELL::BuildGroups (LPTSTR mszGroups)
1903 for (LPTSTR pszGroup = mszGroups; pszGroup && *pszGroup; pszGroup += 1+lstrlen(pszGroup))
1905 // Make sure we have this group in our list-of-groups
1908 if ((lpGroup = (LPPTSGROUP)m_lkGroupName->GetFirstObject (pszGroup)) == NULL)
1910 lpGroup = New2 (PTSGROUP,(this, pszGroup));
1911 m_lGroups->Add (lpGroup);
1917 BOOL CELL::RefreshAccount (LPTSTR pszAccount, LPTSTR pszInstance, OP_CELL_REFRESH_ACCOUNT Op, LPIDENT *plpi)
1921 // See if we can find this thing
1924 if ((lpi = IDENT::FindUser (m_lpiThis, pszAccount, pszInstance)) != NULL)
1926 if (lpi->m_cRef == 0)
1931 if ((lpi = IDENT::FindGroup (m_lpiThis, pszAccount)) != NULL)
1932 if (lpi->m_cRef == 0)
1936 // If we couldn't find it, and Op is _CREATED_*, then make a new account
1938 if ((!lpi) && (Op == CELL_REFRESH_ACCOUNT_CREATED_USER))
1940 LPUSER lpUser = New2 (USER,(this, pszAccount, pszInstance));
1941 m_lUsers->Add (lpUser);
1942 lpi = lpUser->GetIdentifier();
1943 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpi);
1945 else if ((!lpi) && (Op == CELL_REFRESH_ACCOUNT_CREATED_GROUP))
1947 LPPTSGROUP lpGroup = New2 (PTSGROUP,(this, pszAccount));
1948 m_lGroups->Add (lpGroup);
1949 lpi = lpGroup->GetIdentifier();
1950 NOTIFYCALLBACK::SendNotificationToAll (evtCreate, lpi);
1953 // If we did find it, and Op is _DELETED, then remove the account
1955 if (lpi && (Op == CELL_REFRESH_ACCOUNT_DELETED))
1957 if (lpi && (lpi->GetType() == itUSER))
1960 if ((lpUser = lpi->OpenUser()) == NULL)
1964 lpUser->SendDeleteNotifications();
1966 m_lUsers->Remove (lpUser);
1971 else if (lpi && (lpi->GetType() == itGROUP))
1974 if ((lpGroup = lpi->OpenGroup()) == NULL)
1978 lpGroup->SendDeleteNotifications();
1980 m_lGroups->Remove (lpGroup);
1991 // If we still have an ident, refresh the account's properties
1993 if (lpi && (lpi->GetType() == itUSER))
1996 if ((lpUser = lpi->OpenUser()) == NULL)
2000 lpUser->Invalidate();
2001 lpUser->RefreshStatus();
2005 else if (lpi && (lpi->GetType() == itGROUP))
2008 if ((lpGroup = lpi->OpenGroup()) == NULL)
2012 lpGroup->Invalidate();
2013 lpGroup->RefreshStatus();
2024 BOOL CELL::RefreshAccounts (LPTSTR mszAccounts, OP_CELL_REFRESH_ACCOUNT Op)
2027 for (LPTSTR psz = mszAccounts; psz && *psz; psz += 1+lstrlen(psz))
2029 if (!RefreshAccount (psz, NULL, Op))