Controlling Login Information

ConnectedUser.cs
001/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 002using System; 003using System.Collections; 004using Db4objects.Db4o; 005using Db4objects.Db4o.Config; 006using Db4objects.Db4o.Ext; 007using Db4objects.Db4o.Query; 008 009 010namespace Db4objects.Db4odoc.Semaphores 011{ 012 013 /** 014 * This class demonstrates how semaphores can be used 015 * to rule out race conditions when providing exact and 016 * up-to-date information about all connected clients 017 * on a server. The class also can be used to make sure 018 * that only one login is possible with a give user name 019 * and ipAddress combination. 020 */ 021 public class ConnectedUser 022 { 023 024 public const string SemaphoreConnected = "ConnectedUser_"; 025 public const string SemaphoreLockAccess = "ConnectedUser_Lock_"; 026 027 public const int Timeout = 10000; // concurrent access timeout 10 seconds 028 029 String userName; 030 String ipAddress; 031 032 public ConnectedUser(String userName, String ipAddress) 033 { 034 this.userName = userName; 035 this.ipAddress = ipAddress; 036 } 037 038 // make sure to call this on the server before opening the database 039 // to improve querying speed 040 public static void Configure() 041 { 042 IObjectClass objectClass = Db4oFactory.Configure().ObjectClass(typeof(ConnectedUser)); 043 objectClass.ObjectField("userName").Indexed(true); 044 objectClass.ObjectField("ipAddress").Indexed(true); 045 } 046 047 // call this on the client to ensure to have a ConnectedUser record 048 // in the database file and the semaphore set 049 public static void Login(IObjectContainer client, String userName, String ipAddress) 050 { 051 if (!client.Ext().SetSemaphore(SemaphoreLockAccess, Timeout)) 052 { 053 throw new Exception("Timeout trying to get access to ConnectedUser lock"); 054 } 055 IQuery q = client.Query(); 056 q.Constrain(typeof(ConnectedUser)); 057 q.Descend("userName").Constrain(userName); 058 q.Descend("ipAddress").Constrain(ipAddress); 059 if(q.Execute().Size() == 0) 060 { 061 client.Set(new ConnectedUser(userName, ipAddress)); 062 client.Commit(); 063 } 064 String connectedSemaphoreName = SemaphoreConnected + userName + ipAddress; 065 bool unique = client.Ext().SetSemaphore(connectedSemaphoreName, 0); 066 client.Ext().ReleaseSemaphore(SemaphoreLockAccess); 067 if(! unique) 068 { 069 throw new Exception("Two clients with same userName and ipAddress"); 070 } 071 } 072 073 // here is your list of all connected users, callable on the server 074 public static IList ConnectedUsers(IObjectServer server) 075 { 076 IExtObjectContainer serverObjectContainer = server.Ext().ObjectContainer().Ext(); 077 if (serverObjectContainer.SetSemaphore(SemaphoreLockAccess, Timeout)) 078 { 079 throw new Exception("Timeout trying to get access to ConnectedUser lock"); 080 } 081 IList list = new ArrayList(); 082 IQuery q = serverObjectContainer.Query(); 083 q.Constrain(typeof(ConnectedUser)); 084 IObjectSet objectSet = q.Execute(); 085 while(objectSet.HasNext()) 086 { 087 ConnectedUser connectedUser = (ConnectedUser)objectSet.Next(); 088 String connectedSemaphoreName = 089 SemaphoreConnected + 090 connectedUser.userName + 091 connectedUser.ipAddress; 092 if(serverObjectContainer.SetSemaphore(connectedSemaphoreName, Timeout)) 093 { 094 serverObjectContainer.Delete(connectedUser); 095 } 096 else 097 { 098 list.Add(connectedUser); 099 } 100 } 101 serverObjectContainer.Commit(); 102 serverObjectContainer.ReleaseSemaphore(SemaphoreLockAccess); 103 return list; 104 } 105 } 106}

ConnectedUser.vb
01' Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com 02Imports System 03Imports System.Collections 04Imports Db4objects.Db4o 05Imports Db4objects.Db4o.Config 06Imports Db4objects.Db4o.Ext 07Imports Db4objects.Db4o.Query 08 09 10Namespace Db4objects.Db4odoc.Semaphores 11 ' 12 ' This class demonstrates how semaphores can be used 13 ' to rule race conditions when providing exact and 14 ' up-to-date information about all connected clients 15 ' on a server. The class also can be used to make sure 16 ' that only one login is possible with a give user name 17 ' and ipAddress combination. 18 ' 19 Public Class ConnectedUser 20 21 Public Shared ReadOnly SemaphoreConnected As String = "ConnectedUser_" 22 Public Shared ReadOnly SemaphoreLockAccess As String = "ConnectedUser_Lock_" 23 24 Public Shared ReadOnly Timeout As Integer = 10000 ' concurrent access timeout 10 seconds 25 26 Dim userName As String 27 Dim ipAddress As String 28 29 Public Sub New(ByVal userName As String, ByVal ipAddress As String) 30 Me.userName = userName 31 Me.ipAddress = ipAddress 32 End Sub 33 34 ' make sure to call this on the server before opening the database 35 ' to improve querying speed 36 Public Shared Sub Configure() 37 Dim objectClass As IObjectClass = Db4oFactory.Configure().ObjectClass(GetType(ConnectedUser)) 38 objectClass.ObjectField("userName").Indexed(True) 39 objectClass.ObjectField("ipAddress").Indexed(True) 40 End Sub 41 42 ' call this on the client to ensure to have a ConnectedUser record 43 ' in the database file and the semaphore set 44 Public Shared Sub Login(ByVal client As IObjectContainer, ByVal userName As String, ByVal ipAddress As String) 45 If Not client.Ext().SetSemaphore(SemaphoreLockAccess, Timeout) Then 46 Throw New Exception("Timeout Trying to get access to ConnectedUser lock") 47 End If 48 Dim q As IQuery = client.Query() 49 q.Constrain(GetType(ConnectedUser)) 50 q.Descend("userName").Constrain(userName) 51 q.Descend("ipAddress").Constrain(ipAddress) 52 If q.Execute().Size() = 0 Then 53 client.Set(New ConnectedUser(userName, ipAddress)) 54 client.Commit() 55 End If 56 Dim connectedSemaphoreName As String = SemaphoreConnected + userName + ipAddress 57 Dim unique As Boolean = client.Ext().SetSemaphore(connectedSemaphoreName, 0) 58 client.Ext().ReleaseSemaphore(SemaphoreLockAccess) 59 If Not unique Then 60 Throw New Exception("Two clients with same userName and ipAddress") 61 End If 62 End Sub 63 64 ' here is your list of all connected users, callable on the server 65 Public Shared Function ConnectedUsers(ByVal server As IObjectServer) As IList 66 Dim serverObjectContainer As IExtObjectContainer = server.Ext().ObjectContainer().Ext() 67 If serverObjectContainer.SetSemaphore(SemaphoreLockAccess, TIMEOUT) Then 68 Throw New Exception("Timeout Trying to get access to ConnectedUser lock") 69 End If 70 Dim list As IList = New ArrayList() 71 Dim q As IQuery = serverObjectContainer.Query() 72 q.Constrain(GetType(ConnectedUser)) 73 Dim objectSet As IObjectSet = q.Execute() 74 While objectSet.HasNext() 75 Dim connectedUser As ConnectedUser = CType(objectSet.Next(), ConnectedUser) 76 Dim connectedSemaphoreName As String = SemaphoreConnected + connectedUser.userName + connectedUser.ipAddress 77 If serverObjectContainer.SetSemaphore(connectedSemaphoreName, TIMEOUT) Then 78 serverObjectContainer.Delete(connectedUser) 79 Else 80 list.Add(connectedUser) 81 End If 82 End While 83 serverObjectContainer.Commit() 84 serverObjectContainer.ReleaseSemaphore(SemaphoreLockAccess) 85 Return list 86 End Function 87 End Class 88End Namespace