OpenTTD Source 20250205-master-gfd85ab1e2c
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
27extern void AfterLoadCompanyStats();
28extern 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 if (!ge.HasData()) continue;
174
175 StationCargoList &cargo_list = ge.GetData().cargo;
176 [[maybe_unused]] const auto a = cargo_list.PeriodsInTransit();
177 [[maybe_unused]] const auto b = cargo_list.TotalCount();
178 cargo_list.InvalidateCache();
179 assert(a == cargo_list.PeriodsInTransit());
180 assert(b == cargo_list.TotalCount());
181 }
182
183 /* Check docking tiles */
184 TileArea ta;
185 std::map<TileIndex, bool> docking_tiles;
186 for (TileIndex tile : st->docking_station) {
187 ta.Add(tile);
188 docking_tiles[tile] = IsDockingTile(tile);
189 }
190 UpdateStationDockingTiles(st);
191 if (ta.tile != st->docking_station.tile || ta.w != st->docking_station.w || ta.h != st->docking_station.h) {
192 Debug(desync, 2, "warning: station docking mismatch: station {}, company {}", st->index, st->owner);
193 }
194 for (TileIndex tile : ta) {
195 if (docking_tiles[tile] != IsDockingTile(tile)) {
196 Debug(desync, 2, "warning: docking tile mismatch: tile {}", tile);
197 }
198 }
199 }
200
202
203 /* Check industries_near */
204 i = 0;
205 for (Station *st : Station::Iterate()) {
206 if (st->industries_near != old_station_industries_near[i]) {
207 Debug(desync, 2, "warning: station industries near mismatch: station {}", st->index);
208 }
209 i++;
210 }
211
212 /* Check stations_near */
213 i = 0;
214 for (Town *t : Town::Iterate()) {
215 if (t->stations_near != old_town_stations_near[i]) {
216 Debug(desync, 2, "warning: town stations near mismatch: town {}", t->index);
217 }
218 i++;
219 }
220 i = 0;
221 for (Industry *ind : Industry::Iterate()) {
222 if (ind->stations_near != old_industry_stations_near[i]) {
223 Debug(desync, 2, "warning: industry stations near mismatch: industry {}", ind->index);
224 }
225 i++;
226 }
227}
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.
void CheckCaches()
Check the validity of some of the caches.
uint PeriodsInTransit() const
Returns average number of cargo aging periods in transit for a cargo entity.
void InvalidateCache()
Invalidates the cached data and rebuilds it.
CargoList that is used for stations.
uint TotalCount() const
Returns total count of cargo at the station, including cargo which is already reserved for loading.
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 of base types and functions in a cross-platform compatible way.
Stores station stats for a single cargo.
Defines the internal data of a functional industry.
Definition industry.h:66
Represents the covered area of e.g.
uint16_t w
The width of the area.
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.
uint16_t h
The height of the area.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
A Stop for a Road Vehicle.
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.
static void RecomputeCatchmentForAll()
Recomputes catchment of all stations.
Definition station.cpp:533
Town data structure.
Definition town.h:52
Vehicle data structure.
Vehicle * Next() const
Get the next vehicle of this vehicle.
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.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
Definition water_map.h:371