/* * Box Social™ * http://boxsocial.net/ * Copyright © 2007, David Lachlan Smith * * $Id:$ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using System; using System.Collections.Generic; using System.Data; using System.Text; using System.Web; using BoxSocial.IO; namespace BoxSocial.Internals { public sealed class PrimitivesCache { private Core core; private Mysql db; public PrimitivesCache(Core core) { this.core = core; this.db = core.Db; } /// /// A cache of primitives loaded. /// private Dictionary primitivesCached = new Dictionary(); /// /// A cached primitive keys. /// private Dictionary primitivesKeysCached = new Dictionary(); /// /// A list of primitive Ids for batched loading /// private List batchedPrimitivesIds = new List(); public User this[long key] { get { loadBatchedIds(ItemKey.GetTypeId(typeof(User)), key); return (User)primitivesCached[new PrimitiveId(key, ItemKey.GetTypeId(typeof(User)))]; } } /*public Primitive this[string type, long key] { get { loadBatchedIds(type, key); return primitivesCached[new PrimitiveId(type, key)]; } }*/ public Primitive this[ItemKey key] { get { loadBatchedIds(key.TypeId, key.Id); return primitivesCached[new PrimitiveId(key.Id, key.TypeId)]; } } public Primitive this[long key, long typeId] { get { loadBatchedIds(typeId, key); return primitivesCached[new PrimitiveId(key, typeId)]; } } public void LoadUserProfiles(List userIds) { foreach (long userId in userIds) { batchedPrimitivesIds.Add(new PrimitiveId(userId, ItemKey.GetTypeId(typeof(User)))); } } /// /// /// /// private void loadPrimitiveProfiles(List primitiveIds) { Dictionary> idList = new Dictionary>(); foreach (PrimitiveId id in primitiveIds) { if (!primitivesCached.ContainsKey(id)) { if (!idList.ContainsKey(id.TypeId)) { idList.Add(id.TypeId, new List()); } idList[id.TypeId].Add(id.Id); } } foreach (long typeId in idList.Keys) { Type t = core.GetPrimitiveType(typeId); if (t != null) { string keysTable = Primitive.GetTable(t); PrimitiveAttribute attr = core.GetPrimitiveAttributes(typeId); if (attr == null) { continue; } string idField = attr.IdField; SelectQuery query = Primitive.GetSelectQueryStub(t); query.AddCondition(string.Format("`{0}`.`{1}`", keysTable, idField), ConditionEquality.In, idList[typeId]); DataTable primitivesTable = db.Query(query); foreach (DataRow primitiveRow in primitivesTable.Rows) { Primitive newPrimitive = System.Activator.CreateInstance(t, new object[] { core, primitiveRow, core.GetPrimitiveAttributes(typeId).DefaultLoadOptions }) as Primitive; primitivesCached.Add(new PrimitiveId(newPrimitive.Id, typeId), newPrimitive); primitivesKeysCached.Add(new PrimitiveKey(newPrimitive.Key, typeId), new PrimitiveId(newPrimitive.Id, typeId)); } } } } public void LoadUserProfile(long userId) { PrimitiveId key = new PrimitiveId(userId, ItemKey.GetTypeId(typeof(User))); if ((!primitivesCached.ContainsKey(key)) && (!batchedPrimitivesIds.Contains(key))) { batchedPrimitivesIds.Add(key); } } public void LoadPrimitiveProfile(ItemKey key) { if (!primitivesCached.ContainsKey(new PrimitiveId(key.Id, key.TypeId))) { batchedPrimitivesIds.Add(new PrimitiveId(key.Id, key.TypeId)); } } public void LoadPrimitiveProfile(long id, long typeId) { if (!primitivesCached.ContainsKey(new PrimitiveId(id, typeId))) { batchedPrimitivesIds.Add(new PrimitiveId(id, typeId)); } } public List LoadUserProfiles(List usernames) { long userTypeId = ItemKey.GetTypeId(typeof(User)); List usernameList = new List(); List userIds = new List(); foreach (string username in usernames) { PrimitiveKey key = new PrimitiveKey(username, userTypeId); if (!primitivesKeysCached.ContainsKey(key)) { usernameList.Add(username.ToLower()); } } if (usernameList.Count > 0) { SelectQuery query = new SelectQuery("user_keys"); query.AddFields(User.GetFieldsPrefixed(typeof(User))); query.AddFields(UserInfo.GetFieldsPrefixed(typeof(UserInfo))); query.AddFields(UserProfile.GetFieldsPrefixed(typeof(UserProfile))); query.AddField(new DataField("gallery_items", "gallery_item_uri")); query.AddField(new DataField("gallery_items", "gallery_item_parent_path")); query.AddJoin(JoinTypes.Inner, UserInfo.GetTable(typeof(UserInfo)), "user_id", "user_id"); query.AddJoin(JoinTypes.Inner, UserProfile.GetTable(typeof(UserProfile)), "user_id", "user_id"); query.AddJoin(JoinTypes.Left, new DataField("user_profile", "profile_country"), new DataField("countries", "country_iso")); query.AddJoin(JoinTypes.Left, new DataField("user_profile", "profile_religion"), new DataField("religions", "religion_id")); query.AddJoin(JoinTypes.Left, new DataField("user_info", "user_icon"), new DataField("gallery_items", "gallery_item_id")); query.AddCondition("LCASE(`user_keys`.`user_name`)", ConditionEquality.In, usernameList); DataTable usersTable = db.Query(query); foreach (DataRow userRow in usersTable.Rows) { User newUser = new User(core, userRow, UserLoadOptions.All); PrimitiveId pid = new PrimitiveId(newUser.Id, userTypeId); PrimitiveKey kid = new PrimitiveKey(newUser.UserName, userTypeId); if (!primitivesCached.ContainsKey(pid)) { primitivesCached.Add(pid, newUser); } if (!primitivesKeysCached.ContainsKey(kid)) { primitivesKeysCached.Add(kid, new PrimitiveId(newUser.Id, userTypeId)); } if (!userIds.Contains(newUser.Id)) { userIds.Add(newUser.Id); } } } return userIds; } public long LoadUserProfile(string username) { PrimitiveKey key = new PrimitiveKey(username, ItemKey.GetTypeId(typeof(User))); if (primitivesKeysCached.ContainsKey(key)) { return primitivesKeysCached[key].Id; } User newUser = new User(core, username, UserLoadOptions.All); PrimitiveId id = new PrimitiveId(newUser.Id, ItemKey.GetTypeId(typeof(User))); if (!primitivesCached.ContainsKey(id)) { primitivesCached.Add(id, newUser); } return newUser.Id; } private void loadBatchedIds(long typeId, long requestedId) { if (batchedPrimitivesIds.Contains(new PrimitiveId(requestedId, typeId))) { loadPrimitiveProfiles(batchedPrimitivesIds); } } } }