diff options
author | Sean McNamara | 2011-05-02 02:23:18 -0400 |
---|---|---|
committer | Sean McNamara | 2011-05-02 02:23:18 -0400 |
commit | fffd42f5cbbb9e59b6fde3247aeb0d80d990319f (patch) | |
tree | 034b3e8da351954bc1124d91ec1f28e29e6a68c6 /OpenSim | |
parent | First pass at fixing justincc's feedback v2 ( http://opensimulator.org/mantis... (diff) | |
parent | Fixed confusing OSDMap that comes as the response of QueryAccess in the case ... (diff) | |
download | opensim-SC_OLD-fffd42f5cbbb9e59b6fde3247aeb0d80d990319f.zip opensim-SC_OLD-fffd42f5cbbb9e59b6fde3247aeb0d80d990319f.tar.gz opensim-SC_OLD-fffd42f5cbbb9e59b6fde3247aeb0d80d990319f.tar.bz2 opensim-SC_OLD-fffd42f5cbbb9e59b6fde3247aeb0d80d990319f.tar.xz |
Merge git://opensimulator.org/git/opensim
Diffstat (limited to 'OpenSim')
44 files changed, 1293 insertions, 621 deletions
diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs index 6a5d6eb..f5492b3 100644 --- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs +++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs | |||
@@ -56,15 +56,15 @@ namespace OpenSim.Data.MSSQL | |||
56 | string realm, string storeName) | 56 | string realm, string storeName) |
57 | { | 57 | { |
58 | m_Realm = realm; | 58 | m_Realm = realm; |
59 | |||
60 | m_ConnectionString = connectionString; | ||
59 | 61 | ||
60 | if (storeName != String.Empty) | 62 | if (storeName != String.Empty) |
61 | { | 63 | { |
62 | Assembly assem = GetType().Assembly; | ||
63 | m_ConnectionString = connectionString; | ||
64 | using (SqlConnection conn = new SqlConnection(m_ConnectionString)) | 64 | using (SqlConnection conn = new SqlConnection(m_ConnectionString)) |
65 | { | 65 | { |
66 | conn.Open(); | 66 | conn.Open(); |
67 | Migration m = new Migration(conn, assem, storeName); | 67 | Migration m = new Migration(conn, GetType().Assembly, storeName); |
68 | m.Update(); | 68 | m.Update(); |
69 | } | 69 | } |
70 | 70 | ||
diff --git a/OpenSim/Data/MSSQL/MSSQLMigration.cs b/OpenSim/Data/MSSQL/MSSQLMigration.cs index aea31c9..cd395b8 100644 --- a/OpenSim/Data/MSSQL/MSSQLMigration.cs +++ b/OpenSim/Data/MSSQL/MSSQLMigration.cs | |||
@@ -61,7 +61,8 @@ namespace OpenSim.Data.MSSQL | |||
61 | } | 61 | } |
62 | catch | 62 | catch |
63 | { | 63 | { |
64 | // Something went wrong, so we're version 0 | 64 | // Return -1 to indicate table does not exist |
65 | return -1; | ||
65 | } | 66 | } |
66 | } | 67 | } |
67 | return version; | 68 | return version; |
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs index 80ec65e..5155e56 100644 --- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs +++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs | |||
@@ -492,12 +492,11 @@ ELSE | |||
492 | using (SqlConnection conn = new SqlConnection(m_connectionString)) | 492 | using (SqlConnection conn = new SqlConnection(m_connectionString)) |
493 | using (SqlCommand cmd = new SqlCommand(sql, conn)) | 493 | using (SqlCommand cmd = new SqlCommand(sql, conn)) |
494 | { | 494 | { |
495 | conn.Open(); | ||
495 | foreach (TaskInventoryItem taskItem in items) | 496 | foreach (TaskInventoryItem taskItem in items) |
496 | { | 497 | { |
497 | cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem)); | 498 | cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem)); |
498 | conn.Open(); | ||
499 | cmd.ExecuteNonQuery(); | 499 | cmd.ExecuteNonQuery(); |
500 | |||
501 | cmd.Parameters.Clear(); | 500 | cmd.Parameters.Clear(); |
502 | } | 501 | } |
503 | } | 502 | } |
@@ -1154,9 +1153,9 @@ VALUES | |||
1154 | PrimitiveBaseShape baseShape = new PrimitiveBaseShape(); | 1153 | PrimitiveBaseShape baseShape = new PrimitiveBaseShape(); |
1155 | 1154 | ||
1156 | baseShape.Scale = new Vector3( | 1155 | baseShape.Scale = new Vector3( |
1157 | Convert.ToSingle(shapeRow["ScaleX"]), | 1156 | (float)Convert.ToDouble(shapeRow["ScaleX"]), |
1158 | Convert.ToSingle(shapeRow["ScaleY"]), | 1157 | (float)Convert.ToDouble(shapeRow["ScaleY"]), |
1159 | Convert.ToSingle(shapeRow["ScaleZ"])); | 1158 | (float)Convert.ToDouble(shapeRow["ScaleZ"])); |
1160 | 1159 | ||
1161 | // paths | 1160 | // paths |
1162 | baseShape.PCode = Convert.ToByte(shapeRow["PCode"]); | 1161 | baseShape.PCode = Convert.ToByte(shapeRow["PCode"]); |
@@ -1193,8 +1192,11 @@ VALUES | |||
1193 | { | 1192 | { |
1194 | } | 1193 | } |
1195 | 1194 | ||
1196 | if (!(shapeRow["Media"] is System.DBNull)) | 1195 | if (!(shapeRow["Media"] is System.DBNull) ) |
1196 | { | ||
1197 | baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]); | 1197 | baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]); |
1198 | } | ||
1199 | |||
1198 | 1200 | ||
1199 | return baseShape; | 1201 | return baseShape; |
1200 | } | 1202 | } |
@@ -1573,7 +1575,16 @@ VALUES | |||
1573 | parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry)); | 1575 | parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry)); |
1574 | parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams)); | 1576 | parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams)); |
1575 | parameters.Add(_Database.CreateParameter("State", s.State)); | 1577 | parameters.Add(_Database.CreateParameter("State", s.State)); |
1576 | parameters.Add(_Database.CreateParameter("Media", null == s.Media ? null : s.Media.ToXml())); | 1578 | |
1579 | if(null == s.Media ) | ||
1580 | { | ||
1581 | parameters.Add(_Database.CreateParameter("Media", DBNull.Value)); | ||
1582 | } | ||
1583 | else | ||
1584 | { | ||
1585 | parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml())); | ||
1586 | } | ||
1587 | |||
1577 | 1588 | ||
1578 | return parameters.ToArray(); | 1589 | return parameters.ToArray(); |
1579 | } | 1590 | } |
diff --git a/OpenSim/Data/MSSQL/Resources/AuthStore.migrations b/OpenSim/Data/MSSQL/Resources/AuthStore.migrations index 5b90ca3..eb91296 100644 --- a/OpenSim/Data/MSSQL/Resources/AuthStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/AuthStore.migrations | |||
@@ -22,7 +22,11 @@ COMMIT | |||
22 | 22 | ||
23 | BEGIN TRANSACTION | 23 | BEGIN TRANSACTION |
24 | 24 | ||
25 | INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users; | 25 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[users]') AND type in (N'U')) |
26 | INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users; | ||
27 | |||
28 | COMMIT | ||
29 | |||
30 | |||
26 | 31 | ||
27 | 32 | ||
28 | COMMIT \ No newline at end of file | ||
diff --git a/OpenSim/Data/MSSQL/Resources/Avatar.migrations b/OpenSim/Data/MSSQL/Resources/Avatar.migrations index 759e939..5364153 100644 --- a/OpenSim/Data/MSSQL/Resources/Avatar.migrations +++ b/OpenSim/Data/MSSQL/Resources/Avatar.migrations | |||
@@ -13,5 +13,28 @@ PRIMARY KEY CLUSTERED | |||
13 | ) ON [PRIMARY] | 13 | ) ON [PRIMARY] |
14 | 14 | ||
15 | 15 | ||
16 | COMMIT | ||
17 | |||
18 | :VERSION 2 | ||
19 | |||
20 | BEGIN TRANSACTION | ||
21 | |||
22 | CREATE TABLE dbo.Tmp_Avatars | ||
23 | ( | ||
24 | PrincipalID uniqueidentifier NOT NULL, | ||
25 | [Name] varchar(32) NOT NULL, | ||
26 | Value text NOT NULL DEFAULT '', | ||
27 | ) ON [PRIMARY] | ||
28 | TEXTIMAGE_ON [PRIMARY] | ||
29 | |||
30 | IF EXISTS(SELECT * FROM dbo.Avatars) | ||
31 | EXEC('INSERT INTO dbo.Tmp_Avatars (PrincipalID, Name, Value) | ||
32 | SELECT PrincipalID, CONVERT(text, Name), Value FROM dbo.Avatars WITH (HOLDLOCK TABLOCKX)') | ||
33 | |||
34 | DROP TABLE dbo.Avatars | ||
35 | |||
36 | EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT' | ||
37 | |||
38 | COMMIT | ||
39 | |||
16 | 40 | ||
17 | COMMIT \ No newline at end of file | ||
diff --git a/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations b/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations index f981a91..4d8ab0f 100644 --- a/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations | |||
@@ -15,6 +15,8 @@ COMMIT | |||
15 | 15 | ||
16 | BEGIN TRANSACTION | 16 | BEGIN TRANSACTION |
17 | 17 | ||
18 | INSERT INTO Friends (PrincipalID, Friend, Flags, Offered) SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends; | 18 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[userfriends]') AND type in (N'U')) |
19 | INSERT INTO Friends (PrincipalID, Friend, Flags, Offered) | ||
20 | SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends; | ||
19 | 21 | ||
20 | COMMIT \ No newline at end of file | 22 | COMMIT \ No newline at end of file |
diff --git a/OpenSim/Data/MSSQL/Resources/GridStore.migrations b/OpenSim/Data/MSSQL/Resources/GridStore.migrations index d2ca27a..c6342fc 100644 --- a/OpenSim/Data/MSSQL/Resources/GridStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/GridStore.migrations | |||
@@ -222,4 +222,17 @@ ALTER TABLE [regions] ADD [Token] varchar(255) NOT NULL DEFAULT 0; | |||
222 | 222 | ||
223 | COMMIT | 223 | COMMIT |
224 | 224 | ||
225 | :VERSION 8 | ||
225 | 226 | ||
227 | BEGIN TRANSACTION | ||
228 | ALTER TABLE regions ALTER COLUMN regionName VarChar(128) | ||
229 | |||
230 | DROP INDEX IX_regions_name ON dbo.regions | ||
231 | ALTER TABLE regions ALTER COLUMN regionName VarChar(128) null | ||
232 | |||
233 | CREATE NONCLUSTERED INDEX IX_regions_name ON dbo.regions | ||
234 | ( | ||
235 | regionName | ||
236 | ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] | ||
237 | |||
238 | COMMIT \ No newline at end of file | ||
diff --git a/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations b/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations index e2a8d57..4a3cb27 100644 --- a/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations | |||
@@ -238,7 +238,10 @@ alter table inventoryitems | |||
238 | 238 | ||
239 | COMMIT | 239 | COMMIT |
240 | 240 | ||
241 | 241 | :VERSION 8 | |
242 | |||
243 | |||
244 | 242 | ||
243 | ALTER TABLE inventoryitems | ||
244 | ADD CONSTRAINT DF_inventoryitems_creatorID | ||
245 | DEFAULT '00000000-0000-0000-0000-000000000000' FOR creatorID | ||
246 | |||
247 | :GO \ No newline at end of file | ||
diff --git a/OpenSim/Data/MSSQL/Resources/Presence.migrations b/OpenSim/Data/MSSQL/Resources/Presence.migrations index 35f78e1..bcb6328 100644 --- a/OpenSim/Data/MSSQL/Resources/Presence.migrations +++ b/OpenSim/Data/MSSQL/Resources/Presence.migrations | |||
@@ -7,14 +7,7 @@ CREATE TABLE [Presence] ( | |||
7 | [RegionID] uniqueidentifier NOT NULL, | 7 | [RegionID] uniqueidentifier NOT NULL, |
8 | [SessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', | 8 | [SessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', |
9 | [SecureSessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', | 9 | [SecureSessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', |
10 | [Online] char(5) NOT NULL DEFAULT 'false', | 10 | |
11 | [Login] char(16) NOT NULL DEFAULT '0', | ||
12 | [Logout] char(16) NOT NULL DEFAULT '0', | ||
13 | [Position] char(64) NOT NULL DEFAULT '<0,0,0>', | ||
14 | [LookAt] char(64) NOT NULL DEFAULT '<0,0,0>', | ||
15 | [HomeRegionID] uniqueidentifier NOT NULL, | ||
16 | [HomePosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>', | ||
17 | [HomeLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>', | ||
18 | ) | 11 | ) |
19 | ON [PRIMARY] | 12 | ON [PRIMARY] |
20 | 13 | ||
@@ -27,4 +20,12 @@ BEGIN TRANSACTION | |||
27 | CREATE UNIQUE INDEX SessionID ON Presence(SessionID); | 20 | CREATE UNIQUE INDEX SessionID ON Presence(SessionID); |
28 | CREATE INDEX UserID ON Presence(UserID); | 21 | CREATE INDEX UserID ON Presence(UserID); |
29 | 22 | ||
23 | COMMIT | ||
24 | |||
25 | :VERSION 2 | ||
26 | |||
27 | BEGIN TRANSACTION | ||
28 | |||
29 | ALTER TABLE Presence ADD LastSeen DateTime | ||
30 | |||
30 | COMMIT \ No newline at end of file | 31 | COMMIT \ No newline at end of file |
diff --git a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations index e2e8cbb..340b63d 100644 --- a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations | |||
@@ -1,4 +1,3 @@ | |||
1 | |||
2 | :VERSION 1 | 1 | :VERSION 1 |
3 | 2 | ||
4 | CREATE TABLE [dbo].[prims]( | 3 | CREATE TABLE [dbo].[prims]( |
@@ -926,11 +925,121 @@ ALTER TABLE regionsettings ADD loaded_creation_datetime int NOT NULL default 0 | |||
926 | COMMIT | 925 | COMMIT |
927 | 926 | ||
928 | :VERSION 24 | 927 | :VERSION 24 |
929 | -- Added post 0.7 | ||
930 | 928 | ||
931 | BEGIN TRANSACTION | 929 | BEGIN TRANSACTION |
932 | 930 | ||
933 | ALTER TABLE prims ADD COLUMN MediaURL varchar(255) | 931 | ALTER TABLE prims ADD MediaURL varchar(255) |
934 | ALTER TABLE primshapes ADD COLUMN Media TEXT | 932 | ALTER TABLE primshapes ADD Media TEXT NULL |
933 | |||
934 | COMMIT | ||
935 | |||
936 | :VERSION 25 | ||
937 | |||
938 | BEGIN TRANSACTION | ||
939 | CREATE TABLE "regionwindlight" ( | ||
940 | "region_id" varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000', | ||
941 | "water_color_r" [float] NOT NULL DEFAULT '4.000000', | ||
942 | "water_color_g" [float] NOT NULL DEFAULT '38.000000', | ||
943 | "water_color_b" [float] NOT NULL DEFAULT '64.000000', | ||
944 | "water_fog_density_exponent" [float] NOT NULL DEFAULT '4.0', | ||
945 | "underwater_fog_modifier" [float] NOT NULL DEFAULT '0.25', | ||
946 | "reflection_wavelet_scale_1" [float] NOT NULL DEFAULT '2.0', | ||
947 | "reflection_wavelet_scale_2" [float] NOT NULL DEFAULT '2.0', | ||
948 | "reflection_wavelet_scale_3" [float] NOT NULL DEFAULT '2.0', | ||
949 | "fresnel_scale" [float] NOT NULL DEFAULT '0.40', | ||
950 | "fresnel_offset" [float] NOT NULL DEFAULT '0.50', | ||
951 | "refract_scale_above" [float] NOT NULL DEFAULT '0.03', | ||
952 | "refract_scale_below" [float] NOT NULL DEFAULT '0.20', | ||
953 | "blur_multiplier" [float] NOT NULL DEFAULT '0.040', | ||
954 | "big_wave_direction_x" [float] NOT NULL DEFAULT '1.05', | ||
955 | "big_wave_direction_y" [float] NOT NULL DEFAULT '-0.42', | ||
956 | "little_wave_direction_x" [float] NOT NULL DEFAULT '1.11', | ||
957 | "little_wave_direction_y" [float] NOT NULL DEFAULT '-1.16', | ||
958 | "normal_map_texture" varchar(36) NOT NULL DEFAULT '822ded49-9a6c-f61c-cb89-6df54f42cdf4', | ||
959 | "horizon_r" [float] NOT NULL DEFAULT '0.25', | ||
960 | "horizon_g" [float] NOT NULL DEFAULT '0.25', | ||
961 | "horizon_b" [float] NOT NULL DEFAULT '0.32', | ||
962 | "horizon_i" [float] NOT NULL DEFAULT '0.32', | ||
963 | "haze_horizon" [float] NOT NULL DEFAULT '0.19', | ||
964 | "blue_density_r" [float] NOT NULL DEFAULT '0.12', | ||
965 | "blue_density_g" [float] NOT NULL DEFAULT '0.22', | ||
966 | "blue_density_b" [float] NOT NULL DEFAULT '0.38', | ||
967 | "blue_density_i" [float] NOT NULL DEFAULT '0.38', | ||
968 | "haze_density" [float] NOT NULL DEFAULT '0.70', | ||
969 | "density_multiplier" [float] NOT NULL DEFAULT '0.18', | ||
970 | "distance_multiplier" [float] NOT NULL DEFAULT '0.8', | ||
971 | "max_altitude" int NOT NULL DEFAULT '1605', | ||
972 | "sun_moon_color_r" [float] NOT NULL DEFAULT '0.24', | ||
973 | "sun_moon_color_g" [float] NOT NULL DEFAULT '0.26', | ||
974 | "sun_moon_color_b" [float] NOT NULL DEFAULT '0.30', | ||
975 | "sun_moon_color_i" [float] NOT NULL DEFAULT '0.30', | ||
976 | "sun_moon_position" [float] NOT NULL DEFAULT '0.317', | ||
977 | "ambient_r" [float] NOT NULL DEFAULT '0.35', | ||
978 | "ambient_g" [float] NOT NULL DEFAULT '0.35', | ||
979 | "ambient_b" [float] NOT NULL DEFAULT '0.35', | ||
980 | "ambient_i" [float] NOT NULL DEFAULT '0.35', | ||
981 | "east_angle" [float] NOT NULL DEFAULT '0.00', | ||
982 | "sun_glow_focus" [float] NOT NULL DEFAULT '0.10', | ||
983 | "sun_glow_size" [float] NOT NULL DEFAULT '1.75', | ||
984 | "scene_gamma" [float] NOT NULL DEFAULT '1.00', | ||
985 | "star_brightness" [float] NOT NULL DEFAULT '0.00', | ||
986 | "cloud_color_r" [float] NOT NULL DEFAULT '0.41', | ||
987 | "cloud_color_g" [float] NOT NULL DEFAULT '0.41', | ||
988 | "cloud_color_b" [float] NOT NULL DEFAULT '0.41', | ||
989 | "cloud_color_i" [float] NOT NULL DEFAULT '0.41', | ||
990 | "cloud_x" [float] NOT NULL DEFAULT '1.00', | ||
991 | "cloud_y" [float] NOT NULL DEFAULT '0.53', | ||
992 | "cloud_density" [float] NOT NULL DEFAULT '1.00', | ||
993 | "cloud_coverage" [float] NOT NULL DEFAULT '0.27', | ||
994 | "cloud_scale" [float] NOT NULL DEFAULT '0.42', | ||
995 | "cloud_detail_x" [float] NOT NULL DEFAULT '1.00', | ||
996 | "cloud_detail_y" [float] NOT NULL DEFAULT '0.53', | ||
997 | "cloud_detail_density" [float] NOT NULL DEFAULT '0.12', | ||
998 | "cloud_scroll_x" [float] NOT NULL DEFAULT '0.20', | ||
999 | "cloud_scroll_x_lock" tinyint NOT NULL DEFAULT '0', | ||
1000 | "cloud_scroll_y" [float] NOT NULL DEFAULT '0.01', | ||
1001 | "cloud_scroll_y_lock" tinyint NOT NULL DEFAULT '0', | ||
1002 | "draw_classic_clouds" tinyint NOT NULL DEFAULT '1', | ||
1003 | PRIMARY KEY ("region_id") | ||
1004 | ) | ||
1005 | |||
1006 | COMMIT TRANSACTION | ||
1007 | |||
1008 | :VERSION 26 | ||
1009 | |||
1010 | BEGIN TRANSACTION | ||
1011 | |||
1012 | ALTER TABLE regionsettings ADD map_tile_ID CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000' | ||
1013 | |||
1014 | COMMIT | ||
1015 | |||
1016 | :VERSION 27 #--------------------- | ||
935 | 1017 | ||
936 | COMMIT \ No newline at end of file | 1018 | BEGIN TRANSACTION |
1019 | ALTER TABLE land ADD MediaType VARCHAR(32) NOT NULL DEFAULT 'none/none' | ||
1020 | ALTER TABLE land ADD MediaDescription VARCHAR(255) NOT NULL DEFAULT '' | ||
1021 | ALTER TABLE land ADD MediaSize VARCHAR(16) NOT NULL DEFAULT '0,0' | ||
1022 | ALTER TABLE land ADD MediaLoop bit NOT NULL DEFAULT 0 | ||
1023 | ALTER TABLE land ADD ObscureMusic bit NOT NULL DEFAULT 0 | ||
1024 | ALTER TABLE land ADD ObscureMedia bit NOT NULL DEFAULT 0 | ||
1025 | COMMIT | ||
1026 | |||
1027 | :VERSION 28 #--------------------- | ||
1028 | |||
1029 | BEGIN TRANSACTION | ||
1030 | |||
1031 | ALTER TABLE prims | ||
1032 | ADD CONSTRAINT DF_prims_CreatorID | ||
1033 | DEFAULT '00000000-0000-0000-0000-000000000000' | ||
1034 | FOR CreatorID | ||
1035 | |||
1036 | ALTER TABLE prims ALTER COLUMN CreatorID uniqueidentifier NOT NULL | ||
1037 | |||
1038 | ALTER TABLE primitems | ||
1039 | ADD CONSTRAINT DF_primitems_CreatorID | ||
1040 | DEFAULT '00000000-0000-0000-0000-000000000000' | ||
1041 | FOR CreatorID | ||
1042 | |||
1043 | ALTER TABLE primitems ALTER COLUMN CreatorID uniqueidentifier NOT NULL | ||
1044 | |||
1045 | COMMIT | ||
diff --git a/OpenSim/Data/MSSQL/Resources/UserAccount.migrations b/OpenSim/Data/MSSQL/Resources/UserAccount.migrations index 8534e23..a81704d 100644 --- a/OpenSim/Data/MSSQL/Resources/UserAccount.migrations +++ b/OpenSim/Data/MSSQL/Resources/UserAccount.migrations | |||
@@ -19,7 +19,7 @@ CREATE TABLE [UserAccounts] ( | |||
19 | :VERSION 2 | 19 | :VERSION 2 |
20 | 20 | ||
21 | BEGIN TRANSACTION | 21 | BEGIN TRANSACTION |
22 | 22 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[users]') AND type in (N'U')) | |
23 | INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT [UUID] AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, | 23 | INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT [UUID] AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, |
24 | username AS FirstName, | 24 | username AS FirstName, |
25 | lastname AS LastName, | 25 | lastname AS LastName, |
diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index 3dbc215..dbd47d3 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs | |||
@@ -152,27 +152,6 @@ namespace OpenSim.Framework | |||
152 | } | 152 | } |
153 | 153 | ||
154 | /// <summary> | 154 | /// <summary> |
155 | /// Create AgentCircuitData from a Serializable AgentCircuitData | ||
156 | /// </summary> | ||
157 | /// <param name="cAgent"></param> | ||
158 | public AgentCircuitData(sAgentCircuitData cAgent) | ||
159 | { | ||
160 | AgentID = new UUID(cAgent.AgentID); | ||
161 | SessionID = new UUID(cAgent.SessionID); | ||
162 | SecureSessionID = new UUID(cAgent.SecureSessionID); | ||
163 | startpos = new Vector3(cAgent.startposx, cAgent.startposy, cAgent.startposz); | ||
164 | firstname = cAgent.firstname; | ||
165 | lastname = cAgent.lastname; | ||
166 | circuitcode = cAgent.circuitcode; | ||
167 | child = cAgent.child; | ||
168 | InventoryFolder = new UUID(cAgent.InventoryFolder); | ||
169 | BaseFolder = new UUID(cAgent.BaseFolder); | ||
170 | CapsPath = cAgent.CapsPath; | ||
171 | ChildrenCapSeeds = cAgent.ChildrenCapSeeds; | ||
172 | Viewer = cAgent.Viewer; | ||
173 | } | ||
174 | |||
175 | /// <summary> | ||
176 | /// Pack AgentCircuitData into an OSDMap for transmission over LLSD XML or LLSD json | 155 | /// Pack AgentCircuitData into an OSDMap for transmission over LLSD XML or LLSD json |
177 | /// </summary> | 156 | /// </summary> |
178 | /// <returns>map of the agent circuit data</returns> | 157 | /// <returns>map of the agent circuit data</returns> |
@@ -369,52 +348,4 @@ namespace OpenSim.Framework | |||
369 | } | 348 | } |
370 | 349 | ||
371 | 350 | ||
372 | /// <summary> | ||
373 | /// Serializable Agent Circuit Data | ||
374 | /// </summary> | ||
375 | [Serializable] | ||
376 | public class sAgentCircuitData | ||
377 | { | ||
378 | public Guid AgentID; | ||
379 | public Guid BaseFolder; | ||
380 | public string CapsPath = String.Empty; | ||
381 | public Dictionary<ulong, string> ChildrenCapSeeds; | ||
382 | public bool child; | ||
383 | public uint circuitcode; | ||
384 | public string firstname; | ||
385 | public Guid InventoryFolder; | ||
386 | public string lastname; | ||
387 | public Guid SecureSessionID; | ||
388 | public Guid SessionID; | ||
389 | public float startposx; | ||
390 | public float startposy; | ||
391 | public float startposz; | ||
392 | public string Viewer; | ||
393 | public string Channel; | ||
394 | public string Mac; | ||
395 | public string Id0; | ||
396 | |||
397 | public sAgentCircuitData() | ||
398 | { | ||
399 | } | ||
400 | |||
401 | public sAgentCircuitData(AgentCircuitData cAgent) | ||
402 | { | ||
403 | AgentID = cAgent.AgentID.Guid; | ||
404 | SessionID = cAgent.SessionID.Guid; | ||
405 | SecureSessionID = cAgent.SecureSessionID.Guid; | ||
406 | startposx = cAgent.startpos.X; | ||
407 | startposy = cAgent.startpos.Y; | ||
408 | startposz = cAgent.startpos.Z; | ||
409 | firstname = cAgent.firstname; | ||
410 | lastname = cAgent.lastname; | ||
411 | circuitcode = cAgent.circuitcode; | ||
412 | child = cAgent.child; | ||
413 | InventoryFolder = cAgent.InventoryFolder.Guid; | ||
414 | BaseFolder = cAgent.BaseFolder.Guid; | ||
415 | CapsPath = cAgent.CapsPath; | ||
416 | ChildrenCapSeeds = cAgent.ChildrenCapSeeds; | ||
417 | Viewer = cAgent.Viewer; | ||
418 | } | ||
419 | } | ||
420 | } | 351 | } |
diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index ce0b2fb..28fe3ba 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs | |||
@@ -62,7 +62,7 @@ namespace OpenSim.Framework | |||
62 | UUID AgentID { get; set; } | 62 | UUID AgentID { get; set; } |
63 | 63 | ||
64 | OSDMap Pack(); | 64 | OSDMap Pack(); |
65 | void Unpack(OSDMap map); | 65 | void Unpack(OSDMap map, IScene scene); |
66 | } | 66 | } |
67 | 67 | ||
68 | /// <summary> | 68 | /// <summary> |
@@ -122,7 +122,7 @@ namespace OpenSim.Framework | |||
122 | return args; | 122 | return args; |
123 | } | 123 | } |
124 | 124 | ||
125 | public void Unpack(OSDMap args) | 125 | public void Unpack(OSDMap args, IScene scene) |
126 | { | 126 | { |
127 | if (args.ContainsKey("region_handle")) | 127 | if (args.ContainsKey("region_handle")) |
128 | UInt64.TryParse(args["region_handle"].AsString(), out RegionHandle); | 128 | UInt64.TryParse(args["region_handle"].AsString(), out RegionHandle); |
@@ -329,6 +329,10 @@ namespace OpenSim.Framework | |||
329 | 329 | ||
330 | public string CallbackURI; | 330 | public string CallbackURI; |
331 | 331 | ||
332 | // These two must have the same Count | ||
333 | public List<ISceneObject> AttachmentObjects; | ||
334 | public List<string> AttachmentObjectStates; | ||
335 | |||
332 | public virtual OSDMap Pack() | 336 | public virtual OSDMap Pack() |
333 | { | 337 | { |
334 | m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data"); | 338 | m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data"); |
@@ -441,7 +445,30 @@ namespace OpenSim.Framework | |||
441 | if ((CallbackURI != null) && (!CallbackURI.Equals(""))) | 445 | if ((CallbackURI != null) && (!CallbackURI.Equals(""))) |
442 | args["callback_uri"] = OSD.FromString(CallbackURI); | 446 | args["callback_uri"] = OSD.FromString(CallbackURI); |
443 | 447 | ||
448 | // Attachment objects for fatpack messages | ||
449 | if (AttachmentObjects != null) | ||
450 | { | ||
451 | int i = 0; | ||
452 | OSDArray attObjs = new OSDArray(AttachmentObjects.Count); | ||
453 | foreach (ISceneObject so in AttachmentObjects) | ||
454 | { | ||
455 | OSDMap info = new OSDMap(4); | ||
456 | info["sog"] = OSD.FromString(so.ToXml2()); | ||
457 | info["extra"] = OSD.FromString(so.ExtraToXmlString()); | ||
458 | info["modified"] = OSD.FromBoolean(so.HasGroupChanged); | ||
459 | try | ||
460 | { | ||
461 | info["state"] = OSD.FromString(AttachmentObjectStates[i++]); | ||
462 | } | ||
463 | catch (IndexOutOfRangeException e) | ||
464 | { | ||
465 | m_log.WarnFormat("[CHILD AGENT DATA]: scripts list is shorter than object list."); | ||
466 | } | ||
444 | 467 | ||
468 | attObjs.Add(info); | ||
469 | } | ||
470 | args["attach_objects"] = attObjs; | ||
471 | } | ||
445 | return args; | 472 | return args; |
446 | } | 473 | } |
447 | 474 | ||
@@ -450,7 +477,7 @@ namespace OpenSim.Framework | |||
450 | /// Avoiding reflection makes it painful to write, but that's the price! | 477 | /// Avoiding reflection makes it painful to write, but that's the price! |
451 | /// </summary> | 478 | /// </summary> |
452 | /// <param name="hash"></param> | 479 | /// <param name="hash"></param> |
453 | public virtual void Unpack(OSDMap args) | 480 | public virtual void Unpack(OSDMap args, IScene scene) |
454 | { | 481 | { |
455 | m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data"); | 482 | m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data"); |
456 | 483 | ||
@@ -628,6 +655,26 @@ namespace OpenSim.Framework | |||
628 | 655 | ||
629 | if (args["callback_uri"] != null) | 656 | if (args["callback_uri"] != null) |
630 | CallbackURI = args["callback_uri"].AsString(); | 657 | CallbackURI = args["callback_uri"].AsString(); |
658 | |||
659 | // Attachment objects | ||
660 | if (args["attach_objects"] != null && args["attach_objects"].Type == OSDType.Array) | ||
661 | { | ||
662 | OSDArray attObjs = (OSDArray)(args["attach_objects"]); | ||
663 | AttachmentObjects = new List<ISceneObject>(); | ||
664 | AttachmentObjectStates = new List<string>(); | ||
665 | foreach (OSD o in attObjs) | ||
666 | { | ||
667 | if (o.Type == OSDType.Map) | ||
668 | { | ||
669 | OSDMap info = (OSDMap)o; | ||
670 | ISceneObject so = scene.DeserializeObject(info["sog"].AsString()); | ||
671 | so.ExtraFromXmlString(info["extra"].AsString()); | ||
672 | so.HasGroupChanged = info["modified"].AsBoolean(); | ||
673 | AttachmentObjects.Add(so); | ||
674 | AttachmentObjectStates.Add(info["state"].AsString()); | ||
675 | } | ||
676 | } | ||
677 | } | ||
631 | } | 678 | } |
632 | 679 | ||
633 | public AgentData() | 680 | public AgentData() |
@@ -655,9 +702,9 @@ namespace OpenSim.Framework | |||
655 | return base.Pack(); | 702 | return base.Pack(); |
656 | } | 703 | } |
657 | 704 | ||
658 | public override void Unpack(OSDMap map) | 705 | public override void Unpack(OSDMap map, IScene scene) |
659 | { | 706 | { |
660 | base.Unpack(map); | 707 | base.Unpack(map, scene); |
661 | } | 708 | } |
662 | } | 709 | } |
663 | } | 710 | } |
diff --git a/OpenSim/Framework/ClientInfo.cs b/OpenSim/Framework/ClientInfo.cs index fbd18b5..62acb70 100644 --- a/OpenSim/Framework/ClientInfo.cs +++ b/OpenSim/Framework/ClientInfo.cs | |||
@@ -31,10 +31,9 @@ using System.Net; | |||
31 | 31 | ||
32 | namespace OpenSim.Framework | 32 | namespace OpenSim.Framework |
33 | { | 33 | { |
34 | [Serializable] | ||
35 | public class ClientInfo | 34 | public class ClientInfo |
36 | { | 35 | { |
37 | public sAgentCircuitData agentcircuit; | 36 | public AgentCircuitData agentcircuit; |
38 | 37 | ||
39 | public Dictionary<uint, byte[]> needAck; | 38 | public Dictionary<uint, byte[]> needAck; |
40 | 39 | ||
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index f573c32..069987b 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs | |||
@@ -572,34 +572,69 @@ namespace OpenSim.Framework | |||
572 | 572 | ||
573 | public class IEntityUpdate | 573 | public class IEntityUpdate |
574 | { | 574 | { |
575 | public ISceneEntity Entity; | 575 | private ISceneEntity m_entity; |
576 | public uint Flags; | 576 | private uint m_flags; |
577 | private int m_updateTime; | ||
578 | |||
579 | public ISceneEntity Entity | ||
580 | { | ||
581 | get { return m_entity; } | ||
582 | } | ||
583 | |||
584 | public uint Flags | ||
585 | { | ||
586 | get { return m_flags; } | ||
587 | } | ||
588 | |||
589 | public int UpdateTime | ||
590 | { | ||
591 | get { return m_updateTime; } | ||
592 | } | ||
577 | 593 | ||
578 | public virtual void Update(IEntityUpdate update) | 594 | public virtual void Update(IEntityUpdate update) |
579 | { | 595 | { |
580 | this.Flags |= update.Flags; | 596 | m_flags |= update.Flags; |
597 | |||
598 | // Use the older of the updates as the updateTime | ||
599 | if (Util.EnvironmentTickCountCompare(UpdateTime, update.UpdateTime) > 0) | ||
600 | m_updateTime = update.UpdateTime; | ||
581 | } | 601 | } |
582 | 602 | ||
583 | public IEntityUpdate(ISceneEntity entity, uint flags) | 603 | public IEntityUpdate(ISceneEntity entity, uint flags) |
584 | { | 604 | { |
585 | Entity = entity; | 605 | m_entity = entity; |
586 | Flags = flags; | 606 | m_flags = flags; |
607 | m_updateTime = Util.EnvironmentTickCount(); | ||
608 | } | ||
609 | |||
610 | public IEntityUpdate(ISceneEntity entity, uint flags, Int32 updateTime) | ||
611 | { | ||
612 | m_entity = entity; | ||
613 | m_flags = flags; | ||
614 | m_updateTime = updateTime; | ||
587 | } | 615 | } |
588 | } | 616 | } |
589 | |||
590 | 617 | ||
591 | public class EntityUpdate : IEntityUpdate | 618 | public class EntityUpdate : IEntityUpdate |
592 | { | 619 | { |
593 | // public ISceneEntity Entity; | 620 | private float m_timeDilation; |
594 | // public PrimUpdateFlags Flags; | 621 | |
595 | public float TimeDilation; | 622 | public float TimeDilation |
623 | { | ||
624 | get { return m_timeDilation; } | ||
625 | } | ||
596 | 626 | ||
597 | public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation) | 627 | public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation) |
598 | : base(entity,(uint)flags) | 628 | : base(entity, (uint)flags) |
599 | { | 629 | { |
600 | //Entity = entity; | ||
601 | // Flags = flags; | 630 | // Flags = flags; |
602 | TimeDilation = timedilation; | 631 | m_timeDilation = timedilation; |
632 | } | ||
633 | |||
634 | public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation, Int32 updateTime) | ||
635 | : base(entity,(uint)flags,updateTime) | ||
636 | { | ||
637 | m_timeDilation = timedilation; | ||
603 | } | 638 | } |
604 | } | 639 | } |
605 | 640 | ||
diff --git a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs index b62ec07..3e6fdaa 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs +++ b/OpenSim/Framework/PriorityQueue.cs | |||
@@ -34,50 +34,81 @@ using OpenSim.Framework; | |||
34 | using OpenSim.Framework.Client; | 34 | using OpenSim.Framework.Client; |
35 | using log4net; | 35 | using log4net; |
36 | 36 | ||
37 | namespace OpenSim.Region.ClientStack.LindenUDP | 37 | namespace OpenSim.Framework |
38 | { | 38 | { |
39 | public class PriorityQueue | 39 | public class PriorityQueue |
40 | { | 40 | { |
41 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 41 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
42 | 42 | ||
43 | internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity); | 43 | public delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity); |
44 | 44 | ||
45 | // Heap[0] for self updates | 45 | /// <summary> |
46 | // Heap[1..12] for entity updates | 46 | /// Total number of queues (priorities) available |
47 | /// </summary> | ||
48 | public const uint NumberOfQueues = 12; | ||
47 | 49 | ||
48 | internal const uint m_numberOfQueues = 12; | 50 | /// <summary> |
51 | /// Number of queuest (priorities) that are processed immediately | ||
52 | /// </summary. | ||
53 | public const uint NumberOfImmediateQueues = 2; | ||
49 | 54 | ||
50 | private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[m_numberOfQueues]; | 55 | private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[NumberOfQueues]; |
51 | private Dictionary<uint, LookupItem> m_lookupTable; | 56 | private Dictionary<uint, LookupItem> m_lookupTable; |
57 | |||
58 | // internal state used to ensure the deqeues are spread across the priority | ||
59 | // queues "fairly". queuecounts is the amount to pull from each queue in | ||
60 | // each pass. weighted towards the higher priority queues | ||
52 | private uint m_nextQueue = 0; | 61 | private uint m_nextQueue = 0; |
62 | private uint m_countFromQueue = 0; | ||
63 | private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 }; | ||
64 | |||
65 | // next request is a counter of the number of updates queued, it provides | ||
66 | // a total ordering on the updates coming through the queue and is more | ||
67 | // lightweight (and more discriminating) than tick count | ||
53 | private UInt64 m_nextRequest = 0; | 68 | private UInt64 m_nextRequest = 0; |
54 | 69 | ||
70 | /// <summary> | ||
71 | /// Lock for enqueue and dequeue operations on the priority queue | ||
72 | /// </summary> | ||
55 | private object m_syncRoot = new object(); | 73 | private object m_syncRoot = new object(); |
56 | public object SyncRoot { | 74 | public object SyncRoot { |
57 | get { return this.m_syncRoot; } | 75 | get { return this.m_syncRoot; } |
58 | } | 76 | } |
59 | 77 | ||
60 | internal PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { } | 78 | #region constructor |
79 | public PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { } | ||
61 | 80 | ||
62 | internal PriorityQueue(int capacity) | 81 | public PriorityQueue(int capacity) |
63 | { | 82 | { |
64 | m_lookupTable = new Dictionary<uint, LookupItem>(capacity); | 83 | m_lookupTable = new Dictionary<uint, LookupItem>(capacity); |
65 | 84 | ||
66 | for (int i = 0; i < m_heaps.Length; ++i) | 85 | for (int i = 0; i < m_heaps.Length; ++i) |
67 | m_heaps[i] = new MinHeap<MinHeapItem>(capacity); | 86 | m_heaps[i] = new MinHeap<MinHeapItem>(capacity); |
87 | |||
88 | m_nextQueue = NumberOfImmediateQueues; | ||
89 | m_countFromQueue = m_queueCounts[m_nextQueue]; | ||
68 | } | 90 | } |
91 | #endregion Constructor | ||
69 | 92 | ||
70 | internal int Count | 93 | #region PublicMethods |
94 | /// <summary> | ||
95 | /// Return the number of items in the queues | ||
96 | /// </summary> | ||
97 | public int Count | ||
71 | { | 98 | { |
72 | get | 99 | get |
73 | { | 100 | { |
74 | int count = 0; | 101 | int count = 0; |
75 | for (int i = 0; i < m_heaps.Length; ++i) | 102 | for (int i = 0; i < m_heaps.Length; ++i) |
76 | count += m_heaps[i].Count; | 103 | count += m_heaps[i].Count; |
104 | |||
77 | return count; | 105 | return count; |
78 | } | 106 | } |
79 | } | 107 | } |
80 | 108 | ||
109 | /// <summary> | ||
110 | /// Enqueue an item into the specified priority queue | ||
111 | /// </summary> | ||
81 | public bool Enqueue(uint pqueue, IEntityUpdate value) | 112 | public bool Enqueue(uint pqueue, IEntityUpdate value) |
82 | { | 113 | { |
83 | LookupItem lookup; | 114 | LookupItem lookup; |
@@ -91,7 +122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
91 | lookup.Heap.Remove(lookup.Handle); | 122 | lookup.Heap.Remove(lookup.Handle); |
92 | } | 123 | } |
93 | 124 | ||
94 | pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1); | 125 | pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1); |
95 | lookup.Heap = m_heaps[pqueue]; | 126 | lookup.Heap = m_heaps[pqueue]; |
96 | lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle); | 127 | lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle); |
97 | m_lookupTable[localid] = lookup; | 128 | m_lookupTable[localid] = lookup; |
@@ -99,20 +130,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
99 | return true; | 130 | return true; |
100 | } | 131 | } |
101 | 132 | ||
102 | internal bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue) | 133 | /// <summary> |
134 | /// Remove an item from one of the queues. Specifically, it removes the | ||
135 | /// oldest item from the next queue in order to provide fair access to | ||
136 | /// all of the queues | ||
137 | /// </summary> | ||
138 | public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue) | ||
103 | { | 139 | { |
104 | for (int i = 0; i < m_numberOfQueues; ++i) | 140 | // If there is anything in priority queue 0, return it first no |
141 | // matter what else. Breaks fairness. But very useful. | ||
142 | for (int iq = 0; iq < NumberOfImmediateQueues; iq++) | ||
105 | { | 143 | { |
106 | // To get the fair queing, we cycle through each of the | 144 | if (m_heaps[iq].Count > 0) |
107 | // queues when finding an element to dequeue, this code | ||
108 | // assumes that the distribution of updates in the queues | ||
109 | // is polynomial, probably quadractic (eg distance of PI * R^2) | ||
110 | uint h = (uint)((m_nextQueue + i) % m_numberOfQueues); | ||
111 | if (m_heaps[h].Count > 0) | ||
112 | { | 145 | { |
113 | m_nextQueue = (uint)((h + 1) % m_numberOfQueues); | 146 | MinHeapItem item = m_heaps[iq].RemoveMin(); |
147 | m_lookupTable.Remove(item.Value.Entity.LocalId); | ||
148 | timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); | ||
149 | value = item.Value; | ||
114 | 150 | ||
115 | MinHeapItem item = m_heaps[h].RemoveMin(); | 151 | return true; |
152 | } | ||
153 | } | ||
154 | |||
155 | // To get the fair queing, we cycle through each of the | ||
156 | // queues when finding an element to dequeue. | ||
157 | // We pull (NumberOfQueues - QueueIndex) items from each queue in order | ||
158 | // to give lower numbered queues a higher priority and higher percentage | ||
159 | // of the bandwidth. | ||
160 | |||
161 | // Check for more items to be pulled from the current queue | ||
162 | if (m_heaps[m_nextQueue].Count > 0 && m_countFromQueue > 0) | ||
163 | { | ||
164 | m_countFromQueue--; | ||
165 | |||
166 | MinHeapItem item = m_heaps[m_nextQueue].RemoveMin(); | ||
167 | m_lookupTable.Remove(item.Value.Entity.LocalId); | ||
168 | timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); | ||
169 | value = item.Value; | ||
170 | |||
171 | return true; | ||
172 | } | ||
173 | |||
174 | // Find the next non-immediate queue with updates in it | ||
175 | for (int i = 0; i < NumberOfQueues; ++i) | ||
176 | { | ||
177 | m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues); | ||
178 | m_countFromQueue = m_queueCounts[m_nextQueue]; | ||
179 | |||
180 | // if this is one of the immediate queues, just skip it | ||
181 | if (m_nextQueue < NumberOfImmediateQueues) | ||
182 | continue; | ||
183 | |||
184 | if (m_heaps[m_nextQueue].Count > 0) | ||
185 | { | ||
186 | m_countFromQueue--; | ||
187 | |||
188 | MinHeapItem item = m_heaps[m_nextQueue].RemoveMin(); | ||
116 | m_lookupTable.Remove(item.Value.Entity.LocalId); | 189 | m_lookupTable.Remove(item.Value.Entity.LocalId); |
117 | timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); | 190 | timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); |
118 | value = item.Value; | 191 | value = item.Value; |
@@ -126,7 +199,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
126 | return false; | 199 | return false; |
127 | } | 200 | } |
128 | 201 | ||
129 | internal void Reprioritize(UpdatePriorityHandler handler) | 202 | /// <summary> |
203 | /// Reapply the prioritization function to each of the updates currently | ||
204 | /// stored in the priority queues. | ||
205 | /// </summary | ||
206 | public void Reprioritize(UpdatePriorityHandler handler) | ||
130 | { | 207 | { |
131 | MinHeapItem item; | 208 | MinHeapItem item; |
132 | foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values)) | 209 | foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values)) |
@@ -140,7 +217,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
140 | { | 217 | { |
141 | // unless the priority queue has changed, there is no need to modify | 218 | // unless the priority queue has changed, there is no need to modify |
142 | // the entry | 219 | // the entry |
143 | pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1); | 220 | pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1); |
144 | if (pqueue != item.PriorityQueue) | 221 | if (pqueue != item.PriorityQueue) |
145 | { | 222 | { |
146 | lookup.Heap.Remove(lookup.Handle); | 223 | lookup.Heap.Remove(lookup.Handle); |
@@ -161,17 +238,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
161 | } | 238 | } |
162 | } | 239 | } |
163 | 240 | ||
241 | /// <summary> | ||
242 | /// </summary> | ||
164 | public override string ToString() | 243 | public override string ToString() |
165 | { | 244 | { |
166 | string s = ""; | 245 | string s = ""; |
167 | for (int i = 0; i < m_numberOfQueues; i++) | 246 | for (int i = 0; i < NumberOfQueues; i++) |
168 | { | 247 | s += String.Format("{0,7} ",m_heaps[i].Count); |
169 | if (s != "") s += ","; | ||
170 | s += m_heaps[i].Count.ToString(); | ||
171 | } | ||
172 | return s; | 248 | return s; |
173 | } | 249 | } |
174 | 250 | ||
251 | #endregion PublicMethods | ||
252 | |||
175 | #region MinHeapItem | 253 | #region MinHeapItem |
176 | private struct MinHeapItem : IComparable<MinHeapItem> | 254 | private struct MinHeapItem : IComparable<MinHeapItem> |
177 | { | 255 | { |
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs index e7f8bfc..76de6be 100644 --- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs +++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs | |||
@@ -115,7 +115,7 @@ namespace OpenSim.Framework.Tests | |||
115 | position2 = new AgentPosition(); | 115 | position2 = new AgentPosition(); |
116 | 116 | ||
117 | Assert.IsFalse(position2.AgentID == position1.AgentID, "Test Error, position2 should be a blank uninitialized AgentPosition"); | 117 | Assert.IsFalse(position2.AgentID == position1.AgentID, "Test Error, position2 should be a blank uninitialized AgentPosition"); |
118 | position2.Unpack(position1.Pack()); | 118 | position2.Unpack(position1.Pack(), null); |
119 | 119 | ||
120 | Assert.IsTrue(position2.AgentID == position1.AgentID, "Agent ID didn't unpack the same way it packed"); | 120 | Assert.IsTrue(position2.AgentID == position1.AgentID, "Agent ID didn't unpack the same way it packed"); |
121 | Assert.IsTrue(position2.Position == position1.Position, "Position didn't unpack the same way it packed"); | 121 | Assert.IsTrue(position2.Position == position1.Position, "Position didn't unpack the same way it packed"); |
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 5a5046e..aaa2724 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs | |||
@@ -1537,6 +1537,23 @@ namespace OpenSim.Framework | |||
1537 | return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1); | 1537 | return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1); |
1538 | } | 1538 | } |
1539 | 1539 | ||
1540 | // Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount | ||
1541 | // Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount(). | ||
1542 | // A positive return value indicates A occured later than B | ||
1543 | public static Int32 EnvironmentTickCountCompare(Int32 tcA, Int32 tcB) | ||
1544 | { | ||
1545 | // A, B and TC are all between 0 and 0x3fffffff | ||
1546 | int tc = EnvironmentTickCount(); | ||
1547 | |||
1548 | if (tc - tcA >= 0) | ||
1549 | tcA += EnvironmentTickCountMask + 1; | ||
1550 | |||
1551 | if (tc - tcB >= 0) | ||
1552 | tcB += EnvironmentTickCountMask + 1; | ||
1553 | |||
1554 | return tcA - tcB; | ||
1555 | } | ||
1556 | |||
1540 | /// <summary> | 1557 | /// <summary> |
1541 | /// Prints the call stack at any given point. Useful for debugging. | 1558 | /// Prints the call stack at any given point. Useful for debugging. |
1542 | /// </summary> | 1559 | /// </summary> |
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 9d70f63..ac0828b 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs | |||
@@ -142,17 +142,17 @@ namespace OpenSim.Framework | |||
142 | /// </summary> | 142 | /// </summary> |
143 | public static OSDMap PutToService(string url, OSDMap data) | 143 | public static OSDMap PutToService(string url, OSDMap data) |
144 | { | 144 | { |
145 | return ServiceOSDRequest(url,data,"PUT",10000); | 145 | return ServiceOSDRequest(url,data,"PUT",30000); |
146 | } | 146 | } |
147 | 147 | ||
148 | public static OSDMap PostToService(string url, OSDMap data) | 148 | public static OSDMap PostToService(string url, OSDMap data) |
149 | { | 149 | { |
150 | return ServiceOSDRequest(url,data,"POST",10000); | 150 | return ServiceOSDRequest(url,data,"POST",30000); |
151 | } | 151 | } |
152 | 152 | ||
153 | public static OSDMap GetFromService(string url) | 153 | public static OSDMap GetFromService(string url) |
154 | { | 154 | { |
155 | return ServiceOSDRequest(url,null,"GET",10000); | 155 | return ServiceOSDRequest(url,null,"GET",30000); |
156 | } | 156 | } |
157 | 157 | ||
158 | public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout) | 158 | public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout) |
@@ -171,15 +171,15 @@ namespace OpenSim.Framework | |||
171 | request.Timeout = timeout; | 171 | request.Timeout = timeout; |
172 | request.KeepAlive = false; | 172 | request.KeepAlive = false; |
173 | request.MaximumAutomaticRedirections = 10; | 173 | request.MaximumAutomaticRedirections = 10; |
174 | request.ReadWriteTimeout = timeout / 4; | 174 | request.ReadWriteTimeout = timeout * 8; |
175 | request.Headers[OSHeaderRequestID] = reqnum.ToString(); | 175 | request.Headers[OSHeaderRequestID] = reqnum.ToString(); |
176 | 176 | ||
177 | // If there is some input, write it into the request | 177 | // If there is some input, write it into the request |
178 | if (data != null) | 178 | if (data != null) |
179 | { | 179 | { |
180 | string strBuffer = OSDParser.SerializeJsonString(data); | 180 | string strBuffer = OSDParser.SerializeJsonString(data); |
181 | byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer); | 181 | byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer); |
182 | 182 | ||
183 | request.ContentType = "application/json"; | 183 | request.ContentType = "application/json"; |
184 | request.ContentLength = buffer.Length; //Count bytes to send | 184 | request.ContentLength = buffer.Length; //Count bytes to send |
185 | using (Stream requestStream = request.GetRequestStream()) | 185 | using (Stream requestStream = request.GetRequestStream()) |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 0f7f666..43903ce 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -385,6 +385,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
385 | public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } | 385 | public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } |
386 | 386 | ||
387 | /// <summary> | 387 | /// <summary> |
388 | /// Entity update queues | ||
389 | /// </summary> | ||
390 | public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } } | ||
391 | |||
392 | /// <summary> | ||
388 | /// First name of the agent/avatar represented by the client | 393 | /// First name of the agent/avatar represented by the client |
389 | /// </summary> | 394 | /// </summary> |
390 | public string FirstName { get { return m_firstName; } } | 395 | public string FirstName { get { return m_firstName; } } |
@@ -3561,6 +3566,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3561 | m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); | 3566 | m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); |
3562 | } | 3567 | } |
3563 | 3568 | ||
3569 | /// <summary> | ||
3570 | /// Requeue an EntityUpdate when it was not acknowledged by the client. | ||
3571 | /// We will update the priority and put it in the correct queue, merging update flags | ||
3572 | /// with any other updates that may be queued for the same entity. | ||
3573 | /// The original update time is used for the merged update. | ||
3574 | /// </summary> | ||
3575 | private void ResendPrimUpdate(EntityUpdate update) | ||
3576 | { | ||
3577 | // If the update exists in priority queue, it will be updated. | ||
3578 | // If it does not exist then it will be added with the current (rather than its original) priority | ||
3579 | uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); | ||
3580 | |||
3581 | lock (m_entityUpdates.SyncRoot) | ||
3582 | m_entityUpdates.Enqueue(priority, update); | ||
3583 | } | ||
3584 | |||
3585 | /// <summary> | ||
3586 | /// Requeue a list of EntityUpdates when they were not acknowledged by the client. | ||
3587 | /// We will update the priority and put it in the correct queue, merging update flags | ||
3588 | /// with any other updates that may be queued for the same entity. | ||
3589 | /// The original update time is used for the merged update. | ||
3590 | /// </summary> | ||
3591 | private void ResendPrimUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket) | ||
3592 | { | ||
3593 | // m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime); | ||
3594 | |||
3595 | // Remove the update packet from the list of packets waiting for acknowledgement | ||
3596 | // because we are requeuing the list of updates. They will be resent in new packets | ||
3597 | // with the most recent state and priority. | ||
3598 | m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); | ||
3599 | |||
3600 | // Count this as a resent packet since we are going to requeue all of the updates contained in it | ||
3601 | Interlocked.Increment(ref m_udpClient.PacketsResent); | ||
3602 | |||
3603 | foreach (EntityUpdate update in updates) | ||
3604 | ResendPrimUpdate(update); | ||
3605 | } | ||
3606 | |||
3564 | private void ProcessEntityUpdates(int maxUpdates) | 3607 | private void ProcessEntityUpdates(int maxUpdates) |
3565 | { | 3608 | { |
3566 | OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); | 3609 | OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); |
@@ -3568,6 +3611,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3568 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); | 3611 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); |
3569 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); | 3612 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); |
3570 | 3613 | ||
3614 | OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||
3615 | OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||
3616 | OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||
3617 | OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||
3618 | |||
3571 | // Check to see if this is a flush | 3619 | // Check to see if this is a flush |
3572 | if (maxUpdates <= 0) | 3620 | if (maxUpdates <= 0) |
3573 | { | 3621 | { |
@@ -3583,7 +3631,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3583 | float avgTimeDilation = 1.0f; | 3631 | float avgTimeDilation = 1.0f; |
3584 | IEntityUpdate iupdate; | 3632 | IEntityUpdate iupdate; |
3585 | Int32 timeinqueue; // this is just debugging code & can be dropped later | 3633 | Int32 timeinqueue; // this is just debugging code & can be dropped later |
3586 | 3634 | ||
3587 | while (updatesThisCall < maxUpdates) | 3635 | while (updatesThisCall < maxUpdates) |
3588 | { | 3636 | { |
3589 | lock (m_entityUpdates.SyncRoot) | 3637 | lock (m_entityUpdates.SyncRoot) |
@@ -3688,24 +3736,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3688 | if (update.Entity is ScenePresence) | 3736 | if (update.Entity is ScenePresence) |
3689 | { | 3737 | { |
3690 | objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); | 3738 | objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); |
3739 | objectUpdates.Value.Add(update); | ||
3691 | } | 3740 | } |
3692 | else | 3741 | else |
3693 | { | 3742 | { |
3694 | objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); | 3743 | objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); |
3744 | objectUpdates.Value.Add(update); | ||
3695 | } | 3745 | } |
3696 | } | 3746 | } |
3697 | else if (!canUseImproved) | 3747 | else if (!canUseImproved) |
3698 | { | 3748 | { |
3699 | compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); | 3749 | compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); |
3750 | compressedUpdates.Value.Add(update); | ||
3700 | } | 3751 | } |
3701 | else | 3752 | else |
3702 | { | 3753 | { |
3703 | if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) | 3754 | if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) |
3755 | { | ||
3704 | // Self updates go into a special list | 3756 | // Self updates go into a special list |
3705 | terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); | 3757 | terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); |
3758 | terseAgentUpdates.Value.Add(update); | ||
3759 | } | ||
3706 | else | 3760 | else |
3761 | { | ||
3707 | // Everything else goes here | 3762 | // Everything else goes here |
3708 | terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); | 3763 | terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); |
3764 | terseUpdates.Value.Add(update); | ||
3765 | } | ||
3709 | } | 3766 | } |
3710 | 3767 | ||
3711 | #endregion Block Construction | 3768 | #endregion Block Construction |
@@ -3713,28 +3770,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3713 | 3770 | ||
3714 | 3771 | ||
3715 | #region Packet Sending | 3772 | #region Packet Sending |
3716 | |||
3717 | //const float TIME_DILATION = 1.0f; | ||
3718 | |||
3719 | |||
3720 | ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); | 3773 | ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); |
3721 | 3774 | ||
3722 | if (terseAgentUpdateBlocks.IsValueCreated) | 3775 | if (terseAgentUpdateBlocks.IsValueCreated) |
3723 | { | 3776 | { |
3724 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; | 3777 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; |
3725 | 3778 | ||
3726 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); | 3779 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); |
3727 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 3780 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
3728 | packet.RegionData.TimeDilation = timeDilation; | 3781 | packet.RegionData.TimeDilation = timeDilation; |
3729 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | 3782 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; |
3730 | 3783 | ||
3731 | for (int i = 0; i < blocks.Count; i++) | 3784 | for (int i = 0; i < blocks.Count; i++) |
3732 | packet.ObjectData[i] = blocks[i]; | 3785 | packet.ObjectData[i] = blocks[i]; |
3733 | 3786 | // If any of the packets created from this call go unacknowledged, all of the updates will be resent | |
3734 | 3787 | OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); | |
3735 | OutPacket(packet, ThrottleOutPacketType.Unknown, true); | ||
3736 | } | 3788 | } |
3737 | 3789 | ||
3738 | if (objectUpdateBlocks.IsValueCreated) | 3790 | if (objectUpdateBlocks.IsValueCreated) |
3739 | { | 3791 | { |
3740 | List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; | 3792 | List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; |
@@ -3746,8 +3798,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3746 | 3798 | ||
3747 | for (int i = 0; i < blocks.Count; i++) | 3799 | for (int i = 0; i < blocks.Count; i++) |
3748 | packet.ObjectData[i] = blocks[i]; | 3800 | packet.ObjectData[i] = blocks[i]; |
3749 | 3801 | // If any of the packets created from this call go unacknowledged, all of the updates will be resent | |
3750 | OutPacket(packet, ThrottleOutPacketType.Task, true); | 3802 | OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); }); |
3751 | } | 3803 | } |
3752 | 3804 | ||
3753 | if (compressedUpdateBlocks.IsValueCreated) | 3805 | if (compressedUpdateBlocks.IsValueCreated) |
@@ -3761,10 +3813,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3761 | 3813 | ||
3762 | for (int i = 0; i < blocks.Count; i++) | 3814 | for (int i = 0; i < blocks.Count; i++) |
3763 | packet.ObjectData[i] = blocks[i]; | 3815 | packet.ObjectData[i] = blocks[i]; |
3764 | 3816 | // If any of the packets created from this call go unacknowledged, all of the updates will be resent | |
3765 | OutPacket(packet, ThrottleOutPacketType.Task, true); | 3817 | OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); }); |
3766 | } | 3818 | } |
3767 | 3819 | ||
3768 | if (terseUpdateBlocks.IsValueCreated) | 3820 | if (terseUpdateBlocks.IsValueCreated) |
3769 | { | 3821 | { |
3770 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; | 3822 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; |
@@ -3776,8 +3828,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3776 | 3828 | ||
3777 | for (int i = 0; i < blocks.Count; i++) | 3829 | for (int i = 0; i < blocks.Count; i++) |
3778 | packet.ObjectData[i] = blocks[i]; | 3830 | packet.ObjectData[i] = blocks[i]; |
3779 | 3831 | // If any of the packets created from this call go unacknowledged, all of the updates will be resent | |
3780 | OutPacket(packet, ThrottleOutPacketType.Task, true); | 3832 | OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); |
3781 | } | 3833 | } |
3782 | } | 3834 | } |
3783 | 3835 | ||
@@ -3969,7 +4021,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3969 | { | 4021 | { |
3970 | SendFamilyProps = SendFamilyProps || update.SendFamilyProps; | 4022 | SendFamilyProps = SendFamilyProps || update.SendFamilyProps; |
3971 | SendObjectProps = SendObjectProps || update.SendObjectProps; | 4023 | SendObjectProps = SendObjectProps || update.SendObjectProps; |
3972 | Flags |= update.Flags; | 4024 | // other properties may need to be updated by base class |
4025 | base.Update(update); | ||
3973 | } | 4026 | } |
3974 | } | 4027 | } |
3975 | 4028 | ||
@@ -3980,6 +4033,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3980 | m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); | 4033 | m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); |
3981 | } | 4034 | } |
3982 | 4035 | ||
4036 | private void ResendPropertyUpdate(ObjectPropertyUpdate update) | ||
4037 | { | ||
4038 | uint priority = 0; | ||
4039 | lock (m_entityProps.SyncRoot) | ||
4040 | m_entityProps.Enqueue(priority, update); | ||
4041 | } | ||
4042 | |||
4043 | private void ResendPropertyUpdates(List<ObjectPropertyUpdate> updates, OutgoingPacket oPacket) | ||
4044 | { | ||
4045 | // m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime); | ||
4046 | |||
4047 | // Remove the update packet from the list of packets waiting for acknowledgement | ||
4048 | // because we are requeuing the list of updates. They will be resent in new packets | ||
4049 | // with the most recent state. | ||
4050 | m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); | ||
4051 | |||
4052 | // Count this as a resent packet since we are going to requeue all of the updates contained in it | ||
4053 | Interlocked.Increment(ref m_udpClient.PacketsResent); | ||
4054 | |||
4055 | foreach (ObjectPropertyUpdate update in updates) | ||
4056 | ResendPropertyUpdate(update); | ||
4057 | } | ||
4058 | |||
3983 | public void SendObjectPropertiesReply(ISceneEntity entity) | 4059 | public void SendObjectPropertiesReply(ISceneEntity entity) |
3984 | { | 4060 | { |
3985 | uint priority = 0; // time based ordering only | 4061 | uint priority = 0; // time based ordering only |
@@ -3995,6 +4071,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3995 | OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks = | 4071 | OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks = |
3996 | new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>(); | 4072 | new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>(); |
3997 | 4073 | ||
4074 | OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates = | ||
4075 | new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>(); | ||
4076 | |||
4077 | OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates = | ||
4078 | new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>(); | ||
4079 | |||
3998 | IEntityUpdate iupdate; | 4080 | IEntityUpdate iupdate; |
3999 | Int32 timeinqueue; // this is just debugging code & can be dropped later | 4081 | Int32 timeinqueue; // this is just debugging code & can be dropped later |
4000 | 4082 | ||
@@ -4013,6 +4095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4013 | SceneObjectPart sop = (SceneObjectPart)update.Entity; | 4095 | SceneObjectPart sop = (SceneObjectPart)update.Entity; |
4014 | ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); | 4096 | ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); |
4015 | objectFamilyBlocks.Value.Add(objPropDB); | 4097 | objectFamilyBlocks.Value.Add(objPropDB); |
4098 | familyUpdates.Value.Add(update); | ||
4016 | } | 4099 | } |
4017 | } | 4100 | } |
4018 | 4101 | ||
@@ -4023,6 +4106,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4023 | SceneObjectPart sop = (SceneObjectPart)update.Entity; | 4106 | SceneObjectPart sop = (SceneObjectPart)update.Entity; |
4024 | ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); | 4107 | ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); |
4025 | objectPropertiesBlocks.Value.Add(objPropDB); | 4108 | objectPropertiesBlocks.Value.Add(objPropDB); |
4109 | propertyUpdates.Value.Add(update); | ||
4026 | } | 4110 | } |
4027 | } | 4111 | } |
4028 | 4112 | ||
@@ -4030,12 +4114,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4030 | } | 4114 | } |
4031 | 4115 | ||
4032 | 4116 | ||
4033 | Int32 ppcnt = 0; | 4117 | // Int32 ppcnt = 0; |
4034 | Int32 pbcnt = 0; | 4118 | // Int32 pbcnt = 0; |
4035 | 4119 | ||
4036 | if (objectPropertiesBlocks.IsValueCreated) | 4120 | if (objectPropertiesBlocks.IsValueCreated) |
4037 | { | 4121 | { |
4038 | List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value; | 4122 | List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value; |
4123 | List<ObjectPropertyUpdate> updates = propertyUpdates.Value; | ||
4039 | 4124 | ||
4040 | ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); | 4125 | ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); |
4041 | packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count]; | 4126 | packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count]; |
@@ -4043,28 +4128,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4043 | packet.ObjectData[i] = blocks[i]; | 4128 | packet.ObjectData[i] = blocks[i]; |
4044 | 4129 | ||
4045 | packet.Header.Zerocoded = true; | 4130 | packet.Header.Zerocoded = true; |
4046 | OutPacket(packet, ThrottleOutPacketType.Task, true); | ||
4047 | 4131 | ||
4048 | pbcnt += blocks.Count; | 4132 | // Pass in the delegate so that if this packet needs to be resent, we send the current properties |
4049 | ppcnt++; | 4133 | // of the object rather than the properties when the packet was created |
4134 | OutPacket(packet, ThrottleOutPacketType.Task, true, | ||
4135 | delegate(OutgoingPacket oPacket) | ||
4136 | { | ||
4137 | ResendPropertyUpdates(updates, oPacket); | ||
4138 | }); | ||
4139 | |||
4140 | // pbcnt += blocks.Count; | ||
4141 | // ppcnt++; | ||
4050 | } | 4142 | } |
4051 | 4143 | ||
4052 | Int32 fpcnt = 0; | 4144 | // Int32 fpcnt = 0; |
4053 | Int32 fbcnt = 0; | 4145 | // Int32 fbcnt = 0; |
4054 | 4146 | ||
4055 | if (objectFamilyBlocks.IsValueCreated) | 4147 | if (objectFamilyBlocks.IsValueCreated) |
4056 | { | 4148 | { |
4057 | List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value; | 4149 | List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value; |
4058 | 4150 | ||
4059 | // ObjectPropertiesFamilyPacket objPropFamilyPack = | ||
4060 | // (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); | ||
4061 | // | ||
4062 | // objPropFamilyPack.ObjectData = new ObjectPropertiesFamilyPacket.ObjectDataBlock[blocks.Count]; | ||
4063 | // for (int i = 0; i < blocks.Count; i++) | ||
4064 | // objPropFamilyPack.ObjectData[i] = blocks[i]; | ||
4065 | // | ||
4066 | // OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task, true); | ||
4067 | |||
4068 | // one packet per object block... uggh... | 4151 | // one packet per object block... uggh... |
4069 | for (int i = 0; i < blocks.Count; i++) | 4152 | for (int i = 0; i < blocks.Count; i++) |
4070 | { | 4153 | { |
@@ -4073,10 +4156,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4073 | 4156 | ||
4074 | packet.ObjectData = blocks[i]; | 4157 | packet.ObjectData = blocks[i]; |
4075 | packet.Header.Zerocoded = true; | 4158 | packet.Header.Zerocoded = true; |
4076 | OutPacket(packet, ThrottleOutPacketType.Task); | ||
4077 | 4159 | ||
4078 | fpcnt++; | 4160 | // Pass in the delegate so that if this packet needs to be resent, we send the current properties |
4079 | fbcnt++; | 4161 | // of the object rather than the properties when the packet was created |
4162 | List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); | ||
4163 | updates.Add(familyUpdates.Value[i]); | ||
4164 | OutPacket(packet, ThrottleOutPacketType.Task, true, | ||
4165 | delegate(OutgoingPacket oPacket) | ||
4166 | { | ||
4167 | ResendPropertyUpdates(updates, oPacket); | ||
4168 | }); | ||
4169 | |||
4170 | // fpcnt++; | ||
4171 | // fbcnt++; | ||
4080 | } | 4172 | } |
4081 | 4173 | ||
4082 | } | 4174 | } |
@@ -4113,7 +4205,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4113 | 4205 | ||
4114 | return block; | 4206 | return block; |
4115 | } | 4207 | } |
4116 | 4208 | ||
4117 | private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop) | 4209 | private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop) |
4118 | { | 4210 | { |
4119 | //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); | 4211 | //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); |
@@ -11336,7 +11428,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11336 | /// <returns></returns> | 11428 | /// <returns></returns> |
11337 | public byte[] GetThrottlesPacked(float multiplier) | 11429 | public byte[] GetThrottlesPacked(float multiplier) |
11338 | { | 11430 | { |
11339 | return m_udpClient.GetThrottlesPacked(); | 11431 | return m_udpClient.GetThrottlesPacked(multiplier); |
11340 | } | 11432 | } |
11341 | 11433 | ||
11342 | /// <summary> | 11434 | /// <summary> |
@@ -11371,6 +11463,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11371 | /// handles splitting manually</param> | 11463 | /// handles splitting manually</param> |
11372 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) | 11464 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) |
11373 | { | 11465 | { |
11466 | OutPacket(packet, throttlePacketType, doAutomaticSplitting, null); | ||
11467 | } | ||
11468 | |||
11469 | /// <summary> | ||
11470 | /// This is the starting point for sending a simulator packet out to the client | ||
11471 | /// </summary> | ||
11472 | /// <param name="packet">Packet to send</param> | ||
11473 | /// <param name="throttlePacketType">Throttling category for the packet</param> | ||
11474 | /// <param name="doAutomaticSplitting">True to automatically split oversized | ||
11475 | /// packets (the default), or false to disable splitting if the calling code | ||
11476 | /// handles splitting manually</param> | ||
11477 | /// <param name="method">The method to be called in the event this packet is reliable | ||
11478 | /// and unacknowledged. The server will provide normal resend capability if you do not | ||
11479 | /// provide your own method.</param> | ||
11480 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) | ||
11481 | { | ||
11374 | if (m_debugPacketLevel > 0) | 11482 | if (m_debugPacketLevel > 0) |
11375 | { | 11483 | { |
11376 | bool logPacket = true; | 11484 | bool logPacket = true; |
@@ -11396,7 +11504,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11396 | m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); | 11504 | m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); |
11397 | } | 11505 | } |
11398 | 11506 | ||
11399 | m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); | 11507 | m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); |
11400 | } | 11508 | } |
11401 | 11509 | ||
11402 | public bool AddMoney(int debit) | 11510 | public bool AddMoney(int debit) |
@@ -11527,7 +11635,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11527 | 11635 | ||
11528 | info.userEP = m_userEndPoint; | 11636 | info.userEP = m_userEndPoint; |
11529 | info.proxyEP = null; | 11637 | info.proxyEP = null; |
11530 | info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); | 11638 | info.agentcircuit = RequestClientInfo(); |
11531 | 11639 | ||
11532 | return info; | 11640 | return info; |
11533 | } | 11641 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index 7be8a0a..ca5501d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | |||
@@ -135,7 +135,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
135 | private int m_nextOnQueueEmpty = 1; | 135 | private int m_nextOnQueueEmpty = 1; |
136 | 136 | ||
137 | /// <summary>Throttle bucket for this agent's connection</summary> | 137 | /// <summary>Throttle bucket for this agent's connection</summary> |
138 | private readonly TokenBucket m_throttleClient; | 138 | private readonly AdaptiveTokenBucket m_throttleClient; |
139 | public AdaptiveTokenBucket FlowThrottle | ||
140 | { | ||
141 | get { return m_throttleClient; } | ||
142 | } | ||
143 | |||
139 | /// <summary>Throttle bucket for this agent's connection</summary> | 144 | /// <summary>Throttle bucket for this agent's connection</summary> |
140 | private readonly TokenBucket m_throttleCategory; | 145 | private readonly TokenBucket m_throttleCategory; |
141 | /// <summary>Throttle buckets for each packet category</summary> | 146 | /// <summary>Throttle buckets for each packet category</summary> |
@@ -176,9 +181,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
176 | m_maxRTO = maxRTO; | 181 | m_maxRTO = maxRTO; |
177 | 182 | ||
178 | // Create a token bucket throttle for this client that has the scene token bucket as a parent | 183 | // Create a token bucket throttle for this client that has the scene token bucket as a parent |
179 | m_throttleClient = new TokenBucket(parentThrottle, rates.TotalLimit); | 184 | m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled); |
180 | // Create a token bucket throttle for the total categary with the client bucket as a throttle | 185 | // Create a token bucket throttle for the total categary with the client bucket as a throttle |
181 | m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit); | 186 | m_throttleCategory = new TokenBucket(m_throttleClient, 0); |
182 | // Create an array of token buckets for this clients different throttle categories | 187 | // Create an array of token buckets for this clients different throttle categories |
183 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; | 188 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; |
184 | 189 | ||
@@ -189,7 +194,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
189 | // Initialize the packet outboxes, where packets sit while they are waiting for tokens | 194 | // Initialize the packet outboxes, where packets sit while they are waiting for tokens |
190 | m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); | 195 | m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); |
191 | // Initialize the token buckets that control the throttling for each category | 196 | // Initialize the token buckets that control the throttling for each category |
192 | m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetLimit(type)); | 197 | m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type)); |
193 | } | 198 | } |
194 | 199 | ||
195 | // Default the retransmission timeout to three seconds | 200 | // Default the retransmission timeout to three seconds |
@@ -223,26 +228,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
223 | /// <returns>Information about the client connection</returns> | 228 | /// <returns>Information about the client connection</returns> |
224 | public ClientInfo GetClientInfo() | 229 | public ClientInfo GetClientInfo() |
225 | { | 230 | { |
226 | ///<mic> | ||
227 | TokenBucket tb; | ||
228 | |||
229 | tb = m_throttleClient.Parent; | ||
230 | m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"ROOT"); | ||
231 | |||
232 | tb = m_throttleClient; | ||
233 | m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CLIENT"); | ||
234 | |||
235 | tb = m_throttleCategory; | ||
236 | m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CATEGORY"); | ||
237 | |||
238 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) | ||
239 | { | ||
240 | tb = m_throttleCategories[i]; | ||
241 | m_log.WarnFormat("[TOKENS] {4} <{0}:{1}>: Actual={2},Requested={3}",AgentID,i,tb.DripRate,tb.RequestedDripRate," BUCKET"); | ||
242 | } | ||
243 | |||
244 | ///</mic> | ||
245 | |||
246 | // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists | 231 | // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists |
247 | // of pending and needed ACKs for every client every time some method wants information about | 232 | // of pending and needed ACKs for every client every time some method wants information about |
248 | // this connection is a recipe for poor performance | 233 | // this connection is a recipe for poor performance |
@@ -254,12 +239,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
254 | info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; | 239 | info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; |
255 | info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; | 240 | info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; |
256 | info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; | 241 | info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; |
257 | // info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; | ||
258 | info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; | 242 | info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; |
259 | info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; | 243 | info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; |
260 | info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; | 244 | info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; |
261 | info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + | 245 | info.totalThrottle = (int)m_throttleCategory.DripRate; |
262 | info.taskThrottle + info.assetThrottle + info.textureThrottle; | ||
263 | 246 | ||
264 | return info; | 247 | return info; |
265 | } | 248 | } |
@@ -346,8 +329,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
346 | int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); | 329 | int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); |
347 | // State is a subcategory of task that we allocate a percentage to | 330 | // State is a subcategory of task that we allocate a percentage to |
348 | int state = 0; | 331 | int state = 0; |
349 | // int state = (int)((float)task * STATE_TASK_PERCENTAGE); | ||
350 | // task -= state; | ||
351 | 332 | ||
352 | // Make sure none of the throttles are set below our packet MTU, | 333 | // Make sure none of the throttles are set below our packet MTU, |
353 | // otherwise a throttle could become permanently clogged | 334 | // otherwise a throttle could become permanently clogged |
@@ -358,19 +339,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
358 | task = Math.Max(task, LLUDPServer.MTU); | 339 | task = Math.Max(task, LLUDPServer.MTU); |
359 | texture = Math.Max(texture, LLUDPServer.MTU); | 340 | texture = Math.Max(texture, LLUDPServer.MTU); |
360 | asset = Math.Max(asset, LLUDPServer.MTU); | 341 | asset = Math.Max(asset, LLUDPServer.MTU); |
361 | state = Math.Max(state, LLUDPServer.MTU); | ||
362 | |||
363 | int total = resend + land + wind + cloud + task + texture + asset + state; | ||
364 | 342 | ||
365 | //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}", | 343 | //int total = resend + land + wind + cloud + task + texture + asset; |
366 | // AgentID, resend, land, wind, cloud, task, texture, asset, state, total); | 344 | //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", |
345 | // AgentID, resend, land, wind, cloud, task, texture, asset, total); | ||
367 | 346 | ||
368 | // Update the token buckets with new throttle values | 347 | // Update the token buckets with new throttle values |
369 | TokenBucket bucket; | 348 | TokenBucket bucket; |
370 | 349 | ||
371 | bucket = m_throttleCategory; | ||
372 | bucket.RequestedDripRate = total; | ||
373 | |||
374 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; | 350 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; |
375 | bucket.RequestedDripRate = resend; | 351 | bucket.RequestedDripRate = resend; |
376 | 352 | ||
@@ -399,22 +375,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
399 | m_packedThrottles = null; | 375 | m_packedThrottles = null; |
400 | } | 376 | } |
401 | 377 | ||
402 | public byte[] GetThrottlesPacked() | 378 | public byte[] GetThrottlesPacked(float multiplier) |
403 | { | 379 | { |
404 | byte[] data = m_packedThrottles; | 380 | byte[] data = m_packedThrottles; |
405 | 381 | ||
406 | if (data == null) | 382 | if (data == null) |
407 | { | 383 | { |
384 | float rate; | ||
385 | |||
408 | data = new byte[7 * 4]; | 386 | data = new byte[7 * 4]; |
409 | int i = 0; | 387 | int i = 0; |
410 | 388 | ||
411 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4; | 389 | // multiply by 8 to convert bytes back to bits |
412 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4; | 390 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier; |
413 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 0, data, i, 4); i += 4; | 391 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; |
414 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate), 0, data, i, 4); i += 4; | 392 | |
415 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate), 0, data, i, 4); i += 4; | 393 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier; |
416 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4; | 394 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; |
417 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4; | 395 | |
396 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier; | ||
397 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||
398 | |||
399 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier; | ||
400 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||
401 | |||
402 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier; | ||
403 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||
404 | |||
405 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier; | ||
406 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||
407 | |||
408 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier; | ||
409 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||
418 | 410 | ||
419 | m_packedThrottles = data; | 411 | m_packedThrottles = data; |
420 | } | 412 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index d08b25f..aff90c5 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | |||
@@ -297,7 +297,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
297 | delegate(IClientAPI client) | 297 | delegate(IClientAPI client) |
298 | { | 298 | { |
299 | if (client is LLClientView) | 299 | if (client is LLClientView) |
300 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); | 300 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); |
301 | } | 301 | } |
302 | ); | 302 | ); |
303 | } | 303 | } |
@@ -309,7 +309,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
309 | delegate(IClientAPI client) | 309 | delegate(IClientAPI client) |
310 | { | 310 | { |
311 | if (client is LLClientView) | 311 | if (client is LLClientView) |
312 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); | 312 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); |
313 | } | 313 | } |
314 | ); | 314 | ); |
315 | } | 315 | } |
@@ -322,7 +322,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
322 | /// <param name="packet"></param> | 322 | /// <param name="packet"></param> |
323 | /// <param name="category"></param> | 323 | /// <param name="category"></param> |
324 | /// <param name="allowSplitting"></param> | 324 | /// <param name="allowSplitting"></param> |
325 | public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting) | 325 | public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method) |
326 | { | 326 | { |
327 | // CoarseLocationUpdate packets cannot be split in an automated way | 327 | // CoarseLocationUpdate packets cannot be split in an automated way |
328 | if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) | 328 | if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) |
@@ -339,13 +339,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
339 | for (int i = 0; i < packetCount; i++) | 339 | for (int i = 0; i < packetCount; i++) |
340 | { | 340 | { |
341 | byte[] data = datas[i]; | 341 | byte[] data = datas[i]; |
342 | SendPacketData(udpClient, data, packet.Type, category); | 342 | SendPacketData(udpClient, data, packet.Type, category, method); |
343 | } | 343 | } |
344 | } | 344 | } |
345 | else | 345 | else |
346 | { | 346 | { |
347 | byte[] data = packet.ToBytes(); | 347 | byte[] data = packet.ToBytes(); |
348 | SendPacketData(udpClient, data, packet.Type, category); | 348 | SendPacketData(udpClient, data, packet.Type, category, method); |
349 | } | 349 | } |
350 | } | 350 | } |
351 | 351 | ||
@@ -356,7 +356,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
356 | /// <param name="data"></param> | 356 | /// <param name="data"></param> |
357 | /// <param name="type"></param> | 357 | /// <param name="type"></param> |
358 | /// <param name="category"></param> | 358 | /// <param name="category"></param> |
359 | public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category) | 359 | public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method) |
360 | { | 360 | { |
361 | int dataLength = data.Length; | 361 | int dataLength = data.Length; |
362 | bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; | 362 | bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; |
@@ -411,7 +411,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
411 | 411 | ||
412 | #region Queue or Send | 412 | #region Queue or Send |
413 | 413 | ||
414 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); | 414 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); |
415 | // If we were not provided a method for handling unacked, use the UDPServer default method | ||
416 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); | ||
415 | 417 | ||
416 | // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will | 418 | // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will |
417 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object | 419 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object |
@@ -445,7 +447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
445 | packet.Header.Reliable = false; | 447 | packet.Header.Reliable = false; |
446 | packet.Packets = blocks.ToArray(); | 448 | packet.Packets = blocks.ToArray(); |
447 | 449 | ||
448 | SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true); | 450 | SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true, null); |
449 | } | 451 | } |
450 | } | 452 | } |
451 | 453 | ||
@@ -458,17 +460,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
458 | // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit | 460 | // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit |
459 | pc.PingID.OldestUnacked = 0; | 461 | pc.PingID.OldestUnacked = 0; |
460 | 462 | ||
461 | SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false); | 463 | SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null); |
462 | } | 464 | } |
463 | 465 | ||
464 | public void CompletePing(LLUDPClient udpClient, byte pingID) | 466 | public void CompletePing(LLUDPClient udpClient, byte pingID) |
465 | { | 467 | { |
466 | CompletePingCheckPacket completePing = new CompletePingCheckPacket(); | 468 | CompletePingCheckPacket completePing = new CompletePingCheckPacket(); |
467 | completePing.PingID.PingID = pingID; | 469 | completePing.PingID.PingID = pingID; |
468 | SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false); | 470 | SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); |
469 | } | 471 | } |
470 | 472 | ||
471 | public void ResendUnacked(LLUDPClient udpClient) | 473 | public void HandleUnacked(LLUDPClient udpClient) |
472 | { | 474 | { |
473 | if (!udpClient.IsConnected) | 475 | if (!udpClient.IsConnected) |
474 | return; | 476 | return; |
@@ -488,31 +490,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
488 | 490 | ||
489 | if (expiredPackets != null) | 491 | if (expiredPackets != null) |
490 | { | 492 | { |
491 | //m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); | 493 | //m_log.Debug("[LLUDPSERVER]: Handling " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); |
492 | |||
493 | // Exponential backoff of the retransmission timeout | 494 | // Exponential backoff of the retransmission timeout |
494 | udpClient.BackoffRTO(); | 495 | udpClient.BackoffRTO(); |
496 | for (int i = 0; i < expiredPackets.Count; ++i) | ||
497 | expiredPackets[i].UnackedMethod(expiredPackets[i]); | ||
498 | } | ||
499 | } | ||
495 | 500 | ||
496 | // Resend packets | 501 | public void ResendUnacked(OutgoingPacket outgoingPacket) |
497 | for (int i = 0; i < expiredPackets.Count; i++) | 502 | { |
498 | { | 503 | //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed", |
499 | OutgoingPacket outgoingPacket = expiredPackets[i]; | 504 | // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount); |
500 | |||
501 | //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed", | ||
502 | // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount); | ||
503 | 505 | ||
504 | // Set the resent flag | 506 | // Set the resent flag |
505 | outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT); | 507 | outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT); |
506 | outgoingPacket.Category = ThrottleOutPacketType.Resend; | 508 | outgoingPacket.Category = ThrottleOutPacketType.Resend; |
507 | 509 | ||
508 | // Bump up the resend count on this packet | 510 | // Bump up the resend count on this packet |
509 | Interlocked.Increment(ref outgoingPacket.ResendCount); | 511 | Interlocked.Increment(ref outgoingPacket.ResendCount); |
510 | 512 | ||
511 | // Requeue or resend the packet | 513 | // Requeue or resend the packet |
512 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) | 514 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) |
513 | SendPacketFinal(outgoingPacket); | 515 | SendPacketFinal(outgoingPacket); |
514 | } | ||
515 | } | ||
516 | } | 516 | } |
517 | 517 | ||
518 | public void Flush(LLUDPClient udpClient) | 518 | public void Flush(LLUDPClient udpClient) |
@@ -672,7 +672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
672 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) | 672 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) |
673 | { | 673 | { |
674 | for (int i = 0; i < packet.Header.AckList.Length; i++) | 674 | for (int i = 0; i < packet.Header.AckList.Length; i++) |
675 | udpClient.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent); | 675 | udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); |
676 | } | 676 | } |
677 | 677 | ||
678 | // Handle PacketAck packets | 678 | // Handle PacketAck packets |
@@ -681,7 +681,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
681 | PacketAckPacket ackPacket = (PacketAckPacket)packet; | 681 | PacketAckPacket ackPacket = (PacketAckPacket)packet; |
682 | 682 | ||
683 | for (int i = 0; i < ackPacket.Packets.Length; i++) | 683 | for (int i = 0; i < ackPacket.Packets.Length; i++) |
684 | udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent); | 684 | udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); |
685 | 685 | ||
686 | // We don't need to do anything else with PacketAck packets | 686 | // We don't need to do anything else with PacketAck packets |
687 | return; | 687 | return; |
@@ -1096,7 +1096,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1096 | if (udpClient.IsConnected) | 1096 | if (udpClient.IsConnected) |
1097 | { | 1097 | { |
1098 | if (m_resendUnacked) | 1098 | if (m_resendUnacked) |
1099 | ResendUnacked(udpClient); | 1099 | HandleUnacked(udpClient); |
1100 | 1100 | ||
1101 | if (m_sendAcks) | 1101 | if (m_sendAcks) |
1102 | SendAcks(udpClient); | 1102 | SendAcks(udpClient); |
@@ -1152,7 +1152,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1152 | nticksUnack++; | 1152 | nticksUnack++; |
1153 | watch2.Start(); | 1153 | watch2.Start(); |
1154 | 1154 | ||
1155 | ResendUnacked(udpClient); | 1155 | HandleUnacked(udpClient); |
1156 | 1156 | ||
1157 | watch2.Stop(); | 1157 | watch2.Stop(); |
1158 | avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); | 1158 | avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs index 1a1a1cb..76c6c14 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs | |||
@@ -31,6 +31,8 @@ using OpenMetaverse; | |||
31 | 31 | ||
32 | namespace OpenSim.Region.ClientStack.LindenUDP | 32 | namespace OpenSim.Region.ClientStack.LindenUDP |
33 | { | 33 | { |
34 | |||
35 | public delegate void UnackedPacketMethod(OutgoingPacket oPacket); | ||
34 | /// <summary> | 36 | /// <summary> |
35 | /// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is | 37 | /// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is |
36 | /// destined for, along with the serialized packet data, sequence number | 38 | /// destined for, along with the serialized packet data, sequence number |
@@ -52,6 +54,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
52 | public int TickCount; | 54 | public int TickCount; |
53 | /// <summary>Category this packet belongs to</summary> | 55 | /// <summary>Category this packet belongs to</summary> |
54 | public ThrottleOutPacketType Category; | 56 | public ThrottleOutPacketType Category; |
57 | /// <summary>The delegate to be called if this packet is determined to be unacknowledged</summary> | ||
58 | public UnackedPacketMethod UnackedMethod; | ||
55 | 59 | ||
56 | /// <summary> | 60 | /// <summary> |
57 | /// Default constructor | 61 | /// Default constructor |
@@ -60,11 +64,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
60 | /// <param name="buffer">Serialized packet data. If the flags or sequence number | 64 | /// <param name="buffer">Serialized packet data. If the flags or sequence number |
61 | /// need to be updated, they will be injected directly into this binary buffer</param> | 65 | /// need to be updated, they will be injected directly into this binary buffer</param> |
62 | /// <param name="category">Throttling category for this packet</param> | 66 | /// <param name="category">Throttling category for this packet</param> |
63 | public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category) | 67 | public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method) |
64 | { | 68 | { |
65 | Client = client; | 69 | Client = client; |
66 | Buffer = buffer; | 70 | Buffer = buffer; |
67 | Category = category; | 71 | Category = category; |
72 | UnackedMethod = method; | ||
68 | } | 73 | } |
69 | } | 74 | } |
70 | } | 75 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs index aaf6e26..c9aac0b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs | |||
@@ -52,30 +52,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
52 | public int Texture; | 52 | public int Texture; |
53 | /// <summary>Drip rate for asset packets</summary> | 53 | /// <summary>Drip rate for asset packets</summary> |
54 | public int Asset; | 54 | public int Asset; |
55 | /// <summary>Drip rate for state packets</summary> | 55 | |
56 | public int State; | ||
57 | /// <summary>Drip rate for the parent token bucket</summary> | 56 | /// <summary>Drip rate for the parent token bucket</summary> |
58 | public int Total; | 57 | public int Total; |
59 | 58 | ||
60 | /// <summary>Maximum burst rate for resent packets</summary> | 59 | /// <summary>Flag used to enable adaptive throttles</summary> |
61 | public int ResendLimit; | 60 | public bool AdaptiveThrottlesEnabled; |
62 | /// <summary>Maximum burst rate for land packets</summary> | 61 | |
63 | public int LandLimit; | ||
64 | /// <summary>Maximum burst rate for wind packets</summary> | ||
65 | public int WindLimit; | ||
66 | /// <summary>Maximum burst rate for cloud packets</summary> | ||
67 | public int CloudLimit; | ||
68 | /// <summary>Maximum burst rate for task (state and transaction) packets</summary> | ||
69 | public int TaskLimit; | ||
70 | /// <summary>Maximum burst rate for texture packets</summary> | ||
71 | public int TextureLimit; | ||
72 | /// <summary>Maximum burst rate for asset packets</summary> | ||
73 | public int AssetLimit; | ||
74 | /// <summary>Maximum burst rate for state packets</summary> | ||
75 | public int StateLimit; | ||
76 | /// <summary>Burst rate for the parent token bucket</summary> | ||
77 | public int TotalLimit; | ||
78 | |||
79 | /// <summary> | 62 | /// <summary> |
80 | /// Default constructor | 63 | /// Default constructor |
81 | /// </summary> | 64 | /// </summary> |
@@ -86,26 +69,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
86 | { | 69 | { |
87 | IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; | 70 | IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; |
88 | 71 | ||
89 | Resend = throttleConfig.GetInt("resend_default", 12500); | 72 | Resend = throttleConfig.GetInt("resend_default", 6625); |
90 | Land = throttleConfig.GetInt("land_default", 1000); | 73 | Land = throttleConfig.GetInt("land_default", 9125); |
91 | Wind = throttleConfig.GetInt("wind_default", 1000); | 74 | Wind = throttleConfig.GetInt("wind_default", 1750); |
92 | Cloud = throttleConfig.GetInt("cloud_default", 1000); | 75 | Cloud = throttleConfig.GetInt("cloud_default", 1750); |
93 | Task = throttleConfig.GetInt("task_default", 1000); | 76 | Task = throttleConfig.GetInt("task_default", 18500); |
94 | Texture = throttleConfig.GetInt("texture_default", 1000); | 77 | Texture = throttleConfig.GetInt("texture_default", 18500); |
95 | Asset = throttleConfig.GetInt("asset_default", 1000); | 78 | Asset = throttleConfig.GetInt("asset_default", 10500); |
96 | State = throttleConfig.GetInt("state_default", 1000); | ||
97 | |||
98 | ResendLimit = throttleConfig.GetInt("resend_limit", 18750); | ||
99 | LandLimit = throttleConfig.GetInt("land_limit", 29750); | ||
100 | WindLimit = throttleConfig.GetInt("wind_limit", 18750); | ||
101 | CloudLimit = throttleConfig.GetInt("cloud_limit", 18750); | ||
102 | TaskLimit = throttleConfig.GetInt("task_limit", 18750); | ||
103 | TextureLimit = throttleConfig.GetInt("texture_limit", 55750); | ||
104 | AssetLimit = throttleConfig.GetInt("asset_limit", 27500); | ||
105 | StateLimit = throttleConfig.GetInt("state_limit", 37000); | ||
106 | 79 | ||
107 | Total = throttleConfig.GetInt("client_throttle_max_bps", 0); | 80 | Total = throttleConfig.GetInt("client_throttle_max_bps", 0); |
108 | TotalLimit = Total; | 81 | |
82 | AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); | ||
109 | } | 83 | } |
110 | catch (Exception) { } | 84 | catch (Exception) { } |
111 | } | 85 | } |
@@ -128,34 +102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
128 | return Texture; | 102 | return Texture; |
129 | case ThrottleOutPacketType.Asset: | 103 | case ThrottleOutPacketType.Asset: |
130 | return Asset; | 104 | return Asset; |
131 | case ThrottleOutPacketType.State: | ||
132 | return State; | ||
133 | case ThrottleOutPacketType.Unknown: | ||
134 | default: | ||
135 | return 0; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | public int GetLimit(ThrottleOutPacketType type) | ||
140 | { | ||
141 | switch (type) | ||
142 | { | ||
143 | case ThrottleOutPacketType.Resend: | ||
144 | return ResendLimit; | ||
145 | case ThrottleOutPacketType.Land: | ||
146 | return LandLimit; | ||
147 | case ThrottleOutPacketType.Wind: | ||
148 | return WindLimit; | ||
149 | case ThrottleOutPacketType.Cloud: | ||
150 | return CloudLimit; | ||
151 | case ThrottleOutPacketType.Task: | ||
152 | return TaskLimit; | ||
153 | case ThrottleOutPacketType.Texture: | ||
154 | return TextureLimit; | ||
155 | case ThrottleOutPacketType.Asset: | ||
156 | return AssetLimit; | ||
157 | case ThrottleOutPacketType.State: | ||
158 | return StateLimit; | ||
159 | case ThrottleOutPacketType.Unknown: | 105 | case ThrottleOutPacketType.Unknown: |
160 | default: | 106 | default: |
161 | return 0; | 107 | return 0; |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs index 07b0a1d..29fd1a4 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs | |||
@@ -29,6 +29,8 @@ using System; | |||
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using OpenSim.Framework; | ||
33 | |||
32 | using log4net; | 34 | using log4net; |
33 | 35 | ||
34 | namespace OpenSim.Region.ClientStack.LindenUDP | 36 | namespace OpenSim.Region.ClientStack.LindenUDP |
@@ -48,31 +50,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
48 | /// Number of ticks (ms) per quantum, drip rate and max burst | 50 | /// Number of ticks (ms) per quantum, drip rate and max burst |
49 | /// are defined over this interval. | 51 | /// are defined over this interval. |
50 | /// </summary> | 52 | /// </summary> |
51 | private const Int32 m_ticksPerQuantum = 1000; | 53 | protected const Int32 m_ticksPerQuantum = 1000; |
52 | 54 | ||
53 | /// <summary> | 55 | /// <summary> |
54 | /// This is the number of quantums worth of packets that can | 56 | /// This is the number of quantums worth of packets that can |
55 | /// be accommodated during a burst | 57 | /// be accommodated during a burst |
56 | /// </summary> | 58 | /// </summary> |
57 | private const Double m_quantumsPerBurst = 1.5; | 59 | protected const Double m_quantumsPerBurst = 1.5; |
58 | 60 | ||
59 | /// <summary> | 61 | /// <summary> |
60 | /// </summary> | 62 | /// </summary> |
61 | private const Int32 m_minimumDripRate = 1400; | 63 | protected const Int32 m_minimumDripRate = 1400; |
62 | 64 | ||
63 | /// <summary>Time of the last drip, in system ticks</summary> | 65 | /// <summary>Time of the last drip, in system ticks</summary> |
64 | private Int32 m_lastDrip; | 66 | protected Int32 m_lastDrip; |
65 | 67 | ||
66 | /// <summary> | 68 | /// <summary> |
67 | /// The number of bytes that can be sent at this moment. This is the | 69 | /// The number of bytes that can be sent at this moment. This is the |
68 | /// current number of tokens in the bucket | 70 | /// current number of tokens in the bucket |
69 | /// </summary> | 71 | /// </summary> |
70 | private Int64 m_tokenCount; | 72 | protected Int64 m_tokenCount; |
71 | 73 | ||
72 | /// <summary> | 74 | /// <summary> |
73 | /// Map of children buckets and their requested maximum burst rate | 75 | /// Map of children buckets and their requested maximum burst rate |
74 | /// </summary> | 76 | /// </summary> |
75 | private Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); | 77 | protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); |
76 | 78 | ||
77 | #region Properties | 79 | #region Properties |
78 | 80 | ||
@@ -81,7 +83,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
81 | /// parent. The parent bucket will limit the aggregate bandwidth of all | 83 | /// parent. The parent bucket will limit the aggregate bandwidth of all |
82 | /// of its children buckets | 84 | /// of its children buckets |
83 | /// </summary> | 85 | /// </summary> |
84 | private TokenBucket m_parent; | 86 | protected TokenBucket m_parent; |
85 | public TokenBucket Parent | 87 | public TokenBucket Parent |
86 | { | 88 | { |
87 | get { return m_parent; } | 89 | get { return m_parent; } |
@@ -93,7 +95,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
93 | /// of tokens that can accumulate in the bucket at any one time. This | 95 | /// of tokens that can accumulate in the bucket at any one time. This |
94 | /// also sets the total request for leaf nodes | 96 | /// also sets the total request for leaf nodes |
95 | /// </summary> | 97 | /// </summary> |
96 | private Int64 m_burstRate; | 98 | protected Int64 m_burstRate; |
97 | public Int64 RequestedBurstRate | 99 | public Int64 RequestedBurstRate |
98 | { | 100 | { |
99 | get { return m_burstRate; } | 101 | get { return m_burstRate; } |
@@ -118,8 +120,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
118 | /// <remarks>Tokens are added to the bucket any time | 120 | /// <remarks>Tokens are added to the bucket any time |
119 | /// <seealso cref="RemoveTokens"/> is called, at the granularity of | 121 | /// <seealso cref="RemoveTokens"/> is called, at the granularity of |
120 | /// the system tick interval (typically around 15-22ms)</remarks> | 122 | /// the system tick interval (typically around 15-22ms)</remarks> |
121 | private Int64 m_dripRate; | 123 | protected Int64 m_dripRate; |
122 | public Int64 RequestedDripRate | 124 | public virtual Int64 RequestedDripRate |
123 | { | 125 | { |
124 | get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); } | 126 | get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); } |
125 | set { | 127 | set { |
@@ -131,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
131 | } | 133 | } |
132 | } | 134 | } |
133 | 135 | ||
134 | public Int64 DripRate | 136 | public virtual Int64 DripRate |
135 | { | 137 | { |
136 | get { | 138 | get { |
137 | if (m_parent == null) | 139 | if (m_parent == null) |
@@ -149,7 +151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
149 | /// The current total of the requested maximum burst rates of | 151 | /// The current total of the requested maximum burst rates of |
150 | /// this bucket's children buckets. | 152 | /// this bucket's children buckets. |
151 | /// </summary> | 153 | /// </summary> |
152 | private Int64 m_totalDripRequest; | 154 | protected Int64 m_totalDripRequest; |
153 | public Int64 TotalDripRequest | 155 | public Int64 TotalDripRequest |
154 | { | 156 | { |
155 | get { return m_totalDripRequest; } | 157 | get { return m_totalDripRequest; } |
@@ -177,7 +179,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
177 | RequestedDripRate = dripRate; | 179 | RequestedDripRate = dripRate; |
178 | // TotalDripRequest = dripRate; // this will be overwritten when a child node registers | 180 | // TotalDripRequest = dripRate; // this will be overwritten when a child node registers |
179 | // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); | 181 | // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); |
180 | m_lastDrip = Environment.TickCount & Int32.MaxValue; | 182 | m_lastDrip = Util.EnvironmentTickCount(); |
181 | } | 183 | } |
182 | 184 | ||
183 | #endregion Constructor | 185 | #endregion Constructor |
@@ -189,7 +191,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
189 | /// hierarchy. However, if any of the parents is over-booked, then | 191 | /// hierarchy. However, if any of the parents is over-booked, then |
190 | /// the modifier will be less than 1. | 192 | /// the modifier will be less than 1. |
191 | /// </summary> | 193 | /// </summary> |
192 | private double DripRateModifier() | 194 | protected double DripRateModifier() |
193 | { | 195 | { |
194 | Int64 driprate = DripRate; | 196 | Int64 driprate = DripRate; |
195 | return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; | 197 | return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; |
@@ -197,7 +199,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
197 | 199 | ||
198 | /// <summary> | 200 | /// <summary> |
199 | /// </summary> | 201 | /// </summary> |
200 | private double BurstRateModifier() | 202 | protected double BurstRateModifier() |
201 | { | 203 | { |
202 | // for now... burst rate is always m_quantumsPerBurst (constant) | 204 | // for now... burst rate is always m_quantumsPerBurst (constant) |
203 | // larger than drip rate so the ratio of burst requests is the | 205 | // larger than drip rate so the ratio of burst requests is the |
@@ -211,12 +213,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
211 | /// </summary> | 213 | /// </summary> |
212 | public void RegisterRequest(TokenBucket child, Int64 request) | 214 | public void RegisterRequest(TokenBucket child, Int64 request) |
213 | { | 215 | { |
214 | m_children[child] = request; | 216 | lock (m_children) |
215 | // m_totalDripRequest = m_children.Values.Sum(); | 217 | { |
218 | m_children[child] = request; | ||
219 | // m_totalDripRequest = m_children.Values.Sum(); | ||
216 | 220 | ||
217 | m_totalDripRequest = 0; | 221 | m_totalDripRequest = 0; |
218 | foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) | 222 | foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) |
219 | m_totalDripRequest += cref.Value; | 223 | m_totalDripRequest += cref.Value; |
224 | } | ||
220 | 225 | ||
221 | // Pass the new values up to the parent | 226 | // Pass the new values up to the parent |
222 | if (m_parent != null) | 227 | if (m_parent != null) |
@@ -229,12 +234,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
229 | /// </summary> | 234 | /// </summary> |
230 | public void UnregisterRequest(TokenBucket child) | 235 | public void UnregisterRequest(TokenBucket child) |
231 | { | 236 | { |
232 | m_children.Remove(child); | 237 | lock (m_children) |
233 | // m_totalDripRequest = m_children.Values.Sum(); | 238 | { |
239 | m_children.Remove(child); | ||
240 | // m_totalDripRequest = m_children.Values.Sum(); | ||
234 | 241 | ||
235 | m_totalDripRequest = 0; | 242 | m_totalDripRequest = 0; |
236 | foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) | 243 | foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) |
237 | m_totalDripRequest += cref.Value; | 244 | m_totalDripRequest += cref.Value; |
245 | } | ||
246 | |||
238 | 247 | ||
239 | // Pass the new values up to the parent | 248 | // Pass the new values up to the parent |
240 | if (m_parent != null) | 249 | if (m_parent != null) |
@@ -268,7 +277,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
268 | /// Deposit tokens into the bucket from a child bucket that did | 277 | /// Deposit tokens into the bucket from a child bucket that did |
269 | /// not use all of its available tokens | 278 | /// not use all of its available tokens |
270 | /// </summary> | 279 | /// </summary> |
271 | private void Deposit(Int64 count) | 280 | protected void Deposit(Int64 count) |
272 | { | 281 | { |
273 | m_tokenCount += count; | 282 | m_tokenCount += count; |
274 | 283 | ||
@@ -285,7 +294,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
285 | /// call to Drip | 294 | /// call to Drip |
286 | /// </summary> | 295 | /// </summary> |
287 | /// <returns>True if tokens were added to the bucket, otherwise false</returns> | 296 | /// <returns>True if tokens were added to the bucket, otherwise false</returns> |
288 | private void Drip() | 297 | protected void Drip() |
289 | { | 298 | { |
290 | // This should never happen... means we are a leaf node and were created | 299 | // This should never happen... means we are a leaf node and were created |
291 | // with no drip rate... | 300 | // with no drip rate... |
@@ -297,10 +306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
297 | 306 | ||
298 | // Determine the interval over which we are adding tokens, never add | 307 | // Determine the interval over which we are adding tokens, never add |
299 | // more than a single quantum of tokens | 308 | // more than a single quantum of tokens |
300 | Int32 now = Environment.TickCount & Int32.MaxValue; | 309 | Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum); |
301 | Int32 deltaMS = Math.Min(now - m_lastDrip, m_ticksPerQuantum); | 310 | m_lastDrip = Util.EnvironmentTickCount(); |
302 | |||
303 | m_lastDrip = now; | ||
304 | 311 | ||
305 | // This can be 0 in the very unusual case that the timer wrapped | 312 | // This can be 0 in the very unusual case that the timer wrapped |
306 | // It can be 0 if we try add tokens at a sub-tick rate | 313 | // It can be 0 if we try add tokens at a sub-tick rate |
@@ -310,4 +317,77 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
310 | Deposit(deltaMS * DripRate / m_ticksPerQuantum); | 317 | Deposit(deltaMS * DripRate / m_ticksPerQuantum); |
311 | } | 318 | } |
312 | } | 319 | } |
320 | |||
321 | public class AdaptiveTokenBucket : TokenBucket | ||
322 | { | ||
323 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
324 | |||
325 | /// <summary> | ||
326 | /// The minimum rate for flow control. Minimum drip rate is one | ||
327 | /// packet per second. Open the throttle to 15 packets per second | ||
328 | /// or about 160kbps. | ||
329 | /// </summary> | ||
330 | protected const Int64 m_minimumFlow = m_minimumDripRate * 15; | ||
331 | |||
332 | // <summary> | ||
333 | // The maximum rate for flow control. Drip rate can never be | ||
334 | // greater than this. | ||
335 | // </summary> | ||
336 | protected Int64 m_maxDripRate = 0; | ||
337 | protected Int64 MaxDripRate | ||
338 | { | ||
339 | get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); } | ||
340 | set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); } | ||
341 | } | ||
342 | |||
343 | private bool m_enabled = false; | ||
344 | |||
345 | // <summary> | ||
346 | // | ||
347 | // </summary> | ||
348 | public virtual Int64 AdjustedDripRate | ||
349 | { | ||
350 | get { return m_dripRate; } | ||
351 | set { | ||
352 | m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value,m_minimumFlow,MaxDripRate); | ||
353 | m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); | ||
354 | if (m_parent != null) | ||
355 | m_parent.RegisterRequest(this,m_dripRate); | ||
356 | } | ||
357 | } | ||
358 | |||
359 | // <summary> | ||
360 | // | ||
361 | // </summary> | ||
362 | public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate) | ||
363 | { | ||
364 | m_enabled = enabled; | ||
365 | |||
366 | if (m_enabled) | ||
367 | { | ||
368 | // m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled"); | ||
369 | MaxDripRate = maxDripRate; | ||
370 | AdjustedDripRate = m_minimumFlow; | ||
371 | } | ||
372 | } | ||
373 | |||
374 | // <summary> | ||
375 | // | ||
376 | // </summary> | ||
377 | public void ExpirePackets(Int32 count) | ||
378 | { | ||
379 | // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count); | ||
380 | if (m_enabled) | ||
381 | AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count)); | ||
382 | } | ||
383 | |||
384 | // <summary> | ||
385 | // | ||
386 | // </summary> | ||
387 | public void AcknowledgePackets(Int32 count) | ||
388 | { | ||
389 | if (m_enabled) | ||
390 | AdjustedDripRate = AdjustedDripRate + count; | ||
391 | } | ||
392 | } | ||
313 | } | 393 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index d195110..793aefe 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | |||
@@ -65,7 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
65 | /// <summary>Holds packets that need to be added to the unacknowledged list</summary> | 65 | /// <summary>Holds packets that need to be added to the unacknowledged list</summary> |
66 | private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>(); | 66 | private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>(); |
67 | /// <summary>Holds information about pending acknowledgements</summary> | 67 | /// <summary>Holds information about pending acknowledgements</summary> |
68 | private LocklessQueue<PendingAck> m_pendingRemoves = new LocklessQueue<PendingAck>(); | 68 | private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>(); |
69 | /// <summary>Holds information about pending removals</summary> | ||
70 | private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>(); | ||
69 | 71 | ||
70 | /// <summary> | 72 | /// <summary> |
71 | /// Add an unacked packet to the collection | 73 | /// Add an unacked packet to the collection |
@@ -83,15 +85,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
83 | 85 | ||
84 | /// <summary> | 86 | /// <summary> |
85 | /// Marks a packet as acknowledged | 87 | /// Marks a packet as acknowledged |
88 | /// This method is used when an acknowledgement is received from the network for a previously | ||
89 | /// sent packet. Effects of removal this way are to update unacked byte count, adjust RTT | ||
90 | /// and increase throttle to the coresponding client. | ||
86 | /// </summary> | 91 | /// </summary> |
87 | /// <param name="sequenceNumber">Sequence number of the packet to | 92 | /// <param name="sequenceNumber">Sequence number of the packet to |
88 | /// acknowledge</param> | 93 | /// acknowledge</param> |
89 | /// <param name="currentTime">Current value of Environment.TickCount</param> | 94 | /// <param name="currentTime">Current value of Environment.TickCount</param> |
90 | /// <remarks>This does not immediately acknowledge the packet, it only | 95 | /// <remarks>This does not immediately acknowledge the packet, it only |
91 | /// queues the ack so it can be handled in a thread-safe way later</remarks> | 96 | /// queues the ack so it can be handled in a thread-safe way later</remarks> |
92 | public void Remove(uint sequenceNumber, int currentTime, bool fromResend) | 97 | public void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend) |
93 | { | 98 | { |
94 | m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); | 99 | m_pendingAcknowledgements.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); |
100 | } | ||
101 | |||
102 | /// <summary> | ||
103 | /// Marks a packet as no longer needing acknowledgement without a received acknowledgement. | ||
104 | /// This method is called when a packet expires and we no longer need an acknowledgement. | ||
105 | /// When some reliable packet types expire, they are handled in a way other than simply | ||
106 | /// resending them. The only effect of removal this way is to update unacked byte count. | ||
107 | /// </summary> | ||
108 | /// <param name="sequenceNumber">Sequence number of the packet to | ||
109 | /// acknowledge</param> | ||
110 | /// <remarks>The does not immediately remove the packet, it only queues the removal | ||
111 | /// so it can be handled in a thread safe way later</remarks> | ||
112 | public void Remove(uint sequenceNumber) | ||
113 | { | ||
114 | m_pendingRemoves.Enqueue(sequenceNumber); | ||
95 | } | 115 | } |
96 | 116 | ||
97 | /// <summary> | 117 | /// <summary> |
@@ -130,6 +150,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
130 | // is actually sent out again | 150 | // is actually sent out again |
131 | packet.TickCount = 0; | 151 | packet.TickCount = 0; |
132 | 152 | ||
153 | // As with other network applications, assume that an expired packet is | ||
154 | // an indication of some network problem, slow transmission | ||
155 | packet.Client.FlowThrottle.ExpirePackets(1); | ||
156 | |||
133 | expiredPackets.Add(packet); | 157 | expiredPackets.Add(packet); |
134 | } | 158 | } |
135 | } | 159 | } |
@@ -147,29 +171,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
147 | m_packets[pendingAdd.SequenceNumber] = pendingAdd; | 171 | m_packets[pendingAdd.SequenceNumber] = pendingAdd; |
148 | 172 | ||
149 | // Process all the pending removes, including updating statistics and round-trip times | 173 | // Process all the pending removes, including updating statistics and round-trip times |
150 | PendingAck pendingRemove; | 174 | PendingAck pendingAcknowledgement; |
151 | OutgoingPacket ackedPacket; | 175 | while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement)) |
152 | while (m_pendingRemoves.TryDequeue(out pendingRemove)) | ||
153 | { | 176 | { |
154 | if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) | 177 | OutgoingPacket ackedPacket; |
178 | if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket)) | ||
155 | { | 179 | { |
156 | if (ackedPacket != null) | 180 | if (ackedPacket != null) |
157 | { | 181 | { |
158 | m_packets.Remove(pendingRemove.SequenceNumber); | 182 | m_packets.Remove(pendingAcknowledgement.SequenceNumber); |
183 | |||
184 | // As with other network applications, assume that an acknowledged packet is an | ||
185 | // indication that the network can handle a little more load, speed up the transmission | ||
186 | ackedPacket.Client.FlowThrottle.AcknowledgePackets(ackedPacket.Buffer.DataLength); | ||
159 | 187 | ||
160 | // Update stats | 188 | // Update stats |
161 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); | 189 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); |
162 | 190 | ||
163 | if (!pendingRemove.FromResend) | 191 | if (!pendingAcknowledgement.FromResend) |
164 | { | 192 | { |
165 | // Calculate the round-trip time for this packet and its ACK | 193 | // Calculate the round-trip time for this packet and its ACK |
166 | int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; | 194 | int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount; |
167 | if (rtt > 0) | 195 | if (rtt > 0) |
168 | ackedPacket.Client.UpdateRoundTrip(rtt); | 196 | ackedPacket.Client.UpdateRoundTrip(rtt); |
169 | } | 197 | } |
170 | } | 198 | } |
171 | } | 199 | } |
172 | } | 200 | } |
201 | |||
202 | uint pendingRemove; | ||
203 | while(m_pendingRemoves.TryDequeue(out pendingRemove)) | ||
204 | { | ||
205 | OutgoingPacket removedPacket; | ||
206 | if (m_packets.TryGetValue(pendingRemove, out removedPacket)) | ||
207 | { | ||
208 | if (removedPacket != null) | ||
209 | { | ||
210 | m_packets.Remove(pendingRemove); | ||
211 | |||
212 | // Update stats | ||
213 | Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength); | ||
214 | } | ||
215 | } | ||
216 | } | ||
173 | } | 217 | } |
174 | } | 218 | } |
175 | } \ No newline at end of file | 219 | } |
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index 771038e..9d8082b 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs | |||
@@ -41,8 +41,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
41 | /// </summary> | 41 | /// </summary> |
42 | public class AgentAssetTransactions | 42 | public class AgentAssetTransactions |
43 | { | 43 | { |
44 | // private static readonly ILog m_log = LogManager.GetLogger( | 44 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | // MethodBase.GetCurrentMethod().DeclaringType); | ||
46 | 45 | ||
47 | // Fields | 46 | // Fields |
48 | private bool m_dumpAssetsToFile; | 47 | private bool m_dumpAssetsToFile; |
@@ -149,6 +148,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
149 | 148 | ||
150 | if (asset != null) | 149 | if (asset != null) |
151 | { | 150 | { |
151 | // m_log.DebugFormat( | ||
152 | // "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}", | ||
153 | // item.Name, part.Name, transactionID); | ||
154 | |||
152 | asset.FullID = UUID.Random(); | 155 | asset.FullID = UUID.Random(); |
153 | asset.Name = item.Name; | 156 | asset.Name = item.Name; |
154 | asset.Description = item.Description; | 157 | asset.Description = item.Description; |
@@ -156,8 +159,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
156 | item.AssetID = asset.FullID; | 159 | item.AssetID = asset.FullID; |
157 | 160 | ||
158 | m_Scene.AssetService.Store(asset); | 161 | m_Scene.AssetService.Store(asset); |
159 | |||
160 | part.Inventory.UpdateInventoryItem(item); | ||
161 | } | 162 | } |
162 | } | 163 | } |
163 | } | 164 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index ff26264..520d794 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -562,14 +562,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
562 | /// <param name="sp"></param> | 562 | /// <param name="sp"></param> |
563 | /// <param name="so"></param> | 563 | /// <param name="so"></param> |
564 | /// <param name="attachmentpoint"></param> | 564 | /// <param name="attachmentpoint"></param> |
565 | /// <param name="AttachOffset"></param> | 565 | /// <param name="attachOffset"></param> |
566 | /// <param name="silent"></param> | 566 | /// <param name="silent"></param> |
567 | protected void AttachToAgent(ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 AttachOffset, bool silent) | 567 | protected void AttachToAgent(ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) |
568 | { | 568 | { |
569 | // don't attach attachments to child agents | ||
570 | if (avatar.IsChildAgent) return; | ||
571 | 569 | ||
572 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1}", Name, avatar.Name); | 570 | m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", Name, avatar.Name, |
571 | attachmentpoint, attachOffset, so.RootPart.AttachedPos); | ||
573 | 572 | ||
574 | so.DetachFromBackup(); | 573 | so.DetachFromBackup(); |
575 | 574 | ||
@@ -590,8 +589,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
590 | so.RootPart.PhysActor = null; | 589 | so.RootPart.PhysActor = null; |
591 | } | 590 | } |
592 | 591 | ||
593 | so.AbsolutePosition = AttachOffset; | 592 | so.AbsolutePosition = attachOffset; |
594 | so.RootPart.AttachedPos = AttachOffset; | 593 | so.RootPart.AttachedPos = attachOffset; |
595 | so.RootPart.IsAttachment = true; | 594 | so.RootPart.IsAttachment = true; |
596 | 595 | ||
597 | so.RootPart.SetParentLocalId(avatar.LocalId); | 596 | so.RootPart.SetParentLocalId(avatar.LocalId); |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index c88be7d..b985fbb 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -285,11 +285,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
285 | } | 285 | } |
286 | 286 | ||
287 | string reason; | 287 | string reason; |
288 | if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out reason)) | 288 | string version; |
289 | if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) | ||
289 | { | 290 | { |
290 | sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason); | 291 | sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason); |
291 | return; | 292 | return; |
292 | } | 293 | } |
294 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); | ||
293 | 295 | ||
294 | sp.ControllingClient.SendTeleportStart(teleportFlags); | 296 | sp.ControllingClient.SendTeleportStart(teleportFlags); |
295 | 297 | ||
@@ -371,20 +373,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
371 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); | 373 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); |
372 | } | 374 | } |
373 | 375 | ||
374 | // Expect avatar crossing is a heavy-duty function at the destination. | ||
375 | // That is where MakeRoot is called, which fetches appearance and inventory. | ||
376 | // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates. | ||
377 | //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId, | ||
378 | // position, false); | ||
379 | |||
380 | //{ | ||
381 | // avatar.ControllingClient.SendTeleportFailed("Problem with destination."); | ||
382 | // // We should close that agent we just created over at destination... | ||
383 | // List<ulong> lst = new List<ulong>(); | ||
384 | // lst.Add(reg.RegionHandle); | ||
385 | // SendCloseChildAgentAsync(avatar.UUID, lst); | ||
386 | // return; | ||
387 | //} | ||
388 | 376 | ||
389 | SetInTransit(sp.UUID); | 377 | SetInTransit(sp.UUID); |
390 | 378 | ||
@@ -426,7 +414,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
426 | 414 | ||
427 | // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which | 415 | // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which |
428 | // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation | 416 | // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation |
429 | // that the client contacted the destination before we send the attachments and close things here. | 417 | // that the client contacted the destination before we close things here. |
430 | if (!WaitForCallback(sp.UUID)) | 418 | if (!WaitForCallback(sp.UUID)) |
431 | { | 419 | { |
432 | m_log.WarnFormat( | 420 | m_log.WarnFormat( |
@@ -437,14 +425,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
437 | return; | 425 | return; |
438 | } | 426 | } |
439 | 427 | ||
440 | // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it | 428 | // For backwards compatibility |
441 | CrossAttachmentsIntoNewRegion(finalDestination, sp, true); | 429 | if (version == "Unknown" || version == string.Empty) |
430 | { | ||
431 | // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it | ||
432 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old simulator, sending attachments one by one..."); | ||
433 | CrossAttachmentsIntoNewRegion(finalDestination, sp, true); | ||
434 | } | ||
435 | |||
436 | // May need to logout or other cleanup | ||
437 | AgentHasMovedAway(sp, logout); | ||
442 | 438 | ||
443 | // Well, this is it. The agent is over there. | 439 | // Well, this is it. The agent is over there. |
444 | KillEntity(sp.Scene, sp.LocalId); | 440 | KillEntity(sp.Scene, sp.LocalId); |
445 | 441 | ||
446 | // May need to logout or other cleanup | ||
447 | AgentHasMovedAway(sp.ControllingClient.SessionId, logout); | ||
448 | 442 | ||
449 | // Now let's make it officially a child agent | 443 | // Now let's make it officially a child agent |
450 | sp.MakeChildAgent(); | 444 | sp.MakeChildAgent(); |
@@ -485,7 +479,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
485 | 479 | ||
486 | // Fail. Reset it back | 480 | // Fail. Reset it back |
487 | sp.IsChildAgent = false; | 481 | sp.IsChildAgent = false; |
488 | 482 | ReInstantiateScripts(sp); | |
489 | ResetFromTransit(sp.UUID); | 483 | ResetFromTransit(sp.UUID); |
490 | 484 | ||
491 | EnableChildAgents(sp); | 485 | EnableChildAgents(sp); |
@@ -513,8 +507,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
513 | 507 | ||
514 | } | 508 | } |
515 | 509 | ||
516 | protected virtual void AgentHasMovedAway(UUID sessionID, bool logout) | 510 | protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout) |
517 | { | 511 | { |
512 | foreach (SceneObjectGroup sop in sp.Attachments) | ||
513 | { | ||
514 | sop.Scene.DeleteSceneObject(sop, true); | ||
515 | } | ||
516 | sp.Attachments.Clear(); | ||
518 | } | 517 | } |
519 | 518 | ||
520 | protected void KillEntity(Scene scene, uint localID) | 519 | protected void KillEntity(Scene scene, uint localID) |
@@ -784,7 +783,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
784 | GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); | 783 | GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); |
785 | 784 | ||
786 | string reason; | 785 | string reason; |
787 | if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos, out reason)) | 786 | string version; |
787 | if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos, out version, out reason)) | ||
788 | { | 788 | { |
789 | agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); | 789 | agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); |
790 | if (r == null) | 790 | if (r == null) |
@@ -804,7 +804,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
804 | agent.InTransit(); | 804 | agent.InTransit(); |
805 | 805 | ||
806 | CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; | 806 | CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; |
807 | d.BeginInvoke(agent, newpos, neighbourx, neighboury, neighbourRegion, isFlying, CrossAgentToNewRegionCompleted, d); | 807 | d.BeginInvoke(agent, newpos, neighbourx, neighboury, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); |
808 | 808 | ||
809 | return true; | 809 | return true; |
810 | } | 810 | } |
@@ -861,17 +861,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
861 | icon.EndInvoke(iar); | 861 | icon.EndInvoke(iar); |
862 | } | 862 | } |
863 | 863 | ||
864 | public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying); | 864 | public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version); |
865 | 865 | ||
866 | /// <summary> | 866 | /// <summary> |
867 | /// This Closes child agents on neighbouring regions | 867 | /// This Closes child agents on neighbouring regions |
868 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. | 868 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. |
869 | /// </summary> | 869 | /// </summary> |
870 | protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying) | 870 | protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version) |
871 | { | 871 | { |
872 | ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); | 872 | ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); |
873 | 873 | ||
874 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3}", agent.Firstname, agent.Lastname, neighbourx, neighboury); | 874 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}", agent.Firstname, agent.Lastname, neighbourx, neighboury, version); |
875 | 875 | ||
876 | Scene m_scene = agent.Scene; | 876 | Scene m_scene = agent.Scene; |
877 | 877 | ||
@@ -930,6 +930,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
930 | if (!WaitForCallback(agent.UUID)) | 930 | if (!WaitForCallback(agent.UUID)) |
931 | { | 931 | { |
932 | m_log.Debug("[ENTITY TRANSFER MODULE]: Callback never came in crossing agent"); | 932 | m_log.Debug("[ENTITY TRANSFER MODULE]: Callback never came in crossing agent"); |
933 | ReInstantiateScripts(agent); | ||
933 | ResetFromTransit(agent.UUID); | 934 | ResetFromTransit(agent.UUID); |
934 | 935 | ||
935 | // Yikes! We should just have a ref to scene here. | 936 | // Yikes! We should just have a ref to scene here. |
@@ -945,7 +946,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
945 | agent.SendOtherAgentsAvatarDataToMe(); | 946 | agent.SendOtherAgentsAvatarDataToMe(); |
946 | agent.SendOtherAgentsAppearanceToMe(); | 947 | agent.SendOtherAgentsAppearanceToMe(); |
947 | 948 | ||
948 | CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); | 949 | // Backwards compatibility |
950 | if (version == "Unknown" || version == string.Empty) | ||
951 | { | ||
952 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old neighbor, passing attachments one by one..."); | ||
953 | CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); | ||
954 | } | ||
955 | |||
956 | AgentHasMovedAway(agent, false); | ||
949 | 957 | ||
950 | // the user may change their profile information in other region, | 958 | // the user may change their profile information in other region, |
951 | // so the userinfo in UserProfileCache is not reliable any more, delete it | 959 | // so the userinfo in UserProfileCache is not reliable any more, delete it |
@@ -1749,7 +1757,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1749 | return false; | 1757 | return false; |
1750 | } | 1758 | } |
1751 | 1759 | ||
1752 | 1760 | protected void ReInstantiateScripts(ScenePresence sp) | |
1761 | { | ||
1762 | sp.Attachments.ForEach(delegate(SceneObjectGroup sog) | ||
1763 | { | ||
1764 | sog.CreateScriptInstances(0, false, sp.Scene.DefaultScriptEngine, 0); | ||
1765 | sog.ResumeScripts(); | ||
1766 | }); | ||
1767 | } | ||
1753 | #endregion | 1768 | #endregion |
1754 | 1769 | ||
1755 | } | 1770 | } |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 79e76b4..5c53f78 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | |||
@@ -142,11 +142,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
142 | return false; | 142 | return false; |
143 | } | 143 | } |
144 | 144 | ||
145 | protected override void AgentHasMovedAway(UUID sessionID, bool logout) | 145 | protected override void AgentHasMovedAway(ScenePresence sp, bool logout) |
146 | { | 146 | { |
147 | base.AgentHasMovedAway(sp, logout); | ||
147 | if (logout) | 148 | if (logout) |
148 | // Log them out of this grid | 149 | // Log them out of this grid |
149 | m_aScene.PresenceService.LogoutAgent(sessionID); | 150 | m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); |
150 | } | 151 | } |
151 | 152 | ||
152 | protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) | 153 | protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index a298b65..2cf02b5 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs | |||
@@ -41,6 +41,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | |||
41 | public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService | 41 | public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService |
42 | { | 42 | { |
43 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 43 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
44 | // Version of this service | ||
45 | private const string m_Version = "SIMULATION/0.1"; | ||
46 | |||
44 | private List<Scene> m_sceneList = new List<Scene>(); | 47 | private List<Scene> m_sceneList = new List<Scene>(); |
45 | 48 | ||
46 | private IEntityTransferModule m_AgentTransferModule; | 49 | private IEntityTransferModule m_AgentTransferModule; |
@@ -257,9 +260,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | |||
257 | return false; | 260 | return false; |
258 | } | 261 | } |
259 | 262 | ||
260 | public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason) | 263 | public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) |
261 | { | 264 | { |
262 | reason = "Communications failure"; | 265 | reason = "Communications failure"; |
266 | version = m_Version; | ||
263 | if (destination == null) | 267 | if (destination == null) |
264 | return false; | 268 | return false; |
265 | 269 | ||
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index 67f4d60..f8cea71 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs | |||
@@ -179,7 +179,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | |||
179 | return true; | 179 | return true; |
180 | 180 | ||
181 | // else do the remote thing | 181 | // else do the remote thing |
182 | if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) | 182 | if (!m_localBackend.IsLocalRegion(destination.RegionID)) |
183 | { | 183 | { |
184 | return m_remoteConnector.CreateAgent(destination, aCircuit, teleportFlags, out reason); | 184 | return m_remoteConnector.CreateAgent(destination, aCircuit, teleportFlags, out reason); |
185 | } | 185 | } |
@@ -229,19 +229,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | |||
229 | 229 | ||
230 | } | 230 | } |
231 | 231 | ||
232 | public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason) | 232 | public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) |
233 | { | 233 | { |
234 | reason = "Communications failure"; | 234 | reason = "Communications failure"; |
235 | version = "Unknown"; | ||
235 | if (destination == null) | 236 | if (destination == null) |
236 | return false; | 237 | return false; |
237 | 238 | ||
238 | // Try local first | 239 | // Try local first |
239 | if (m_localBackend.QueryAccess(destination, id, position, out reason)) | 240 | if (m_localBackend.QueryAccess(destination, id, position, out version, out reason)) |
240 | return true; | 241 | return true; |
241 | 242 | ||
242 | // else do the remote thing | 243 | // else do the remote thing |
243 | if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) | 244 | if (!m_localBackend.IsLocalRegion(destination.RegionID)) |
244 | return m_remoteConnector.QueryAccess(destination, id, position, out reason); | 245 | return m_remoteConnector.QueryAccess(destination, id, position, out version, out reason); |
245 | 246 | ||
246 | return false; | 247 | return false; |
247 | 248 | ||
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index e3ed905..4595a29 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs | |||
@@ -119,16 +119,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
119 | 119 | ||
120 | private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity) | 120 | private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity) |
121 | { | 121 | { |
122 | return 1; | 122 | // And anything attached to this avatar gets top priority as well |
123 | if (entity is SceneObjectPart) | ||
124 | { | ||
125 | SceneObjectPart sop = (SceneObjectPart)entity; | ||
126 | if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar) | ||
127 | return 1; | ||
128 | } | ||
129 | |||
130 | return PriorityQueue.NumberOfImmediateQueues; // first queue past the immediate queues | ||
123 | } | 131 | } |
124 | 132 | ||
125 | private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity) | 133 | private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity) |
126 | { | 134 | { |
135 | // And anything attached to this avatar gets top priority as well | ||
136 | if (entity is SceneObjectPart) | ||
137 | { | ||
138 | SceneObjectPart sop = (SceneObjectPart)entity; | ||
139 | if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar) | ||
140 | return 1; | ||
141 | } | ||
142 | |||
127 | return ComputeDistancePriority(client,entity,false); | 143 | return ComputeDistancePriority(client,entity,false); |
128 | } | 144 | } |
129 | 145 | ||
130 | private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) | 146 | private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) |
131 | { | 147 | { |
148 | // And anything attached to this avatar gets top priority as well | ||
149 | if (entity is SceneObjectPart) | ||
150 | { | ||
151 | SceneObjectPart sop = (SceneObjectPart)entity; | ||
152 | if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar) | ||
153 | return 1; | ||
154 | } | ||
155 | |||
132 | return ComputeDistancePriority(client,entity,true); | 156 | return ComputeDistancePriority(client,entity,true); |
133 | } | 157 | } |
134 | 158 | ||
@@ -141,18 +165,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
141 | { | 165 | { |
142 | if (!presence.IsChildAgent) | 166 | if (!presence.IsChildAgent) |
143 | { | 167 | { |
168 | // All avatars other than our own go into pqueue 1 | ||
169 | if (entity is ScenePresence) | ||
170 | return 1; | ||
171 | |||
144 | if (entity is SceneObjectPart) | 172 | if (entity is SceneObjectPart) |
145 | { | 173 | { |
174 | // Attachments are high priority, | ||
175 | if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) | ||
176 | return 1; | ||
177 | |||
146 | // Non physical prims are lower priority than physical prims | 178 | // Non physical prims are lower priority than physical prims |
147 | PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; | 179 | PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; |
148 | if (physActor == null || !physActor.IsPhysical) | 180 | if (physActor == null || !physActor.IsPhysical) |
149 | pqueue++; | 181 | pqueue++; |
150 | |||
151 | // Attachments are high priority, | ||
152 | // MIC: shouldn't these already be in the highest priority queue already | ||
153 | // since their root position is same as the avatars? | ||
154 | if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) | ||
155 | pqueue = 1; | ||
156 | } | 182 | } |
157 | } | 183 | } |
158 | } | 184 | } |
@@ -172,7 +198,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
172 | 198 | ||
173 | // m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId); | 199 | // m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId); |
174 | // throw new InvalidOperationException("Prioritization agent not defined"); | 200 | // throw new InvalidOperationException("Prioritization agent not defined"); |
175 | return Int32.MaxValue; | 201 | return PriorityQueue.NumberOfQueues - 1; |
176 | } | 202 | } |
177 | 203 | ||
178 | // Use group position for child prims, since we are putting child prims in | 204 | // Use group position for child prims, since we are putting child prims in |
@@ -197,8 +223,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
197 | 223 | ||
198 | // And convert the distance to a priority queue, this computation gives queues | 224 | // And convert the distance to a priority queue, this computation gives queues |
199 | // at 10, 20, 40, 80, 160, 320, 640, and 1280m | 225 | // at 10, 20, 40, 80, 160, 320, 640, and 1280m |
200 | uint pqueue = 1; | 226 | uint pqueue = PriorityQueue.NumberOfImmediateQueues; |
201 | for (int i = 0; i < 8; i++) | 227 | uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; |
228 | |||
229 | for (int i = 0; i < queues - 1; i++) | ||
202 | { | 230 | { |
203 | if (distance < 10 * Math.Pow(2.0,i)) | 231 | if (distance < 10 * Math.Pow(2.0,i)) |
204 | break; | 232 | break; |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 0f85925..b0f0de6 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -1430,6 +1430,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1430 | } | 1430 | } |
1431 | else // Updating existing item with new perms etc | 1431 | else // Updating existing item with new perms etc |
1432 | { | 1432 | { |
1433 | // m_log.DebugFormat( | ||
1434 | // "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()", | ||
1435 | // currentItem.Name, part.Name); | ||
1436 | |||
1433 | IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); | 1437 | IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); |
1434 | if (agentTransactions != null) | 1438 | if (agentTransactions != null) |
1435 | { | 1439 | { |
@@ -2039,6 +2043,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2039 | if (rot != null) | 2043 | if (rot != null) |
2040 | group.UpdateGroupRotationR((Quaternion)rot); | 2044 | group.UpdateGroupRotationR((Quaternion)rot); |
2041 | 2045 | ||
2046 | // TODO: This needs to be refactored with the similar code in | ||
2047 | // SceneGraph.AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) | ||
2048 | // possibly by allowing this method to take a null rotation. | ||
2049 | if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero) | ||
2050 | group.RootPart.ApplyImpulse((vel * group.GetMass()), false); | ||
2051 | |||
2042 | // We can only call this after adding the scene object, since the scene object references the scene | 2052 | // We can only call this after adding the scene object, since the scene object references the scene |
2043 | // to find out if scripts should be activated at all. | 2053 | // to find out if scripts should be activated at all. |
2044 | group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); | 2054 | group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 01de824..7c5e246 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -1229,7 +1229,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1229 | 1229 | ||
1230 | // Increment the frame counter | 1230 | // Increment the frame counter |
1231 | ++Frame; | 1231 | ++Frame; |
1232 | |||
1233 | try | 1232 | try |
1234 | { | 1233 | { |
1235 | // Check if any objects have reached their targets | 1234 | // Check if any objects have reached their targets |
@@ -2316,7 +2315,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2316 | /// <returns></returns> | 2315 | /// <returns></returns> |
2317 | public bool IncomingCreateObject(ISceneObject sog) | 2316 | public bool IncomingCreateObject(ISceneObject sog) |
2318 | { | 2317 | { |
2319 | //m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); | 2318 | //m_log.DebugFormat(" >>> IncomingCreateObject(sog) <<< {0} deleted? {1} isAttach? {2}", ((SceneObjectGroup)sog).AbsolutePosition, |
2319 | // ((SceneObjectGroup)sog).IsDeleted, ((SceneObjectGroup)sog).RootPart.IsAttachment); | ||
2320 | |||
2320 | SceneObjectGroup newObject; | 2321 | SceneObjectGroup newObject; |
2321 | try | 2322 | try |
2322 | { | 2323 | { |
@@ -2334,9 +2335,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
2334 | return false; | 2335 | return false; |
2335 | } | 2336 | } |
2336 | 2337 | ||
2337 | newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject)); | 2338 | // For attachments, we need to wait until the agent is root |
2338 | 2339 | // before we restart the scripts, or else some functions won't work. | |
2339 | newObject.ResumeScripts(); | 2340 | if (!newObject.IsAttachment) |
2341 | { | ||
2342 | newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject)); | ||
2343 | newObject.ResumeScripts(); | ||
2344 | } | ||
2345 | else | ||
2346 | { | ||
2347 | ScenePresence sp; | ||
2348 | if (TryGetScenePresence(newObject.OwnerID, out sp)) | ||
2349 | { | ||
2350 | // If the scene presence is here and already a root | ||
2351 | // agent, we came from a ;egacy region. Start the scripts | ||
2352 | // here as they used to start. | ||
2353 | // TODO: Remove in 0.7.3 | ||
2354 | if (!sp.IsChildAgent) | ||
2355 | { | ||
2356 | newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject)); | ||
2357 | newObject.ResumeScripts(); | ||
2358 | } | ||
2359 | } | ||
2360 | } | ||
2340 | 2361 | ||
2341 | // Do this as late as possible so that listeners have full access to the incoming object | 2362 | // Do this as late as possible so that listeners have full access to the incoming object |
2342 | EventManager.TriggerOnIncomingSceneObject(newObject); | 2363 | EventManager.TriggerOnIncomingSceneObject(newObject); |
@@ -2453,17 +2474,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2453 | ScenePresence sp = GetScenePresence(sog.OwnerID); | 2474 | ScenePresence sp = GetScenePresence(sog.OwnerID); |
2454 | 2475 | ||
2455 | if (sp != null) | 2476 | if (sp != null) |
2456 | { | 2477 | return sp.GetStateSource(); |
2457 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(sp.UUID); | ||
2458 | 2478 | ||
2459 | if (aCircuit != null && (aCircuit.teleportFlags != (uint)TeleportFlags.Default)) | ||
2460 | { | ||
2461 | // This will get your attention | ||
2462 | //m_log.Error("[XXX] Triggering CHANGED_TELEPORT"); | ||
2463 | |||
2464 | return 5; // StateSource.Teleporting | ||
2465 | } | ||
2466 | } | ||
2467 | return 2; // StateSource.PrimCrossing | 2479 | return 2; // StateSource.PrimCrossing |
2468 | } | 2480 | } |
2469 | 2481 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 3281eab..3b60f8c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | |||
@@ -693,8 +693,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
693 | { | 693 | { |
694 | TaskInventoryItem it = GetInventoryItem(item.ItemID); | 694 | TaskInventoryItem it = GetInventoryItem(item.ItemID); |
695 | if (it != null) | 695 | if (it != null) |
696 | |||
697 | { | 696 | { |
697 | // m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); | ||
698 | |||
698 | item.ParentID = m_part.UUID; | 699 | item.ParentID = m_part.UUID; |
699 | item.ParentPartID = m_part.UUID; | 700 | item.ParentPartID = m_part.UUID; |
700 | 701 | ||
@@ -711,14 +712,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
711 | m_items[item.ItemID] = item; | 712 | m_items[item.ItemID] = item; |
712 | m_inventorySerial++; | 713 | m_inventorySerial++; |
713 | } | 714 | } |
714 | 715 | ||
715 | if (fireScriptEvents) | 716 | if (fireScriptEvents) |
716 | m_part.TriggerScriptChangedEvent(Changed.INVENTORY); | 717 | m_part.TriggerScriptChangedEvent(Changed.INVENTORY); |
718 | |||
717 | if (considerChanged) | 719 | if (considerChanged) |
718 | { | 720 | { |
719 | HasInventoryChanged = true; | 721 | HasInventoryChanged = true; |
720 | m_part.ParentGroup.HasGroupChanged = true; | 722 | m_part.ParentGroup.HasGroupChanged = true; |
721 | } | 723 | } |
724 | |||
722 | return true; | 725 | return true; |
723 | } | 726 | } |
724 | else | 727 | else |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 00a1487..5b86735 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -840,6 +840,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
840 | 840 | ||
841 | //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); | 841 | //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); |
842 | 842 | ||
843 | bool wasChild = m_isChildAgent; | ||
844 | m_isChildAgent = false; | ||
845 | |||
843 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); | 846 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); |
844 | if (gm != null) | 847 | if (gm != null) |
845 | m_grouptitle = gm.GetGroupTitle(m_uuid); | 848 | m_grouptitle = gm.GetGroupTitle(m_uuid); |
@@ -929,14 +932,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
929 | // Animator.SendAnimPack(); | 932 | // Animator.SendAnimPack(); |
930 | 933 | ||
931 | m_scene.SwapRootAgentCount(false); | 934 | m_scene.SwapRootAgentCount(false); |
932 | 935 | ||
933 | //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid); | 936 | // The initial login scene presence is already root when it gets here |
934 | //if (userInfo != null) | 937 | // and it has already rezzed the attachments and started their scripts. |
935 | // userInfo.FetchInventory(); | 938 | // We do the following only for non-login agents, because their scripts |
936 | //else | 939 | // haven't started yet. |
937 | // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid); | 940 | if (wasChild && Attachments != null && Attachments.Count > 0) |
938 | 941 | { | |
939 | m_isChildAgent = false; | 942 | m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); |
943 | // Resume scripts | ||
944 | Attachments.ForEach(delegate(SceneObjectGroup sog) | ||
945 | { | ||
946 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); | ||
947 | sog.ResumeScripts(); | ||
948 | }); | ||
949 | } | ||
940 | 950 | ||
941 | // send the animations of the other presences to me | 951 | // send the animations of the other presences to me |
942 | m_scene.ForEachScenePresence(delegate(ScenePresence presence) | 952 | m_scene.ForEachScenePresence(delegate(ScenePresence presence) |
@@ -948,6 +958,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
948 | m_scene.EventManager.TriggerOnMakeRootAgent(this); | 958 | m_scene.EventManager.TriggerOnMakeRootAgent(this); |
949 | } | 959 | } |
950 | 960 | ||
961 | public int GetStateSource() | ||
962 | { | ||
963 | AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID); | ||
964 | |||
965 | if (aCircuit != null && (aCircuit.teleportFlags != (uint)TeleportFlags.Default)) | ||
966 | { | ||
967 | // This will get your attention | ||
968 | //m_log.Error("[XXX] Triggering CHANGED_TELEPORT"); | ||
969 | |||
970 | return 5; // StateSource.Teleporting | ||
971 | } | ||
972 | return 2; // StateSource.PrimCrossing | ||
973 | } | ||
974 | |||
951 | /// <summary> | 975 | /// <summary> |
952 | /// This turns a root agent into a child agent | 976 | /// This turns a root agent into a child agent |
953 | /// when an agent departs this region for a neighbor, this gets called. | 977 | /// when an agent departs this region for a neighbor, this gets called. |
@@ -1139,7 +1163,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1139 | AbsolutePosition = pos; | 1163 | AbsolutePosition = pos; |
1140 | } | 1164 | } |
1141 | 1165 | ||
1142 | m_isChildAgent = false; | ||
1143 | bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | 1166 | bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); |
1144 | MakeRootAgent(AbsolutePosition, m_flying); | 1167 | MakeRootAgent(AbsolutePosition, m_flying); |
1145 | 1168 | ||
@@ -2340,12 +2363,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2340 | 2363 | ||
2341 | #region Update Client(s) | 2364 | #region Update Client(s) |
2342 | 2365 | ||
2366 | |||
2343 | /// <summary> | 2367 | /// <summary> |
2344 | /// Sends a location update to the client connected to this scenePresence | 2368 | /// Sends a location update to the client connected to this scenePresence |
2345 | /// </summary> | 2369 | /// </summary> |
2346 | /// <param name="remoteClient"></param> | 2370 | /// <param name="remoteClient"></param> |
2347 | public void SendTerseUpdateToClient(IClientAPI remoteClient) | 2371 | public void SendTerseUpdateToClient(IClientAPI remoteClient) |
2348 | { | 2372 | { |
2373 | |||
2349 | // If the client is inactive, it's getting its updates from another | 2374 | // If the client is inactive, it's getting its updates from another |
2350 | // server. | 2375 | // server. |
2351 | if (remoteClient.IsActive) | 2376 | if (remoteClient.IsActive) |
@@ -2358,8 +2383,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2358 | //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); | 2383 | //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); |
2359 | 2384 | ||
2360 | remoteClient.SendPrimUpdate( | 2385 | remoteClient.SendPrimUpdate( |
2361 | this, | 2386 | this, |
2362 | PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | 2387 | PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity |
2363 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); | 2388 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); |
2364 | 2389 | ||
2365 | m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); | 2390 | m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); |
@@ -2367,16 +2392,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
2367 | } | 2392 | } |
2368 | } | 2393 | } |
2369 | 2394 | ||
2395 | |||
2396 | // vars to support reduced update frequency when velocity is unchanged | ||
2397 | private Vector3 lastVelocitySentToAllClients = Vector3.Zero; | ||
2398 | private int lastTerseUpdateToAllClientsTick = Util.EnvironmentTickCount(); | ||
2399 | |||
2370 | /// <summary> | 2400 | /// <summary> |
2371 | /// Send a location/velocity/accelleration update to all agents in scene | 2401 | /// Send a location/velocity/accelleration update to all agents in scene |
2372 | /// </summary> | 2402 | /// </summary> |
2373 | public void SendTerseUpdateToAllClients() | 2403 | public void SendTerseUpdateToAllClients() |
2374 | { | 2404 | { |
2375 | m_perfMonMS = Util.EnvironmentTickCount(); | 2405 | int currentTick = Util.EnvironmentTickCount(); |
2376 | |||
2377 | m_scene.ForEachClient(SendTerseUpdateToClient); | ||
2378 | 2406 | ||
2379 | m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); | 2407 | // decrease update frequency when avatar is moving but velocity is not changing |
2408 | if (m_velocity.Length() < 0.01f | ||
2409 | || Vector3.Distance(lastVelocitySentToAllClients, m_velocity) > 0.01f | ||
2410 | || currentTick - lastTerseUpdateToAllClientsTick > 1500) | ||
2411 | { | ||
2412 | m_perfMonMS = currentTick; | ||
2413 | lastVelocitySentToAllClients = m_velocity; | ||
2414 | lastTerseUpdateToAllClientsTick = currentTick; | ||
2415 | |||
2416 | m_scene.ForEachClient(SendTerseUpdateToClient); | ||
2417 | |||
2418 | m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); | ||
2419 | } | ||
2380 | } | 2420 | } |
2381 | 2421 | ||
2382 | public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs) | 2422 | public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs) |
@@ -2632,18 +2672,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2632 | cadu.GroupAccess = 0; | 2672 | cadu.GroupAccess = 0; |
2633 | cadu.Position = AbsolutePosition; | 2673 | cadu.Position = AbsolutePosition; |
2634 | cadu.regionHandle = m_rootRegionHandle; | 2674 | cadu.regionHandle = m_rootRegionHandle; |
2675 | |||
2676 | // Throttles | ||
2635 | float multiplier = 1; | 2677 | float multiplier = 1; |
2636 | int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); | 2678 | int childRegions = m_knownChildRegions.Count; |
2637 | if (innacurateNeighbors != 0) | 2679 | if (childRegions != 0) |
2638 | { | 2680 | multiplier = 1f / childRegions; |
2639 | multiplier = 1f / (float)innacurateNeighbors; | 2681 | |
2640 | } | 2682 | // Minimum throttle for a child region is 1/4 of the root region throttle |
2641 | if (multiplier <= 0f) | 2683 | if (multiplier <= 0.25f) |
2642 | { | ||
2643 | multiplier = 0.25f; | 2684 | multiplier = 0.25f; |
2644 | } | ||
2645 | 2685 | ||
2646 | //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); | ||
2647 | cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); | 2686 | cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); |
2648 | cadu.Velocity = Velocity; | 2687 | cadu.Velocity = Velocity; |
2649 | 2688 | ||
@@ -3039,16 +3078,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3039 | 3078 | ||
3040 | // Throttles | 3079 | // Throttles |
3041 | float multiplier = 1; | 3080 | float multiplier = 1; |
3042 | int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); | 3081 | int childRegions = m_knownChildRegions.Count; |
3043 | if (innacurateNeighbors != 0) | 3082 | if (childRegions != 0) |
3044 | { | 3083 | multiplier = 1f / childRegions; |
3045 | multiplier = 1f / innacurateNeighbors; | 3084 | |
3046 | } | 3085 | // Minimum throttle for a child region is 1/4 of the root region throttle |
3047 | if (multiplier <= 0f) | 3086 | if (multiplier <= 0.25f) |
3048 | { | ||
3049 | multiplier = 0.25f; | 3087 | multiplier = 0.25f; |
3050 | } | 3088 | |
3051 | //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); | ||
3052 | cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); | 3089 | cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); |
3053 | 3090 | ||
3054 | cAgent.HeadRotation = m_headrotation; | 3091 | cAgent.HeadRotation = m_headrotation; |
@@ -3064,54 +3101,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3064 | 3101 | ||
3065 | cAgent.Appearance = new AvatarAppearance(m_appearance); | 3102 | cAgent.Appearance = new AvatarAppearance(m_appearance); |
3066 | 3103 | ||
3067 | /* | ||
3068 | try | ||
3069 | { | ||
3070 | // We might not pass the Wearables in all cases... | ||
3071 | // They're only needed so that persistent changes to the appearance | ||
3072 | // are preserved in the new region where the user is moving to. | ||
3073 | // But in Hypergrid we might not let this happen. | ||
3074 | int i = 0; | ||
3075 | UUID[] wears = new UUID[m_appearance.Wearables.Length * 2]; | ||
3076 | foreach (AvatarWearable aw in m_appearance.Wearables) | ||
3077 | { | ||
3078 | if (aw != null) | ||
3079 | { | ||
3080 | wears[i++] = aw.ItemID; | ||
3081 | wears[i++] = aw.AssetID; | ||
3082 | } | ||
3083 | else | ||
3084 | { | ||
3085 | wears[i++] = UUID.Zero; | ||
3086 | wears[i++] = UUID.Zero; | ||
3087 | } | ||
3088 | } | ||
3089 | cAgent.Wearables = wears; | ||
3090 | |||
3091 | cAgent.VisualParams = m_appearance.VisualParams; | ||
3092 | |||
3093 | if (m_appearance.Texture != null) | ||
3094 | cAgent.AgentTextures = m_appearance.Texture.GetBytes(); | ||
3095 | } | ||
3096 | catch (Exception e) | ||
3097 | { | ||
3098 | m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message); | ||
3099 | } | ||
3100 | |||
3101 | //Attachments | ||
3102 | List<int> attPoints = m_appearance.GetAttachedPoints(); | ||
3103 | if (attPoints != null) | ||
3104 | { | ||
3105 | //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count); | ||
3106 | int i = 0; | ||
3107 | AvatarAttachment[] attachs = new AvatarAttachment[attPoints.Count]; | ||
3108 | foreach (int point in attPoints) | ||
3109 | { | ||
3110 | attachs[i++] = new AvatarAttachment(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point)); | ||
3111 | } | ||
3112 | cAgent.Attachments = attachs; | ||
3113 | } | ||
3114 | */ | ||
3115 | lock (scriptedcontrols) | 3104 | lock (scriptedcontrols) |
3116 | { | 3105 | { |
3117 | ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; | 3106 | ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; |
@@ -3131,9 +3120,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
3131 | } | 3120 | } |
3132 | catch { } | 3121 | catch { } |
3133 | 3122 | ||
3134 | // cAgent.GroupID = ?? | 3123 | // Attachment objects |
3135 | // Groups??? | 3124 | if (m_attachments != null && m_attachments.Count > 0) |
3136 | 3125 | { | |
3126 | cAgent.AttachmentObjects = new List<ISceneObject>(); | ||
3127 | cAgent.AttachmentObjectStates = new List<string>(); | ||
3128 | IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>(); | ||
3129 | foreach (SceneObjectGroup sog in m_attachments) | ||
3130 | { | ||
3131 | // We need to make a copy and pass that copy | ||
3132 | // because of transfers withn the same sim | ||
3133 | ISceneObject clone = sog.CloneForNewScene(); | ||
3134 | // Attachment module assumes that GroupPosition holds the offsets...! | ||
3135 | ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos; | ||
3136 | ((SceneObjectGroup)clone).RootPart.IsAttachment = false; | ||
3137 | cAgent.AttachmentObjects.Add(clone); | ||
3138 | cAgent.AttachmentObjectStates.Add(sog.GetStateSnapshot()); | ||
3139 | // Let's remove the scripts of the original object here | ||
3140 | sog.RemoveScriptInstances(true); | ||
3141 | } | ||
3142 | } | ||
3137 | } | 3143 | } |
3138 | 3144 | ||
3139 | public void CopyFrom(AgentData cAgent) | 3145 | public void CopyFrom(AgentData cAgent) |
@@ -3174,50 +3180,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3174 | AddToPhysicalScene(isFlying); | 3180 | AddToPhysicalScene(isFlying); |
3175 | } | 3181 | } |
3176 | 3182 | ||
3177 | /* | ||
3178 | uint i = 0; | ||
3179 | try | ||
3180 | { | ||
3181 | if (cAgent.Wearables == null) | ||
3182 | cAgent.Wearables = new UUID[0]; | ||
3183 | AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2]; | ||
3184 | for (uint n = 0; n < cAgent.Wearables.Length; n += 2) | ||
3185 | { | ||
3186 | UUID itemId = cAgent.Wearables[n]; | ||
3187 | UUID assetId = cAgent.Wearables[n + 1]; | ||
3188 | wears[i++] = new AvatarWearable(itemId, assetId); | ||
3189 | } | ||
3190 | // m_appearance.Wearables = wears; | ||
3191 | Primitive.TextureEntry textures = null; | ||
3192 | if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1) | ||
3193 | textures = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length); | ||
3194 | |||
3195 | byte[] visuals = null; | ||
3196 | |||
3197 | if ((cAgent.VisualParams != null) && (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT)) | ||
3198 | visuals = (byte[])cAgent.VisualParams.Clone(); | ||
3199 | |||
3200 | m_appearance = new AvatarAppearance(cAgent.AgentID,wears,textures,visuals); | ||
3201 | } | ||
3202 | catch (Exception e) | ||
3203 | { | ||
3204 | m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message); | ||
3205 | } | ||
3206 | |||
3207 | // Attachments | ||
3208 | try | ||
3209 | { | ||
3210 | if (cAgent.Attachments != null) | ||
3211 | { | ||
3212 | m_appearance.ClearAttachments(); | ||
3213 | foreach (AvatarAttachment att in cAgent.Attachments) | ||
3214 | { | ||
3215 | m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID); | ||
3216 | } | ||
3217 | } | ||
3218 | } | ||
3219 | catch { } | ||
3220 | */ | ||
3221 | try | 3183 | try |
3222 | { | 3184 | { |
3223 | lock (scriptedcontrols) | 3185 | lock (scriptedcontrols) |
@@ -3247,8 +3209,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
3247 | } | 3209 | } |
3248 | catch { } | 3210 | catch { } |
3249 | 3211 | ||
3250 | //cAgent.GroupID = ?? | 3212 | if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0) |
3251 | //Groups??? | 3213 | { |
3214 | m_attachments = new List<SceneObjectGroup>(); | ||
3215 | int i = 0; | ||
3216 | foreach (ISceneObject so in cAgent.AttachmentObjects) | ||
3217 | { | ||
3218 | ((SceneObjectGroup)so).LocalId = 0; | ||
3219 | ((SceneObjectGroup)so).RootPart.UpdateFlag = 0; | ||
3220 | so.SetState(cAgent.AttachmentObjectStates[i++], m_scene); | ||
3221 | m_scene.IncomingCreateObject(so); | ||
3222 | } | ||
3223 | } | ||
3252 | } | 3224 | } |
3253 | 3225 | ||
3254 | public bool CopyAgent(out IAgentData agent) | 3226 | public bool CopyAgent(out IAgentData agent) |
@@ -3271,10 +3243,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3271 | 3243 | ||
3272 | m_updateflag = true; | 3244 | m_updateflag = true; |
3273 | 3245 | ||
3274 | // The magic constant 0.95f seems to make walking feel less jerky, | 3246 | Velocity = force; |
3275 | // probably because it hackishly accounts for the overall latency of | ||
3276 | // these Velocity updates -- Diva | ||
3277 | Velocity = force * .95F; | ||
3278 | 3247 | ||
3279 | m_forceToApply = null; | 3248 | m_forceToApply = null; |
3280 | } | 3249 | } |
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index 6a24cc1..db17d8f 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs | |||
@@ -82,6 +82,14 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
82 | m_scenes[scene.RegionInfo.RegionID] = scene; | 82 | m_scenes[scene.RegionInfo.RegionID] = scene; |
83 | 83 | ||
84 | scene.AddCommand( | 84 | scene.AddCommand( |
85 | this, "show pqueues", | ||
86 | "show pqueues [full]", | ||
87 | "Show priority queue data for each client", | ||
88 | "Without the 'full' option, only root agents are shown." | ||
89 | + " With the 'full' option child agents are also shown.", | ||
90 | ShowPQueuesReport); | ||
91 | |||
92 | scene.AddCommand( | ||
85 | this, "show queues", | 93 | this, "show queues", |
86 | "show queues [full]", | 94 | "show queues [full]", |
87 | "Show queue data for each client", | 95 | "Show queue data for each client", |
@@ -119,6 +127,11 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
119 | // m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); | 127 | // m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); |
120 | } | 128 | } |
121 | 129 | ||
130 | protected void ShowPQueuesReport(string module, string[] cmd) | ||
131 | { | ||
132 | MainConsole.Instance.Output(GetPQueuesReport(cmd)); | ||
133 | } | ||
134 | |||
122 | protected void ShowQueuesReport(string module, string[] cmd) | 135 | protected void ShowQueuesReport(string module, string[] cmd) |
123 | { | 136 | { |
124 | MainConsole.Instance.Output(GetQueuesReport(cmd)); | 137 | MainConsole.Instance.Output(GetQueuesReport(cmd)); |
@@ -155,6 +168,80 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
155 | ""); | 168 | ""); |
156 | } | 169 | } |
157 | 170 | ||
171 | |||
172 | /// <summary> | ||
173 | /// Generate UDP Queue data report for each client | ||
174 | /// </summary> | ||
175 | /// <param name="showParams"></param> | ||
176 | /// <returns></returns> | ||
177 | protected string GetPQueuesReport(string[] showParams) | ||
178 | { | ||
179 | bool showChildren = false; | ||
180 | string pname = ""; | ||
181 | |||
182 | if (showParams.Length > 2 && showParams[2] == "full") | ||
183 | showChildren = true; | ||
184 | else if (showParams.Length > 3) | ||
185 | pname = showParams[2] + " " + showParams[3]; | ||
186 | |||
187 | StringBuilder report = new StringBuilder(); | ||
188 | |||
189 | int columnPadding = 2; | ||
190 | int maxNameLength = 18; | ||
191 | int maxRegionNameLength = 14; | ||
192 | int maxTypeLength = 4; | ||
193 | int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding; | ||
194 | |||
195 | report.Append(GetColumnEntry("User", maxNameLength, columnPadding)); | ||
196 | report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding)); | ||
197 | report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); | ||
198 | |||
199 | report.AppendFormat( | ||
200 | "{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7} {10,7} {11,7}\n", | ||
201 | "Pri 0", | ||
202 | "Pri 1", | ||
203 | "Pri 2", | ||
204 | "Pri 3", | ||
205 | "Pri 4", | ||
206 | "Pri 5", | ||
207 | "Pri 6", | ||
208 | "Pri 7", | ||
209 | "Pri 8", | ||
210 | "Pri 9", | ||
211 | "Pri 10", | ||
212 | "Pri 11"); | ||
213 | |||
214 | lock (m_scenes) | ||
215 | { | ||
216 | foreach (Scene scene in m_scenes.Values) | ||
217 | { | ||
218 | scene.ForEachClient( | ||
219 | delegate(IClientAPI client) | ||
220 | { | ||
221 | if (client is LLClientView) | ||
222 | { | ||
223 | bool isChild = scene.PresenceChildStatus(client.AgentId); | ||
224 | if (isChild && !showChildren) | ||
225 | return; | ||
226 | |||
227 | string name = client.Name; | ||
228 | if (pname != "" && name != pname) | ||
229 | return; | ||
230 | |||
231 | string regionName = scene.RegionInfo.RegionName; | ||
232 | |||
233 | report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); | ||
234 | report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding)); | ||
235 | report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); | ||
236 | report.AppendLine(((LLClientView)client).EntityUpdateQueue.ToString()); | ||
237 | } | ||
238 | }); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | return report.ToString(); | ||
243 | } | ||
244 | |||
158 | /// <summary> | 245 | /// <summary> |
159 | /// Generate UDP Queue data report for each client | 246 | /// Generate UDP Queue data report for each client |
160 | /// </summary> | 247 | /// </summary> |
@@ -163,10 +250,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
163 | protected string GetQueuesReport(string[] showParams) | 250 | protected string GetQueuesReport(string[] showParams) |
164 | { | 251 | { |
165 | bool showChildren = false; | 252 | bool showChildren = false; |
253 | string pname = ""; | ||
166 | 254 | ||
167 | if (showParams.Length > 2 && showParams[2] == "full") | 255 | if (showParams.Length > 2 && showParams[2] == "full") |
168 | showChildren = true; | 256 | showChildren = true; |
169 | 257 | else if (showParams.Length > 3) | |
258 | pname = showParams[2] + " " + showParams[3]; | ||
259 | |||
170 | StringBuilder report = new StringBuilder(); | 260 | StringBuilder report = new StringBuilder(); |
171 | 261 | ||
172 | int columnPadding = 2; | 262 | int columnPadding = 2; |
@@ -224,6 +314,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
224 | return; | 314 | return; |
225 | 315 | ||
226 | string name = client.Name; | 316 | string name = client.Name; |
317 | if (pname != "" && name != pname) | ||
318 | return; | ||
319 | |||
227 | string regionName = scene.RegionInfo.RegionName; | 320 | string regionName = scene.RegionInfo.RegionName; |
228 | 321 | ||
229 | report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); | 322 | report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); |
@@ -249,10 +342,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
249 | protected string GetThrottlesReport(string[] showParams) | 342 | protected string GetThrottlesReport(string[] showParams) |
250 | { | 343 | { |
251 | bool showChildren = false; | 344 | bool showChildren = false; |
345 | string pname = ""; | ||
252 | 346 | ||
253 | if (showParams.Length > 2 && showParams[2] == "full") | 347 | if (showParams.Length > 2 && showParams[2] == "full") |
254 | showChildren = true; | 348 | showChildren = true; |
255 | 349 | else if (showParams.Length > 3) | |
350 | pname = showParams[2] + " " + showParams[3]; | ||
351 | |||
256 | StringBuilder report = new StringBuilder(); | 352 | StringBuilder report = new StringBuilder(); |
257 | 353 | ||
258 | int columnPadding = 2; | 354 | int columnPadding = 2; |
@@ -302,7 +398,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
302 | if (client is LLClientView) | 398 | if (client is LLClientView) |
303 | { | 399 | { |
304 | LLClientView llClient = client as LLClientView; | 400 | LLClientView llClient = client as LLClientView; |
305 | 401 | ||
306 | if (firstClient) | 402 | if (firstClient) |
307 | { | 403 | { |
308 | report.AppendLine(GetServerThrottlesReport(llClient.UDPServer)); | 404 | report.AppendLine(GetServerThrottlesReport(llClient.UDPServer)); |
@@ -314,6 +410,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
314 | return; | 410 | return; |
315 | 411 | ||
316 | string name = client.Name; | 412 | string name = client.Name; |
413 | if (pname != "" && name != pname) | ||
414 | return; | ||
415 | |||
317 | string regionName = scene.RegionInfo.RegionName; | 416 | string regionName = scene.RegionInfo.RegionName; |
318 | 417 | ||
319 | LLUDPClient llUdpClient = llClient.UDPClient; | 418 | LLUDPClient llUdpClient = llClient.UDPClient; |
@@ -352,7 +451,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
352 | int maxRegionNameLength = 14; | 451 | int maxRegionNameLength = 14; |
353 | int maxTypeLength = 4; | 452 | int maxTypeLength = 4; |
354 | 453 | ||
355 | string name = "SERVER AGENT LIMITS"; | 454 | string name = "SERVER AGENT RATES"; |
356 | 455 | ||
357 | report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); | 456 | report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); |
358 | report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding)); | 457 | report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding)); |
@@ -362,13 +461,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
362 | report.AppendFormat( | 461 | report.AppendFormat( |
363 | "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", | 462 | "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", |
364 | (throttleRates.Total * 8) / 1000, | 463 | (throttleRates.Total * 8) / 1000, |
365 | (throttleRates.ResendLimit * 8) / 1000, | 464 | (throttleRates.Resend * 8) / 1000, |
366 | (throttleRates.LandLimit * 8) / 1000, | 465 | (throttleRates.Land * 8) / 1000, |
367 | (throttleRates.WindLimit * 8) / 1000, | 466 | (throttleRates.Wind * 8) / 1000, |
368 | (throttleRates.CloudLimit * 8) / 1000, | 467 | (throttleRates.Cloud * 8) / 1000, |
369 | (throttleRates.TaskLimit * 8) / 1000, | 468 | (throttleRates.Task * 8) / 1000, |
370 | (throttleRates.TextureLimit * 8) / 1000, | 469 | (throttleRates.Texture * 8) / 1000, |
371 | (throttleRates.AssetLimit * 8) / 1000); | 470 | (throttleRates.Asset * 8) / 1000); |
372 | 471 | ||
373 | return report.ToString(); | 472 | return report.ToString(); |
374 | } | 473 | } |
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 64774d8..f89b824 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -88,7 +88,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
88 | 88 | ||
89 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); | 89 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); |
90 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); | 90 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); |
91 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | 91 | if(mesh_config != null) |
92 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | ||
92 | 93 | ||
93 | try | 94 | try |
94 | { | 95 | { |
diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index 372a59c..8b6fb4f 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs | |||
@@ -50,6 +50,7 @@ namespace OpenSim.Server.Handlers.Simulation | |||
50 | public class AgentHandler | 50 | public class AgentHandler |
51 | { | 51 | { |
52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
53 | |||
53 | private ISimulationService m_SimulationService; | 54 | private ISimulationService m_SimulationService; |
54 | 55 | ||
55 | protected bool m_Proxy = false; | 56 | protected bool m_Proxy = false; |
@@ -275,7 +276,7 @@ namespace OpenSim.Server.Handlers.Simulation | |||
275 | AgentData agent = new AgentData(); | 276 | AgentData agent = new AgentData(); |
276 | try | 277 | try |
277 | { | 278 | { |
278 | agent.Unpack(args); | 279 | agent.Unpack(args, m_SimulationService.GetScene(destination.RegionHandle)); |
279 | } | 280 | } |
280 | catch (Exception ex) | 281 | catch (Exception ex) |
281 | { | 282 | { |
@@ -295,7 +296,7 @@ namespace OpenSim.Server.Handlers.Simulation | |||
295 | AgentPosition agent = new AgentPosition(); | 296 | AgentPosition agent = new AgentPosition(); |
296 | try | 297 | try |
297 | { | 298 | { |
298 | agent.Unpack(args); | 299 | agent.Unpack(args, m_SimulationService.GetScene(destination.RegionHandle)); |
299 | } | 300 | } |
300 | catch (Exception ex) | 301 | catch (Exception ex) |
301 | { | 302 | { |
@@ -342,7 +343,8 @@ namespace OpenSim.Server.Handlers.Simulation | |||
342 | destination.RegionID = regionID; | 343 | destination.RegionID = regionID; |
343 | 344 | ||
344 | string reason; | 345 | string reason; |
345 | bool result = m_SimulationService.QueryAccess(destination, id, position, out reason); | 346 | string version; |
347 | bool result = m_SimulationService.QueryAccess(destination, id, position, out version, out reason); | ||
346 | 348 | ||
347 | responsedata["int_response_code"] = HttpStatusCode.OK; | 349 | responsedata["int_response_code"] = HttpStatusCode.OK; |
348 | 350 | ||
@@ -350,6 +352,7 @@ namespace OpenSim.Server.Handlers.Simulation | |||
350 | 352 | ||
351 | resp["success"] = OSD.FromBoolean(result); | 353 | resp["success"] = OSD.FromBoolean(result); |
352 | resp["reason"] = OSD.FromString(reason); | 354 | resp["reason"] = OSD.FromString(reason); |
355 | resp["version"] = OSD.FromString(version); | ||
353 | 356 | ||
354 | responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); | 357 | responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); |
355 | } | 358 | } |
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 93b3ae6..5cb8269 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs | |||
@@ -241,7 +241,7 @@ namespace OpenSim.Services.Connectors.Simulation | |||
241 | if (args != null) | 241 | if (args != null) |
242 | { | 242 | { |
243 | agent = new CompleteAgentData(); | 243 | agent = new CompleteAgentData(); |
244 | agent.Unpack(args); | 244 | agent.Unpack(args, null); |
245 | return true; | 245 | return true; |
246 | } | 246 | } |
247 | } | 247 | } |
@@ -256,9 +256,10 @@ namespace OpenSim.Services.Connectors.Simulation | |||
256 | 256 | ||
257 | /// <summary> | 257 | /// <summary> |
258 | /// </summary> | 258 | /// </summary> |
259 | public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason) | 259 | public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) |
260 | { | 260 | { |
261 | reason = "Failed to contact destination"; | 261 | reason = "Failed to contact destination"; |
262 | version = "Unknown"; | ||
262 | 263 | ||
263 | // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position); | 264 | // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position); |
264 | 265 | ||
@@ -275,9 +276,16 @@ namespace OpenSim.Services.Connectors.Simulation | |||
275 | { | 276 | { |
276 | OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000); | 277 | OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000); |
277 | bool success = result["success"].AsBoolean(); | 278 | bool success = result["success"].AsBoolean(); |
278 | reason = result["reason"].AsString(); | 279 | if (result.ContainsKey("_Result")) |
280 | { | ||
281 | OSDMap data = (OSDMap)result["_Result"]; | ||
282 | |||
283 | reason = data["reason"].AsString(); | ||
284 | if (data["version"] != null && data["version"].AsString() != string.Empty) | ||
285 | version = data["version"].AsString(); | ||
279 | 286 | ||
280 | //m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1}", uri, success); | 287 | m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1} version {2} ({3})", uri, success, version, data["version"].AsString()); |
288 | } | ||
281 | 289 | ||
282 | if (!success) | 290 | if (!success) |
283 | { | 291 | { |
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs index b66bfed..9385b8d 100644 --- a/OpenSim/Services/HypergridService/GatekeeperService.cs +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs | |||
@@ -29,6 +29,7 @@ using System; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Net; | 30 | using System.Net; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Text.RegularExpressions; | ||
32 | 33 | ||
33 | using OpenSim.Framework; | 34 | using OpenSim.Framework; |
34 | using OpenSim.Services.Interfaces; | 35 | using OpenSim.Services.Interfaces; |
@@ -57,6 +58,9 @@ namespace OpenSim.Services.HypergridService | |||
57 | private static IUserAgentService m_UserAgentService; | 58 | private static IUserAgentService m_UserAgentService; |
58 | private static ISimulationService m_SimulationService; | 59 | private static ISimulationService m_SimulationService; |
59 | 60 | ||
61 | protected string m_AllowedClients = string.Empty; | ||
62 | protected string m_DeniedClients = string.Empty; | ||
63 | |||
60 | private static UUID m_ScopeID; | 64 | private static UUID m_ScopeID; |
61 | private static bool m_AllowTeleportsToAnyRegion; | 65 | private static bool m_AllowTeleportsToAnyRegion; |
62 | private static string m_ExternalName; | 66 | private static string m_ExternalName; |
@@ -104,6 +108,9 @@ namespace OpenSim.Services.HypergridService | |||
104 | else if (simulationService != string.Empty) | 108 | else if (simulationService != string.Empty) |
105 | m_SimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args); | 109 | m_SimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args); |
106 | 110 | ||
111 | m_AllowedClients = serverConfig.GetString("AllowedClients", string.Empty); | ||
112 | m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty); | ||
113 | |||
107 | if (m_GridService == null || m_PresenceService == null || m_SimulationService == null) | 114 | if (m_GridService == null || m_PresenceService == null || m_SimulationService == null) |
108 | throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function."); | 115 | throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function."); |
109 | 116 | ||
@@ -181,8 +188,36 @@ namespace OpenSim.Services.HypergridService | |||
181 | string authURL = string.Empty; | 188 | string authURL = string.Empty; |
182 | if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) | 189 | if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) |
183 | authURL = aCircuit.ServiceURLs["HomeURI"].ToString(); | 190 | authURL = aCircuit.ServiceURLs["HomeURI"].ToString(); |
184 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to login foreign agent {0} {1} @ {2} ({3}) at destination {4}", | 191 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9}", |
185 | aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName); | 192 | aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName, |
193 | aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0); | ||
194 | |||
195 | // | ||
196 | // Check client | ||
197 | // | ||
198 | if (m_AllowedClients != string.Empty) | ||
199 | { | ||
200 | Regex arx = new Regex(m_AllowedClients); | ||
201 | Match am = arx.Match(aCircuit.Viewer); | ||
202 | |||
203 | if (!am.Success) | ||
204 | { | ||
205 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", aCircuit.Viewer); | ||
206 | return false; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | if (m_DeniedClients != string.Empty) | ||
211 | { | ||
212 | Regex drx = new Regex(m_DeniedClients); | ||
213 | Match dm = drx.Match(aCircuit.Viewer); | ||
214 | |||
215 | if (dm.Success) | ||
216 | { | ||
217 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", aCircuit.Viewer); | ||
218 | return false; | ||
219 | } | ||
220 | } | ||
186 | 221 | ||
187 | // | 222 | // |
188 | // Authenticate the user | 223 | // Authenticate the user |
diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs index 55c9cc5..5f9ce6d 100644 --- a/OpenSim/Services/Interfaces/ISimulationService.cs +++ b/OpenSim/Services/Interfaces/ISimulationService.cs | |||
@@ -67,7 +67,7 @@ namespace OpenSim.Services.Interfaces | |||
67 | 67 | ||
68 | bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent); | 68 | bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent); |
69 | 69 | ||
70 | bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason); | 70 | bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason); |
71 | 71 | ||
72 | /// <summary> | 72 | /// <summary> |
73 | /// Message from receiving region to departing region, telling it got contacted by the client. | 73 | /// Message from receiving region to departing region, telling it got contacted by the client. |
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index d364aa4..9bcc3dd 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs | |||
@@ -77,7 +77,11 @@ namespace OpenSim.Services.LLLoginService | |||
77 | protected string m_MapTileURL; | 77 | protected string m_MapTileURL; |
78 | protected string m_SearchURL; | 78 | protected string m_SearchURL; |
79 | 79 | ||
80 | protected string m_AllowedClients; | ||
81 | protected string m_DeniedClients; | ||
82 | |||
80 | IConfig m_LoginServerConfig; | 83 | IConfig m_LoginServerConfig; |
84 | IConfig m_ClientsConfig; | ||
81 | 85 | ||
82 | public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService) | 86 | public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService) |
83 | { | 87 | { |
@@ -105,7 +109,10 @@ namespace OpenSim.Services.LLLoginService | |||
105 | m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty); | 109 | m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty); |
106 | m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty); | 110 | m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty); |
107 | m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty); | 111 | m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty); |
108 | 112 | ||
113 | m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty); | ||
114 | m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty); | ||
115 | |||
109 | // These are required; the others aren't | 116 | // These are required; the others aren't |
110 | if (accountService == string.Empty || authService == string.Empty) | 117 | if (accountService == string.Empty || authService == string.Empty) |
111 | throw new Exception("LoginService is missing service specifications"); | 118 | throw new Exception("LoginService is missing service specifications"); |
@@ -215,11 +222,38 @@ namespace OpenSim.Services.LLLoginService | |||
215 | bool success = false; | 222 | bool success = false; |
216 | UUID session = UUID.Random(); | 223 | UUID session = UUID.Random(); |
217 | 224 | ||
218 | m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} from {2} with user agent {3} starting in {4}", | 225 | m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} at {2} using viewer {3}, channel {4}, IP {5}, Mac {6}, Id0 {7}", |
219 | firstName, lastName, clientIP.Address.ToString(), clientVersion, startLocation); | 226 | firstName, lastName, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0); |
220 | try | 227 | try |
221 | { | 228 | { |
222 | // | 229 | // |
230 | // Check client | ||
231 | // | ||
232 | if (m_AllowedClients != string.Empty) | ||
233 | { | ||
234 | Regex arx = new Regex(m_AllowedClients); | ||
235 | Match am = arx.Match(clientVersion); | ||
236 | |||
237 | if (!am.Success) | ||
238 | { | ||
239 | m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is not allowed", clientVersion); | ||
240 | return LLFailedLoginResponse.LoginBlockedProblem; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | if (m_DeniedClients != string.Empty) | ||
245 | { | ||
246 | Regex drx = new Regex(m_DeniedClients); | ||
247 | Match dm = drx.Match(clientVersion); | ||
248 | |||
249 | if (dm.Success) | ||
250 | { | ||
251 | m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is denied", clientVersion); | ||
252 | return LLFailedLoginResponse.LoginBlockedProblem; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | // | ||
223 | // Get the account and check that it exists | 257 | // Get the account and check that it exists |
224 | // | 258 | // |
225 | UserAccount account = m_UserAccountService.GetUserAccount(scopeID, firstName, lastName); | 259 | UserAccount account = m_UserAccountService.GetUserAccount(scopeID, firstName, lastName); |