public void UpdateDatabase() { try { //look for subsidies before we add new blocks because we depend on lastKnowBlockHeight to know where to start looking var subsidies = GetNewSubsidies(); if (subsidies.Count > 0) { Retry.ExecuteAction(() => { using (P2PoolDb db = new P2PoolDb()) { foreach (var subsidy in subsidies) { var existingSubsidy = db.Subsidies.Find(subsidy.TxHash); if (existingSubsidy == null) { Log(string.Format("Adding subsidy of {0} BTC, {1}", subsidy.Amount, subsidy.TxHash)); db.Subsidies.Add(subsidy); } else if (existingSubsidy.BlockHeight != subsidy.BlockHeight || existingSubsidy.BlockHash != subsidy.BlockHash) { Log(string.Format("Updating subsidy of {0} BTC, {1}", subsidy.Amount, subsidy.TxHash)); existingSubsidy.BlockHash = subsidy.BlockHash; existingSubsidy.BlockHeight = subsidy.BlockHeight; } db.SaveChanges(); } } }); } var blocks = GetNewBlocks(); if (blocks.Count > 0) { Retry.ExecuteAction(() => { using (P2PoolDb db = new P2PoolDb()) { foreach (var block in blocks) { var existingBlock = db.Blocks.Find(block.Id); if (existingBlock == null) { Log(string.Format("Adding block {0}, {1}{2}", block.BlockHeight, block.Id, block.IsP2Pool ? " (p2pool)" : "")); db.Blocks.Add(block); } else { Log(string.Format("Updating block {0}, {1}{2}", block.BlockHeight, block.Id, block.IsP2Pool ? " (p2pool)" : "")); existingBlock.BlockHeight = block.BlockHeight; existingBlock.Difficulty = block.Difficulty; existingBlock.GenerationTxHash = block.GenerationTxHash; existingBlock.IsOrphaned = block.IsOrphaned; existingBlock.IsP2Pool = block.IsP2Pool; existingBlock.PrevBlock = block.PrevBlock; existingBlock.Timestamp = block.Timestamp; } db.SaveChanges(); } //the following logic is too simplistic and only finds orphaned blocks if they are immediatly orphaned (vs a race between to candidate chains that lasts more than 1 block) // this clears the orphaned flag from any blocks that now have a later block pointing at them //db.Database.ExecuteSqlCommand("update p2pool_Blocks set isorphaned=0 where isorphaned=1 and exists (select * from p2pool_Blocks as b2 where b2.PrevBlock = p2pool_Blocks.Id)"); // this sets the orphaned flag for any blocks that aren't pointed at by some later block db.Database.ExecuteSqlCommand("update p2pool_Blocks set isorphaned=1 where blockheight < (select max(blockheight) from p2pool_Blocks) and not exists (select * from p2pool_Blocks as b2 where b2.PrevBlock = p2pool_Blocks.Id)"); } }); } } catch (Exception ex) { Log("UpdateDatabase: " + ex.Message); } }
public void UpdateStats() { try { int timestamp = DateTime.UtcNow.ToUnixTime(); int remainder = timestamp % 300; timestamp -= remainder; Log(string.Format("Updating stats for timestamp {0}", timestamp)); IEnumerable<string> servers = null; bool updatedData = false; P2PWebClient client = new P2PWebClient(); client.RequestTimeout = 3000; Retry.ExecuteAction(() => { using (P2PoolDb db = new P2PoolDb()) { var existingUsersCount = (from u in db.Users where u.Timestamp == timestamp select u.Address).Count(); if (existingUsersCount == 0) { JObject users = null; if (servers == null) { servers = GetServers(); } foreach (var server in servers) { if (string.IsNullOrWhiteSpace(server)) { continue; } try { var baseUrl = new Uri(server.Trim()); users = JObject.Parse(client.DownloadString(new Uri(baseUrl, "/users"))); Log(string.Format(" Stats: Retrived users from {0}", server)); break; } catch (Exception ex) { Log(" Stats: " + ex.Message); } } if (users == null) { return; } Dictionary<string, decimal> addresses = new Dictionary<string, decimal>(); foreach (var userEntry in users.Properties()) { string address = P2PHelper.ExtractAddress(userEntry.Name) ?? "Unknown"; if (address != null) { decimal portion = 0; if (addresses.ContainsKey(address)) { portion += addresses[address]; } portion += (decimal)userEntry.Value; addresses[address] = portion; } } foreach (var item in addresses) { User user = new User() { Timestamp = timestamp, Address = item.Key, Portion = item.Value }; db.Users.Add(user); } db.SaveChanges(); updatedData = true; Log(string.Format(" Stats: Added {0} users", addresses.Count)); } } }); Retry.ExecuteAction(() => { using (P2PoolDb db = new P2PoolDb()) { Stat entry = db.Stats.Find(timestamp); if (entry == null) { decimal rate = -1; if (servers == null) { servers = GetServers(); } foreach (var server in servers) { if (string.IsNullOrWhiteSpace(server)) { continue; } try { var baseUrl = new Uri(server.Trim()); rate = decimal.Parse(client.DownloadString(new Uri(baseUrl, "/rate"))) / 1000000000m; Log(string.Format(" Stats: Retrived rate from {0}", server)); break; } catch (Exception ex) { Log(" Stats: " + ex.Message); } } if (rate == -1) { return; } int userCount; userCount = db.Database.SqlQuery<int>("select count (distinct address) from p2pool_Users where timestamp >= @start and timestamp <= @end", new SqlParameter("start", timestamp - 86400), new SqlParameter("end", timestamp)).First(); entry = new Stat { Timestamp = timestamp, Rate = rate, Users = userCount }; db.Stats.Add(entry); db.SaveChanges(); updatedData = true; Log(string.Format(" Stats: Saved new rate: {0}", rate)); } } }); if (updatedData) { Retry.ExecuteAction(() => { using (P2PoolDb db = new P2PoolDb()) { CurrentPayouts entry = db.CurrentPayouts.Find(1); if (entry != null) { JObject payouts = null; if (servers == null) { servers = GetServers(); } foreach (var server in servers) { if (string.IsNullOrWhiteSpace(server)) { continue; } try { var baseUrl = new Uri(server.Trim()); payouts = JObject.Parse(client.DownloadString(new Uri(baseUrl, "/current_payouts"))); Log(string.Format(" Stats: Retrived payouts from {0}", server)); break; } catch (Exception ex) { Log(" Stats: " + ex.Message); } } if (payouts == null) { return; } entry.Payouts = payouts.ToString(); entry.Updated = timestamp; db.SaveChanges(); Log(" Stats: Saved updated payouts"); } } }); //cleanup old user stats Retry.ExecuteAction(() => { using (P2PoolDb db = new P2PoolDb()) { // delete all the specific user stats older than 3 days var result = db.Database.ExecuteSqlCommand("delete from p2pool_Users where [Timestamp] < @cutoff", new SqlParameter("cutoff", timestamp - 259200)); Log(string.Format(" Stats: Deleted old user rows", result)); } }); } } catch (Exception ex) { Log(" Stats: UpdateStats Exception: " + ex.Message); } }