OpenTTD Source  20241108-master-g80f628063a
cachecheck.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD 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.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "aircraft.h"
12 #include "company_base.h"
13 #include "debug.h"
14 #include "industry.h"
15 #include "roadstop_base.h"
16 #include "roadveh.h"
17 #include "ship.h"
18 #include "station_base.h"
19 #include "station_map.h"
20 #include "subsidy_func.h"
21 #include "town.h"
22 #include "train.h"
23 #include "vehicle_base.h"
24 
25 #include "safeguards.h"
26 
27 extern void AfterLoadCompanyStats();
28 extern void RebuildTownCaches();
29 
37 {
38  /* Return here so it is easy to add checks that are run
39  * always to aid testing of caches. */
40  if (_debug_desync_level <= 1) return;
41 
42  /* Check the town caches. */
43  std::vector<TownCache> old_town_caches;
44  for (const Town *t : Town::Iterate()) {
45  old_town_caches.push_back(t->cache);
46  }
47 
50 
51  uint i = 0;
52  for (Town *t : Town::Iterate()) {
53  if (old_town_caches[i] != t->cache) {
54  Debug(desync, 2, "warning: town cache mismatch: town {}", t->index);
55  }
56  i++;
57  }
58 
59  /* Check company infrastructure cache. */
60  std::vector<CompanyInfrastructure> old_infrastructure;
61  for (const Company *c : Company::Iterate()) old_infrastructure.push_back(c->infrastructure);
62 
64 
65  i = 0;
66  for (const Company *c : Company::Iterate()) {
67  if (old_infrastructure[i] != c->infrastructure) {
68  Debug(desync, 2, "warning: infrastructure cache mismatch: company {}", c->index);
69  }
70  i++;
71  }
72 
73  /* Strict checking of the road stop cache entries */
74  for (const RoadStop *rs : RoadStop::Iterate()) {
75  if (IsBayRoadStopTile(rs->xy)) continue;
76 
77  assert(rs->GetEntry(DIAGDIR_NE) != rs->GetEntry(DIAGDIR_NW));
78  rs->GetEntry(DIAGDIR_NE)->CheckIntegrity(rs);
79  rs->GetEntry(DIAGDIR_NW)->CheckIntegrity(rs);
80  }
81 
82  std::vector<NewGRFCache> grf_cache;
83  std::vector<VehicleCache> veh_cache;
84  std::vector<GroundVehicleCache> gro_cache;
85  std::vector<TrainCache> tra_cache;
86 
87  for (Vehicle *v : Vehicle::Iterate()) {
88  if (v != v->First() || v->vehstatus & VS_CRASHED || !v->IsPrimaryVehicle()) continue;
89 
90  for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
92  grf_cache.emplace_back(u->grf_cache);
93  veh_cache.emplace_back(u->vcache);
94  switch (u->type) {
95  case VEH_TRAIN:
96  gro_cache.emplace_back(Train::From(u)->gcache);
97  tra_cache.emplace_back(Train::From(u)->tcache);
98  break;
99  case VEH_ROAD:
100  gro_cache.emplace_back(RoadVehicle::From(u)->gcache);
101  break;
102  default:
103  break;
104  }
105  }
106 
107  switch (v->type) {
108  case VEH_TRAIN: Train::From(v)->ConsistChanged(CCF_TRACK); break;
111  case VEH_SHIP: Ship::From(v)->UpdateCache(); break;
112  default: break;
113  }
114 
115  uint length = 0;
116  for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
118  if (grf_cache[length] != u->grf_cache) {
119  Debug(desync, 2, "warning: newgrf cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length);
120  }
121  if (veh_cache[length] != u->vcache) {
122  Debug(desync, 2, "warning: vehicle cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length);
123  }
124  switch (u->type) {
125  case VEH_TRAIN:
126  if (gro_cache[length] != Train::From(u)->gcache) {
127  Debug(desync, 2, "warning: train ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
128  }
129  if (tra_cache[length] != Train::From(u)->tcache) {
130  Debug(desync, 2, "warning: train cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
131  }
132  break;
133  case VEH_ROAD:
134  if (gro_cache[length] != RoadVehicle::From(u)->gcache) {
135  Debug(desync, 2, "warning: road vehicle ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
136  }
137  break;
138  default:
139  break;
140  }
141  length++;
142  }
143 
144  grf_cache.clear();
145  veh_cache.clear();
146  gro_cache.clear();
147  tra_cache.clear();
148  }
149 
150  /* Check whether the caches are still valid */
151  for (Vehicle *v : Vehicle::Iterate()) {
152  [[maybe_unused]] const auto a = v->cargo.PeriodsInTransit();
153  [[maybe_unused]] const auto b = v->cargo.TotalCount();
154  [[maybe_unused]] const auto c = v->cargo.GetFeederShare();
155  v->cargo.InvalidateCache();
156  assert(a == v->cargo.PeriodsInTransit());
157  assert(b == v->cargo.TotalCount());
158  assert(c == v->cargo.GetFeederShare());
159  }
160 
161  /* Backup stations_near */
162  std::vector<StationList> old_town_stations_near;
163  for (Town *t : Town::Iterate()) old_town_stations_near.push_back(t->stations_near);
164 
165  std::vector<StationList> old_industry_stations_near;
166  for (Industry *ind : Industry::Iterate()) old_industry_stations_near.push_back(ind->stations_near);
167 
168  std::vector<IndustryList> old_station_industries_near;
169  for (Station *st : Station::Iterate()) old_station_industries_near.push_back(st->industries_near);
170 
171  for (Station *st : Station::Iterate()) {
172  for (GoodsEntry &ge : st->goods) {
173  [[maybe_unused]] const auto a = ge.cargo.PeriodsInTransit();
174  [[maybe_unused]] const auto b = ge.cargo.TotalCount();
175  ge.cargo.InvalidateCache();
176  assert(a == ge.cargo.PeriodsInTransit());
177  assert(b == ge.cargo.TotalCount());
178  }
179 
180  /* Check docking tiles */
181  TileArea ta;
182  std::map<TileIndex, bool> docking_tiles;
183  for (TileIndex tile : st->docking_station) {
184  ta.Add(tile);
185  docking_tiles[tile] = IsDockingTile(tile);
186  }
187  UpdateStationDockingTiles(st);
188  if (ta.tile != st->docking_station.tile || ta.w != st->docking_station.w || ta.h != st->docking_station.h) {
189  Debug(desync, 2, "warning: station docking mismatch: station {}, company {}", st->index, st->owner);
190  }
191  for (TileIndex tile : ta) {
192  if (docking_tiles[tile] != IsDockingTile(tile)) {
193  Debug(desync, 2, "warning: docking tile mismatch: tile {}", tile);
194  }
195  }
196  }
197 
199 
200  /* Check industries_near */
201  i = 0;
202  for (Station *st : Station::Iterate()) {
203  if (st->industries_near != old_station_industries_near[i]) {
204  Debug(desync, 2, "warning: station industries near mismatch: station {}", st->index);
205  }
206  i++;
207  }
208 
209  /* Check stations_near */
210  i = 0;
211  for (Town *t : Town::Iterate()) {
212  if (t->stations_near != old_town_stations_near[i]) {
213  Debug(desync, 2, "warning: town stations near mismatch: town {}", t->index);
214  }
215  i++;
216  }
217  i = 0;
218  for (Industry *ind : Industry::Iterate()) {
219  if (ind->stations_near != old_industry_stations_near[i]) {
220  Debug(desync, 2, "warning: industry stations near mismatch: industry {}", ind->index);
221  }
222  i++;
223  }
224 }
Base for aircraft.
void UpdateAircraftCache(Aircraft *v, bool update_range=false)
Update cached values of an aircraft.
void RebuildTownCaches()
Rebuild all the cached variables of towns.
Definition: town_sl.cpp:27
void AfterLoadCompanyStats()
Rebuilding of company statistics after loading a savegame.
Definition: company_sl.cpp:96
void CheckCaches()
Check the validity of some of the caches.
Definition: cachecheck.cpp:36
uint PeriodsInTransit() const
Returns average number of cargo aging periods in transit for a cargo entity.
Definition: cargopacket.h:338
void InvalidateCache()
Invalidates the cached data and rebuilds it.
uint TotalCount() const
Returns total count of cargo at the station, including cargo which is already reserved for loading.
Definition: cargopacket.h:607
Definition of stuff that is very close to a company, like the company struct itself.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
Base of all industries.
void FillNewGRFVehicleCache(const Vehicle *v)
Fill the grf_cache of the given vehicle.
Base class for roadstops.
Road vehicle states.
void RoadVehUpdateCache(RoadVehicle *v, bool same_length=false)
Update the cache of a road vehicle.
A number of safeguards to prevent using unsafe methods.
Base for ships.
Base classes/functions for stations.
Maps accessors for stations.
bool IsBayRoadStopTile(Tile t)
Is tile t a bay (non-drive through) road stop station?
Definition: station_map.h:266
Definition of base types and functions in a cross-platform compatible way.
Stores station stats for a single cargo.
Definition: station_base.h:166
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Definition: station_base.h:210
Defines the internal data of a functional industry.
Definition: industry.h:66
Represents the covered area of e.g.
Definition: tilearea_type.h:18
uint16_t w
The width of the area.
Definition: tilearea_type.h:20
void Add(TileIndex to_add)
Add a single tile to a tile area; enlarge if needed.
Definition: tilearea.cpp:43
TileIndex tile
The base tile of the area.
Definition: tilearea_type.h:19
uint16_t h
The height of the area.
Definition: tilearea_type.h:21
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
A Stop for a Road Vehicle.
Definition: roadstop_base.h:22
void UpdateCache()
Update the caches of this ship.
Definition: ship_cmd.cpp:232
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Station data structure.
Definition: station_base.h:439
static void RecomputeCatchmentForAll()
Recomputes catchment of all stations.
Definition: station.cpp:530
Town data structure.
Definition: town.h:54
Vehicle data structure.
Definition: vehicle_base.h:244
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:632
void RebuildSubsidisedSourceAndDestinationCache()
Perform a full rebuild of the subsidies cache.
Definition: subsidy.cpp:134
Functions related to subsidies.
Base of the town class.
Base for the train class.
@ CCF_TRACK
Valid changes while vehicle is driving, and possibly changing tracks.
Definition: train.h:48
Base class for all vehicles.
@ VS_CRASHED
Vehicle is crashed.
Definition: vehicle_base.h:40
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
Definition: water_map.h:371