/// <summary> /// Push NotificationMessages to clients on an interval basis /// Same interval is used to release locks of timed out users /// </summary> private void PushNotifications() { while(true) { lock (currentUsers) { List<string> goneUserSessions = new List<string>(); foreach (KeyValuePair<string, UserContext> e in currentUsers) { if(e.Value.ConnectionState == CommunicationState.Closed) { string goneUserLogin = e.Value.LoginName; Console.WriteLine("User {0} gone, release locks ..................", goneUserLogin); LockBatch batch = TMImplementation.Instance.GetCurrentLocks(goneUserLogin); if(!TMImplementation.Instance.Unlock(goneUserLogin, batch)) { // This will not happen, anyway : ) Console.WriteLine("It seems like not all locks have been released for user: {0}.", goneUserLogin); } LockMessage msg = new LockMessage(goneUserLogin, false, batch); // this is be perfectly valid because same thread can acquire same mutex multiple times NotifyAll(msg); goneUserSessions.Add(e.Key); } else { e.Value.PushNextMessage(); } } foreach(string sessionId in goneUserSessions) { currentUsers.Remove(sessionId); } } Thread.Sleep(pushInterval); } }
public UnlockResponse Unlock(int id, ItemType itemType) { UnlockResponse r = new UnlockResponse(); UserContext userContext = null; if(!ValidSession(out userContext)) { r.Success = false; r.ErrorDesc = "No valid session"; } else { LockBatch batch = null; Type type = ResourceMap.ItemTypeToModelType(itemType); if(type == typeof(CollectionPoint)) { r.Success = tm.Unlock<CollectionPoint>(id, userContext.LoginName, out batch); } else if (type == typeof(Customer)) { r.Success = tm.Unlock<Customer>(id, userContext.LoginName, out batch); } else { r.Success = false; r.ErrorDesc = "You can't unlock this item."; } //notify all clients on unlock success if(r.Success) { LockMessage lockMsg = new LockMessage(userContext.LoginName, false, batch); userContextProvider.NotifyAll(lockMsg); } } return r; }
public LoginResponse Login(string loginName) { LoginResponse r = new LoginResponse(); userContextProvider.AddUser(OperationContext.Current.SessionId, loginName); UserContext context = null; if (ValidSession(out context)) { r.Success = true; List<string> currentUser = userContextProvider.GetCurrentUsers(); foreach(string userLogin in currentUser) { LockBatch currentLocks = tm.GetCurrentLocks(userLogin); LockMessage msg = new LockMessage(userLogin, true, currentLocks); userContextProvider.NotifyUser(OperationContext.Current.SessionId, msg); } } else { r.Success = false; r.ErrorDesc = "Login failed"; } return r; }
public LockResponse TryLock(int id, ItemType itemType) { Console.WriteLine("Lock request for item {0} with id: {1}", itemType, id); LockResponse r = new LockResponse(); UserContext userContext = null; if(!ValidSession(out userContext)) { r.Success = false; r.ErrorDesc = "No valid session"; return r; } else { LockBatch batch = null; Type type = ResourceMap.ItemTypeToModelType(itemType); if (type == typeof(CollectionPoint)) { r.Success = tm.TryLock<CollectionPoint>(id, userContext.LoginName, out batch); } else if (type == typeof(Customer)) { r.Success = tm.TryLock<Customer>(id, userContext.LoginName, out batch); } else { r.Success = false; r.ErrorDesc = "You can't lock this item."; } //notify all clients on lock success if (r.Success) { LockMessage lockMsg = new LockMessage(userContext.LoginName, true, batch); userContextProvider.NotifyAll(lockMsg); } } return r; }