From 725be60bb7a15e63bb6c65de3730dc6f9dae4bf1 Mon Sep 17 00:00:00 2001 From: Arseny Sher Date: Fri, 16 Sep 2022 16:21:07 +0300 Subject: [PATCH 01/64] Storage messaging rfc 2. --- docs/rfcs/018-storage-messaging-2.md | 163 +++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 docs/rfcs/018-storage-messaging-2.md diff --git a/docs/rfcs/018-storage-messaging-2.md b/docs/rfcs/018-storage-messaging-2.md new file mode 100644 index 0000000000..364f62dd2e --- /dev/null +++ b/docs/rfcs/018-storage-messaging-2.md @@ -0,0 +1,163 @@ +# Storage messaging + +Safekeepers need to communicate to each other to +* Trim WAL on safekeepers; +* Decide on which SK should push WAL to the S3; +* Decide on when to shut down SK<->pageserver connection; +* Understand state of each other to perform peer recovery; + +Pageservers need to communicate to safekeepers to decide which SK should provide +WAL to the pageserver. + +This is an iteration on [015-storage-messaging](https://github.com/neondatabase/neon/blob/main/docs/rfcs/015-storage-messaging.md) describing current situation, +potential performance issue and ways to address it. + +## Background + +What we have currently is very close to etcd variant described in +015-storage-messaging. Basically, we have single `SkTimelineInfo` message +periodically sent by all safekeepers to etcd for each timeline. +* Safekeepers subscribe to it to learn status of peers (currently they subscribe to + 'everything', but they can and should fetch data only for timelines they hold). +* Pageserver subscribes to it (separate watch per timeline) to learn safekeepers + positions; based on that, it decides from which safekeepers to pull WAL. + +Also, safekeepers use etcd elections API to make sure only single safekeeper +offloads WAL. + +It works, and callmemaybe is gone. However, this has a performance +hazard. Currently deployed etcd can do about 6k puts per second (using its own +`benchmark` tool); on my 6 core laptop, while running on tmpfs, this gets to +35k. Making benchmark closer to our usage [etcd watch bench](https://github.com/arssher/etcd-client/blob/watch-bench/examples/watch_bench.rs), +I get ~10k received messages per second with various number of publisher-subscribers +(laptop, tmpfs). Diving this by 12 (3 sks generate msg, 1 ps + 3 sk consume them) we +get about 800 active timelines, if message is sent each second. Not extremely +low, but quite reachable. + +A lot of idle watches seem to be ok though -- which is good, as pageserver +subscribes to all its timelines regardless of their activity. + +Also, running etcd with fsyncs disabled is messy -- data dir must be wiped on +each restart or there is a risk of corruption errors. + +The reason is etcd making much more than what we need; it is a fault tolerant +store with strong consistency, but I claim all we need here is just simplest pub +sub with best effort delivery, because +* We already have centralized source of truth for long running data, like which + tlis are on which nodes -- the console. +* Momentary data (safekeeper/pageserver progress) doesn't make sense to persist. + Instead of putting each change to broker, expecting it to reliably deliver it + is better to just have constant flow of data for active timelines: 1) they + serve as natural heartbeats -- if node can't send, we shouldn't pull WAL from + it 2) it is simpler -- no need to track delivery to/from the broker. + Moreover, latency here is important: the faster we obtain fresh data, the + faster we can switch to proper safekeeper after failure. +* As for WAL offloading leader election, it is trivial to achieve through these + heartbeats -- just take suitable node through deterministic rule (min node + id). Once network is stable, this is a converging process (well, except + complicated failure topology, but even then making it converge is not + hard). Such elections bear some risk of several offloaders running + concurrently for a short period of time, but that's harmless. + + Generally, if one needs strong consistency, electing leader per se is not + enough; it must be accompanied with number (logical clock ts), checked at + every action to track causality. s3 doesn't provide CAS, so it can't + differentiate old/new leader, this must be solved differently. + + We could use etcd CAS (its most powerful/useful primitive actually) to issue + these leader numbers (and e.g. prefix files in s3), but currently I don't see + need for that. + + +Obviously best effort pub sub is much more simpler and performant; the one proposed is + +## gRPC broker + +I took tonic and [prototyped](https://github.com/neondatabase/neon/blob/asher/neon-broker/broker/src/broker.rs) the replacement of functionality we currently use +with grpc streams and tokio mpsc channels. The implementation description is at the file header. + +It is just 500 lines of code and core functionality is complete. 1-1 pub sub +gives about 120k received messages per second; having multiple subscribers in +different connecitons quickly scales to 1 million received messages per second. +I had concerns about many concurrent streams in singe connection, but 2^20 +subscribers still work (though eat memory, with 10 publishers 20GB are consumed; +in this implementation each publisher holds full copy of all subscribers). There +is `bench.rs` nearby which I used for testing. + +`SkTimelineInfo` is wired here, but another message can be added (e.g. if +pageservers want to communicate with each other) with templating. + +### Fault tolerance + +Since such broker is stateless, we can run it under k8s. Or add proxying to +other members, with best-effort this is simple. + +### Security implications + +Communication happens in a private network that is not exposed to users; +additionaly we can add auth to the broker. + +## Alternative: get existing pub-sub + +We could take some existing pub sub solution, e.g. RabbitMQ, Redis. But in this +case IMV simplicity of our own outweights external dependency costs (RabbitMQ is +much more complicated and needs VM; Redis Rust client maintenance is not +ideal...). Also note that projects like CockroachDB and TiDB are based on gRPC +as well. + +## Alternative: direct communication + +Apart from being transport, broker solves one more task: discovery, i.e. letting +safekeepers and pageservers find each other. We can let safekeepers know, for +each timeline, both other safekeepers for this timeline and pageservers serving +it. In this case direct communication is possible: + - each safekeeper pushes to each other safekeeper status of timelines residing + on both of them, letting remove WAL, decide who offloads, decide on peer + recovery; + - each safekeeper pushes to each pageserver status of timelines residing on + both of them, letting pageserver choose from which sk to pull WAL; + +It was mostly described in [014-safekeeper-gossip](https://github.com/neondatabase/neon/blob/main/docs/rfcs/014-safekeepers-gossip.md), but I want to recap on that. + +The main pro is less one dependency: less moving parts, easier to run Neon +locally/manually, less places to monitor. Fault tolerance for broker disappears, +no kuber or something. To me this is a big thing. + +Also (though not a big thing) idle watches for inactive timelines disappear: +naturally safekeepers learn about compute connection first and start pushing +status to pageserver(s), notifying it should pull. + +Importantly, I think that eventually knowing and persisting peers and +pageservers on safekeepers is inevitable: +- Knowing peer safekeepers for the timeline is required for correct + automatic membership change -- new member set must be hardened on old + majority before proceeding. It is required to get rid of sync-safekeepers + as well (peer recovery up to flush_lsn). +- Knowing pageservers where the timeline is attached is needed to + 1. Understand when to shut down activity on the timeline, i.e. push data to + the broker. We can have a lot of timelines sleeping quietly which + shouldn't occupy resources. + 2. Preserve WAL for these (currently we offload to s3 and take it from there, + but serving locally is better, and we get one less condition on which WAL + can be removed from s3). + +I suppose this membership data should be passed to safekeepers directly from the +console because +1. Console is the original source of this data, conceptually this is the + simplest way (rather than passing it through compute or something). +2. We already have similar code for deleting timeline on safekeepers + (and attaching/detaching timeline on pageserver), this is a typical + action -- queue operation against storage node and execute it until it + completes (or timeline is dropped). + +Cons of direct communication are +- It is more complicated: each safekeeper should maintain set of peers it talks + to, and set of timelines for each such peer -- they ought to be multiplexed + into single connection. +- Totally, we have O(n^2) connections instead of O(n) with broker schema + (still O(n) on each node). However, these are relatively stable, async and + thus not very expensive, I don't think this is a big problem. Up to 10k + storage nodes I doubt connection overhead would be noticeable. + +I'd use gRPC for direct communication, and in this sense gRPC based broker is a +step towards it. From a22165d41ea4046d393e131e9ae47fe22e09dec5 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Sat, 8 Oct 2022 10:07:33 +0300 Subject: [PATCH 02/64] Add tests for comparing root and child branch performance. Author: Thang Pham --- .../performance/test_branch_creation.py | 43 +++++++++ test_runner/performance/test_branching.py | 94 +++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 test_runner/performance/test_branching.py diff --git a/test_runner/performance/test_branch_creation.py b/test_runner/performance/test_branch_creation.py index 9cb346de47..4b109c150f 100644 --- a/test_runner/performance/test_branch_creation.py +++ b/test_runner/performance/test_branch_creation.py @@ -3,12 +3,15 @@ import statistics import threading import time import timeit +from contextlib import closing from typing import List import pytest from fixtures.benchmark_fixture import MetricReport from fixtures.compare_fixtures import NeonCompare from fixtures.log_helper import log +from fixtures.neon_fixtures import wait_for_last_record_lsn +from fixtures.types import Lsn def _record_branch_creation_durations(neon_compare: NeonCompare, durs: List[float]): @@ -107,3 +110,43 @@ def test_branch_creation_many(neon_compare: NeonCompare, n_branches: int): branch_creation_durations.append(dur) _record_branch_creation_durations(neon_compare, branch_creation_durations) + + +# Test measures the branch creation time when branching from a timeline with a lot of relations. +# +# This test measures the latency of branch creation under two scenarios +# 1. The ancestor branch is not under any workloads +# 2. The ancestor branch is under a workload (busy) +# +# To simulate the workload, the test runs a concurrent insertion on the ancestor branch right before branching. +def test_branch_creation_many_relations(neon_compare: NeonCompare): + env = neon_compare.env + + timeline_id = env.neon_cli.create_branch("root") + + pg = env.postgres.create_start("root") + with closing(pg.connect()) as conn: + with conn.cursor() as cur: + for i in range(10000): + cur.execute(f"CREATE TABLE t{i} as SELECT g FROM generate_series(1, 1000) g") + + # Wait for the pageserver to finish processing all the pending WALs, + # as we don't want the LSN wait time to be included during the branch creation + flush_lsn = Lsn(pg.safe_psql("SELECT pg_current_wal_flush_lsn()")[0][0]) + wait_for_last_record_lsn( + env.pageserver.http_client(), env.initial_tenant, timeline_id, flush_lsn + ) + + with neon_compare.record_duration("create_branch_time_not_busy_root"): + env.neon_cli.create_branch("child_not_busy", "root") + + # run a concurrent insertion to make the ancestor "busy" during the branch creation + thread = threading.Thread( + target=pg.safe_psql, args=("INSERT INTO t0 VALUES (generate_series(1, 100000))",) + ) + thread.start() + + with neon_compare.record_duration("create_branch_time_busy_root"): + env.neon_cli.create_branch("child_busy", "root") + + thread.join() diff --git a/test_runner/performance/test_branching.py b/test_runner/performance/test_branching.py new file mode 100644 index 0000000000..562e751458 --- /dev/null +++ b/test_runner/performance/test_branching.py @@ -0,0 +1,94 @@ +import timeit +from pathlib import Path +from typing import List + +from fixtures.benchmark_fixture import PgBenchRunResult +from fixtures.compare_fixtures import NeonCompare +from performance.test_perf_pgbench import utc_now_timestamp + +# ----------------------------------------------------------------------- +# Start of `test_compare_child_and_root_*` tests +# ----------------------------------------------------------------------- + +# `test_compare_child_and_root_*` tests compare the performance of a branch and its child branch(s). +# A common pattern in those tests is initializing a root branch then creating a child branch(s) from the root. +# Each test then runs a similar workload for both child branch and root branch. Each measures and reports +# some latencies/metrics during the workload for performance comparison between a branch and its ancestor. + + +def test_compare_child_and_root_pgbench_perf(neon_compare: NeonCompare): + env = neon_compare.env + pg_bin = neon_compare.pg_bin + + def run_pgbench_on_branch(branch: str, cmd: List[str]): + run_start_timestamp = utc_now_timestamp() + t0 = timeit.default_timer() + out = pg_bin.run_capture( + cmd, + ) + run_duration = timeit.default_timer() - t0 + run_end_timestamp = utc_now_timestamp() + + stdout = Path(f"{out}.stdout").read_text() + + res = PgBenchRunResult.parse_from_stdout( + stdout=stdout, + run_duration=run_duration, + run_start_timestamp=run_start_timestamp, + run_end_timestamp=run_end_timestamp, + ) + neon_compare.zenbenchmark.record_pg_bench_result(branch, res) + + env.neon_cli.create_branch("root") + pg_root = env.postgres.create_start("root") + pg_bin.run_capture(["pgbench", "-i", pg_root.connstr(), "-s10"]) + + env.neon_cli.create_branch("child", "root") + pg_child = env.postgres.create_start("child") + + run_pgbench_on_branch("root", ["pgbench", "-c10", "-T10", pg_root.connstr()]) + run_pgbench_on_branch("child", ["pgbench", "-c10", "-T10", pg_child.connstr()]) + + +def test_compare_child_and_root_write_perf(neon_compare: NeonCompare): + env = neon_compare.env + env.neon_cli.create_branch("root") + pg_root = env.postgres.create_start("root") + + pg_root.safe_psql( + "CREATE TABLE foo(key serial primary key, t text default 'foooooooooooooooooooooooooooooooooooooooooooooooooooo')", + ) + + env.neon_cli.create_branch("child", "root") + pg_child = env.postgres.create_start("child") + + with neon_compare.record_duration("root_run_duration"): + pg_root.safe_psql("INSERT INTO foo SELECT FROM generate_series(1,1000000)") + with neon_compare.record_duration("child_run_duration"): + pg_child.safe_psql("INSERT INTO foo SELECT FROM generate_series(1,1000000)") + + +def test_compare_child_and_root_read_perf(neon_compare: NeonCompare): + env = neon_compare.env + env.neon_cli.create_branch("root") + pg_root = env.postgres.create_start("root") + + pg_root.safe_psql_many( + [ + "CREATE TABLE foo(key serial primary key, t text default 'foooooooooooooooooooooooooooooooooooooooooooooooooooo')", + "INSERT INTO foo SELECT FROM generate_series(1,1000000)", + ] + ) + + env.neon_cli.create_branch("child", "root") + pg_child = env.postgres.create_start("child") + + with neon_compare.record_duration("root_run_duration"): + pg_root.safe_psql("SELECT count(*) from foo") + with neon_compare.record_duration("child_run_duration"): + pg_child.safe_psql("SELECT count(*) from foo") + + +# ----------------------------------------------------------------------- +# End of `test_compare_child_and_root_*` tests +# ----------------------------------------------------------------------- From 9f79e7edea01e381dfc781383d0d65c6d18b5d1b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 8 Oct 2022 15:42:17 +0300 Subject: [PATCH 03/64] Merge pageserver helper binaries and provide it for deployment (#2590) --- Dockerfile | 10 +- pageserver/src/bin/dump_layerfile.rs | 35 ------ pageserver/src/bin/pageserver_binutils.rs | 144 ++++++++++++++++++++++ pageserver/src/bin/update_metadata.rs | 75 ----------- pageserver/src/tenant/delta_layer.rs | 2 +- pageserver/src/tenant/filename.rs | 2 +- pageserver/src/tenant/image_layer.rs | 2 +- 7 files changed, 152 insertions(+), 118 deletions(-) delete mode 100644 pageserver/src/bin/dump_layerfile.rs create mode 100644 pageserver/src/bin/pageserver_binutils.rs delete mode 100644 pageserver/src/bin/update_metadata.rs diff --git a/Dockerfile b/Dockerfile index 69402919ec..cb4e213687 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,7 +44,7 @@ COPY . . # Show build caching stats to check if it was used in the end. # Has to be the part of the same RUN since cachepot daemon is killed in the end of this RUN, losing the compilation stats. RUN set -e \ -&& mold -run cargo build --bin pageserver --bin safekeeper --bin proxy --locked --release \ +&& mold -run cargo build --bin pageserver --bin pageserver_binutils --bin safekeeper --bin proxy --locked --release \ && cachepot -s # Build final image @@ -63,9 +63,10 @@ RUN set -e \ && useradd -d /data neon \ && chown -R neon:neon /data -COPY --from=build --chown=neon:neon /home/nonroot/target/release/pageserver /usr/local/bin -COPY --from=build --chown=neon:neon /home/nonroot/target/release/safekeeper /usr/local/bin -COPY --from=build --chown=neon:neon /home/nonroot/target/release/proxy /usr/local/bin +COPY --from=build --chown=neon:neon /home/nonroot/target/release/pageserver /usr/local/bin +COPY --from=build --chown=neon:neon /home/nonroot/target/release/pageserver_binutils /usr/local/bin +COPY --from=build --chown=neon:neon /home/nonroot/target/release/safekeeper /usr/local/bin +COPY --from=build --chown=neon:neon /home/nonroot/target/release/proxy /usr/local/bin COPY --from=pg-build /home/nonroot/pg_install/v14 /usr/local/v14/ COPY --from=pg-build /home/nonroot/pg_install/v15 /usr/local/v15/ @@ -85,4 +86,3 @@ VOLUME ["/data"] USER neon EXPOSE 6400 EXPOSE 9898 -CMD ["/bin/bash"] diff --git a/pageserver/src/bin/dump_layerfile.rs b/pageserver/src/bin/dump_layerfile.rs deleted file mode 100644 index f5247ee609..0000000000 --- a/pageserver/src/bin/dump_layerfile.rs +++ /dev/null @@ -1,35 +0,0 @@ -//! Main entry point for the dump_layerfile executable -//! -//! A handy tool for debugging, that's all. -use anyhow::Result; -use clap::{App, Arg}; -use pageserver::page_cache; -use pageserver::tenant::dump_layerfile_from_path; -use pageserver::virtual_file; -use std::path::PathBuf; -use utils::project_git_version; - -project_git_version!(GIT_VERSION); - -fn main() -> Result<()> { - let arg_matches = App::new("Neon dump_layerfile utility") - .about("Dump contents of one layer file, for debugging") - .version(GIT_VERSION) - .arg( - Arg::new("path") - .help("Path to file to dump") - .required(true) - .index(1), - ) - .get_matches(); - - let path = PathBuf::from(arg_matches.value_of("path").unwrap()); - - // Basic initialization of things that don't change after startup - virtual_file::init(10); - page_cache::init(100); - - dump_layerfile_from_path(&path, true)?; - - Ok(()) -} diff --git a/pageserver/src/bin/pageserver_binutils.rs b/pageserver/src/bin/pageserver_binutils.rs new file mode 100644 index 0000000000..ec7699f194 --- /dev/null +++ b/pageserver/src/bin/pageserver_binutils.rs @@ -0,0 +1,144 @@ +//! A helper tool to manage pageserver binary files. +//! Accepts a file as an argument, attempts to parse it with all ways possible +//! and prints its interpreted context. +//! +//! Separate, `metadata` subcommand allows to print and update pageserver's metadata file. +use std::{ + path::{Path, PathBuf}, + str::FromStr, +}; + +use anyhow::Context; +use clap::{App, Arg}; + +use pageserver::{ + page_cache, + tenant::{dump_layerfile_from_path, metadata::TimelineMetadata}, + virtual_file, +}; +use postgres_ffi::ControlFileData; +use utils::{lsn::Lsn, project_git_version}; + +project_git_version!(GIT_VERSION); + +const METADATA_SUBCOMMAND: &str = "metadata"; + +fn main() -> anyhow::Result<()> { + let arg_matches = App::new("Neon Pageserver binutils") + .about("Reads pageserver (and related) binary files management utility") + .version(GIT_VERSION) + .arg(Arg::new("path").help("Input file path").required(false)) + .subcommand( + App::new(METADATA_SUBCOMMAND) + .about("Read and update pageserver metadata file") + .arg( + Arg::new("metadata_path") + .help("Input metadata file path") + .required(false), + ) + .arg( + Arg::new("disk_consistent_lsn") + .long("disk_consistent_lsn") + .takes_value(true) + .help("Replace disk consistent Lsn"), + ) + .arg( + Arg::new("prev_record_lsn") + .long("prev_record_lsn") + .takes_value(true) + .help("Replace previous record Lsn"), + ), + ) + .get_matches(); + + match arg_matches.subcommand() { + Some((subcommand_name, subcommand_matches)) => { + let path = PathBuf::from( + subcommand_matches + .value_of("metadata_path") + .context("'metadata_path' argument is missing")?, + ); + anyhow::ensure!( + subcommand_name == METADATA_SUBCOMMAND, + "Unknown subcommand {subcommand_name}" + ); + handle_metadata(&path, subcommand_matches)?; + } + None => { + let path = PathBuf::from( + arg_matches + .value_of("path") + .context("'path' argument is missing")?, + ); + println!( + "No subcommand specified, attempting to guess the format for file {}", + path.display() + ); + if let Err(e) = read_pg_control_file(&path) { + println!( + "Failed to read input file as a pg control one: {e:#}\n\ + Attempting to read it as layer file" + ); + print_layerfile(&path)?; + } + } + }; + Ok(()) +} + +fn read_pg_control_file(control_file_path: &Path) -> anyhow::Result<()> { + let control_file = ControlFileData::decode(&std::fs::read(&control_file_path)?)?; + println!("{control_file:?}"); + let control_file_initdb = Lsn(control_file.checkPoint); + println!( + "pg_initdb_lsn: {}, aligned: {}", + control_file_initdb, + control_file_initdb.align() + ); + Ok(()) +} + +fn print_layerfile(path: &Path) -> anyhow::Result<()> { + // Basic initialization of things that don't change after startup + virtual_file::init(10); + page_cache::init(100); + dump_layerfile_from_path(path, true) +} + +fn handle_metadata(path: &Path, arg_matches: &clap::ArgMatches) -> Result<(), anyhow::Error> { + let metadata_bytes = std::fs::read(&path)?; + let mut meta = TimelineMetadata::from_bytes(&metadata_bytes)?; + println!("Current metadata:\n{meta:?}"); + let mut update_meta = false; + if let Some(disk_consistent_lsn) = arg_matches.value_of("disk_consistent_lsn") { + meta = TimelineMetadata::new( + Lsn::from_str(disk_consistent_lsn)?, + meta.prev_record_lsn(), + meta.ancestor_timeline(), + meta.ancestor_lsn(), + meta.latest_gc_cutoff_lsn(), + meta.initdb_lsn(), + meta.pg_version(), + ); + update_meta = true; + } + if let Some(prev_record_lsn) = arg_matches.value_of("prev_record_lsn") { + meta = TimelineMetadata::new( + meta.disk_consistent_lsn(), + Some(Lsn::from_str(prev_record_lsn)?), + meta.ancestor_timeline(), + meta.ancestor_lsn(), + meta.latest_gc_cutoff_lsn(), + meta.initdb_lsn(), + meta.pg_version(), + ); + update_meta = true; + } + + if update_meta { + let metadata_bytes = meta.to_bytes()?; + std::fs::write(&path, &metadata_bytes)?; + } + + Ok(()) +} diff --git a/pageserver/src/bin/update_metadata.rs b/pageserver/src/bin/update_metadata.rs deleted file mode 100644 index e66049c457..0000000000 --- a/pageserver/src/bin/update_metadata.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! Main entry point for the edit_metadata executable -//! -//! A handy tool for debugging, that's all. -use anyhow::Result; -use clap::{App, Arg}; -use pageserver::tenant::metadata::TimelineMetadata; -use std::path::PathBuf; -use std::str::FromStr; -use utils::{lsn::Lsn, project_git_version}; - -project_git_version!(GIT_VERSION); - -fn main() -> Result<()> { - let arg_matches = App::new("Neon update metadata utility") - .about("Dump or update metadata file") - .version(GIT_VERSION) - .arg( - Arg::new("path") - .help("Path to metadata file") - .required(true), - ) - .arg( - Arg::new("disk_lsn") - .short('d') - .long("disk_lsn") - .takes_value(true) - .help("Replace disk constistent lsn"), - ) - .arg( - Arg::new("prev_lsn") - .short('p') - .long("prev_lsn") - .takes_value(true) - .help("Previous record LSN"), - ) - .get_matches(); - - let path = PathBuf::from(arg_matches.value_of("path").unwrap()); - let metadata_bytes = std::fs::read(&path)?; - let mut meta = TimelineMetadata::from_bytes(&metadata_bytes)?; - println!("Current metadata:\n{:?}", &meta); - - let mut update_meta = false; - - if let Some(disk_lsn) = arg_matches.value_of("disk_lsn") { - meta = TimelineMetadata::new( - Lsn::from_str(disk_lsn)?, - meta.prev_record_lsn(), - meta.ancestor_timeline(), - meta.ancestor_lsn(), - meta.latest_gc_cutoff_lsn(), - meta.initdb_lsn(), - meta.pg_version(), - ); - update_meta = true; - } - - if let Some(prev_lsn) = arg_matches.value_of("prev_lsn") { - meta = TimelineMetadata::new( - meta.disk_consistent_lsn(), - Some(Lsn::from_str(prev_lsn)?), - meta.ancestor_timeline(), - meta.ancestor_lsn(), - meta.latest_gc_cutoff_lsn(), - meta.initdb_lsn(), - meta.pg_version(), - ); - update_meta = true; - } - if update_meta { - let metadata_bytes = meta.to_bytes()?; - std::fs::write(&path, &metadata_bytes)?; - } - Ok(()) -} diff --git a/pageserver/src/tenant/delta_layer.rs b/pageserver/src/tenant/delta_layer.rs index 57c5be91a4..41715ab0a4 100644 --- a/pageserver/src/tenant/delta_layer.rs +++ b/pageserver/src/tenant/delta_layer.rs @@ -556,7 +556,7 @@ impl DeltaLayer { /// Create a DeltaLayer struct representing an existing file on disk. /// - /// This variant is only used for debugging purposes, by the 'dump_layerfile' binary. + /// This variant is only used for debugging purposes, by the 'pageserver_binutils' binary. pub fn new_for_path(path: &Path, file: F) -> Result where F: FileExt, diff --git a/pageserver/src/tenant/filename.rs b/pageserver/src/tenant/filename.rs index 5ebac2332d..0ebf2d479b 100644 --- a/pageserver/src/tenant/filename.rs +++ b/pageserver/src/tenant/filename.rs @@ -177,7 +177,7 @@ impl fmt::Display for ImageFileName { /// /// This is used by DeltaLayer and ImageLayer. Normally, this holds a reference to the /// global config, and paths to layer files are constructed using the tenant/timeline -/// path from the config. But in the 'dump_layerfile' binary, we need to construct a Layer +/// path from the config. But in the 'pageserver_binutils' binary, we need to construct a Layer /// struct for a file on disk, without having a page server running, so that we have no /// config. In that case, we use the Path variant to hold the full path to the file on /// disk. diff --git a/pageserver/src/tenant/image_layer.rs b/pageserver/src/tenant/image_layer.rs index 92bf022fee..cbfa0134b0 100644 --- a/pageserver/src/tenant/image_layer.rs +++ b/pageserver/src/tenant/image_layer.rs @@ -357,7 +357,7 @@ impl ImageLayer { /// Create an ImageLayer struct representing an existing file on disk. /// - /// This variant is only used for debugging purposes, by the 'dump_layerfile' binary. + /// This variant is only used for debugging purposes, by the 'pageserver_binutils' binary. pub fn new_for_path(path: &Path, file: F) -> Result where F: std::os::unix::prelude::FileExt, From 01d2c52c8245fdd4f8ed562b210a07e41bf45bdb Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 8 Oct 2022 09:57:05 +0300 Subject: [PATCH 04/64] Tidy up feature reporting --- pageserver/src/bin/pageserver.rs | 23 +++++++++++++---------- pageserver/src/http/routes.rs | 2 +- run_clippy.sh | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/pageserver/src/bin/pageserver.rs b/pageserver/src/bin/pageserver.rs index fb79ad3945..46a36c6118 100644 --- a/pageserver/src/bin/pageserver.rs +++ b/pageserver/src/bin/pageserver.rs @@ -31,11 +31,20 @@ use utils::{ project_git_version!(GIT_VERSION); +const FEATURES: &[&str] = &[ + #[cfg(feature = "testing")] + "testing", + #[cfg(feature = "fail/failpoints")] + "fail/failpoints", + #[cfg(feature = "profiling")] + "profiling", +]; + fn version() -> String { format!( - "{GIT_VERSION} profiling:{} failpoints:{}", - cfg!(feature = "profiling"), - fail::has_failpoints() + "{GIT_VERSION} failpoints: {}, features: {:?}", + fail::has_failpoints(), + FEATURES, ) } @@ -86,13 +95,7 @@ fn main() -> anyhow::Result<()> { .get_matches(); if arg_matches.is_present("enabled-features") { - let features: &[&str] = &[ - #[cfg(feature = "testing")] - "testing", - #[cfg(feature = "profiling")] - "profiling", - ]; - println!("{{\"features\": {features:?} }}"); + println!("{{\"features\": {FEATURES:?} }}"); return Ok(()); } diff --git a/pageserver/src/http/routes.rs b/pageserver/src/http/routes.rs index e743f27aff..f1318cb325 100644 --- a/pageserver/src/http/routes.rs +++ b/pageserver/src/http/routes.rs @@ -784,7 +784,7 @@ async fn tenant_config_handler(mut request: Request) -> Result) -> Result, ApiError> { if !fail::has_failpoints() { return Err(ApiError::BadRequest(anyhow!( diff --git a/run_clippy.sh b/run_clippy.sh index 9feb8de4ea..bf770432d0 100755 --- a/run_clippy.sh +++ b/run_clippy.sh @@ -13,7 +13,7 @@ # avoid running regular linting script that checks every feature. if [[ "$OSTYPE" == "darwin"* ]]; then # no extra features to test currently, add more here when needed - cargo clippy --locked --all --all-targets -- -A unknown_lints -D warnings + cargo clippy --locked --all --all-targets --features testing -- -A unknown_lints -D warnings else # * `-A unknown_lints` – do not warn about unknown lint suppressions # that people with newer toolchains might use From 3be3bb77302c371d1c58fda7d17dbf56dd9ad061 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 8 Oct 2022 10:03:52 +0300 Subject: [PATCH 05/64] Be more verbose with initdb for pageserver timeline creation --- pageserver/src/tenant.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index c2fb9ef242..4da5790f51 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -1094,12 +1094,22 @@ impl Tenant { /// Create the cluster temporarily in 'initdbpath' directory inside the repository /// to get bootstrap data for timeline initialization. -fn run_initdb(conf: &'static PageServerConf, initdbpath: &Path, pg_version: u32) -> Result<()> { - info!("running initdb in {}... ", initdbpath.display()); +fn run_initdb( + conf: &'static PageServerConf, + initdb_target_dir: &Path, + pg_version: u32, +) -> Result<()> { + let initdb_bin_path = conf.pg_bin_dir(pg_version).join("initdb"); + let initdb_lib_dir = conf.pg_lib_dir(pg_version); + info!( + "running {} in {}, libdir: {}", + initdb_bin_path.display(), + initdb_target_dir.display(), + initdb_lib_dir.display(), + ); - let initdb_path = conf.pg_bin_dir(pg_version).join("initdb"); - let initdb_output = Command::new(initdb_path) - .args(&["-D", &initdbpath.to_string_lossy()]) + let initdb_output = Command::new(initdb_bin_path) + .args(&["-D", &initdb_target_dir.to_string_lossy()]) .args(&["-U", &conf.superuser]) .args(&["-E", "utf8"]) .arg("--no-instructions") @@ -1107,8 +1117,8 @@ fn run_initdb(conf: &'static PageServerConf, initdbpath: &Path, pg_version: u32) // so no need to fsync it .arg("--no-sync") .env_clear() - .env("LD_LIBRARY_PATH", conf.pg_lib_dir(pg_version)) - .env("DYLD_LIBRARY_PATH", conf.pg_lib_dir(pg_version)) + .env("LD_LIBRARY_PATH", &initdb_lib_dir) + .env("DYLD_LIBRARY_PATH", &initdb_lib_dir) .stdout(Stdio::null()) .output() .context("failed to execute initdb")?; From 3e35f10adca053afd6c786237cc06bc6f8db5050 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 8 Oct 2022 12:21:17 +0300 Subject: [PATCH 06/64] Add a script to reformat the project --- scripts/reformat | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100755 scripts/reformat diff --git a/scripts/reformat b/scripts/reformat new file mode 100755 index 0000000000..67140a705a --- /dev/null +++ b/scripts/reformat @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -euox pipefail + +# Runs all formatting tools to ensure the project is up to date +echo 'Reformatting Rust code' +cargo fmt +echo 'Reformatting Python code' +poetry run isort test_runner +poetry run flake8 test_runner +poetry run black test_runner From 13f0e7a5b4a2ea1187955926e036d4ac57ed094c Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 8 Oct 2022 23:53:12 +0300 Subject: [PATCH 07/64] Deploy pageserver_binutils to the envs --- .github/ansible/get_binaries.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ansible/get_binaries.sh b/.github/ansible/get_binaries.sh index a484bfb0a0..9d2d0926f5 100755 --- a/.github/ansible/get_binaries.sh +++ b/.github/ansible/get_binaries.sh @@ -23,6 +23,7 @@ docker cp ${ID}:/data/postgres_install.tar.gz . tar -xzf postgres_install.tar.gz -C neon_install mkdir neon_install/bin/ docker cp ${ID}:/usr/local/bin/pageserver neon_install/bin/ +docker cp ${ID}:/usr/local/bin/pageserver_binutils neon_install/bin/ docker cp ${ID}:/usr/local/bin/safekeeper neon_install/bin/ docker cp ${ID}:/usr/local/bin/proxy neon_install/bin/ docker cp ${ID}:/usr/local/v14/bin/ neon_install/v14/bin/ From 34bea270f0e320c1f77f76c0f0b0000774935b68 Mon Sep 17 00:00:00 2001 From: Sergey Melnikov Date: Mon, 10 Oct 2022 12:12:50 +0300 Subject: [PATCH 08/64] Fix POSTGRES_DISTRIB_DIR for benchmarks on ec2 runner (#2594) --- .github/workflows/benchmarking.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmarking.yml b/.github/workflows/benchmarking.yml index 4d91e9fa74..6c7dce9beb 100644 --- a/.github/workflows/benchmarking.yml +++ b/.github/workflows/benchmarking.yml @@ -46,7 +46,7 @@ jobs: runs-on: [self-hosted, zenith-benchmarker] env: - POSTGRES_DISTRIB_DIR: /tmp/pg_install + POSTGRES_DISTRIB_DIR: /usr/pgsql DEFAULT_PG_VERSION: 14 steps: From 241e5497574146f7c29775ffdd311b801a5cc78c Mon Sep 17 00:00:00 2001 From: Sergey Melnikov Date: Tue, 11 Oct 2022 01:07:19 +0300 Subject: [PATCH 09/64] Switch neon-stress etcd to dedicatd instance (#2602) --- .github/ansible/neon-stress.hosts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ansible/neon-stress.hosts b/.github/ansible/neon-stress.hosts index 750fd8106a..c1bc8243f8 100644 --- a/.github/ansible/neon-stress.hosts +++ b/.github/ansible/neon-stress.hosts @@ -16,5 +16,5 @@ env_name = neon-stress console_mgmt_base_url = http://neon-stress-console.local bucket_name = neon-storage-ireland bucket_region = eu-west-1 -etcd_endpoints = etcd-stress.local:2379 +etcd_endpoints = neon-stress-etcd.local:2379 safekeeper_enable_s3_offload = false From e52029309059ef2197aaff1a725deb4d42976fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lassi=20P=C3=B6l=C3=B6nen?= Date: Tue, 11 Oct 2022 09:54:32 +0300 Subject: [PATCH 10/64] Add build info metric to pageserver, safekeeper and proxy (#2596) * Test that we emit build info metric for pageserver, safekeeper and proxy with some non-zero length revision label * Emit libmetrics_build_info on startup of pageserver, safekeeper and proxy with label "revision" which tells the git revision. --- libs/metrics/src/lib.rs | 10 ++++++++++ pageserver/src/bin/pageserver.rs | 4 ++++ proxy/src/main.rs | 2 ++ safekeeper/src/bin/safekeeper.rs | 2 ++ test_runner/fixtures/neon_fixtures.py | 5 +++++ test_runner/regress/test_build_info_metric.py | 19 +++++++++++++++++++ 6 files changed, 42 insertions(+) create mode 100644 test_runner/regress/test_build_info_metric.py diff --git a/libs/metrics/src/lib.rs b/libs/metrics/src/lib.rs index e290828d37..880ab0e83c 100644 --- a/libs/metrics/src/lib.rs +++ b/libs/metrics/src/lib.rs @@ -77,6 +77,16 @@ pub const DISK_WRITE_SECONDS_BUCKETS: &[f64] = &[ 0.000_050, 0.000_100, 0.000_500, 0.001, 0.003, 0.005, 0.01, 0.05, 0.1, 0.3, 0.5, ]; +pub fn set_build_info_metric(revision: &str) { + let metric = register_int_gauge_vec!( + "libmetrics_build_info", + "Build/version information", + &["revision"] + ) + .expect("Failed to register build info metric"); + metric.with_label_values(&[revision]).set(1); +} + // Records I/O stats in a "cross-platform" way. // Compiles both on macOS and Linux, but current macOS implementation always returns 0 as values for I/O stats. // An alternative is to read procfs (`/proc/[pid]/io`) which does not work under macOS at all, hence abandoned. diff --git a/pageserver/src/bin/pageserver.rs b/pageserver/src/bin/pageserver.rs index 46a36c6118..4cd82e37b1 100644 --- a/pageserver/src/bin/pageserver.rs +++ b/pageserver/src/bin/pageserver.rs @@ -10,6 +10,8 @@ use clap::{App, Arg}; use daemonize::Daemonize; use fail::FailScenario; +use metrics::set_build_info_metric; + use pageserver::{ config::{defaults::*, PageServerConf}, http, page_cache, page_service, profiling, task_mgr, @@ -359,6 +361,8 @@ fn start_pageserver(conf: &'static PageServerConf, daemonize: bool) -> Result<() }, ); + set_build_info_metric(GIT_VERSION); + // All started up! Now just sit and wait for shutdown signal. signals.handle(|signal| match signal { Signal::Quit => { diff --git a/proxy/src/main.rs b/proxy/src/main.rs index 2e6c365d32..91ef26a37f 100644 --- a/proxy/src/main.rs +++ b/proxy/src/main.rs @@ -23,6 +23,7 @@ use anyhow::{bail, Context}; use clap::{self, Arg}; use config::ProxyConfig; use futures::FutureExt; +use metrics::set_build_info_metric; use std::{borrow::Cow, future::Future, net::SocketAddr}; use tokio::{net::TcpListener, task::JoinError}; use tracing::info; @@ -166,6 +167,7 @@ async fn main() -> anyhow::Result<()> { ] .map(flatten_err); + set_build_info_metric(GIT_VERSION); // This will block until all tasks have completed. // Furthermore, the first one to fail will cancel the rest. let _: Vec<()> = futures::future::try_join_all(tasks).await?; diff --git a/safekeeper/src/bin/safekeeper.rs b/safekeeper/src/bin/safekeeper.rs index e4545dad87..3f55d823cc 100644 --- a/safekeeper/src/bin/safekeeper.rs +++ b/safekeeper/src/bin/safekeeper.rs @@ -17,6 +17,7 @@ use toml_edit::Document; use tracing::*; use url::{ParseError, Url}; +use metrics::set_build_info_metric; use safekeeper::broker; use safekeeper::control_file; use safekeeper::defaults::{ @@ -363,6 +364,7 @@ fn start_safekeeper(mut conf: SafeKeeperConf, given_id: Option, init: bo })?, ); + set_build_info_metric(GIT_VERSION); // TODO: put more thoughts into handling of failed threads // We probably should restart them. diff --git a/test_runner/fixtures/neon_fixtures.py b/test_runner/fixtures/neon_fixtures.py index 28c65223ba..5df0f5cc50 100644 --- a/test_runner/fixtures/neon_fixtures.py +++ b/test_runner/fixtures/neon_fixtures.py @@ -1961,6 +1961,11 @@ class NeonProxy(PgProtocol): def _wait_until_ready(self): requests.get(f"http://{self.host}:{self.http_port}/v1/status") + def get_metrics(self) -> str: + request_result = requests.get(f"http://{self.host}:{self.http_port}/metrics") + request_result.raise_for_status() + return request_result.text + def __enter__(self): return self diff --git a/test_runner/regress/test_build_info_metric.py b/test_runner/regress/test_build_info_metric.py new file mode 100644 index 0000000000..b75b5bd775 --- /dev/null +++ b/test_runner/regress/test_build_info_metric.py @@ -0,0 +1,19 @@ +from fixtures.metrics import parse_metrics +from fixtures.neon_fixtures import NeonEnvBuilder, NeonProxy + + +def test_build_info_metric(neon_env_builder: NeonEnvBuilder, link_proxy: NeonProxy): + neon_env_builder.num_safekeepers = 1 + env = neon_env_builder.init_start() + + parsed_metrics = {} + + parsed_metrics["pageserver"] = parse_metrics(env.pageserver.http_client().get_metrics()) + parsed_metrics["safekeeper"] = parse_metrics(env.safekeepers[0].http_client().get_metrics_str()) + parsed_metrics["proxy"] = parse_metrics(link_proxy.get_metrics()) + + for component, metrics in parsed_metrics.items(): + sample = metrics.query_one("libmetrics_build_info") + + assert "revision" in sample.labels + assert len(sample.labels["revision"]) > 0 From db26bc49cca14c31005ae9e1dd3bf63fdaaeff50 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Tue, 11 Oct 2022 14:47:55 +0300 Subject: [PATCH 11/64] Remove obsolete FIXME comment. Commit c634cb1d36 removed the trait and changed the function to return a &TimelineWriter, as the FIXME said we should do, but forgot to remove the FIXME. --- pageserver/src/tenant/timeline.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index 247e076230..3639e30fee 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -475,10 +475,6 @@ impl Timeline { } /// Mutate the timeline with a [`TimelineWriter`]. - /// - /// FIXME: This ought to return &'a TimelineWriter, where TimelineWriter - /// is a generic type in this trait. But that doesn't currently work in - /// Rust: https://rust-lang.github.io/rfcs/1598-generic_associated_types.html pub fn writer(&self) -> TimelineWriter<'_> { TimelineWriter { tl: self, From 47366522a88f7fe06503de9639b89338e82c2f1a Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Tue, 11 Oct 2022 14:47:59 +0300 Subject: [PATCH 12/64] Make the return type of 'list_timelines' simpler. It's enough to return just the Timeline references. You can get the timeline's ID easily from Timeline. --- pageserver/src/http/routes.rs | 7 ++++--- pageserver/src/tenant.rs | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pageserver/src/http/routes.rs b/pageserver/src/http/routes.rs index f1318cb325..2b4ad86310 100644 --- a/pageserver/src/http/routes.rs +++ b/pageserver/src/http/routes.rs @@ -145,9 +145,9 @@ fn list_local_timelines( let timelines = tenant.list_timelines(); let mut local_timeline_info = Vec::with_capacity(timelines.len()); - for (timeline_id, repository_timeline) in timelines { + for repository_timeline in timelines { local_timeline_info.push(( - timeline_id, + repository_timeline.timeline_id, local_timeline_info_from_timeline( &repository_timeline, include_non_incremental_logical_size, @@ -218,7 +218,8 @@ async fn timeline_list_handler(request: Request) -> Result, .map_err(|e: JoinError| ApiError::InternalServerError(e.into()))??; let mut response_data = Vec::with_capacity(timelines.len()); - for (timeline_id, timeline) in timelines { + for timeline in timelines { + let timeline_id = timeline.timeline_id; let local = match local_timeline_info_from_timeline( &timeline, include_non_incremental_logical_size, diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index 4da5790f51..994e1db47b 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -144,12 +144,12 @@ impl Tenant { /// Lists timelines the tenant contains. /// Up to tenant's implementation to omit certain timelines that ar not considered ready for use. - pub fn list_timelines(&self) -> Vec<(TimelineId, Arc)> { + pub fn list_timelines(&self) -> Vec> { self.timelines .lock() .unwrap() - .iter() - .map(|(timeline_id, timeline_entry)| (*timeline_id, Arc::clone(timeline_entry))) + .values() + .map(Arc::clone) .collect() } From 676c63c32961d2582d8140adda2ec659a37482a8 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Tue, 11 Oct 2022 14:48:02 +0300 Subject: [PATCH 13/64] Improve comments. --- pageserver/src/tenant.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index 994e1db47b..31d4696a31 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -153,8 +153,9 @@ impl Tenant { .collect() } - /// Create a new, empty timeline. The caller is responsible for loading data into it - /// Initdb lsn is provided for timeline impl to be able to perform checks for some operations against it. + /// This is used to create the initial 'main' timeline during bootstrapping, + /// or when importing a new base backup. The caller is expected to load an + /// initial image of the datadir to the new timeline after this. pub fn create_empty_timeline( &self, new_timeline_id: TimelineId, @@ -906,6 +907,7 @@ impl Tenant { Ok(totals) } + /// Branch an existing timeline fn branch_timeline( &self, src: TimelineId, @@ -981,7 +983,7 @@ impl Tenant { dst_prev, Some(src), start_lsn, - *src_timeline.latest_gc_cutoff_lsn.read(), + *src_timeline.latest_gc_cutoff_lsn.read(), // FIXME: should we hold onto this guard longer? src_timeline.initdb_lsn, src_timeline.pg_version, ); From e5e40a31f4ce84a37f88aad2fe612d144fc55e6f Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Tue, 11 Oct 2022 14:48:04 +0300 Subject: [PATCH 14/64] Clean up terms "delete timeline" and "detach tenant". You cannot attach/detach an individual timeline, attach/detach always applies to the whole tenant. However, you can *delete* a single timeline from a tenant. Fix some comments and error messages that confused these two operations. --- pageserver/src/tenant.rs | 2 +- test_runner/regress/test_normal_work.py | 2 +- test_runner/regress/test_tenant_detach.py | 2 +- test_runner/regress/test_timeline_delete.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index 31d4696a31..3dd2f92b5e 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -346,7 +346,7 @@ impl Tenant { ensure!( !children_exist, - "Cannot detach timeline which has child timelines" + "Cannot delete timeline which has child timelines" ); let timeline_entry = match timelines.entry(timeline_id) { Entry::Occupied(e) => e, diff --git a/test_runner/regress/test_normal_work.py b/test_runner/regress/test_normal_work.py index 002d697288..73918ee476 100644 --- a/test_runner/regress/test_normal_work.py +++ b/test_runner/regress/test_normal_work.py @@ -39,7 +39,7 @@ def test_normal_work(neon_env_builder: NeonEnvBuilder, num_timelines: int, num_s * restart compute * check that the data is there * stop compute - * detach timeline + * detach tenant Repeat check for several tenants/timelines. """ diff --git a/test_runner/regress/test_tenant_detach.py b/test_runner/regress/test_tenant_detach.py index f18e6867a9..a310eac1f7 100644 --- a/test_runner/regress/test_tenant_detach.py +++ b/test_runner/regress/test_tenant_detach.py @@ -70,7 +70,7 @@ def test_tenant_detach_smoke(neon_env_builder: NeonEnvBuilder): break # else is called if the loop finished without reaching "break" else: - pytest.fail(f"could not detach timeline: {last_error}") + pytest.fail(f"could not detach tenant: {last_error}") gc_thread.join(timeout=10) diff --git a/test_runner/regress/test_timeline_delete.py b/test_runner/regress/test_timeline_delete.py index 2eea8dd3cc..ac248c1b4b 100644 --- a/test_runner/regress/test_timeline_delete.py +++ b/test_runner/regress/test_timeline_delete.py @@ -32,7 +32,7 @@ def test_timeline_delete(neon_simple_env: NeonEnv): ps_http = env.pageserver.http_client() with pytest.raises( - NeonPageserverApiException, match="Cannot detach timeline which has child timelines" + NeonPageserverApiException, match="Cannot delete timeline which has child timelines" ): timeline_path = ( From 6d0dacc4ce57d89ef2f9691e6a79d9998d331ac8 Mon Sep 17 00:00:00 2001 From: Arseny Sher Date: Wed, 31 Aug 2022 17:40:40 +0300 Subject: [PATCH 15/64] Recreate timeline on pageserver in s3_wal_replay test. That's closer to real usage than switching to brand new pageserver. --- test_runner/regress/test_wal_acceptor.py | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/test_runner/regress/test_wal_acceptor.py b/test_runner/regress/test_wal_acceptor.py index d5a5ec2f36..1f9a0157fc 100644 --- a/test_runner/regress/test_wal_acceptor.py +++ b/test_runner/regress/test_wal_acceptor.py @@ -1,7 +1,6 @@ import os import pathlib import random -import shutil import signal import subprocess import sys @@ -481,13 +480,6 @@ def test_s3_wal_replay(neon_env_builder: NeonEnvBuilder, remote_storage_kind: Re env = neon_env_builder.init_start() env.neon_cli.create_branch("test_s3_wal_replay") - env.pageserver.stop() - pageserver_tenants_dir = os.path.join(env.repo_dir, "tenants") - pageserver_fresh_copy = os.path.join(env.repo_dir, "tenants_fresh") - log.info(f"Creating a copy of pageserver in a fresh state at {pageserver_fresh_copy}") - shutil.copytree(pageserver_tenants_dir, pageserver_fresh_copy) - env.pageserver.start() - pg = env.postgres.create_start("test_s3_wal_replay") # learn neon timeline from compute @@ -525,25 +517,19 @@ def test_s3_wal_replay(neon_env_builder: NeonEnvBuilder, remote_storage_kind: Re last_lsn = query_scalar(cur, "SELECT pg_current_wal_flush_lsn()") - pageserver_lsn = env.pageserver.http_client().timeline_detail(tenant_id, timeline_id)["local"][ - "last_record_lsn" - ] + ps_cli = env.pageserver.http_client() + pageserver_lsn = ps_cli.timeline_detail(tenant_id, timeline_id)["local"]["last_record_lsn"] lag = Lsn(last_lsn) - Lsn(pageserver_lsn) log.info( f"Pageserver last_record_lsn={pageserver_lsn}; flush_lsn={last_lsn}; lag before replay is {lag / 1024}kb" ) - # replace pageserver with a fresh copy pg.stop_and_destroy() - env.pageserver.stop() - log.info(f"Removing current pageserver state at {pageserver_tenants_dir}") - shutil.rmtree(pageserver_tenants_dir) - log.info(f"Copying fresh pageserver state from {pageserver_fresh_copy}") - shutil.move(pageserver_fresh_copy, pageserver_tenants_dir) + # recreate timeline on pageserver from scratch + ps_cli.timeline_delete(tenant_id, timeline_id) + ps_cli.timeline_create(tenant_id, timeline_id) - # start pageserver and wait for replay - env.pageserver.start() wait_lsn_timeout = 60 * 3 started_at = time.time() last_debug_print = 0.0 From 93775f6ca75060f86395427e993b5c393ec16a60 Mon Sep 17 00:00:00 2001 From: Alexander Bayandin Date: Wed, 12 Oct 2022 10:22:24 +0100 Subject: [PATCH 16/64] GitHub Actions: replace deprecated set-output with GITHUB_OUTPUT (#2608) --- .github/actions/allure-report/action.yml | 4 ++-- .github/actions/download/action.yml | 4 ++-- .github/actions/neon-project-create/action.yml | 8 ++++---- .github/actions/neon-project-delete/action.yml | 2 +- .github/workflows/benchmarking.yml | 2 +- .github/workflows/build_and_test.yml | 14 +++++++------- .github/workflows/codestyle.yml | 4 ++-- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/actions/allure-report/action.yml b/.github/actions/allure-report/action.yml index ec751f51fc..dfb314571b 100644 --- a/.github/actions/allure-report/action.yml +++ b/.github/actions/allure-report/action.yml @@ -47,7 +47,7 @@ runs: else key=branch-$(echo ${GITHUB_REF#refs/heads/} | tr -c "[:alnum:]._-" "-") fi - echo "::set-output name=KEY::${key}" + echo "KEY=${key}" >> $GITHUB_OUTPUT - uses: actions/setup-java@v3 if: ${{ inputs.action == 'generate' }} @@ -186,7 +186,7 @@ runs: aws s3 cp --only-show-errors ./index.html "s3://${BUCKET}/${REPORT_PREFIX}/latest/index.html" echo "[Allure Report](${REPORT_URL})" >> ${GITHUB_STEP_SUMMARY} - echo "::set-output name=report-url::${REPORT_URL}" + echo "report-url=${REPORT_URL}" >> $GITHUB_OUTPUT - name: Release Allure lock if: ${{ inputs.action == 'generate' && always() }} diff --git a/.github/actions/download/action.yml b/.github/actions/download/action.yml index 731ef6639d..eb34d4206a 100644 --- a/.github/actions/download/action.yml +++ b/.github/actions/download/action.yml @@ -34,7 +34,7 @@ runs: S3_KEY=$(aws s3api list-objects-v2 --bucket ${BUCKET} --prefix ${PREFIX%$GITHUB_RUN_ATTEMPT} | jq -r '.Contents[].Key' | grep ${FILENAME} | sort --version-sort | tail -1 || true) if [ -z "${S3_KEY}" ]; then if [ "${SKIP_IF_DOES_NOT_EXIST}" = "true" ]; then - echo '::set-output name=SKIPPED::true' + echo 'SKIPPED=true' >> $GITHUB_OUTPUT exit 0 else echo 2>&1 "Neither s3://${BUCKET}/${PREFIX}/${FILENAME} nor its version from previous attempts exist" @@ -42,7 +42,7 @@ runs: fi fi - echo '::set-output name=SKIPPED::false' + echo 'SKIPPED=false' >> $GITHUB_OUTPUT mkdir -p $(dirname $ARCHIVE) time aws s3 cp --only-show-errors s3://${BUCKET}/${S3_KEY} ${ARCHIVE} diff --git a/.github/actions/neon-project-create/action.yml b/.github/actions/neon-project-create/action.yml index 2f58ae77ad..b4fd151582 100644 --- a/.github/actions/neon-project-create/action.yml +++ b/.github/actions/neon-project-create/action.yml @@ -41,8 +41,8 @@ runs: ;; esac - echo "::set-output name=api_host::${API_HOST}" - echo "::set-output name=region_id::${REGION_ID}" + echo "api_host=${API_HOST}" >> $GITHUB_OUTPUT + echo "region_id=${REGION_ID}" >> $GITHUB_OUTPUT env: ENVIRONMENT: ${{ inputs.environment }} REGION_ID: ${{ inputs.region_id }} @@ -72,10 +72,10 @@ runs: dsn=$(echo $project | jq --raw-output '.roles[] | select(.name != "web_access") | .dsn')/main echo "::add-mask::${dsn}" - echo "::set-output name=dsn::${dsn}" + echo "dsn=${dsn}" >> $GITHUB_OUTPUT project_id=$(echo $project | jq --raw-output '.id') - echo "::set-output name=project_id::${project_id}" + echo "project_id=${project_id}" >> $GITHUB_OUTPUT env: API_KEY: ${{ inputs.api_key }} API_HOST: ${{ steps.parse-input.outputs.api_host }} diff --git a/.github/actions/neon-project-delete/action.yml b/.github/actions/neon-project-delete/action.yml index e7c6f58901..d417c489ef 100644 --- a/.github/actions/neon-project-delete/action.yml +++ b/.github/actions/neon-project-delete/action.yml @@ -32,7 +32,7 @@ runs: ;; esac - echo "::set-output name=api_host::${API_HOST}" + echo "api_host=${API_HOST}" >> $GITHUB_OUTPUT env: ENVIRONMENT: ${{ inputs.environment }} diff --git a/.github/workflows/benchmarking.yml b/.github/workflows/benchmarking.yml index 6c7dce9beb..dee5968ef3 100644 --- a/.github/workflows/benchmarking.yml +++ b/.github/workflows/benchmarking.yml @@ -204,7 +204,7 @@ jobs: ;; esac - echo "::set-output name=connstr::${CONNSTR}" + echo "connstr=${CONNSTR}" >> $GITHUB_OUTPUT psql ${CONNSTR} -c "SELECT version();" env: diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 7cc8715526..2c6aa02b22 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -35,12 +35,12 @@ jobs: echo ref:$GITHUB_REF_NAME echo rev:$(git rev-list --count HEAD) if [[ "$GITHUB_REF_NAME" == "main" ]]; then - echo "::set-output name=tag::$(git rev-list --count HEAD)" + echo "tag=$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT elif [[ "$GITHUB_REF_NAME" == "release" ]]; then - echo "::set-output name=tag::release-$(git rev-list --count HEAD)" + echo "tag=release-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT else echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main' or 'release'" - echo "::set-output name=tag::$GITHUB_RUN_ID" + echo "tag=$GITHUB_RUN_ID" >> $GITHUB_OUTPUT fi shell: bash id: build-tag @@ -78,12 +78,12 @@ jobs: - name: Set pg 14 revision for caching id: pg_v14_rev - run: echo ::set-output name=pg_rev::$(git rev-parse HEAD:vendor/postgres-v14) + run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v14) >> $GITHUB_OUTPUT shell: bash -euxo pipefail {0} - name: Set pg 15 revision for caching id: pg_v15_rev - run: echo ::set-output name=pg_rev::$(git rev-parse HEAD:vendor/postgres-v15) + run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v15) >> $GITHUB_OUTPUT shell: bash -euxo pipefail {0} # Set some environment variables used by all the steps. @@ -671,10 +671,10 @@ jobs: if [[ "$GITHUB_REF_NAME" == "main" ]]; then STAGING='{"env_name": "staging", "proxy_job": "neon-proxy", "proxy_config": "staging.proxy", "kubeconfig_secret": "STAGING_KUBECONFIG_DATA"}' NEON_STRESS='{"env_name": "neon-stress", "proxy_job": "neon-stress-proxy", "proxy_config": "neon-stress.proxy", "kubeconfig_secret": "NEON_STRESS_KUBECONFIG_DATA"}' - echo "::set-output name=include::[$STAGING, $NEON_STRESS]" + echo "include=[$STAGING, $NEON_STRESS]" >> $GITHUB_OUTPUT elif [[ "$GITHUB_REF_NAME" == "release" ]]; then PRODUCTION='{"env_name": "production", "proxy_job": "neon-proxy", "proxy_config": "production.proxy", "kubeconfig_secret": "PRODUCTION_KUBECONFIG_DATA"}' - echo "::set-output name=include::[$PRODUCTION]" + echo "include=[$PRODUCTION]" >> $GITHUB_OUTPUT else echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main' or 'release'" exit 1 diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml index 6d39958bab..961d811a51 100644 --- a/.github/workflows/codestyle.yml +++ b/.github/workflows/codestyle.yml @@ -56,12 +56,12 @@ jobs: - name: Set pg 14 revision for caching id: pg_v14_rev - run: echo ::set-output name=pg_rev::$(git rev-parse HEAD:vendor/postgres-v14) + run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v14) >> $GITHUB_OUTPUT shell: bash -euxo pipefail {0} - name: Set pg 15 revision for caching id: pg_v15_rev - run: echo ::set-output name=pg_rev::$(git rev-parse HEAD:vendor/postgres-v15) + run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v15) >> $GITHUB_OUTPUT shell: bash -euxo pipefail {0} - name: Cache postgres v14 build From 771e61425ec0a0521f3c93c10783c41fbd3867d2 Mon Sep 17 00:00:00 2001 From: danieltprice <10074684+danieltprice@users.noreply.github.com> Date: Wed, 12 Oct 2022 08:38:28 -0300 Subject: [PATCH 17/64] Update release-pr.md (#2600) Update the Release Notes PR example that is referenced from the checklist. The Release Notes file structure changed recently. --- .github/PULL_REQUEST_TEMPLATE/release-pr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/release-pr.md b/.github/PULL_REQUEST_TEMPLATE/release-pr.md index 6f86114060..8fcc3bd4af 100644 --- a/.github/PULL_REQUEST_TEMPLATE/release-pr.md +++ b/.github/PULL_REQUEST_TEMPLATE/release-pr.md @@ -10,7 +10,7 @@ ### Checklist after release -- [ ] Based on the merged commits write release notes and open a PR into `website` repo ([example](https://github.com/neondatabase/website/pull/120/files)) +- [ ] Based on the merged commits write release notes and open a PR into `website` repo ([example](https://github.com/neondatabase/website/pull/219/files)) - [ ] Check [#dev-production-stream](https://neondb.slack.com/archives/C03F5SM1N02) Slack channel - [ ] Check [stuck projects page](https://console.neon.tech/admin/projects?sort=last_active&order=desc&stuck=true) - [ ] Check [recent operation failures](https://console.neon.tech/admin/operations?action=create_timeline%2Cstart_compute%2Cstop_compute%2Csuspend_compute%2Capply_config%2Cdelete_timeline%2Cdelete_tenant%2Ccreate_branch%2Ccheck_availability&sort=updated_at&order=desc&had_retries=some) From 6ace79345de41e4569856c7ad6978cb1bb1e1765 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanov Date: Wed, 12 Oct 2022 21:00:44 +0300 Subject: [PATCH 18/64] [proxy] Add more context to console requests logging (#2583) --- proxy/src/auth/backend/console.rs | 68 ++++++++++++++----------------- proxy/src/auth/backend/link.rs | 7 ++-- proxy/src/http.rs | 11 +++++ proxy/src/proxy.rs | 8 ++-- proxy/src/stream.rs | 8 ++-- 5 files changed, 53 insertions(+), 49 deletions(-) diff --git a/proxy/src/auth/backend/console.rs b/proxy/src/auth/backend/console.rs index 7dbb173b88..cf99aa08ef 100644 --- a/proxy/src/auth/backend/console.rs +++ b/proxy/src/auth/backend/console.rs @@ -8,36 +8,20 @@ use crate::{ http, scram, stream::PqStream, }; +use futures::TryFutureExt; use serde::{Deserialize, Serialize}; use std::future::Future; use thiserror::Error; use tokio::io::{AsyncRead, AsyncWrite}; -use tracing::info; +use tracing::{error, info, info_span}; const REQUEST_FAILED: &str = "Console request failed"; #[derive(Debug, Error)] -pub enum TransportError { - #[error("Console responded with a malformed JSON: {0}")] - BadResponse(#[from] serde_json::Error), +#[error("{}", REQUEST_FAILED)] +pub struct TransportError(#[from] std::io::Error); - /// HTTP status (other than 200) returned by the console. - #[error("Console responded with an HTTP status: {0}")] - HttpStatus(reqwest::StatusCode), - - #[error(transparent)] - Io(#[from] std::io::Error), -} - -impl UserFacingError for TransportError { - fn to_string_client(&self) -> String { - use TransportError::*; - match self { - HttpStatus(_) => self.to_string(), - _ => REQUEST_FAILED.to_owned(), - } - } -} +impl UserFacingError for TransportError {} // Helps eliminate graceless `.map_err` calls without introducing another ctor. impl From for TransportError { @@ -162,15 +146,19 @@ impl<'a> Api<'a> { ]) .build()?; - info!(id = request_id, url = req.url().as_str(), "request"); - let resp = self.endpoint.execute(req).await?; - if !resp.status().is_success() { - return Err(TransportError::HttpStatus(resp.status()).into()); - } + let span = info_span!("http", id = request_id, url = req.url().as_str()); + info!(parent: &span, "request auth info"); + let msg = self + .endpoint + .checked_execute(req) + .and_then(|r| r.json::()) + .await + .map_err(|e| { + error!(parent: &span, "{e}"); + e + })?; - let response: GetRoleSecretResponse = serde_json::from_str(&resp.text().await?)?; - - scram::ServerSecret::parse(&response.role_secret) + scram::ServerSecret::parse(&msg.role_secret) .map(AuthInfo::Scram) .ok_or(GetAuthInfoError::BadSecret) } @@ -189,17 +177,21 @@ impl<'a> Api<'a> { ]) .build()?; - info!(id = request_id, url = req.url().as_str(), "request"); - let resp = self.endpoint.execute(req).await?; - if !resp.status().is_success() { - return Err(TransportError::HttpStatus(resp.status()).into()); - } - - let response: GetWakeComputeResponse = serde_json::from_str(&resp.text().await?)?; + let span = info_span!("http", id = request_id, url = req.url().as_str()); + info!(parent: &span, "request wake-up"); + let msg = self + .endpoint + .checked_execute(req) + .and_then(|r| r.json::()) + .await + .map_err(|e| { + error!(parent: &span, "{e}"); + e + })?; // Unfortunately, ownership won't let us use `Option::ok_or` here. - let (host, port) = match parse_host_port(&response.address) { - None => return Err(WakeComputeError::BadComputeAddress(response.address)), + let (host, port) = match parse_host_port(&msg.address) { + None => return Err(WakeComputeError::BadComputeAddress(msg.address)), Some(x) => x, }; diff --git a/proxy/src/auth/backend/link.rs b/proxy/src/auth/backend/link.rs index 863ed53645..c8ca418144 100644 --- a/proxy/src/auth/backend/link.rs +++ b/proxy/src/auth/backend/link.rs @@ -1,7 +1,7 @@ use crate::{auth, compute, error::UserFacingError, stream::PqStream, waiters}; use thiserror::Error; use tokio::io::{AsyncRead, AsyncWrite}; -use tracing::info; +use tracing::{info, info_span}; use utils::pq_proto::{BeMessage as Be, BeParameterStatusMessage}; #[derive(Debug, Error)] @@ -51,11 +51,12 @@ pub async fn handle_user( client: &mut PqStream, ) -> auth::Result { let psql_session_id = new_psql_session_id(); + let span = info_span!("link", psql_session_id = &psql_session_id); let greeting = hello_message(link_uri, &psql_session_id); let db_info = super::with_waiter(psql_session_id, |waiter| async { // Give user a URL to spawn a new database. - info!("sending the auth URL to the user"); + info!(parent: &span, "sending the auth URL to the user"); client .write_message_noflush(&Be::AuthenticationOk)? .write_message_noflush(&BeParameterStatusMessage::encoding())? @@ -63,7 +64,7 @@ pub async fn handle_user( .await?; // Wait for web console response (see `mgmt`). - info!("waiting for console's reply..."); + info!(parent: &span, "waiting for console's reply..."); waiter.await?.map_err(LinkAuthError::AuthFailed) }) .await?; diff --git a/proxy/src/http.rs b/proxy/src/http.rs index dbeb3dc784..6f9145678b 100644 --- a/proxy/src/http.rs +++ b/proxy/src/http.rs @@ -17,6 +17,7 @@ impl Endpoint { Self { endpoint, client } } + #[inline(always)] pub fn url(&self) -> &ApiUrl { &self.endpoint } @@ -36,6 +37,16 @@ impl Endpoint { ) -> Result { self.client.execute(request).await } + + /// Execute a [request](reqwest::Request) and raise an error if status != 200. + pub async fn checked_execute( + &self, + request: reqwest::Request, + ) -> Result { + self.execute(request) + .await + .and_then(|r| r.error_for_status()) + } } #[cfg(test)] diff --git a/proxy/src/proxy.rs b/proxy/src/proxy.rs index 5dcaa000cf..889445239a 100644 --- a/proxy/src/proxy.rs +++ b/proxy/src/proxy.rs @@ -1,7 +1,7 @@ use crate::auth; use crate::cancellation::{self, CancelMap}; use crate::config::{ProxyConfig, TlsConfig}; -use crate::stream::{MetricsStream, PqStream, Stream}; +use crate::stream::{MeasuredStream, PqStream, Stream}; use anyhow::{bail, Context}; use futures::TryFutureExt; use metrics::{register_int_counter, IntCounter}; @@ -64,7 +64,7 @@ pub async fn task_main( let cancel_map = Arc::new(CancelMap::default()); loop { let (socket, peer_addr) = listener.accept().await?; - info!("accepted connection from {peer_addr}"); + info!("accepted postgres client connection from {peer_addr}"); let session_id = uuid::Uuid::new_v4(); let cancel_map = Arc::clone(&cancel_map); @@ -270,8 +270,8 @@ impl Client<'_, S> { // Starting from here we only proxy the client's traffic. info!("performing the proxy pass..."); - let mut db = MetricsStream::new(db.stream, inc_proxied); - let mut client = MetricsStream::new(stream.into_inner(), inc_proxied); + let mut db = MeasuredStream::new(db.stream, inc_proxied); + let mut client = MeasuredStream::new(stream.into_inner(), inc_proxied); let _ = tokio::io::copy_bidirectional(&mut client, &mut db).await?; Ok(()) diff --git a/proxy/src/stream.rs b/proxy/src/stream.rs index 54ff8bcc07..2a224944e2 100644 --- a/proxy/src/stream.rs +++ b/proxy/src/stream.rs @@ -231,7 +231,7 @@ impl AsyncWrite for Stream { pin_project! { /// This stream tracks all writes and calls user provided /// callback when the underlying stream is flushed. - pub struct MetricsStream { + pub struct MeasuredStream { #[pin] stream: S, write_count: usize, @@ -239,7 +239,7 @@ pin_project! { } } -impl MetricsStream { +impl MeasuredStream { pub fn new(stream: S, inc_write_count: W) -> Self { Self { stream, @@ -249,7 +249,7 @@ impl MetricsStream { } } -impl AsyncRead for MetricsStream { +impl AsyncRead for MeasuredStream { fn poll_read( self: Pin<&mut Self>, context: &mut task::Context<'_>, @@ -259,7 +259,7 @@ impl AsyncRead for MetricsStream { } } -impl AsyncWrite for MetricsStream { +impl AsyncWrite for MeasuredStream { fn poll_write( self: Pin<&mut Self>, context: &mut task::Context<'_>, From 09dda35dacba832f49f13d481033e6d3b1857951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s?= Date: Wed, 12 Oct 2022 21:28:39 +0200 Subject: [PATCH 19/64] Return broken tenants due to non existing timelines dir (#2552) (#2575) Co-authored-by: andres --- pageserver/src/lib.rs | 58 -------- pageserver/src/storage_sync.rs | 34 +++-- pageserver/src/tenant_mgr.rs | 205 ++++++++++++++++------------ test_runner/regress/test_tenants.py | 19 ++- 4 files changed, 155 insertions(+), 161 deletions(-) diff --git a/pageserver/src/lib.rs b/pageserver/src/lib.rs index 7937f72de7..fe5114a247 100644 --- a/pageserver/src/lib.rs +++ b/pageserver/src/lib.rs @@ -119,32 +119,6 @@ impl TenantTimelineValues { fn new() -> Self { Self(HashMap::new()) } - - fn with_capacity(capacity: usize) -> Self { - Self(HashMap::with_capacity(capacity)) - } - - /// A convenience method to map certain values and omit some of them, if needed. - /// Tenants that won't have any timeline entries due to the filtering, will still be preserved - /// in the structure. - fn filter_map(self, map: F) -> TenantTimelineValues - where - F: Fn(T) -> Option, - { - let capacity = self.0.len(); - self.0.into_iter().fold( - TenantTimelineValues::::with_capacity(capacity), - |mut new_values, (tenant_id, old_values)| { - let new_timeline_values = new_values.0.entry(tenant_id).or_default(); - for (timeline_id, old_value) in old_values { - if let Some(new_value) = map(old_value) { - new_timeline_values.insert(timeline_id, new_value); - } - } - new_values - }, - ) - } } /// A suffix to be used during file sync from the remote storage, @@ -181,35 +155,3 @@ mod backoff_defaults_tests { ); } } - -#[cfg(test)] -mod tests { - use crate::tenant::harness::TIMELINE_ID; - - use super::*; - - #[test] - fn tenant_timeline_value_mapping() { - let first_tenant = TenantId::generate(); - let second_tenant = TenantId::generate(); - assert_ne!(first_tenant, second_tenant); - - let mut initial = TenantTimelineValues::new(); - initial - .0 - .entry(first_tenant) - .or_default() - .insert(TIMELINE_ID, "test_value"); - let _ = initial.0.entry(second_tenant).or_default(); - assert_eq!(initial.0.len(), 2, "Should have entries for both tenants"); - - let filtered = initial.filter_map(|_| None::<&str>).0; - assert_eq!( - filtered.len(), - 2, - "Should have entries for both tenants even after filtering away all entries" - ); - assert!(filtered.contains_key(&first_tenant)); - assert!(filtered.contains_key(&second_tenant)); - } -} diff --git a/pageserver/src/storage_sync.rs b/pageserver/src/storage_sync.rs index bee460d173..e8844baf5d 100644 --- a/pageserver/src/storage_sync.rs +++ b/pageserver/src/storage_sync.rs @@ -169,9 +169,14 @@ use self::{ upload::{upload_index_part, upload_timeline_layers, UploadedTimeline}, }; use crate::{ - config::PageServerConf, exponential_backoff, storage_sync::index::RemoteIndex, task_mgr, - task_mgr::TaskKind, task_mgr::BACKGROUND_RUNTIME, tenant::metadata::TimelineMetadata, - tenant_mgr::attach_local_tenants, + config::PageServerConf, + exponential_backoff, + storage_sync::index::RemoteIndex, + task_mgr, + task_mgr::TaskKind, + task_mgr::BACKGROUND_RUNTIME, + tenant::metadata::TimelineMetadata, + tenant_mgr::{attach_local_tenants, TenantAttachData}, }; use crate::{ metrics::{IMAGE_SYNC_TIME, REMAINING_SYNC_ITEMS, REMOTE_INDEX_UPLOAD}, @@ -572,7 +577,10 @@ pub fn schedule_layer_download(tenant_id: TenantId, timeline_id: TimelineId) { /// See module docs for loop step description. pub fn spawn_storage_sync_task( conf: &'static PageServerConf, - local_timeline_files: TenantTimelineValues<(TimelineMetadata, HashSet)>, + local_timeline_files: HashMap< + TenantId, + HashMap)>, + >, storage: GenericRemoteStorage, max_concurrent_timelines_sync: NonZeroUsize, max_sync_errors: NonZeroU32, @@ -595,7 +603,7 @@ pub fn spawn_storage_sync_task( let mut keys_for_index_part_downloads = HashSet::new(); let mut timelines_to_sync = HashMap::new(); - for (tenant_id, timeline_data) in local_timeline_files.0 { + for (tenant_id, timeline_data) in local_timeline_files { if timeline_data.is_empty() { info!("got empty tenant {}", tenant_id); let _ = empty_tenants.0.entry(tenant_id).or_default(); @@ -698,7 +706,7 @@ async fn storage_sync_loop( "Sync loop step completed, {} new tenant state update(s)", updated_tenants.len() ); - let mut timelines_to_attach = TenantTimelineValues::new(); + let mut timelines_to_attach = HashMap::new(); let index_accessor = index.read().await; for tenant_id in updated_tenants { let tenant_entry = match index_accessor.tenant_entry(&tenant_id) { @@ -724,12 +732,16 @@ async fn storage_sync_loop( // and register them all at once in a tenant for download // to be submitted in a single operation to tenant // so it can apply them at once to internal timeline map. - timelines_to_attach.0.insert( + timelines_to_attach.insert( tenant_id, - tenant_entry - .iter() - .map(|(&id, entry)| (id, entry.metadata.clone())) - .collect(), + TenantAttachData::Ready( + tenant_entry + .iter() + .map(|(&id, entry)| { + (id, (entry.metadata.clone(), HashSet::new())) + }) + .collect(), + ), ); } } diff --git a/pageserver/src/tenant_mgr.rs b/pageserver/src/tenant_mgr.rs index 0e8ee8c067..c6698ee22f 100644 --- a/pageserver/src/tenant_mgr.rs +++ b/pageserver/src/tenant_mgr.rs @@ -22,7 +22,7 @@ use crate::tenant::{ }; use crate::tenant_config::TenantConfOpt; use crate::walredo::PostgresRedoManager; -use crate::{TenantTimelineValues, TEMP_FILE_SUFFIX}; +use crate::TEMP_FILE_SUFFIX; use utils::crashsafe_dir::{self, path_with_suffix_extension}; use utils::id::{TenantId, TimelineId}; @@ -70,34 +70,54 @@ pub fn init_tenant_mgr( .remote_storage_config .as_ref() .expect("remote storage without config"); - + let mut broken_tenants = HashMap::new(); + let mut ready_tenants = HashMap::new(); + for (tenant_id, tenant_attach_data) in local_tenant_files.into_iter() { + match tenant_attach_data { + TenantAttachData::Ready(t) => { + ready_tenants.insert(tenant_id, t); + } + TenantAttachData::Broken(e) => { + broken_tenants.insert(tenant_id, TenantAttachData::Broken(e)); + } + } + } let SyncStartupData { remote_index, local_timeline_init_statuses, } = storage_sync::spawn_storage_sync_task( conf, - local_tenant_files, + ready_tenants, storage, storage_config.max_concurrent_syncs, storage_config.max_sync_errors, ) .context("Failed to spawn the storage sync thread")?; - ( - remote_index, - local_timeline_init_statuses.filter_map(|init_status| match init_status { - LocalTimelineInitStatus::LocallyComplete(metadata) => Some(metadata), - LocalTimelineInitStatus::NeedsSync => None, - }), - ) + let n = local_timeline_init_statuses.0.len(); + let mut synced_timelines = local_timeline_init_statuses.0.into_iter().fold( + HashMap::::with_capacity(n), + |mut new_values, (tenant_id, old_values)| { + let new_timeline_values = new_values + .entry(tenant_id) + .or_insert_with(|| TenantAttachData::Ready(HashMap::new())); + if let TenantAttachData::Ready(t) = new_timeline_values { + for (timeline_id, old_value) in old_values { + if let LocalTimelineInitStatus::LocallyComplete(metadata) = old_value { + t.insert(timeline_id, (metadata, HashSet::new())); + } + } + } + new_values + }, + ); + synced_timelines.extend(broken_tenants); + + (remote_index, synced_timelines) } else { info!("No remote storage configured, skipping storage sync, considering all local timelines with correct metadata files enabled"); - ( - RemoteIndex::default(), - local_tenant_files.filter_map(|(metadata, _)| Some(metadata)), - ) + (RemoteIndex::default(), local_tenant_files) }; - attach_local_tenants(conf, &remote_index, tenants_to_attach); Ok(remote_index) @@ -117,18 +137,12 @@ pub fn init_tenant_mgr( pub fn attach_local_tenants( conf: &'static PageServerConf, remote_index: &RemoteIndex, - tenants_to_attach: TenantTimelineValues, + tenants_to_attach: HashMap, ) { let _entered = info_span!("attach_local_tenants").entered(); - let number_of_tenants = tenants_to_attach.0.len(); - - for (tenant_id, local_timelines) in tenants_to_attach.0 { - info!( - "Attaching {} timelines for {tenant_id}", - local_timelines.len() - ); - debug!("Timelines to attach: {local_timelines:?}"); + let number_of_tenants = tenants_to_attach.len(); + for (tenant_id, local_timelines) in tenants_to_attach { let mut tenants_accessor = tenants_state::write_tenants(); let tenant = match tenants_accessor.entry(tenant_id) { hash_map::Entry::Occupied(o) => { @@ -137,25 +151,55 @@ pub fn attach_local_tenants( } hash_map::Entry::Vacant(v) => { info!("Tenant {tenant_id} was not found in pageserver's memory, loading it"); - let tenant = load_local_tenant(conf, tenant_id, remote_index); + let tenant = Arc::new(Tenant::new( + conf, + TenantConfOpt::default(), + Arc::new(PostgresRedoManager::new(conf, tenant_id)), + tenant_id, + remote_index.clone(), + conf.remote_storage_config.is_some(), + )); + match local_timelines { + TenantAttachData::Broken(_) => { + tenant.set_state(TenantState::Broken); + } + TenantAttachData::Ready(_) => { + match Tenant::load_tenant_config(conf, tenant_id) { + Ok(tenant_conf) => { + tenant.update_tenant_config(tenant_conf); + tenant.activate(false); + } + Err(e) => { + error!("Failed to read config for tenant {tenant_id}, disabling tenant: {e:?}"); + tenant.set_state(TenantState::Broken); + } + }; + } + } v.insert(Arc::clone(&tenant)); tenant } }; drop(tenants_accessor); - - if tenant.current_state() == TenantState::Broken { - warn!("Skipping timeline load for broken tenant {tenant_id}") - } else { - let has_timelines = !local_timelines.is_empty(); - match tenant.init_attach_timelines(local_timelines) { - Ok(()) => { - info!("successfully loaded local timelines for tenant {tenant_id}"); - tenant.activate(has_timelines); - } - Err(e) => { - error!("Failed to attach tenant timelines: {e:?}"); - tenant.set_state(TenantState::Broken); + match local_timelines { + TenantAttachData::Broken(e) => warn!("{}", e), + TenantAttachData::Ready(ref timelines) => { + info!("Attaching {} timelines for {tenant_id}", timelines.len()); + debug!("Timelines to attach: {local_timelines:?}"); + let has_timelines = !timelines.is_empty(); + let timelines_to_attach = timelines + .iter() + .map(|(&k, (v, _))| (k, v.clone())) + .collect(); + match tenant.init_attach_timelines(timelines_to_attach) { + Ok(()) => { + info!("successfully loaded local timelines for tenant {tenant_id}"); + tenant.activate(has_timelines); + } + Err(e) => { + error!("Failed to attach tenant timelines: {e:?}"); + tenant.set_state(TenantState::Broken); + } } } } @@ -164,44 +208,6 @@ pub fn attach_local_tenants( info!("Processed {number_of_tenants} local tenants during attach") } -fn load_local_tenant( - conf: &'static PageServerConf, - tenant_id: TenantId, - remote_index: &RemoteIndex, -) -> Arc { - let tenant = Arc::new(Tenant::new( - conf, - TenantConfOpt::default(), - Arc::new(PostgresRedoManager::new(conf, tenant_id)), - tenant_id, - remote_index.clone(), - conf.remote_storage_config.is_some(), - )); - - let tenant_timelines_dir = conf.timelines_path(&tenant_id); - if !tenant_timelines_dir.is_dir() { - error!( - "Tenant {} has no timelines directory at {}", - tenant_id, - tenant_timelines_dir.display() - ); - tenant.set_state(TenantState::Broken); - } else { - match Tenant::load_tenant_config(conf, tenant_id) { - Ok(tenant_conf) => { - tenant.update_tenant_config(tenant_conf); - tenant.activate(false); - } - Err(e) => { - error!("Failed to read config for tenant {tenant_id}, disabling tenant: {e:?}"); - tenant.set_state(TenantState::Broken); - } - } - } - - tenant -} - /// /// Shut down all tenants. This runs as part of pageserver shutdown. /// @@ -475,16 +481,21 @@ pub fn list_tenant_info(remote_index: &RemoteTimelineIndex) -> Vec { .collect() } +#[derive(Debug)] +pub enum TenantAttachData { + Ready(HashMap)>), + Broken(anyhow::Error), +} /// Attempts to collect information about all tenant and timelines, existing on the local FS. /// If finds any, deletes all temporary files and directories, created before. Also removes empty directories, /// that may appear due to such removals. /// Does not fail on particular timeline or tenant collection errors, rather logging them and ignoring the entities. fn local_tenant_timeline_files( config: &'static PageServerConf, -) -> anyhow::Result)>> { +) -> anyhow::Result> { let _entered = info_span!("local_tenant_timeline_files").entered(); - let mut local_tenant_timeline_files = TenantTimelineValues::new(); + let mut local_tenant_timeline_files = HashMap::new(); let tenants_dir = config.tenants_path(); for tenants_dir_entry in fs::read_dir(&tenants_dir) .with_context(|| format!("Failed to list tenants dir {}", tenants_dir.display()))? @@ -506,19 +517,31 @@ fn local_tenant_timeline_files( } } else { match collect_timelines_for_tenant(config, &tenant_dir_path) { - Ok((tenant_id, collected_files)) => { + Ok((tenant_id, TenantAttachData::Broken(e))) => { + local_tenant_timeline_files.entry(tenant_id).or_insert(TenantAttachData::Broken(e)); + }, + Ok((tenant_id, TenantAttachData::Ready(collected_files))) => { if collected_files.is_empty() { match remove_if_empty(&tenant_dir_path) { Ok(true) => info!("Removed empty tenant directory {}", tenant_dir_path.display()), Ok(false) => { // insert empty timeline entry: it has some non-temporary files inside that we cannot remove // so make obvious for HTTP API callers, that something exists there and try to load the tenant - let _ = local_tenant_timeline_files.0.entry(tenant_id).or_default(); + let _ = local_tenant_timeline_files.entry(tenant_id).or_insert_with(|| TenantAttachData::Ready(HashMap::new())); }, Err(e) => error!("Failed to remove empty tenant directory: {e:?}"), } } else { - local_tenant_timeline_files.0.entry(tenant_id).or_default().extend(collected_files.into_iter()) + match local_tenant_timeline_files.entry(tenant_id) { + hash_map::Entry::Vacant(entry) => { + entry.insert(TenantAttachData::Ready(collected_files)); + } + hash_map::Entry::Occupied(entry) =>{ + if let TenantAttachData::Ready(old_timelines) = entry.into_mut() { + old_timelines.extend(collected_files); + } + }, + } } }, Err(e) => error!( @@ -541,7 +564,7 @@ fn local_tenant_timeline_files( info!( "Collected files for {} tenants", - local_tenant_timeline_files.0.len() + local_tenant_timeline_files.len(), ); Ok(local_tenant_timeline_files) } @@ -583,10 +606,7 @@ fn is_temporary(path: &Path) -> bool { fn collect_timelines_for_tenant( config: &'static PageServerConf, tenant_path: &Path, -) -> anyhow::Result<( - TenantId, - HashMap)>, -)> { +) -> anyhow::Result<(TenantId, TenantAttachData)> { let tenant_id = tenant_path .file_name() .and_then(OsStr::to_str) @@ -595,6 +615,17 @@ fn collect_timelines_for_tenant( .context("Could not parse tenant id out of the tenant dir name")?; let timelines_dir = config.timelines_path(&tenant_id); + if !timelines_dir.as_path().is_dir() { + return Ok(( + tenant_id, + TenantAttachData::Broken(anyhow::anyhow!( + "Tenant {} has no timelines directory at {}", + tenant_id, + timelines_dir.display() + )), + )); + } + let mut tenant_timelines = HashMap::new(); for timelines_dir_entry in fs::read_dir(&timelines_dir) .with_context(|| format!("Failed to list timelines dir entry for tenant {tenant_id}"))? @@ -652,7 +683,7 @@ fn collect_timelines_for_tenant( debug!("Tenant {tenant_id} has no timelines loaded"); } - Ok((tenant_id, tenant_timelines)) + Ok((tenant_id, TenantAttachData::Ready(tenant_timelines))) } // discover timeline files and extract timeline metadata diff --git a/test_runner/regress/test_tenants.py b/test_runner/regress/test_tenants.py index f49b6fccb9..37c5a130e2 100644 --- a/test_runner/regress/test_tenants.py +++ b/test_runner/regress/test_tenants.py @@ -258,11 +258,20 @@ def test_pageserver_with_empty_tenants( tenants = client.tenant_list() assert ( - len(tenants) == 1 - ), "Pageserver should attach only tenants with empty timelines/ dir on restart" - loaded_tenant = tenants[0] - assert loaded_tenant["id"] == str( - tenant_with_empty_timelines_dir + len(tenants) == 2 + ), "Pageserver should attach only tenants with empty or not existing timelines/ dir on restart" + + [broken_tenant] = [t for t in tenants if t["id"] == str(tenant_without_timelines_dir)] + assert ( + broken_tenant + ), f"A broken tenant {tenant_without_timelines_dir} should exists in the tenant list" + assert ( + broken_tenant["state"] == "Broken" + ), f"Tenant {tenant_without_timelines_dir} without timelines dir should be broken" + + [loaded_tenant] = [t for t in tenants if t["id"] == str(tenant_with_empty_timelines_dir)] + assert ( + loaded_tenant ), f"Tenant {tenant_with_empty_timelines_dir} should be loaded as the only one with tenants/ directory" assert loaded_tenant["state"] == { "Active": {"background_jobs_running": False} From ebf54b0de0b42d3b5e1460b1241025297cc8d0ee Mon Sep 17 00:00:00 2001 From: Alexander Bayandin Date: Thu, 13 Oct 2022 10:00:29 +0100 Subject: [PATCH 20/64] Nightly Benchmarks: Add 50 GB projects (#2612) --- .github/workflows/benchmarking.yml | 38 +++++++++++++++++------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/.github/workflows/benchmarking.yml b/.github/workflows/benchmarking.yml index dee5968ef3..6091c8d7ff 100644 --- a/.github/workflows/benchmarking.yml +++ b/.github/workflows/benchmarking.yml @@ -138,22 +138,31 @@ jobs: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} pgbench-compare: - env: - TEST_PG_BENCH_DURATIONS_MATRIX: "60m" - TEST_PG_BENCH_SCALES_MATRIX: "10gb" - POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install - DEFAULT_PG_VERSION: 14 - TEST_OUTPUT: /tmp/test_output - BUILD_TYPE: remote - SAVE_PERF_REPORT: ${{ github.event.inputs.save_perf_report || ( github.ref == 'refs/heads/main' ) }} - strategy: fail-fast: false matrix: # neon-captest-new: Run pgbench in a freshly created project # neon-captest-reuse: Same, but reusing existing project # neon-captest-prefetch: Same, with prefetching enabled (new project) - platform: [ neon-captest-new, neon-captest-reuse, neon-captest-prefetch, rds-aurora ] + platform: [ neon-captest-new, neon-captest-reuse, neon-captest-prefetch ] + db_size: [ 10gb ] + include: + - platform: neon-captest-new + db_size: 50gb + - platform: neon-captest-prefetch + db_size: 50gb + - platform: rds-aurora + db_size: 50gb + + env: + TEST_PG_BENCH_DURATIONS_MATRIX: "60m" + TEST_PG_BENCH_SCALES_MATRIX: ${{ matrix.db_size }} + POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install + DEFAULT_PG_VERSION: 14 + TEST_OUTPUT: /tmp/test_output + BUILD_TYPE: remote + SAVE_PERF_REPORT: ${{ github.event.inputs.save_perf_report || ( github.ref == 'refs/heads/main' ) }} + PLATFORM: ${{ matrix.platform }} runs-on: dev container: @@ -178,7 +187,7 @@ jobs: echo "${POSTGRES_DISTRIB_DIR}/v${DEFAULT_PG_VERSION}/bin" >> $GITHUB_PATH - name: Create Neon Project - if: matrix.platform != 'neon-captest-reuse' + if: contains(fromJson('["neon-captest-new", "neon-captest-prefetch"]'), matrix.platform) id: create-neon-project uses: ./.github/actions/neon-project-create with: @@ -207,8 +216,6 @@ jobs: echo "connstr=${CONNSTR}" >> $GITHUB_OUTPUT psql ${CONNSTR} -c "SELECT version();" - env: - PLATFORM: ${{ matrix.platform }} - name: Set database options if: matrix.platform == 'neon-captest-prefetch' @@ -227,7 +234,6 @@ jobs: save_perf_report: ${{ env.SAVE_PERF_REPORT }} extra_params: -m remote_cluster --timeout 21600 -k test_pgbench_remote_init env: - PLATFORM: ${{ matrix.platform }} BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }} VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}" PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}" @@ -241,7 +247,6 @@ jobs: save_perf_report: ${{ env.SAVE_PERF_REPORT }} extra_params: -m remote_cluster --timeout 21600 -k test_pgbench_remote_simple_update env: - PLATFORM: ${{ matrix.platform }} BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }} VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}" PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}" @@ -255,7 +260,6 @@ jobs: save_perf_report: ${{ env.SAVE_PERF_REPORT }} extra_params: -m remote_cluster --timeout 21600 -k test_pgbench_remote_select_only env: - PLATFORM: ${{ matrix.platform }} BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }} VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}" PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}" @@ -268,7 +272,7 @@ jobs: build_type: ${{ env.BUILD_TYPE }} - name: Delete Neon Project - if: ${{ matrix.platform != 'neon-captest-reuse' && always() }} + if: ${{ steps.create-neon-project.outputs.project_id && always() }} uses: ./.github/actions/neon-project-delete with: environment: dev From 14c623b254457f1dd4e1b0a64782cf5f568176bf Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 13 Oct 2022 13:54:15 +0300 Subject: [PATCH 21/64] Make it possible to build with old cargo version. I'm using the Rust compiler and cargo versions from Debian packages, but the latest available cargo Debian package is quite old, version 1.57. The 'named-profiles' features was not stabilized at that version yet, so ever since commit a463749f5, I've had to manually add this line to the Cargo.toml file to compile. I've been wishing that someone would update the cargo Debian package, but it doesn't seem to be happening any time soon. This doesn't seem to bother anyone else but me, but it shouldn't hurt anyone else either. If there was a good reason, I could install a newer cargo version with 'rustup', but if all we need is this one line in Cargo.toml, I'd prefer to continue using the Debian packages. --- Cargo.toml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index bc2a705558..32c243bf44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,14 @@ +# 'named-profiles' feature was stabilized in cargo 1.57. This line makes the +# build work with older cargo versions. +# +# We have this because as of this writing, the latest cargo Debian package +# that's available is 1.56. (Confusingly, the Debian package version number +# is 0.57, whereas 'cargo --version' says 1.56.) +# +# See https://tracker.debian.org/pkg/cargo for the current status of the +# package. When that gets updated, we can remove this. +cargo-features = ["named-profiles"] + [workspace] members = [ "compute_tools", From 9fe4548e13774d7f1e5f9b5d23e57da971419442 Mon Sep 17 00:00:00 2001 From: Arseny Sher Date: Wed, 12 Oct 2022 18:14:02 +0400 Subject: [PATCH 22/64] Reimplement explicit timeline creation on safekeepers. With the ability to pass commit_lsn. This allows to perform project WAL recovery through different (from the original) set of safekeepers (or under different ttid) by 1) moving WAL files to s3 under proper ttid; 2) explicitly creating timeline on safekeepers, setting commit_lsn to the latest point; 3) putting the lastest .parital file to the timeline directory on safekeepers, if desired. Extend test_s3_wal_replay to exersise this behaviour. Also extends timeline_status endpoint to return postgres information. --- control_plane/src/safekeeper.rs | 27 +--- libs/safekeeper_api/src/models.rs | 17 ++- libs/utils/src/lsn.rs | 5 + pgxn/neon/walproposer.c | 6 - safekeeper/src/http/routes.rs | 28 ++++- safekeeper/src/json_ctrl.rs | 2 + safekeeper/src/receive_wal.rs | 3 +- safekeeper/src/safekeeper.rs | 15 ++- safekeeper/src/timeline.rs | 15 ++- safekeeper/src/timelines_global_map.rs | 13 +- test_runner/fixtures/neon_fixtures.py | 14 +++ test_runner/regress/test_wal_acceptor.py | 152 +++++++++++++++-------- 12 files changed, 195 insertions(+), 102 deletions(-) diff --git a/control_plane/src/safekeeper.rs b/control_plane/src/safekeeper.rs index 34b2f3000a..64a89124d2 100644 --- a/control_plane/src/safekeeper.rs +++ b/control_plane/src/safekeeper.rs @@ -12,13 +12,8 @@ use nix::unistd::Pid; use postgres::Config; use reqwest::blocking::{Client, RequestBuilder, Response}; use reqwest::{IntoUrl, Method}; -use safekeeper_api::models::TimelineCreateRequest; use thiserror::Error; -use utils::{ - connstring::connection_address, - http::error::HttpErrorBody, - id::{NodeId, TenantId, TimelineId}, -}; +use utils::{connstring::connection_address, http::error::HttpErrorBody, id::NodeId}; use crate::local_env::{LocalEnv, SafekeeperConf}; use crate::storage::PageServerNode; @@ -281,24 +276,4 @@ impl SafekeeperNode { .error_from_body()?; Ok(()) } - - pub fn timeline_create( - &self, - tenant_id: TenantId, - timeline_id: TimelineId, - peer_ids: Vec, - ) -> Result<()> { - Ok(self - .http_request( - Method::POST, - format!("{}/tenant/{}/timeline", self.http_base_url, tenant_id), - ) - .json(&TimelineCreateRequest { - timeline_id, - peer_ids, - }) - .send()? - .error_from_body()? - .json()?) - } } diff --git a/libs/safekeeper_api/src/models.rs b/libs/safekeeper_api/src/models.rs index e13ea50eaf..4119650b99 100644 --- a/libs/safekeeper_api/src/models.rs +++ b/libs/safekeeper_api/src/models.rs @@ -1,8 +1,21 @@ use serde::{Deserialize, Serialize}; -use utils::id::{NodeId, TimelineId}; +use utils::{ + id::{NodeId, TenantId, TimelineId}, + lsn::Lsn, +}; #[derive(Serialize, Deserialize)] pub struct TimelineCreateRequest { + #[serde(with = "serde_with::rust::display_fromstr")] + pub tenant_id: TenantId, + #[serde(with = "serde_with::rust::display_fromstr")] pub timeline_id: TimelineId, - pub peer_ids: Vec, + pub peer_ids: Option>, + pub pg_version: u32, + pub system_id: Option, + pub wal_seg_size: Option, + #[serde(with = "serde_with::rust::display_fromstr")] + pub commit_lsn: Lsn, + // If not passed, it is assigned to the beginning of commit_lsn segment. + pub local_start_lsn: Option, } diff --git a/libs/utils/src/lsn.rs b/libs/utils/src/lsn.rs index 1090f4c679..289cec12a8 100644 --- a/libs/utils/src/lsn.rs +++ b/libs/utils/src/lsn.rs @@ -66,6 +66,11 @@ impl Lsn { (self.0 % seg_sz as u64) as usize } + /// Compute LSN of the segment start. + pub fn segment_lsn(self, seg_sz: usize) -> Lsn { + Lsn(self.0 - (self.0 % seg_sz as u64)) + } + /// Compute the segment number pub fn segment_number(self, seg_sz: usize) -> u64 { self.0 / seg_sz as u64 diff --git a/pgxn/neon/walproposer.c b/pgxn/neon/walproposer.c index fc0b660a64..ff37be2de1 100644 --- a/pgxn/neon/walproposer.c +++ b/pgxn/neon/walproposer.c @@ -1471,12 +1471,6 @@ SendProposerElected(Safekeeper *sk) */ th = &sk->voteResponse.termHistory; - /* - * If any WAL is present on the sk, it must be authorized by some term. - * OTOH, without any WAL there are no term swiches in the log. - */ - Assert((th->n_entries == 0) == - (sk->voteResponse.flushLsn == InvalidXLogRecPtr)); /* We must start somewhere. */ Assert(propTermHistory.n_entries >= 1); diff --git a/safekeeper/src/http/routes.rs b/safekeeper/src/http/routes.rs index 43c0a17f84..6efd09c7e2 100644 --- a/safekeeper/src/http/routes.rs +++ b/safekeeper/src/http/routes.rs @@ -1,8 +1,8 @@ -use anyhow::anyhow; use hyper::{Body, Request, Response, StatusCode, Uri}; use anyhow::Context; use once_cell::sync::Lazy; +use postgres_ffi::WAL_SEGMENT_SIZE; use serde::Serialize; use serde::Serializer; use std::collections::{HashMap, HashSet}; @@ -10,6 +10,7 @@ use std::fmt::Display; use std::sync::Arc; use tokio::task::JoinError; +use crate::safekeeper::ServerInfo; use crate::safekeeper::Term; use crate::safekeeper::TermHistory; @@ -77,6 +78,7 @@ struct TimelineStatus { #[serde(serialize_with = "display_serialize")] timeline_id: TimelineId, acceptor_state: AcceptorStateStatus, + pg_info: ServerInfo, #[serde(serialize_with = "display_serialize")] flush_lsn: Lsn, #[serde(serialize_with = "display_serialize")] @@ -121,6 +123,7 @@ async fn timeline_status_handler(request: Request) -> Result) -> Result Result ReceiveWalConn<'pg> { system_id: greeting.system_id, wal_seg_size: greeting.wal_seg_size, }; - GlobalTimelines::create(spg.ttid, server_info)? + GlobalTimelines::create(spg.ttid, server_info, Lsn::INVALID, Lsn::INVALID)? } _ => bail!("unexpected message {:?} instead of greeting", next_msg), }; diff --git a/safekeeper/src/safekeeper.rs b/safekeeper/src/safekeeper.rs index 7869aa8b3a..7b11aaf92a 100644 --- a/safekeeper/src/safekeeper.rs +++ b/safekeeper/src/safekeeper.rs @@ -222,6 +222,8 @@ impl SafeKeeperState { ttid: &TenantTimelineId, server_info: ServerInfo, peers: Vec, + commit_lsn: Lsn, + local_start_lsn: Lsn, ) -> SafeKeeperState { SafeKeeperState { tenant_id: ttid.tenant_id, @@ -233,10 +235,10 @@ impl SafeKeeperState { server: server_info, proposer_uuid: [0; 16], timeline_start_lsn: Lsn(0), - local_start_lsn: Lsn(0), - commit_lsn: Lsn(0), - backup_lsn: Lsn::INVALID, - peer_horizon_lsn: Lsn(0), + local_start_lsn, + commit_lsn, + backup_lsn: local_start_lsn, + peer_horizon_lsn: local_start_lsn, remote_consistent_lsn: Lsn(0), peers: Peers(peers.iter().map(|p| (*p, PeerInfo::new())).collect()), } @@ -252,6 +254,8 @@ impl SafeKeeperState { wal_seg_size: 0, }, vec![], + Lsn::INVALID, + Lsn::INVALID, ) } } @@ -740,7 +744,8 @@ where "setting timeline_start_lsn to {:?}", state.timeline_start_lsn ); - + } + if state.local_start_lsn == Lsn(0) { state.local_start_lsn = msg.start_streaming_at; info!("setting local_start_lsn to {:?}", state.local_start_lsn); } diff --git a/safekeeper/src/timeline.rs b/safekeeper/src/timeline.rs index dc7503af65..3fb77bf582 100644 --- a/safekeeper/src/timeline.rs +++ b/safekeeper/src/timeline.rs @@ -107,6 +107,14 @@ impl SharedState { bail!(TimelineError::UninitialinzedPgVersion(*ttid)); } + if state.commit_lsn < state.local_start_lsn { + bail!( + "commit_lsn {} is higher than local_start_lsn {}", + state.commit_lsn, + state.local_start_lsn + ); + } + // We don't want to write anything to disk, because we may have existing timeline there. // These functions should not change anything on disk. let control_store = control_file::FileStorage::create_new(ttid, conf, state)?; @@ -286,7 +294,7 @@ pub struct Timeline { /// Sending here asks for wal backup launcher attention (start/stop /// offloading). Sending ttid instead of concrete command allows to do /// sending without timeline lock. - wal_backup_launcher_tx: Sender, + pub wal_backup_launcher_tx: Sender, /// Used to broadcast commit_lsn updates to all background jobs. commit_lsn_watch_tx: watch::Sender, @@ -339,10 +347,12 @@ impl Timeline { ttid: TenantTimelineId, wal_backup_launcher_tx: Sender, server_info: ServerInfo, + commit_lsn: Lsn, + local_start_lsn: Lsn, ) -> Result { let (commit_lsn_watch_tx, commit_lsn_watch_rx) = watch::channel(Lsn::INVALID); let (cancellation_tx, cancellation_rx) = watch::channel(false); - let state = SafeKeeperState::new(&ttid, server_info, vec![]); + let state = SafeKeeperState::new(&ttid, server_info, vec![], commit_lsn, local_start_lsn); Ok(Timeline { ttid, @@ -381,6 +391,7 @@ impl Timeline { match || -> Result<()> { shared_state.sk.persist()?; // TODO: add more initialization steps here + shared_state.update_status(self.ttid); Ok(()) }() { Ok(_) => Ok(()), diff --git a/safekeeper/src/timelines_global_map.rs b/safekeeper/src/timelines_global_map.rs index cf99a243d7..a5d373a1da 100644 --- a/safekeeper/src/timelines_global_map.rs +++ b/safekeeper/src/timelines_global_map.rs @@ -15,6 +15,7 @@ use std::sync::{Arc, Mutex, MutexGuard}; use tokio::sync::mpsc::Sender; use tracing::*; use utils::id::{TenantId, TenantTimelineId, TimelineId}; +use utils::lsn::Lsn; struct GlobalTimelinesState { timelines: HashMap>, @@ -153,7 +154,12 @@ impl GlobalTimelines { /// Create a new timeline with the given id. If the timeline already exists, returns /// an existing timeline. - pub fn create(ttid: TenantTimelineId, server_info: ServerInfo) -> Result> { + pub fn create( + ttid: TenantTimelineId, + server_info: ServerInfo, + commit_lsn: Lsn, + local_start_lsn: Lsn, + ) -> Result> { let (conf, wal_backup_launcher_tx) = { let state = TIMELINES_STATE.lock().unwrap(); if let Ok(timeline) = state.get(&ttid) { @@ -170,6 +176,8 @@ impl GlobalTimelines { ttid, wal_backup_launcher_tx, server_info, + commit_lsn, + local_start_lsn, )?); // Take a lock and finish the initialization holding this mutex. No other threads @@ -190,6 +198,9 @@ impl GlobalTimelines { Ok(_) => { // We are done with bootstrap, release the lock, return the timeline. drop(shared_state); + timeline + .wal_backup_launcher_tx + .blocking_send(timeline.ttid)?; Ok(timeline) } Err(e) => { diff --git a/test_runner/fixtures/neon_fixtures.py b/test_runner/fixtures/neon_fixtures.py index 5df0f5cc50..0d6b6f4cd7 100644 --- a/test_runner/fixtures/neon_fixtures.py +++ b/test_runner/fixtures/neon_fixtures.py @@ -2339,6 +2339,7 @@ class Safekeeper: @dataclass class SafekeeperTimelineStatus: acceptor_epoch: int + pg_version: int flush_lsn: Lsn timeline_start_lsn: Lsn backup_lsn: Lsn @@ -2367,6 +2368,18 @@ class SafekeeperHttpClient(requests.Session): def check_status(self): self.get(f"http://localhost:{self.port}/v1/status").raise_for_status() + def timeline_create( + self, tenant_id: TenantId, timeline_id: TimelineId, pg_version: int, commit_lsn: Lsn + ): + body = { + "tenant_id": str(tenant_id), + "timeline_id": str(timeline_id), + "pg_version": pg_version, + "commit_lsn": str(commit_lsn), + } + res = self.post(f"http://localhost:{self.port}/v1/tenant/timeline", json=body) + res.raise_for_status() + def timeline_status( self, tenant_id: TenantId, timeline_id: TimelineId ) -> SafekeeperTimelineStatus: @@ -2375,6 +2388,7 @@ class SafekeeperHttpClient(requests.Session): resj = res.json() return SafekeeperTimelineStatus( acceptor_epoch=resj["acceptor_state"]["epoch"], + pg_version=resj["pg_info"]["pg_version"], flush_lsn=Lsn(resj["flush_lsn"]), timeline_start_lsn=Lsn(resj["timeline_start_lsn"]), backup_lsn=Lsn(resj["backup_lsn"]), diff --git a/test_runner/regress/test_wal_acceptor.py b/test_runner/regress/test_wal_acceptor.py index 1f9a0157fc..9c8e66e0e2 100644 --- a/test_runner/regress/test_wal_acceptor.py +++ b/test_runner/regress/test_wal_acceptor.py @@ -1,6 +1,7 @@ import os import pathlib import random +import shutil import signal import subprocess import sys @@ -8,6 +9,7 @@ import threading import time from contextlib import closing from dataclasses import dataclass, field +from functools import partial from pathlib import Path from typing import Any, List, Optional @@ -371,51 +373,48 @@ def test_wal_removal(neon_env_builder: NeonEnvBuilder, auth_enabled: bool): ) # wait till first segment is removed on all safekeepers + wait( + lambda first_segments=first_segments: all(not os.path.exists(p) for p in first_segments), + "first segment get removed", + ) + + +# Wait for something, defined as f() returning True, raising error if this +# doesn't happen without timeout seconds. +def wait(f, desc, timeout=30): started_at = time.time() while True: - if all(not os.path.exists(p) for p in first_segments): + if f(): break elapsed = time.time() - started_at - if elapsed > 20: - raise RuntimeError(f"timed out waiting {elapsed:.0f}s for first segment get removed") + if elapsed > timeout: + raise RuntimeError(f"timed out waiting {elapsed:.0f}s for {desc}") time.sleep(0.5) -def wait_segment_offload(tenant_id, timeline_id, live_sk, seg_end: Lsn): - started_at = time.time() - http_cli = live_sk.http_client() - while True: - tli_status = http_cli.timeline_status(tenant_id, timeline_id) - log.info(f"live sk status is {tli_status}") - - if tli_status.backup_lsn >= seg_end: - break - elapsed = time.time() - started_at - if elapsed > 30: - raise RuntimeError( - f"timed out waiting {elapsed:.0f}s for segment ending at {seg_end} get offloaded" - ) - time.sleep(0.5) - - -def wait_wal_trim(tenant_id, timeline_id, sk, target_size_mb): - started_at = time.time() +def is_segment_offloaded( + sk: Safekeeper, tenant_id: TenantId, timeline_id: TimelineId, seg_end: Lsn +): http_cli = sk.http_client() - while True: - tli_status = http_cli.timeline_status(tenant_id, timeline_id) - sk_wal_size = get_dir_size(os.path.join(sk.data_dir(), str(tenant_id), str(timeline_id))) - sk_wal_size_mb = sk_wal_size / 1024 / 1024 - log.info(f"Safekeeper id={sk.id} wal_size={sk_wal_size_mb:.2f}MB status={tli_status}") + tli_status = http_cli.timeline_status(tenant_id, timeline_id) + log.info(f"sk status is {tli_status}") + return tli_status.backup_lsn >= seg_end - if sk_wal_size_mb <= target_size_mb: - break - elapsed = time.time() - started_at - if elapsed > 20: - raise RuntimeError( - f"timed out waiting {elapsed:.0f}s for sk_id={sk.id} to trim WAL to {target_size_mb:.2f}MB, current size is {sk_wal_size_mb:.2f}MB" - ) - time.sleep(0.5) +def is_flush_lsn_caught_up(sk: Safekeeper, tenant_id: TenantId, timeline_id: TimelineId, lsn: Lsn): + http_cli = sk.http_client() + tli_status = http_cli.timeline_status(tenant_id, timeline_id) + log.info(f"sk status is {tli_status}") + return tli_status.flush_lsn >= lsn + + +def is_wal_trimmed(sk: Safekeeper, tenant_id: TenantId, timeline_id: TimelineId, target_size_mb): + http_cli = sk.http_client() + tli_status = http_cli.timeline_status(tenant_id, timeline_id) + sk_wal_size = get_dir_size(os.path.join(sk.data_dir(), str(tenant_id), str(timeline_id))) + sk_wal_size_mb = sk_wal_size / 1024 / 1024 + log.info(f"Safekeeper id={sk.id} wal_size={sk_wal_size_mb:.2f}MB status={tli_status}") + return sk_wal_size_mb <= target_size_mb @pytest.mark.parametrize("remote_storage_kind", available_remote_storages()) @@ -451,7 +450,10 @@ def test_wal_backup(neon_env_builder: NeonEnvBuilder, remote_storage_kind: Remot cur.execute("insert into t select generate_series(1,250000), 'payload'") live_sk = [sk for sk in env.safekeepers if sk != victim][0] - wait_segment_offload(tenant_id, timeline_id, live_sk, seg_end) + wait( + partial(is_segment_offloaded, live_sk, tenant_id, timeline_id, seg_end), + f"segment ending at {seg_end} get offloaded", + ) victim.start() @@ -463,7 +465,11 @@ def test_wal_backup(neon_env_builder: NeonEnvBuilder, remote_storage_kind: Remot with closing(pg.connect()) as conn: with conn.cursor() as cur: cur.execute("insert into t select generate_series(1,250000), 'payload'") - wait_segment_offload(tenant_id, timeline_id, env.safekeepers[1], Lsn("0/5000000")) + seg_end = Lsn("0/5000000") + wait( + partial(is_segment_offloaded, env.safekeepers[1], tenant_id, timeline_id, seg_end), + f"segment ending at {seg_end} get offloaded", + ) @pytest.mark.parametrize("remote_storage_kind", available_remote_storages()) @@ -494,38 +500,72 @@ def test_s3_wal_replay(neon_env_builder: NeonEnvBuilder, remote_storage_kind: Re cur.execute("insert into t values (1, 'payload')") expected_sum += 1 - offloaded_seg_end = [Lsn("0/3000000")] - for seg_end in offloaded_seg_end: - # roughly fills two segments - cur.execute("insert into t select generate_series(1,500000), 'payload'") - expected_sum += 500000 * 500001 // 2 + offloaded_seg_end = Lsn("0/3000000") + # roughly fills two segments + cur.execute("insert into t select generate_series(1,500000), 'payload'") + expected_sum += 500000 * 500001 // 2 - assert query_scalar(cur, "select sum(key) from t") == expected_sum + assert query_scalar(cur, "select sum(key) from t") == expected_sum - for sk in env.safekeepers: - wait_segment_offload(tenant_id, timeline_id, sk, seg_end) + for sk in env.safekeepers: + wait( + partial(is_segment_offloaded, sk, tenant_id, timeline_id, offloaded_seg_end), + f"segment ending at {offloaded_seg_end} get offloaded", + ) # advance remote_consistent_lsn to trigger WAL trimming # this LSN should be less than commit_lsn, so timeline will be active=true in safekeepers, to push etcd updates env.safekeepers[0].http_client().record_safekeeper_info( - tenant_id, timeline_id, {"remote_consistent_lsn": str(offloaded_seg_end[-1])} + tenant_id, timeline_id, {"remote_consistent_lsn": str(offloaded_seg_end)} ) + last_lsn = Lsn(query_scalar(cur, "SELECT pg_current_wal_flush_lsn()")) + for sk in env.safekeepers: # require WAL to be trimmed, so no more than one segment is left on disk - wait_wal_trim(tenant_id, timeline_id, sk, 16 * 1.5) - - last_lsn = query_scalar(cur, "SELECT pg_current_wal_flush_lsn()") + target_size_mb = 16 * 1.5 + wait( + partial(is_wal_trimmed, sk, tenant_id, timeline_id, target_size_mb), + f"sk_id={sk.id} to trim WAL to {target_size_mb:.2f}MB", + ) + # wait till everyone puts data up to last_lsn on disk, we are + # going to recreate state on safekeepers claiming they have data till last_lsn. + wait( + partial(is_flush_lsn_caught_up, sk, tenant_id, timeline_id, last_lsn), + f"sk_id={sk.id} to flush {last_lsn}", + ) ps_cli = env.pageserver.http_client() - pageserver_lsn = ps_cli.timeline_detail(tenant_id, timeline_id)["local"]["last_record_lsn"] - lag = Lsn(last_lsn) - Lsn(pageserver_lsn) + pageserver_lsn = Lsn(ps_cli.timeline_detail(tenant_id, timeline_id)["local"]["last_record_lsn"]) + lag = last_lsn - pageserver_lsn log.info( f"Pageserver last_record_lsn={pageserver_lsn}; flush_lsn={last_lsn}; lag before replay is {lag / 1024}kb" ) pg.stop_and_destroy() + # Also delete and manually create timeline on safekeepers -- this tests + # scenario of manual recovery on different set of safekeepers. + + # save the last (partial) file to put it back after recreation; others will be fetched from s3 + sk = env.safekeepers[0] + tli_dir = Path(sk.data_dir()) / str(tenant_id) / str(timeline_id) + f_partial = Path([f for f in os.listdir(tli_dir) if f.endswith(".partial")][0]) + f_partial_path = tli_dir / f_partial + f_partial_saved = Path(sk.data_dir()) / f_partial.name + f_partial_path.rename(f_partial_saved) + + pg_version = sk.http_client().timeline_status(tenant_id, timeline_id).pg_version + + for sk in env.safekeepers: + cli = sk.http_client() + cli.timeline_delete_force(tenant_id, timeline_id) + cli.timeline_create(tenant_id, timeline_id, pg_version, last_lsn) + f_partial_path = ( + Path(sk.data_dir()) / str(tenant_id) / str(timeline_id) / f_partial_saved.name + ) + shutil.copy(f_partial_saved, f_partial_path) + # recreate timeline on pageserver from scratch ps_cli.timeline_delete(tenant_id, timeline_id) ps_cli.timeline_create(tenant_id, timeline_id) @@ -539,10 +579,12 @@ def test_s3_wal_replay(neon_env_builder: NeonEnvBuilder, remote_storage_kind: Re if elapsed > wait_lsn_timeout: raise RuntimeError("Timed out waiting for WAL redo") - pageserver_lsn = env.pageserver.http_client().timeline_detail(tenant_id, timeline_id)[ - "local" - ]["last_record_lsn"] - lag = Lsn(last_lsn) - Lsn(pageserver_lsn) + pageserver_lsn = Lsn( + env.pageserver.http_client().timeline_detail(tenant_id, timeline_id)["local"][ + "last_record_lsn" + ] + ) + lag = last_lsn - pageserver_lsn if time.time() > last_debug_print + 10 or lag <= 0: last_debug_print = time.time() From a13b48694362df10546434c94b843165139a786f Mon Sep 17 00:00:00 2001 From: Anastasia Lubennikova Date: Fri, 14 Oct 2022 10:37:30 +0300 Subject: [PATCH 23/64] Bump vendor/postgres-v15. Rebase to 15.0 --- vendor/postgres-v15 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/postgres-v15 b/vendor/postgres-v15 index ff18cec1ee..339f2d642d 160000 --- a/vendor/postgres-v15 +++ b/vendor/postgres-v15 @@ -1 +1 @@ -Subproject commit ff18cec1ee9b80055accd9c76b040875329b11ed +Subproject commit 339f2d642d7d430c44839f8293ae271f90e3cb81 From ee64a6b80b1413612630161f0500bdfe44a52db5 Mon Sep 17 00:00:00 2001 From: Anastasia Lubennikova Date: Fri, 14 Oct 2022 17:11:14 +0300 Subject: [PATCH 24/64] Fix CI: push versioned compute images to production ECR --- .github/workflows/build_and_test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 2c6aa02b22..69b17113ed 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -622,6 +622,8 @@ jobs: crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/neon:$GITHUB_RUN_ID 093970136003.dkr.ecr.us-east-2.amazonaws.com/neon:latest crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-tools:$GITHUB_RUN_ID 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-tools:latest crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node:$GITHUB_RUN_ID 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-node:latest + crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v14:$GITHUB_RUN_ID 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-node-v14:latest + crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v15:$GITHUB_RUN_ID 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-node-v15:latest - name: Configure Docker Hub login run: | From 500239176ccf515253d896ad00bfe3f202e84134 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 14 Oct 2022 17:31:36 +0300 Subject: [PATCH 25/64] Make TimelineInfo.local field mandatory. It was only None when you queried the status of a timeline with 'timeline_detail' mgmt API call, and it was still being downloaded. You can check for that status with the 'tenant_status' API call instead, checking for has_in_progress_downloads field. Anothere case was if an error happened while trying to get the current logical size, in a 'timeline_detail' request. It might make sense to tolerate such errors, and leave the fields we cannot fill in as empty, None, 0 or similar, but it doesn't make sense to me to leave the whole 'local' struct empty in tht case. --- control_plane/src/bin/neon_local.rs | 41 +++++---------- libs/pageserver_api/src/models.rs | 2 +- pageserver/src/http/routes.rs | 60 +++++++++------------- test_runner/regress/test_remote_storage.py | 7 ++- 4 files changed, 39 insertions(+), 71 deletions(-) diff --git a/control_plane/src/bin/neon_local.rs b/control_plane/src/bin/neon_local.rs index 0c26842b34..244ae5cfd0 100644 --- a/control_plane/src/bin/neon_local.rs +++ b/control_plane/src/bin/neon_local.rs @@ -358,9 +358,7 @@ fn print_timelines_tree( // Memorize all direct children of each timeline. for timeline in timelines.iter() { - if let Some(ancestor_timeline_id) = - timeline.local.as_ref().and_then(|l| l.ancestor_timeline_id) - { + if let Some(ancestor_timeline_id) = timeline.local.ancestor_timeline_id { timelines_hash .get_mut(&ancestor_timeline_id) .context("missing timeline info in the HashMap")? @@ -371,13 +369,7 @@ fn print_timelines_tree( for timeline in timelines_hash.values() { // Start with root local timelines (no ancestors) first. - if timeline - .info - .local - .as_ref() - .and_then(|l| l.ancestor_timeline_id) - .is_none() - { + if timeline.info.local.ancestor_timeline_id.is_none() { print_timeline(0, &Vec::from([true]), timeline, &timelines_hash)?; } } @@ -394,17 +386,17 @@ fn print_timeline( timeline: &TimelineTreeEl, timelines: &HashMap, ) -> Result<()> { - let local_remote = match (timeline.info.local.as_ref(), timeline.info.remote.as_ref()) { - (None, None) => unreachable!("in this case no info for a timeline is found"), - (None, Some(_)) => "(R)", - (Some(_), None) => "(L)", - (Some(_), Some(_)) => "(L+R)", + let local_remote = if timeline.info.remote.is_some() { + "(L)" + } else { + "(L+R)" }; + // Draw main padding print!("{} ", local_remote); if nesting_level > 0 { - let ancestor_lsn = match timeline.info.local.as_ref().and_then(|i| i.ancestor_lsn) { + let ancestor_lsn = match timeline.info.local.ancestor_lsn { Some(lsn) => lsn.to_string(), None => "Unknown Lsn".to_string(), }; @@ -597,10 +589,7 @@ fn handle_tenant(tenant_match: &ArgMatches, env: &mut local_env::LocalEnv) -> an Some(pg_version), )?; let new_timeline_id = timeline_info.timeline_id; - let last_record_lsn = timeline_info - .local - .context(format!("Failed to get last record LSN: no local timeline info for timeline {new_timeline_id}"))? - .last_record_lsn; + let last_record_lsn = timeline_info.local.last_record_lsn; env.register_branch_mapping( DEFAULT_BRANCH_NAME.to_string(), @@ -655,10 +644,7 @@ fn handle_timeline(timeline_match: &ArgMatches, env: &mut local_env::LocalEnv) - pageserver.timeline_create(tenant_id, None, None, None, Some(pg_version))?; let new_timeline_id = timeline_info.timeline_id; - let last_record_lsn = timeline_info - .local - .expect("no local timeline info") - .last_record_lsn; + let last_record_lsn = timeline_info.local.last_record_lsn; env.register_branch_mapping(new_branch_name.to_string(), tenant_id, new_timeline_id)?; println!( @@ -738,10 +724,7 @@ fn handle_timeline(timeline_match: &ArgMatches, env: &mut local_env::LocalEnv) - )?; let new_timeline_id = timeline_info.timeline_id; - let last_record_lsn = timeline_info - .local - .expect("no local timeline info") - .last_record_lsn; + let last_record_lsn = timeline_info.local.last_record_lsn; env.register_branch_mapping(new_branch_name.to_string(), tenant_id, new_timeline_id)?; @@ -801,7 +784,7 @@ fn handle_pg(pg_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<()> { // Use the LSN at the end of the timeline. timeline_infos .get(&node.timeline_id) - .and_then(|bi| bi.local.as_ref().map(|l| l.last_record_lsn.to_string())) + .map(|bi| bi.local.last_record_lsn.to_string()) .unwrap_or_else(|| "?".to_string()) } Some(lsn) => { diff --git a/libs/pageserver_api/src/models.rs b/libs/pageserver_api/src/models.rs index 43059ead84..8f38a02189 100644 --- a/libs/pageserver_api/src/models.rs +++ b/libs/pageserver_api/src/models.rs @@ -169,7 +169,7 @@ pub struct TimelineInfo { pub tenant_id: TenantId, #[serde_as(as = "DisplayFromStr")] pub timeline_id: TimelineId, - pub local: Option, + pub local: LocalTimelineInfo, pub remote: Option, } diff --git a/pageserver/src/http/routes.rs b/pageserver/src/http/routes.rs index 2b4ad86310..21cc87631f 100644 --- a/pageserver/src/http/routes.rs +++ b/pageserver/src/http/routes.rs @@ -184,7 +184,7 @@ async fn timeline_create_handler(mut request: Request) -> Result) -> Result, let mut response_data = Vec::with_capacity(timelines.len()); for timeline in timelines { let timeline_id = timeline.timeline_id; - let local = match local_timeline_info_from_timeline( + let local = local_timeline_info_from_timeline( &timeline, include_non_incremental_logical_size, include_non_incremental_physical_size, - ) { - Ok(local) => Some(local), - Err(e) => { - error!("Failed to convert tenant timeline {timeline_id} into the local one: {e:?}"); - None - } - }; + ) + .context("Failed to convert tenant timeline {timeline_id} into the local one: {e:?}") + .map_err(ApiError::InternalServerError)?; response_data.push(TimelineInfo { tenant_id, @@ -300,19 +296,15 @@ async fn timeline_detail_handler(request: Request) -> Result Some(local_info), - Err(e) => { - error!("Failed to get local timeline info: {e:#}"); - None - } - }; + let timeline = timeline.map_err(ApiError::NotFound)?; + + let local_timeline_info = local_timeline_info_from_timeline( + &timeline, + include_non_incremental_logical_size, + include_non_incremental_physical_size, + ) + .context("Failed to get local timeline info: {e:#}") + .map_err(ApiError::InternalServerError)?; let remote_timeline_info = { let remote_index_read = get_state(&request).remote_index.read().await; @@ -331,21 +323,15 @@ async fn timeline_detail_handler(request: Request) -> Result) -> Result, ApiError> { diff --git a/test_runner/regress/test_remote_storage.py b/test_runner/regress/test_remote_storage.py index 3e775b10b0..9cf8a1e940 100644 --- a/test_runner/regress/test_remote_storage.py +++ b/test_runner/regress/test_remote_storage.py @@ -111,10 +111,9 @@ def test_remote_storage_backup_and_restore( with pytest.raises(Exception, match="Conflict: Tenant download is already in progress"): client.tenant_attach(tenant_id) - detail = client.timeline_detail(tenant_id, timeline_id) - log.info("Timeline detail with active failpoint: %s", detail) - assert detail["local"] is None - assert detail["remote"]["awaits_download"] + tenant_status = client.tenant_status(tenant_id) + log.info("Tenant status with active failpoint: %s", tenant_status) + assert tenant_status["has_in_progress_downloads"] is True # trigger temporary download files removal env.pageserver.stop() From 538876650a0c303aeae4fac71336a3d62aa6da28 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 14 Oct 2022 17:31:43 +0300 Subject: [PATCH 26/64] Merge 'local' and 'remote' parts of TimelineInfo into one struct. The 'local' part was always filled in, so that was easy to merge into into the TimelineInfo itself. 'remote' only contained two fields, 'remote_consistent_lsn' and 'awaits_download'. I made 'remote_consistent_lsn' an optional field, and 'awaits_download' is now false if the timeline is not present remotely. However, I kept stub versions of the 'local' and 'remote' structs for backwards-compatibility, with a few fields that are actively used by the control plane. They just duplicate the fields from TimelineInfo now. They can be removed later, once the control plane has been updated to use the new fields. --- control_plane/src/bin/neon_local.rs | 23 +- libs/pageserver_api/src/models.rs | 47 ++-- pageserver/src/http/openapi_spec.yml | 60 +++-- pageserver/src/http/routes.rs | 208 ++++++++---------- scripts/export_import_between_pageservers.py | 6 +- test_runner/fixtures/neon_fixtures.py | 30 +-- test_runner/regress/test_import.py | 4 +- test_runner/regress/test_pageserver_api.py | 12 +- test_runner/regress/test_remote_storage.py | 22 +- test_runner/regress/test_tenant_relocation.py | 13 +- test_runner/regress/test_timeline_delete.py | 2 +- test_runner/regress/test_timeline_size.py | 84 ++++--- test_runner/regress/test_wal_acceptor.py | 13 +- .../regress/test_wal_acceptor_async.py | 4 +- 14 files changed, 252 insertions(+), 276 deletions(-) diff --git a/control_plane/src/bin/neon_local.rs b/control_plane/src/bin/neon_local.rs index 244ae5cfd0..08797fe907 100644 --- a/control_plane/src/bin/neon_local.rs +++ b/control_plane/src/bin/neon_local.rs @@ -358,7 +358,7 @@ fn print_timelines_tree( // Memorize all direct children of each timeline. for timeline in timelines.iter() { - if let Some(ancestor_timeline_id) = timeline.local.ancestor_timeline_id { + if let Some(ancestor_timeline_id) = timeline.ancestor_timeline_id { timelines_hash .get_mut(&ancestor_timeline_id) .context("missing timeline info in the HashMap")? @@ -369,7 +369,7 @@ fn print_timelines_tree( for timeline in timelines_hash.values() { // Start with root local timelines (no ancestors) first. - if timeline.info.local.ancestor_timeline_id.is_none() { + if timeline.info.ancestor_timeline_id.is_none() { print_timeline(0, &Vec::from([true]), timeline, &timelines_hash)?; } } @@ -386,17 +386,8 @@ fn print_timeline( timeline: &TimelineTreeEl, timelines: &HashMap, ) -> Result<()> { - let local_remote = if timeline.info.remote.is_some() { - "(L)" - } else { - "(L+R)" - }; - - // Draw main padding - print!("{} ", local_remote); - if nesting_level > 0 { - let ancestor_lsn = match timeline.info.local.ancestor_lsn { + let ancestor_lsn = match timeline.info.ancestor_lsn { Some(lsn) => lsn.to_string(), None => "Unknown Lsn".to_string(), }; @@ -589,7 +580,7 @@ fn handle_tenant(tenant_match: &ArgMatches, env: &mut local_env::LocalEnv) -> an Some(pg_version), )?; let new_timeline_id = timeline_info.timeline_id; - let last_record_lsn = timeline_info.local.last_record_lsn; + let last_record_lsn = timeline_info.last_record_lsn; env.register_branch_mapping( DEFAULT_BRANCH_NAME.to_string(), @@ -644,7 +635,7 @@ fn handle_timeline(timeline_match: &ArgMatches, env: &mut local_env::LocalEnv) - pageserver.timeline_create(tenant_id, None, None, None, Some(pg_version))?; let new_timeline_id = timeline_info.timeline_id; - let last_record_lsn = timeline_info.local.last_record_lsn; + let last_record_lsn = timeline_info.last_record_lsn; env.register_branch_mapping(new_branch_name.to_string(), tenant_id, new_timeline_id)?; println!( @@ -724,7 +715,7 @@ fn handle_timeline(timeline_match: &ArgMatches, env: &mut local_env::LocalEnv) - )?; let new_timeline_id = timeline_info.timeline_id; - let last_record_lsn = timeline_info.local.last_record_lsn; + let last_record_lsn = timeline_info.last_record_lsn; env.register_branch_mapping(new_branch_name.to_string(), tenant_id, new_timeline_id)?; @@ -784,7 +775,7 @@ fn handle_pg(pg_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<()> { // Use the LSN at the end of the timeline. timeline_infos .get(&node.timeline_id) - .map(|bi| bi.local.last_record_lsn.to_string()) + .map(|bi| bi.last_record_lsn.to_string()) .unwrap_or_else(|| "?".to_string()) } Some(lsn) => { diff --git a/libs/pageserver_api/src/models.rs b/libs/pageserver_api/src/models.rs index 8f38a02189..a153f1a01e 100644 --- a/libs/pageserver_api/src/models.rs +++ b/libs/pageserver_api/src/models.rs @@ -123,9 +123,15 @@ pub struct TenantInfo { pub has_in_progress_downloads: Option, } +/// This represents the output of the "timeline_detail" and "timeline_list" API calls. #[serde_as] #[derive(Debug, Serialize, Deserialize, Clone)] -pub struct LocalTimelineInfo { +pub struct TimelineInfo { + #[serde_as(as = "DisplayFromStr")] + pub tenant_id: TenantId, + #[serde_as(as = "DisplayFromStr")] + pub timeline_id: TimelineId, + #[serde_as(as = "Option")] pub ancestor_timeline_id: Option, #[serde_as(as = "Option")] @@ -149,28 +155,33 @@ pub struct LocalTimelineInfo { /// the timestamp (in microseconds) of the last received message pub last_received_msg_ts: Option, pub pg_version: u32, + + #[serde_as(as = "Option")] + pub remote_consistent_lsn: Option, + pub awaits_download: bool, + + // Some of the above fields are duplicated in 'local' and 'remote', for backwards- + // compatility with older clients. + pub local: LocalTimelineInfo, + pub remote: RemoteTimelineInfo, +} + +#[serde_as] +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct LocalTimelineInfo { + #[serde_as(as = "Option")] + pub ancestor_timeline_id: Option, + #[serde_as(as = "Option")] + pub ancestor_lsn: Option, + pub current_logical_size: Option, // is None when timeline is Unloaded + pub current_physical_size: Option, // is None when timeline is Unloaded } #[serde_as] #[derive(Debug, Serialize, Deserialize, Clone)] pub struct RemoteTimelineInfo { - #[serde_as(as = "DisplayFromStr")] - pub remote_consistent_lsn: Lsn, - pub awaits_download: bool, -} - -/// -/// This represents the output of the "timeline_detail" API call. -/// -#[serde_as] -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct TimelineInfo { - #[serde_as(as = "DisplayFromStr")] - pub tenant_id: TenantId, - #[serde_as(as = "DisplayFromStr")] - pub timeline_id: TimelineId, - pub local: LocalTimelineInfo, - pub remote: Option, + #[serde_as(as = "Option")] + pub remote_consistent_lsn: Option, } pub type ConfigureFailpointsRequest = Vec; diff --git a/pageserver/src/http/openapi_spec.yml b/pageserver/src/http/openapi_spec.yml index 97fdcd7bbd..05809a92da 100644 --- a/pageserver/src/http/openapi_spec.yml +++ b/pageserver/src/http/openapi_spec.yml @@ -207,7 +207,6 @@ paths: schema: $ref: "#/components/schemas/Error" - /v1/tenant/{tenant_id}/timeline/{timeline_id}/get_lsn_by_timestamp: parameters: - name: tenant_id @@ -612,6 +611,9 @@ components: required: - timeline_id - tenant_id + - last_record_lsn + - disk_consistent_lsn + - awaits_download properties: timeline_id: type: string @@ -619,33 +621,15 @@ components: tenant_id: type: string format: hex - local: - $ref: "#/components/schemas/LocalTimelineInfo" - remote: - $ref: "#/components/schemas/RemoteTimelineInfo" - RemoteTimelineInfo: - type: object - required: - - awaits_download - - remote_consistent_lsn - properties: - awaits_download: - type: boolean - remote_consistent_lsn: - type: string - format: hex - LocalTimelineInfo: - type: object - required: - - last_record_lsn - - disk_consistent_lsn - properties: last_record_lsn: type: string format: hex disk_consistent_lsn: type: string format: hex + remote_consistent_lsn: + type: string + format: hex ancestor_timeline_id: type: string format: hex @@ -670,7 +654,39 @@ components: format: hex last_received_msg_ts: type: integer + awaits_download: + type: boolean + # These 'local' and 'remote' fields just duplicate some of the fields + # above. They are kept for backwards-compatibility. They can be removed, + # when the control plane has been updated to look at the above fields + # directly. + local: + $ref: "#/components/schemas/LocalTimelineInfo" + remote: + $ref: "#/components/schemas/RemoteTimelineInfo" + + LocalTimelineInfo: + type: object + properties: + ancestor_timeline_id: + type: string + format: hex + ancestor_lsn: + type: string + format: hex + current_logical_size: + type: integer + current_physical_size: + type: integer + RemoteTimelineInfo: + type: object + required: + - remote_consistent_lsn + properties: + remote_consistent_lsn: + type: string + format: hex Error: type: object required: diff --git a/pageserver/src/http/routes.rs b/pageserver/src/http/routes.rs index 21cc87631f..4d7339ec13 100644 --- a/pageserver/src/http/routes.rs +++ b/pageserver/src/http/routes.rs @@ -79,13 +79,13 @@ fn get_config(request: &Request) -> &'static PageServerConf { get_state(request).conf } -// Helper functions to construct a LocalTimelineInfo struct for a timeline - -fn local_timeline_info_from_timeline( +// Helper function to construct a TimelineInfo struct for a timeline +async fn build_timeline_info( + state: &State, timeline: &Arc, include_non_incremental_logical_size: bool, include_non_incremental_physical_size: bool, -) -> anyhow::Result { +) -> anyhow::Result { let last_record_lsn = timeline.get_last_record_lsn(); let (wal_source_connstr, last_received_msg_lsn, last_received_msg_ts) = { let guard = timeline.last_received_wal.lock().unwrap(); @@ -100,24 +100,47 @@ fn local_timeline_info_from_timeline( } }; - let info = LocalTimelineInfo { - ancestor_timeline_id: timeline.get_ancestor_timeline_id(), - ancestor_lsn: { - match timeline.get_ancestor_lsn() { - Lsn(0) => None, - lsn @ Lsn(_) => Some(lsn), - } - }, + let (remote_consistent_lsn, awaits_download) = if let Some(remote_entry) = state + .remote_index + .read() + .await + .timeline_entry(&TenantTimelineId { + tenant_id: timeline.tenant_id, + timeline_id: timeline.timeline_id, + }) { + ( + Some(remote_entry.metadata.disk_consistent_lsn()), + remote_entry.awaits_download, + ) + } else { + (None, false) + }; + + let ancestor_timeline_id = timeline.get_ancestor_timeline_id(); + let ancestor_lsn = match timeline.get_ancestor_lsn() { + Lsn(0) => None, + lsn @ Lsn(_) => Some(lsn), + }; + let current_logical_size = match timeline.get_current_logical_size() { + Ok(size) => Some(size), + Err(err) => { + error!("Timeline info creation failed to get current logical size: {err:?}"); + None + } + }; + let current_physical_size = Some(timeline.get_physical_size()); + + let info = TimelineInfo { + tenant_id: timeline.tenant_id, + timeline_id: timeline.timeline_id, + ancestor_timeline_id, + ancestor_lsn, disk_consistent_lsn: timeline.get_disk_consistent_lsn(), last_record_lsn, prev_record_lsn: Some(timeline.get_prev_record_lsn()), latest_gc_cutoff_lsn: *timeline.get_latest_gc_cutoff_lsn(), - current_logical_size: Some( - timeline - .get_current_logical_size() - .context("Timeline info creation failed to get current logical size")?, - ), - current_physical_size: Some(timeline.get_physical_size()), + current_logical_size, + current_physical_size, current_logical_size_non_incremental: if include_non_incremental_logical_size { Some(timeline.get_current_logical_size_non_incremental(last_record_lsn)?) } else { @@ -132,32 +155,25 @@ fn local_timeline_info_from_timeline( last_received_msg_lsn, last_received_msg_ts, pg_version: timeline.pg_version, + + remote_consistent_lsn, + awaits_download, + + // Duplicate some fields in 'local' and 'remote' fields, for backwards-compatility + // with the control plane. + local: LocalTimelineInfo { + ancestor_timeline_id, + ancestor_lsn, + current_logical_size, + current_physical_size, + }, + remote: RemoteTimelineInfo { + remote_consistent_lsn, + }, }; Ok(info) } -fn list_local_timelines( - tenant_id: TenantId, - include_non_incremental_logical_size: bool, - include_non_incremental_physical_size: bool, -) -> Result> { - let tenant = tenant_mgr::get_tenant(tenant_id, true)?; - let timelines = tenant.list_timelines(); - - let mut local_timeline_info = Vec::with_capacity(timelines.len()); - for repository_timeline in timelines { - local_timeline_info.push(( - repository_timeline.timeline_id, - local_timeline_info_from_timeline( - &repository_timeline, - include_non_incremental_logical_size, - include_non_incremental_physical_size, - )?, - )) - } - Ok(local_timeline_info) -} - // healthcheck handler async fn status_handler(request: Request) -> Result, ApiError> { let config = get_config(&request); @@ -169,6 +185,8 @@ async fn timeline_create_handler(mut request: Request) -> Result) -> Result { // Created. Construct a TimelineInfo for it. - let local_info = local_timeline_info_from_timeline(&new_timeline, false, false) + let timeline_info = build_timeline_info(state, &new_timeline, false, false) + .await .map_err(ApiError::InternalServerError)?; - Ok(Some(TimelineInfo { - tenant_id, - timeline_id: new_timeline.timeline_id, - local: local_info, - remote: None, - })) + Ok(Some(timeline_info)) } Ok(None) => Ok(None), // timeline already exists Err(err) => Err(ApiError::InternalServerError(err)), @@ -209,6 +223,8 @@ async fn timeline_list_handler(request: Request) -> Result, query_param_present(&request, "include-non-incremental-physical-size"); check_permission(&request, Some(tenant_id))?; + let state = get_state(&request); + let timelines = tokio::task::spawn_blocking(move || { let _enter = info_span!("timeline_list", tenant = %tenant_id).entered(); let tenant = tenant_mgr::get_tenant(tenant_id, true).map_err(ApiError::NotFound)?; @@ -219,32 +235,17 @@ async fn timeline_list_handler(request: Request) -> Result, let mut response_data = Vec::with_capacity(timelines.len()); for timeline in timelines { - let timeline_id = timeline.timeline_id; - let local = local_timeline_info_from_timeline( + let timeline_info = build_timeline_info( + state, &timeline, include_non_incremental_logical_size, include_non_incremental_physical_size, ) - .context("Failed to convert tenant timeline {timeline_id} into the local one: {e:?}") - .map_err(ApiError::InternalServerError)?; + .await + .context("Failed to convert tenant timeline {timeline_id} into the local one: {e:?}") + .map_err(ApiError::InternalServerError)?; - response_data.push(TimelineInfo { - tenant_id, - timeline_id, - local, - remote: get_state(&request) - .remote_index - .read() - .await - .timeline_entry(&TenantTimelineId { - tenant_id, - timeline_id, - }) - .map(|remote_entry| RemoteTimelineInfo { - remote_consistent_lsn: remote_entry.metadata.disk_consistent_lsn(), - awaits_download: remote_entry.awaits_download, - }), - }) + response_data.push(timeline_info); } json_response(StatusCode::OK, response_data) @@ -289,7 +290,9 @@ async fn timeline_detail_handler(request: Request) -> Result) -> Result((local_timeline_info, remote_timeline_info)) + Ok::<_, ApiError>(timeline_info) } .instrument(info_span!("timeline_detail", tenant = %tenant_id, timeline = %timeline_id)) .await?; - json_response( - StatusCode::OK, - TimelineInfo { - tenant_id, - timeline_id, - local: local_timeline_info, - remote: remote_timeline_info, - }, - ) + json_response(StatusCode::OK, timeline_info) } async fn get_lsn_by_timestamp_handler(request: Request) -> Result, ApiError> { @@ -553,36 +538,27 @@ async fn tenant_status(request: Request) -> Result, ApiErro false }); - let tenant_state = match tenant { - Ok(tenant) => tenant.current_state(), + let (tenant_state, current_physical_size) = match tenant { + Ok(tenant) => { + let timelines = tenant.list_timelines(); + // Calculate total physical size of all timelines + let mut current_physical_size = 0; + for timeline in timelines { + current_physical_size += timeline.get_physical_size(); + } + + (tenant.current_state(), Some(current_physical_size)) + } Err(e) => { error!("Failed to get local tenant state: {e:#}"); if has_in_progress_downloads { - TenantState::Paused + (TenantState::Paused, None) } else { - TenantState::Broken + (TenantState::Broken, None) } } }; - let current_physical_size = - match tokio::task::spawn_blocking(move || list_local_timelines(tenant_id, false, false)) - .await - .map_err(|e: JoinError| ApiError::InternalServerError(e.into()))? - { - Err(err) => { - // Getting local timelines can fail when no local tenant directory is on disk (e.g, when tenant data is being downloaded). - // In that case, put a warning message into log and operate normally. - warn!("Failed to get local timelines for tenant {tenant_id}: {err}"); - None - } - Ok(local_timeline_infos) => Some( - local_timeline_infos - .into_iter() - .fold(0, |acc, x| acc + x.1.current_physical_size.unwrap()), - ), - }; - json_response( StatusCode::OK, TenantInfo { diff --git a/scripts/export_import_between_pageservers.py b/scripts/export_import_between_pageservers.py index 6f6c3864dd..152ce40cea 100755 --- a/scripts/export_import_between_pageservers.py +++ b/scripts/export_import_between_pageservers.py @@ -317,13 +317,13 @@ def remote_consistent_lsn( ) -> int: detail = pageserver_http_client.timeline_detail(tenant, timeline) - if detail["remote"] is None: + lsn_str = detail["remote_consistent_lsn"] + if lsn_str is None: # No remote information at all. This happens right after creating # a timeline, before any part of it has been uploaded to remote # storage yet. return 0 else: - lsn_str = detail["remote"]["remote_consistent_lsn"] assert isinstance(lsn_str, str) return lsn_from_hex(lsn_str) @@ -577,7 +577,7 @@ def main(args: argparse.Namespace): args.work_dir, f"{timeline['tenant_id']}_{timeline['timeline_id']}.tar" ) - pg_version = timeline["local"]["pg_version"] + pg_version = timeline["pg_version"] # Export timeline from old pageserver if args.only_import is False: diff --git a/test_runner/fixtures/neon_fixtures.py b/test_runner/fixtures/neon_fixtures.py index 0d6b6f4cd7..88910d2bdf 100644 --- a/test_runner/fixtures/neon_fixtures.py +++ b/test_runner/fixtures/neon_fixtures.py @@ -1179,7 +1179,7 @@ CREATE_TIMELINE_ID_EXTRACTOR = re.compile( r"^Created timeline '(?P[^']+)'", re.MULTILINE ) TIMELINE_DATA_EXTRACTOR = re.compile( - r"\s(?P[^\s]+)\s\[(?P[^\]]+)\]", re.MULTILINE + r"\s?(?P[^\s]+)\s\[(?P[^\]]+)\]", re.MULTILINE ) @@ -1430,8 +1430,8 @@ class NeonCli(AbstractNeonCli): Returns a list of (branch_name, timeline_id) tuples out of parsed `neon timeline list` CLI output. """ - # (L) main [b49f7954224a0ad25cc0013ea107b54b] - # (L) ┣━ @0/16B5A50: test_cli_branch_list_main [20f98c79111b9015d84452258b7d5540] + # main [b49f7954224a0ad25cc0013ea107b54b] + # ┣━ @0/16B5A50: test_cli_branch_list_main [20f98c79111b9015d84452258b7d5540] res = self.raw_cli( ["timeline", "list", "--tenant-id", str(tenant_id or self.env.initial_tenant)] ) @@ -2702,19 +2702,6 @@ def wait_until(number_of_iterations: int, interval: float, func): raise Exception("timed out while waiting for %s" % func) from last_exception -def assert_timeline_local( - pageserver_http_client: NeonPageserverHttpClient, tenant: TenantId, timeline: TimelineId -): - timeline_detail = pageserver_http_client.timeline_detail( - tenant, - timeline, - include_non_incremental_logical_size=True, - include_non_incremental_physical_size=True, - ) - assert timeline_detail.get("local", {}).get("disk_consistent_lsn"), timeline_detail - return timeline_detail - - def assert_no_in_progress_downloads_for_tenant( pageserver_http_client: NeonPageserverHttpClient, tenant: TenantId, @@ -2728,15 +2715,14 @@ def remote_consistent_lsn( ) -> Lsn: detail = pageserver_http_client.timeline_detail(tenant, timeline) - if detail["remote"] is None: + lsn_str = detail["remote_consistent_lsn"] + if lsn_str is None: # No remote information at all. This happens right after creating # a timeline, before any part of it has been uploaded to remote # storage yet. return Lsn(0) - else: - lsn_str = detail["remote"]["remote_consistent_lsn"] - assert isinstance(lsn_str, str) - return Lsn(lsn_str) + assert isinstance(lsn_str, str) + return Lsn(lsn_str) def wait_for_upload( @@ -2768,7 +2754,7 @@ def last_record_lsn( ) -> Lsn: detail = pageserver_http_client.timeline_detail(tenant, timeline) - lsn_str = detail["local"]["last_record_lsn"] + lsn_str = detail["last_record_lsn"] assert isinstance(lsn_str, str) return Lsn(lsn_str) diff --git a/test_runner/regress/test_import.py b/test_runner/regress/test_import.py index c84d282a4d..5910b4f74f 100644 --- a/test_runner/regress/test_import.py +++ b/test_runner/regress/test_import.py @@ -155,8 +155,8 @@ def test_import_from_pageserver_multisegment(pg_bin: PgBin, neon_env_builder: Ne lsn = _generate_data(num_rows, pg) logical_size = env.pageserver.http_client().timeline_detail(env.initial_tenant, timeline)[ - "local" - ]["current_logical_size"] + "current_logical_size" + ] log.info(f"timeline logical size = {logical_size / (1024 ** 2)}MB") assert logical_size > 1024**3 # = 1GB diff --git a/test_runner/regress/test_pageserver_api.py b/test_runner/regress/test_pageserver_api.py index def6bd5b33..bab96cff4f 100644 --- a/test_runner/regress/test_pageserver_api.py +++ b/test_runner/regress/test_pageserver_api.py @@ -93,7 +93,6 @@ def check_client(client: NeonPageserverHttpClient, initial_tenant: TenantId): assert TenantId(timeline_details["tenant_id"]) == tenant_id assert TimelineId(timeline_details["timeline_id"]) == timeline_id - assert timeline_details.get("local") is not None def test_pageserver_http_get_wal_receiver_not_found(neon_simple_env: NeonEnv): @@ -125,16 +124,15 @@ def expect_updated_msg_lsn( timeline_details = client.timeline_detail(tenant_id, timeline_id=timeline_id) # a successful `timeline_details` response must contain the below fields - local_timeline_details = timeline_details["local"] - assert "wal_source_connstr" in local_timeline_details.keys() - assert "last_received_msg_lsn" in local_timeline_details.keys() - assert "last_received_msg_ts" in local_timeline_details.keys() + assert "wal_source_connstr" in timeline_details.keys() + assert "last_received_msg_lsn" in timeline_details.keys() + assert "last_received_msg_ts" in timeline_details.keys() assert ( - local_timeline_details["last_received_msg_lsn"] is not None + timeline_details["last_received_msg_lsn"] is not None ), "the last received message's LSN is empty" - last_msg_lsn = Lsn(local_timeline_details["last_received_msg_lsn"]) + last_msg_lsn = Lsn(timeline_details["last_received_msg_lsn"]) assert ( prev_msg_lsn is None or prev_msg_lsn < last_msg_lsn ), f"the last received message's LSN {last_msg_lsn} hasn't been updated \ diff --git a/test_runner/regress/test_remote_storage.py b/test_runner/regress/test_remote_storage.py index 9cf8a1e940..0a02a80de5 100644 --- a/test_runner/regress/test_remote_storage.py +++ b/test_runner/regress/test_remote_storage.py @@ -10,8 +10,8 @@ import pytest from fixtures.log_helper import log from fixtures.neon_fixtures import ( NeonEnvBuilder, + NeonPageserverHttpClient, RemoteStorageKind, - assert_timeline_local, available_remote_storages, wait_for_last_record_lsn, wait_for_upload, @@ -125,16 +125,15 @@ def test_remote_storage_backup_and_restore( wait_until( number_of_iterations=20, interval=1, - func=lambda: assert_timeline_local(client, tenant_id, timeline_id), + func=lambda: expect_tenant_to_download_timeline(client, tenant_id), ) detail = client.timeline_detail(tenant_id, timeline_id) - assert detail["local"] is not None log.info("Timeline detail after attach completed: %s", detail) assert ( - Lsn(detail["local"]["last_record_lsn"]) >= current_lsn + Lsn(detail["last_record_lsn"]) >= current_lsn ), "current db Lsn should should not be less than the one stored on remote storage" - assert not detail["remote"]["awaits_download"] + assert not detail["awaits_download"] pg = env.postgres.create_start("main") with pg.cursor() as cur: @@ -143,3 +142,16 @@ def test_remote_storage_backup_and_restore( query_scalar(cur, f"SELECT secret FROM t{checkpoint_number} WHERE id = {data_id};") == f"{data_secret}|{checkpoint_number}" ) + + +def expect_tenant_to_download_timeline( + client: NeonPageserverHttpClient, + tenant_id: TenantId, +): + for tenant in client.tenant_list(): + if tenant["id"] == str(tenant_id): + assert not tenant.get( + "has_in_progress_downloads", True + ), f"Tenant {tenant_id} should have no downloads in progress" + return + assert False, f"Tenant {tenant_id} is missing on pageserver" diff --git a/test_runner/regress/test_tenant_relocation.py b/test_runner/regress/test_tenant_relocation.py index 2b01546198..a3245d65e4 100644 --- a/test_runner/regress/test_tenant_relocation.py +++ b/test_runner/regress/test_tenant_relocation.py @@ -16,7 +16,6 @@ from fixtures.neon_fixtures import ( PortDistributor, Postgres, assert_no_in_progress_downloads_for_tenant, - assert_timeline_local, base_dir, neon_binpath, pg_distrib_dir, @@ -167,18 +166,18 @@ def check_timeline_attached( old_current_lsn: Lsn, ): # new pageserver should be in sync (modulo wal tail or vacuum activity) with the old one because there was no new writes since checkpoint - new_timeline_detail = assert_timeline_local(new_pageserver_http_client, tenant_id, timeline_id) + new_timeline_detail = new_pageserver_http_client.timeline_detail(tenant_id, timeline_id) # when load is active these checks can break because lsns are not static # so let's check with some margin assert_abs_margin_ratio( - int(Lsn(new_timeline_detail["local"]["disk_consistent_lsn"])), - int(Lsn(old_timeline_detail["local"]["disk_consistent_lsn"])), + int(Lsn(new_timeline_detail["disk_consistent_lsn"])), + int(Lsn(old_timeline_detail["disk_consistent_lsn"])), 0.03, ) assert_abs_margin_ratio( - int(Lsn(new_timeline_detail["local"]["disk_consistent_lsn"])), int(old_current_lsn), 0.03 + int(Lsn(new_timeline_detail["disk_consistent_lsn"])), int(old_current_lsn), 0.03 ) @@ -301,10 +300,10 @@ def test_tenant_relocation( # wait until pageserver receives that data wait_for_last_record_lsn(pageserver_http, tenant_id, timeline_id_main, current_lsn_main) - timeline_detail_main = assert_timeline_local(pageserver_http, tenant_id, timeline_id_main) + timeline_detail_main = pageserver_http.timeline_detail(tenant_id, timeline_id_main) wait_for_last_record_lsn(pageserver_http, tenant_id, timeline_id_second, current_lsn_second) - timeline_detail_second = assert_timeline_local(pageserver_http, tenant_id, timeline_id_second) + timeline_detail_second = pageserver_http.timeline_detail(tenant_id, timeline_id_second) if with_load == "with_load": # create load table diff --git a/test_runner/regress/test_timeline_delete.py b/test_runner/regress/test_timeline_delete.py index ac248c1b4b..de05d445ed 100644 --- a/test_runner/regress/test_timeline_delete.py +++ b/test_runner/regress/test_timeline_delete.py @@ -65,7 +65,7 @@ def test_timeline_delete(neon_simple_env: NeonEnv): # check 404 with pytest.raises( NeonPageserverApiException, - match=f"Timeline {env.initial_tenant}/{leaf_timeline_id} is not found neither locally nor remotely", + match=f"Timeline {leaf_timeline_id} was not found for tenant {env.initial_tenant}", ): ps_http.timeline_detail(env.initial_tenant, leaf_timeline_id) diff --git a/test_runner/regress/test_timeline_size.py b/test_runner/regress/test_timeline_size.py index 3a482be5db..d26d5f3afa 100644 --- a/test_runner/regress/test_timeline_size.py +++ b/test_runner/regress/test_timeline_size.py @@ -16,7 +16,6 @@ from fixtures.neon_fixtures import ( PortDistributor, Postgres, VanillaPostgres, - assert_timeline_local, wait_for_last_flush_lsn, ) from fixtures.types import TenantId, TimelineId @@ -44,20 +43,16 @@ def test_timeline_size(neon_simple_env: NeonEnv): """ ) - res = assert_timeline_local(client, env.initial_tenant, new_timeline_id) - local_details = res["local"] - assert ( - local_details["current_logical_size"] - == local_details["current_logical_size_non_incremental"] + res = client.timeline_detail( + env.initial_tenant, new_timeline_id, include_non_incremental_logical_size=True ) + assert res["current_logical_size"] == res["current_logical_size_non_incremental"] cur.execute("TRUNCATE foo") - res = assert_timeline_local(client, env.initial_tenant, new_timeline_id) - local_details = res["local"] - assert ( - local_details["current_logical_size"] - == local_details["current_logical_size_non_incremental"] + res = client.timeline_detail( + env.initial_tenant, new_timeline_id, include_non_incremental_logical_size=True ) + assert res["current_logical_size"] == res["current_logical_size_non_incremental"] def test_timeline_size_createdropdb(neon_simple_env: NeonEnv): @@ -66,22 +61,22 @@ def test_timeline_size_createdropdb(neon_simple_env: NeonEnv): client = env.pageserver.http_client() wait_for_timeline_size_init(client, tenant=env.initial_tenant, timeline=new_timeline_id) - timeline_details = assert_timeline_local(client, env.initial_tenant, new_timeline_id) + timeline_details = client.timeline_detail( + env.initial_tenant, new_timeline_id, include_non_incremental_logical_size=True + ) pgmain = env.postgres.create_start("test_timeline_size_createdropdb") log.info("postgres is running on 'test_timeline_size_createdropdb' branch") with closing(pgmain.connect()) as conn: with conn.cursor() as cur: - res = assert_timeline_local(client, env.initial_tenant, new_timeline_id) - local_details = res["local"] - assert ( - local_details["current_logical_size"] - == local_details["current_logical_size_non_incremental"] + res = client.timeline_detail( + env.initial_tenant, new_timeline_id, include_non_incremental_logical_size=True ) + assert res["current_logical_size"] == res["current_logical_size_non_incremental"] assert ( - timeline_details["local"]["current_logical_size_non_incremental"] - == local_details["current_logical_size_non_incremental"] + timeline_details["current_logical_size_non_incremental"] + == res["current_logical_size_non_incremental"] ), "no writes should not change the incremental logical size" cur.execute("CREATE DATABASE foodb") @@ -97,21 +92,21 @@ def test_timeline_size_createdropdb(neon_simple_env: NeonEnv): """ ) - res = assert_timeline_local(client, env.initial_tenant, new_timeline_id) - local_details = res["local"] + res = client.timeline_detail( + env.initial_tenant, + new_timeline_id, + include_non_incremental_logical_size=True, + ) assert ( - local_details["current_logical_size"] - == local_details["current_logical_size_non_incremental"] + res["current_logical_size"] == res["current_logical_size_non_incremental"] ) cur.execute("DROP DATABASE foodb") - res = assert_timeline_local(client, env.initial_tenant, new_timeline_id) - local_details = res["local"] - assert ( - local_details["current_logical_size"] - == local_details["current_logical_size_non_incremental"] + res = client.timeline_detail( + env.initial_tenant, new_timeline_id, include_non_incremental_logical_size=True ) + assert res["current_logical_size"] == res["current_logical_size_non_incremental"] # wait until received_lsn_lag is 0 @@ -210,10 +205,11 @@ def test_timeline_size_quota(neon_env_builder: NeonEnvBuilder): pg_cluster_size = cur.fetchone() log.info(f"pg_cluster_size = {pg_cluster_size}") - new_res = assert_timeline_local(client, env.initial_tenant, new_timeline_id) + new_res = client.timeline_detail( + env.initial_tenant, new_timeline_id, include_non_incremental_logical_size=True + ) assert ( - new_res["local"]["current_logical_size"] - == new_res["local"]["current_logical_size_non_incremental"] + new_res["current_logical_size"] == new_res["current_logical_size_non_incremental"] ), "after the WAL is streamed, current_logical_size is expected to be calculated and to be equal its non-incremental value" @@ -419,7 +415,7 @@ def test_tenant_physical_size(neon_simple_env: NeonEnv): def get_timeline_physical_size(timeline: TimelineId): res = client.timeline_detail(tenant, timeline, include_non_incremental_physical_size=True) - return res["local"]["current_physical_size_non_incremental"] + return res["current_physical_size_non_incremental"] timeline_total_size = get_timeline_physical_size(timeline) for i in range(10): @@ -450,13 +446,10 @@ def assert_physical_size(env: NeonEnv, tenant_id: TenantId, timeline_id: Timelin """Check the current physical size returned from timeline API matches the total physical size of the timeline on disk""" client = env.pageserver.http_client() - res = assert_timeline_local(client, tenant_id, timeline_id) + res = client.timeline_detail(tenant_id, timeline_id, include_non_incremental_physical_size=True) timeline_path = env.timeline_dir(tenant_id, timeline_id) - assert ( - res["local"]["current_physical_size"] - == res["local"]["current_physical_size_non_incremental"] - ) - assert res["local"]["current_physical_size"] == get_timeline_dir_size(timeline_path) + assert res["current_physical_size"] == res["current_physical_size_non_incremental"] + assert res["current_physical_size"] == get_timeline_dir_size(timeline_path) # Timeline logical size initialization is an asynchronous background task that runs once, @@ -465,13 +458,16 @@ def wait_for_timeline_size_init( client: NeonPageserverHttpClient, tenant: TenantId, timeline: TimelineId ): for i in range(10): - timeline_details = assert_timeline_local(client, tenant, timeline) - if ( - timeline_details["local"]["current_logical_size"] - == timeline_details["local"]["current_logical_size_non_incremental"] - ): + timeline_details = client.timeline_detail( + tenant, timeline, include_non_incremental_logical_size=True + ) + current_logical_size = timeline_details["current_logical_size"] + non_incremental = timeline_details["current_logical_size_non_incremental"] + if current_logical_size == non_incremental: return - log.info(f"waiting for current_logical_size of a timeline to be calculated, iteration {i}") + log.info( + f"waiting for current_logical_size of a timeline to be calculated, iteration {i}: {current_logical_size} vs {non_incremental}" + ) time.sleep(1) raise Exception( f"timed out while waiting for current_logical_size of a timeline to reach its non-incremental value, details: {timeline_details}" diff --git a/test_runner/regress/test_wal_acceptor.py b/test_runner/regress/test_wal_acceptor.py index 9c8e66e0e2..4451ba9d57 100644 --- a/test_runner/regress/test_wal_acceptor.py +++ b/test_runner/regress/test_wal_acceptor.py @@ -127,14 +127,9 @@ def test_many_timelines(neon_env_builder: NeonEnvBuilder): for timeline_detail in timeline_details: timeline_id = TimelineId(timeline_detail["timeline_id"]) - local_timeline_detail = timeline_detail.get("local") - if local_timeline_detail is None: - log.debug(f"Timeline {timeline_id} is not present locally, skipping") - continue - m = TimelineMetrics( timeline_id=timeline_id, - last_record_lsn=Lsn(local_timeline_detail["last_record_lsn"]), + last_record_lsn=Lsn(timeline_detail["last_record_lsn"]), ) for sk_m in sk_metrics: m.flush_lsns.append(Lsn(sk_m.flush_lsn_inexact[(tenant_id, timeline_id)])) @@ -536,7 +531,7 @@ def test_s3_wal_replay(neon_env_builder: NeonEnvBuilder, remote_storage_kind: Re ) ps_cli = env.pageserver.http_client() - pageserver_lsn = Lsn(ps_cli.timeline_detail(tenant_id, timeline_id)["local"]["last_record_lsn"]) + pageserver_lsn = Lsn(ps_cli.timeline_detail(tenant_id, timeline_id)["last_record_lsn"]) lag = last_lsn - pageserver_lsn log.info( f"Pageserver last_record_lsn={pageserver_lsn}; flush_lsn={last_lsn}; lag before replay is {lag / 1024}kb" @@ -580,9 +575,7 @@ def test_s3_wal_replay(neon_env_builder: NeonEnvBuilder, remote_storage_kind: Re raise RuntimeError("Timed out waiting for WAL redo") pageserver_lsn = Lsn( - env.pageserver.http_client().timeline_detail(tenant_id, timeline_id)["local"][ - "last_record_lsn" - ] + env.pageserver.http_client().timeline_detail(tenant_id, timeline_id)["last_record_lsn"] ) lag = last_lsn - pageserver_lsn diff --git a/test_runner/regress/test_wal_acceptor_async.py b/test_runner/regress/test_wal_acceptor_async.py index 9d2008296a..70ae6bae18 100644 --- a/test_runner/regress/test_wal_acceptor_async.py +++ b/test_runner/regress/test_wal_acceptor_async.py @@ -179,9 +179,7 @@ async def run_restarts_under_load( log.info(f"Postgres flush_lsn {flush_lsn}") pageserver_lsn = Lsn( - env.pageserver.http_client().timeline_detail(tenant_id, timeline_id)["local"][ - "last_record_lsn" - ] + env.pageserver.http_client().timeline_detail(tenant_id, timeline_id)["last_record_lsn"] ) sk_ps_lag = flush_lsn - pageserver_lsn log.info(f"Pageserver last_record_lsn={pageserver_lsn} lag={sk_ps_lag / 1024}kb") From 9c24de254fd93d5b002665da6ea2b1426cafa55c Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 14 Oct 2022 16:41:35 +0300 Subject: [PATCH 27/64] Add description and license fields to OpenAPI spec. These were added earlier to the control plane's copy of this file. This is the master version of this file, so let's keep it in sync. --- pageserver/src/http/openapi_spec.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pageserver/src/http/openapi_spec.yml b/pageserver/src/http/openapi_spec.yml index 05809a92da..626cc07429 100644 --- a/pageserver/src/http/openapi_spec.yml +++ b/pageserver/src/http/openapi_spec.yml @@ -1,7 +1,11 @@ openapi: "3.0.2" info: title: Page Server API + description: Neon Pageserver API version: "1.0" + license: + name: "Apache" + url: https://github.com/neondatabase/neon/blob/main/LICENSE servers: - url: "" paths: From f03b7c345821083d1e6c91397b7eca06fb54a63b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 15 Oct 2022 01:55:31 +0300 Subject: [PATCH 28/64] Bump regular dependencies (#2618) * etcd-client is not updated, since we plan to replace it with another client and the new version errors with some missing prost library error * clap had released another major update that requires changing every CLI declaration again, deserves a separate PR --- Cargo.lock | 763 ++++++++++++++++-------------- control_plane/Cargo.toml | 8 +- libs/etcd_broker/Cargo.toml | 2 +- libs/pageserver_api/Cargo.toml | 2 +- libs/remote_storage/Cargo.toml | 2 +- libs/safekeeper_api/Cargo.toml | 2 +- libs/safekeeper_api/src/models.rs | 9 +- libs/utils/Cargo.toml | 6 +- pageserver/Cargo.toml | 6 +- safekeeper/Cargo.toml | 4 +- workspace_hack/Cargo.toml | 9 +- 11 files changed, 436 insertions(+), 377 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8488fc4f9d..7659be6c92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] @@ -44,31 +44,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27d3d00d3d115395a7a8a4dc045feb7aa82b641e485f7e15f4e67ac16f4f56d" [[package]] -name = "ansi_term" -version = "0.12.1" +name = "android_system_properties" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "winapi", + "libc", ] [[package]] -name = "anyhow" -version = "1.0.59" +name = "anes" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anyhow" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" dependencies = [ "backtrace", ] [[package]] name = "arrayvec" -version = "0.4.12" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "asn1-rs" @@ -83,7 +86,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.12", + "time 0.3.15", ] [[package]] @@ -169,9 +172,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.5.13" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9496f0c1d1afb7a2af4338bbe1d969cddfead41d87a9fb3aaa6d0bbc7af648" +checksum = "c9e3356844c4d6a6d6467b8da2cffb4a2820be256f50a3a386c9d152bab31043" dependencies = [ "async-trait", "axum-core", @@ -181,7 +184,7 @@ dependencies = [ "http", "http-body", "hyper", - "itoa 1.0.3", + "itoa", "matchit", "memchr", "mime", @@ -266,7 +269,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "clap 3.2.16", + "clap", "env_logger", "lazy_static", "lazycell", @@ -309,9 +312,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] @@ -331,20 +334,19 @@ dependencies = [ "lazy_static", "memchr", "regex-automata", - "serde", ] [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "bytemuck" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835" +checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" [[package]] name = "byteorder" @@ -390,23 +392,52 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "serde", "time 0.1.44", + "wasm-bindgen", "winapi", ] [[package]] -name = "clang-sys" -version = "1.3.3" +name = "ciborium" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" + +[[package]] +name = "ciborium-ll" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clang-sys" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" dependencies = [ "glob", "libc", @@ -415,20 +446,9 @@ dependencies = [ [[package]] name = "clap" -version = "2.34.0" +version = "3.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "bitflags", - "textwrap 0.11.0", - "unicode-width", -] - -[[package]] -name = "clap" -version = "3.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9" +checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" dependencies = [ "atty", "bitflags", @@ -436,7 +456,7 @@ dependencies = [ "indexmap", "strsim", "termcolor", - "textwrap 0.15.0", + "textwrap", ] [[package]] @@ -468,10 +488,20 @@ dependencies = [ ] [[package]] -name = "combine" -version = "4.6.4" +name = "codespan-reporting" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "combine" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ "bytes", "memchr", @@ -479,9 +509,9 @@ dependencies = [ [[package]] name = "comfy-table" -version = "5.0.1" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b103d85ca6e209388771bfb7aa6b68a7aeec4afbf6f0a0264bfbf50360e5212e" +checksum = "85914173c2f558d61613bfbbf1911f14e630895087a7ed2fafc0f5319e1536e7" dependencies = [ "crossterm", "strum", @@ -495,7 +525,7 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", - "clap 3.2.16", + "clap", "env_logger", "futures", "hyper", @@ -514,18 +544,18 @@ dependencies = [ [[package]] name = "const_format" -version = "0.2.26" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "939dc9e2eb9077e0679d2ce32de1ded8531779360b003b4a972a7a39ec263495" +checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.22" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef196d5d972878a48da7decb7686eded338b4858fbabeed513d63a7c98b2b82d" +checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650" dependencies = [ "proc-macro2", "quote", @@ -537,10 +567,10 @@ name = "control_plane" version = "0.1.0" dependencies = [ "anyhow", - "clap 3.2.16", + "clap", "comfy-table", "git-version", - "nix", + "nix 0.25.0", "once_cell", "pageserver_api", "postgres", @@ -595,9 +625,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -622,15 +652,16 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" dependencies = [ + "anes", "atty", "cast", - "clap 2.34.0", + "ciborium", + "clap", "criterion-plot", - "csv", "itertools", "lazy_static", "num-traits", @@ -639,7 +670,6 @@ dependencies = [ "rayon", "regex", "serde", - "serde_cbor", "serde_derive", "serde_json", "tinytemplate", @@ -648,9 +678,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.5" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", "itertools", @@ -691,15 +721,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset", - "once_cell", "scopeguard", ] @@ -715,9 +744,9 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.23.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" +checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" dependencies = [ "bitflags", "crossterm_winapi", @@ -759,25 +788,47 @@ dependencies = [ ] [[package]] -name = "csv" -version = "1.1.6" +name = "cxx" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "19f39818dcfc97d45b03953c1292efc4e80954e1583c4aa770bac1383e2310a4" dependencies = [ - "bstr", - "csv-core", - "itoa 0.4.8", - "ryu", - "serde", + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", ] [[package]] -name = "csv-core" -version = "0.1.10" +name = "cxx-build" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +checksum = "3e580d70777c116df50c390d1211993f62d40302881e54d4b79727acb83d0199" dependencies = [ - "memchr", + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56a46460b88d1cec95112c8c363f0e2c39afdb237f60583b0b36343bf627ea9c" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747b608fecf06b0d72d440f27acc99288207324b793be2c17991839f3d4995ea" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -792,9 +843,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.13.4" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02" dependencies = [ "darling_core", "darling_macro", @@ -802,9 +853,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.4" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f" dependencies = [ "fnv", "ident_case", @@ -816,9 +867,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.13.4" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" dependencies = [ "darling_core", "quote", @@ -865,11 +916,11 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ - "block-buffer 0.10.2", + "block-buffer 0.10.3", "crypto-common", "subtle", ] @@ -908,9 +959,9 @@ dependencies = [ [[package]] name = "either" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "embedded-hal" @@ -933,9 +984,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" dependencies = [ "atty", "humantime", @@ -979,12 +1030,12 @@ dependencies = [ [[package]] name = "fail" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3245a0ca564e7f3c797d20d833a6870f57a728ac967d5225b3ffdef4465011" +checksum = "fe5e43d0f78a42ad591453aedb1d7ae631ce7ee445c7643691055a9ed8d3b01c" dependencies = [ - "lazy_static", "log", + "once_cell", "rand", ] @@ -1056,11 +1107,10 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] @@ -1085,9 +1135,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" dependencies = [ "futures-channel", "futures-core", @@ -1100,9 +1150,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" dependencies = [ "futures-core", "futures-sink", @@ -1110,15 +1160,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" dependencies = [ "futures-core", "futures-task", @@ -1127,15 +1177,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" dependencies = [ "proc-macro2", "quote", @@ -1144,21 +1194,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-channel", "futures-core", @@ -1229,9 +1279,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "h2" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" dependencies = [ "bytes", "fnv", @@ -1283,15 +1333,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "heck" version = "0.4.0" @@ -1338,7 +1379,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -1349,7 +1390,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.3", + "itoa", ] [[package]] @@ -1371,9 +1412,9 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -1412,7 +1453,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.3", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -1459,6 +1500,30 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde6edd6cef363e9359ed3c98ba64590ba9eecba2293eb5a723ab32aee8926aa" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1467,11 +1532,10 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -1484,6 +1548,7 @@ checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", + "serde", ] [[package]] @@ -1495,7 +1560,7 @@ dependencies = [ "ahash", "atty", "indexmap", - "itoa 1.0.3", + "itoa", "lazy_static", "log", "num-format", @@ -1541,30 +1606,24 @@ checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" -version = "0.4.8" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1603,15 +1662,6 @@ dependencies = [ "libc", ] -[[package]] -name = "kstring" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b310ccceade8121d7d77fee406160e457c2f4e7c7982d589da3499bc7ea4526" -dependencies = [ - "serde", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -1626,9 +1676,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.127" +version = "0.2.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" +checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" [[package]] name = "libloading" @@ -1647,10 +1697,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" [[package]] -name = "lock_api" -version = "0.4.7" +name = "link-cplusplus" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -1675,12 +1734,6 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "matchit" version = "0.5.0" @@ -1700,11 +1753,11 @@ dependencies = [ [[package]] name = "md-5" -version = "0.10.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658646b21e0b72f7866c7038ab086d3d5e1cd6271f060fd37defb241949d0582" +checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -1721,9 +1774,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7" +checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" dependencies = [ "libc", ] @@ -1761,9 +1814,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] @@ -1833,10 +1886,18 @@ dependencies = [ ] [[package]] -name = "nodrop" -version = "0.1.14" +name = "nix" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "libc", + "memoffset", + "pin-utils", +] [[package]] name = "nom" @@ -1866,6 +1927,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -1879,12 +1950,12 @@ dependencies = [ [[package]] name = "num-format" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" +checksum = "54b862ff8df690cf089058c98b183676a7ed0f974cc08b426800093227cbff3b" dependencies = [ "arrayvec", - "itoa 0.4.8", + "itoa", ] [[package]] @@ -1946,9 +2017,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "oorandom" @@ -1964,9 +2035,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.41" +version = "0.10.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", "cfg-if", @@ -1996,9 +2067,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.75" +version = "0.9.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" dependencies = [ "autocfg", "cc", @@ -2009,9 +2080,15 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.2.0" +version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pageserver" @@ -2024,7 +2101,7 @@ dependencies = [ "byteorder", "bytes", "chrono", - "clap 3.2.16", + "clap", "close_fds", "const_format", "crc32c", @@ -2041,7 +2118,7 @@ dependencies = [ "hyper", "itertools", "metrics", - "nix", + "nix 0.25.0", "num-traits", "once_cell", "pageserver_api", @@ -2149,9 +2226,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "petgraph" @@ -2183,18 +2260,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", @@ -2221,9 +2298,9 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "plotters" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9428003b84df1496fb9d6eeee9c5f8145cb41ca375eb0dad204328888832811f" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", @@ -2240,9 +2317,9 @@ checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0918736323d1baff32ee0eade54984f6f201ad7e97d5cfb5d6ab4a358529615" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] @@ -2271,10 +2348,10 @@ dependencies = [ "fallible-iterator", "hmac 0.12.1", "lazy_static", - "md-5 0.10.1", + "md-5 0.10.5", "memchr", "rand", - "sha2 0.10.2", + "sha2 0.10.6", "stringprep", ] @@ -2324,7 +2401,7 @@ dependencies = [ "lazy_static", "libc", "log", - "nix", + "nix 0.23.1", "parking_lot 0.11.2", "symbolic-demangle", "tempfile", @@ -2339,9 +2416,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "prettyplease" -version = "0.1.18" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697ae720ee02011f439e0701db107ffe2916d83f718342d65d7f8bf7b8a5fee9" +checksum = "83fead41e178796ef8274dc612a7d8ce4c7e10ca35cd2c5b5ad24cac63aeb6c0" dependencies = [ "proc-macro2", "syn", @@ -2355,9 +2432,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" dependencies = [ "unicode-ident", ] @@ -2377,9 +2454,9 @@ dependencies = [ [[package]] name = "prometheus" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cface98dfa6d645ea4c789839f176e4b072265d085bfcc48eaa8d137f58d3c39" +checksum = "45c8babc29389186697fe5a2a4859d697825496b83db5d0b65271cdc0488e88c" dependencies = [ "cfg-if", "fnv", @@ -2410,7 +2487,7 @@ dependencies = [ "bytes", "cfg-if", "cmake", - "heck 0.4.0", + "heck", "itertools", "lazy_static", "log", @@ -2456,7 +2533,7 @@ dependencies = [ "base64", "bstr", "bytes", - "clap 3.2.16", + "clap", "futures", "git-version", "hashbrown", @@ -2479,7 +2556,7 @@ dependencies = [ "scopeguard", "serde", "serde_json", - "sha2 0.10.2", + "sha2 0.10.6", "socket2", "thiserror", "tokio", @@ -2537,9 +2614,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -2667,9 +2744,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" dependencies = [ "base64", "bytes", @@ -2683,9 +2760,9 @@ dependencies = [ "hyper-rustls", "ipnet", "js-sys", - "lazy_static", "log", "mime", + "once_cell", "percent-encoding", "pin-project-lite", "rustls", @@ -2706,9 +2783,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b221de559e4a29df3b957eec92bc0de6bc8eaf6ca9cfed43e5e1d67ff65a34" +checksum = "3603b7d71ca82644f79b5a06d1220e9a58ede60bd32255f698cb1af8838b8db3" dependencies = [ "bytemuck", ] @@ -2895,7 +2972,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.13", + "semver 1.0.14", ] [[package]] @@ -2957,7 +3034,7 @@ dependencies = [ "async-trait", "byteorder", "bytes", - "clap 3.2.16", + "clap", "const_format", "crc32c", "daemonize", @@ -3027,6 +3104,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "sct" version = "0.7.0" @@ -3039,9 +3122,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -3071,9 +3154,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "semver-parser" @@ -3083,28 +3166,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.142" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - [[package]] name = "serde_derive" -version = "1.0.142" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b5b8d809babe02f538c2cfec6f2c1ed10804c0e5a6a041a049a4f5588ccc2e" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote", @@ -3113,11 +3186,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074" dependencies = [ - "itoa 1.0.3", + "itoa", "ryu", "serde", ] @@ -3129,26 +3202,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.3", + "itoa", "ryu", "serde", ] [[package]] name = "serde_with" -version = "1.14.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "368f2d60d049ea019a84dcd6687b0d1e0030fe663ae105039bdf967ed5e6a9a7" dependencies = [ + "base64", + "chrono", + "hex", + "indexmap", "serde", + "serde_json", "serde_with_macros", + "time 0.3.15", ] [[package]] name = "serde_with_macros" -version = "1.5.2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "1ccadfacf6cf10faad22bbadf55986bdd0856edfb5d9210aa1dcf1f516e84e93" dependencies = [ "darling", "proc-macro2", @@ -3171,13 +3250,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -3234,7 +3313,7 @@ dependencies = [ "num-bigint", "num-traits", "thiserror", - "time 0.3.12", + "time 0.3.15", ] [[package]] @@ -3254,15 +3333,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -3313,17 +3392,17 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strum" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" [[package]] name = "strum_macros" -version = "0.23.1" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck 0.3.3", + "heck", "proc-macro2", "quote", "rustversion", @@ -3361,9 +3440,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.99" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" dependencies = [ "proc-macro2", "quote", @@ -3424,33 +3503,24 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.11.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "textwrap" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" [[package]] name = "thiserror" -version = "1.0.32" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.32" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -3479,14 +3549,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b7cc93fc23ba97fde84f7eea56c55d1ba183f495c6715defdfc7b9cb8c870f" +checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" dependencies = [ - "itoa 1.0.3", - "js-sys", + "itoa", "libc", "num_threads", + "serde", "time-macros", ] @@ -3523,9 +3593,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.20.1" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95" dependencies = [ "autocfg", "bytes", @@ -3621,9 +3691,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", "pin-project-lite", @@ -3632,9 +3702,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -3655,14 +3725,13 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.13.4" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744e9ed5b352340aa47ce033716991b5589e23781acb97cad37d4ea70560f55b" +checksum = "5376256e44f2443f8896ac012507c19a012df0fe8758b55246ae51a2279db51f" dependencies = [ "combine", "indexmap", "itertools", - "kstring", "serde", ] @@ -3752,9 +3821,9 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" [[package]] name = "tower-service" @@ -3764,9 +3833,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "log", @@ -3777,9 +3846,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", @@ -3788,9 +3857,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", "valuable", @@ -3819,13 +3888,13 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.11" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" dependencies = [ - "ansi_term", - "lazy_static", "matchers", + "nu-ansi-term", + "once_cell", "regex", "sharded-slab", "smallvec", @@ -3855,36 +3924,30 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "untrusted" @@ -3894,13 +3957,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -3920,7 +3982,7 @@ dependencies = [ "hyper", "jsonwebtoken", "metrics", - "nix", + "nix 0.25.0", "once_cell", "pin-project-lite", "postgres", @@ -3997,7 +4059,7 @@ name = "wal_craft" version = "0.1.0" dependencies = [ "anyhow", - "clap 3.2.16", + "clap", "env_logger", "log", "once_cell", @@ -4042,9 +4104,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4052,9 +4114,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -4067,9 +4129,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if", "js-sys", @@ -4079,9 +4141,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4089,9 +4151,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -4102,15 +4164,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -4128,22 +4190,22 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.4" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" +checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" dependencies = [ "webpki", ] [[package]] name = "which" -version = "4.2.5" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" dependencies = [ "either", - "lazy_static", "libc", + "once_cell", ] [[package]] @@ -4235,18 +4297,16 @@ version = "0.1.0" dependencies = [ "ahash", "anyhow", - "bstr", "bytes", "chrono", + "clap", "crossbeam-utils", "either", "fail", "hashbrown", "indexmap", - "itoa 0.4.8", "libc", "log", - "memchr", "nom", "num-bigint", "num-integer", @@ -4254,13 +4314,12 @@ dependencies = [ "prost", "rand", "regex", - "regex-automata", "regex-syntax", "scopeguard", "serde", "stable_deref_trait", "syn", - "time 0.3.12", + "time 0.3.15", "tokio", "tokio-util", "tracing", @@ -4283,7 +4342,7 @@ dependencies = [ "oid-registry", "rusticata-macros", "thiserror", - "time 0.3.12", + "time 0.3.15", ] [[package]] diff --git a/control_plane/Cargo.toml b/control_plane/Cargo.toml index ee8481e141..690b63613a 100644 --- a/control_plane/Cargo.toml +++ b/control_plane/Cargo.toml @@ -5,18 +5,18 @@ edition = "2021" [dependencies] clap = "3.0" -comfy-table = "5.0.1" +comfy-table = "6.1" git-version = "0.3.5" tar = "0.4.38" -postgres = { git = "https://github.com/neondatabase/rust-postgres.git", rev="d052ee8b86fff9897c77b0fe89ea9daba0e1fa38" } +postgres = { git = "https://github.com/neondatabase/rust-postgres.git", rev = "d052ee8b86fff9897c77b0fe89ea9daba0e1fa38" } serde = { version = "1.0", features = ["derive"] } -serde_with = "1.12.0" +serde_with = "2.0" toml = "0.5" once_cell = "1.13.0" regex = "1" anyhow = "1.0" thiserror = "1" -nix = "0.23" +nix = "0.25" reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "rustls-tls"] } # Note: Do not directly depend on pageserver or safekeeper; use pageserver_api or safekeeper_api diff --git a/libs/etcd_broker/Cargo.toml b/libs/etcd_broker/Cargo.toml index f7bfbad4ba..b18dcbe5a3 100644 --- a/libs/etcd_broker/Cargo.toml +++ b/libs/etcd_broker/Cargo.toml @@ -8,7 +8,7 @@ regex = "1.4.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1" - serde_with = "1.12.0" + serde_with = "2.0" once_cell = "1.13.0" utils = { path = "../utils" } diff --git a/libs/pageserver_api/Cargo.toml b/libs/pageserver_api/Cargo.toml index be8762100c..5995325a2f 100644 --- a/libs/pageserver_api/Cargo.toml +++ b/libs/pageserver_api/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] serde = { version = "1.0", features = ["derive"] } -serde_with = "1.12.0" +serde_with = "2.0" const_format = "0.2.21" utils = { path = "../utils" } diff --git a/libs/remote_storage/Cargo.toml b/libs/remote_storage/Cargo.toml index cec344a4ad..f54d91905c 100644 --- a/libs/remote_storage/Cargo.toml +++ b/libs/remote_storage/Cargo.toml @@ -15,7 +15,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1" tokio = { version = "1.17", features = ["sync", "macros", "fs", "io-util"] } tokio-util = { version = "0.7", features = ["io"] } -toml_edit = { version = "0.13", features = ["easy"] } +toml_edit = { version = "0.14", features = ["easy"] } tracing = "0.1.27" workspace_hack = { version = "0.1", path = "../../workspace_hack" } diff --git a/libs/safekeeper_api/Cargo.toml b/libs/safekeeper_api/Cargo.toml index 852d643f30..15bdecd71d 100644 --- a/libs/safekeeper_api/Cargo.toml +++ b/libs/safekeeper_api/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] serde = { version = "1.0", features = ["derive"] } -serde_with = "1.12.0" +serde_with = "2.0" const_format = "0.2.21" utils = { path = "../utils" } diff --git a/libs/safekeeper_api/src/models.rs b/libs/safekeeper_api/src/models.rs index 4119650b99..85c6439367 100644 --- a/libs/safekeeper_api/src/models.rs +++ b/libs/safekeeper_api/src/models.rs @@ -1,20 +1,23 @@ use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DisplayFromStr}; + use utils::{ id::{NodeId, TenantId, TimelineId}, lsn::Lsn, }; +#[serde_as] #[derive(Serialize, Deserialize)] pub struct TimelineCreateRequest { - #[serde(with = "serde_with::rust::display_fromstr")] + #[serde_as(as = "DisplayFromStr")] pub tenant_id: TenantId, - #[serde(with = "serde_with::rust::display_fromstr")] + #[serde_as(as = "DisplayFromStr")] pub timeline_id: TimelineId, pub peer_ids: Option>, pub pg_version: u32, pub system_id: Option, pub wal_seg_size: Option, - #[serde(with = "serde_with::rust::display_fromstr")] + #[serde_as(as = "DisplayFromStr")] pub commit_lsn: Lsn, // If not passed, it is assigned to the beginning of commit_lsn segment. pub local_start_lsn: Option, diff --git a/libs/utils/Cargo.toml b/libs/utils/Cargo.toml index ef2aa8b305..a7baddada4 100644 --- a/libs/utils/Cargo.toml +++ b/libs/utils/Cargo.toml @@ -20,7 +20,7 @@ tokio = { version = "1.17", features = ["macros"]} tokio-rustls = "0.23" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } -nix = "0.23.0" +nix = "0.25" signal-hook = "0.3.10" rand = "0.8.3" jsonwebtoken = "8" @@ -28,7 +28,7 @@ hex = { version = "0.4.3", features = ["serde"] } rustls = "0.20.2" rustls-split = "0.3.0" git-version = "0.3.5" -serde_with = "1.12.0" +serde_with = "2.0" once_cell = "1.13.0" @@ -40,7 +40,7 @@ byteorder = "1.4.3" bytes = "1.0.1" hex-literal = "0.3" tempfile = "3.2" -criterion = "0.3" +criterion = "0.4" rustls-pemfile = "1" [[bench]] diff --git a/pageserver/Cargo.toml b/pageserver/Cargo.toml index 88430f3a86..ea0cf3f18a 100644 --- a/pageserver/Cargo.toml +++ b/pageserver/Cargo.toml @@ -38,18 +38,18 @@ tar = "0.4.33" humantime = "2.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1" -serde_with = "1.12.0" +serde_with = "2.0" humantime-serde = "1.1.1" pprof = { git = "https://github.com/neondatabase/pprof-rs.git", branch = "wallclock-profiling", features = ["flamegraph"], optional = true } -toml_edit = { version = "0.13", features = ["easy"] } +toml_edit = { version = "0.14", features = ["easy"] } scopeguard = "1.1.0" const_format = "0.2.21" tracing = "0.1.36" signal-hook = "0.3.10" url = "2" -nix = "0.23" +nix = "0.25" once_cell = "1.13.0" crossbeam-utils = "0.8.5" fail = "0.5.0" diff --git a/safekeeper/Cargo.toml b/safekeeper/Cargo.toml index cb1cecade9..ddc3956d74 100644 --- a/safekeeper/Cargo.toml +++ b/safekeeper/Cargo.toml @@ -22,14 +22,14 @@ humantime = "2.1.0" url = "2.2.2" signal-hook = "0.3.10" serde = { version = "1.0", features = ["derive"] } -serde_with = "1.12.0" +serde_with = "2.0" hex = "0.4.3" const_format = "0.2.21" tokio-postgres = { git = "https://github.com/neondatabase/rust-postgres.git", rev="d052ee8b86fff9897c77b0fe89ea9daba0e1fa38" } git-version = "0.3.5" async-trait = "0.1" once_cell = "1.13.0" -toml_edit = { version = "0.13", features = ["easy"] } +toml_edit = { version = "0.14", features = ["easy"] } thiserror = "1" parking_lot = "0.12.1" diff --git a/workspace_hack/Cargo.toml b/workspace_hack/Cargo.toml index 6977665c7d..af055ed9a4 100644 --- a/workspace_hack/Cargo.toml +++ b/workspace_hack/Cargo.toml @@ -16,18 +16,16 @@ publish = false [dependencies] ahash = { version = "0.7", features = ["std"] } anyhow = { version = "1", features = ["backtrace", "std"] } -bstr = { version = "0.2", features = ["lazy_static", "regex-automata", "serde", "serde1", "serde1-nostd", "std", "unicode"] } bytes = { version = "1", features = ["serde", "std"] } -chrono = { version = "0.4", features = ["clock", "libc", "oldtime", "serde", "std", "time", "winapi"] } +chrono = { version = "0.4", features = ["clock", "iana-time-zone", "js-sys", "oldtime", "serde", "std", "time", "wasm-bindgen", "wasmbind", "winapi"] } +clap = { version = "3", features = ["atty", "color", "std", "strsim", "suggestions", "termcolor"] } crossbeam-utils = { version = "0.8", features = ["once_cell", "std"] } either = { version = "1", features = ["use_std"] } fail = { version = "0.5", default-features = false, features = ["failpoints"] } hashbrown = { version = "0.12", features = ["ahash", "inline-more", "raw"] } indexmap = { version = "1", default-features = false, features = ["std"] } -itoa = { version = "0.4", features = ["i128", "std"] } libc = { version = "0.2", features = ["extra_traits", "std"] } log = { version = "0.4", default-features = false, features = ["serde", "std"] } -memchr = { version = "2", features = ["std", "use_std"] } nom = { version = "7", features = ["alloc", "std"] } num-bigint = { version = "0.4", features = ["std"] } num-integer = { version = "0.1", default-features = false, features = ["i128", "std"] } @@ -35,7 +33,6 @@ num-traits = { version = "0.2", features = ["i128", "libm", "std"] } prost = { version = "0.10", features = ["prost-derive", "std"] } rand = { version = "0.8", features = ["alloc", "getrandom", "libc", "rand_chacha", "rand_hc", "small_rng", "std", "std_rng"] } regex = { version = "1", features = ["aho-corasick", "memchr", "perf", "perf-cache", "perf-dfa", "perf-inline", "perf-literal", "std", "unicode", "unicode-age", "unicode-bool", "unicode-case", "unicode-gencat", "unicode-perl", "unicode-script", "unicode-segment"] } -regex-automata = { version = "0.1", features = ["regex-syntax", "std"] } regex-syntax = { version = "0.6", features = ["unicode", "unicode-age", "unicode-bool", "unicode-case", "unicode-gencat", "unicode-perl", "unicode-script", "unicode-segment"] } scopeguard = { version = "1", features = ["use_std"] } serde = { version = "1", features = ["alloc", "derive", "serde_derive", "std"] } @@ -51,12 +48,12 @@ uuid = { version = "0.8", features = ["getrandom", "serde", "std", "v4"] } ahash = { version = "0.7", features = ["std"] } anyhow = { version = "1", features = ["backtrace", "std"] } bytes = { version = "1", features = ["serde", "std"] } +clap = { version = "3", features = ["atty", "color", "std", "strsim", "suggestions", "termcolor"] } either = { version = "1", features = ["use_std"] } hashbrown = { version = "0.12", features = ["ahash", "inline-more", "raw"] } indexmap = { version = "1", default-features = false, features = ["std"] } libc = { version = "0.2", features = ["extra_traits", "std"] } log = { version = "0.4", default-features = false, features = ["serde", "std"] } -memchr = { version = "2", features = ["std", "use_std"] } nom = { version = "7", features = ["alloc", "std"] } prost = { version = "0.10", features = ["prost-derive", "std"] } regex = { version = "1", features = ["aho-corasick", "memchr", "perf", "perf-cache", "perf-dfa", "perf-inline", "perf-literal", "std", "unicode", "unicode-age", "unicode-bool", "unicode-case", "unicode-gencat", "unicode-perl", "unicode-script", "unicode-segment"] } From 5d6553d41d383459ef5fb9ebfc1199faed978ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lassi=20P=C3=B6l=C3=B6nen?= Date: Sun, 16 Oct 2022 14:37:10 +0300 Subject: [PATCH 29/64] Fix pageserver configuration generation bug (#2584) * We had an issue with `lineinfile` usage for pageserver configuration file: if the S3 bucket related values were changed, it would have resulted in duplicate keys, resulting in invalid toml. So to fix the issue, we should keep the configuration in structured format (yaml in this case) so we can always generate syntactically correct toml. Inventories are converted to yaml just so that it's easier to maintain the configuration there. Another alternative would have been a separate variable files. * Keep the ansible collections dir, but locally installed collections should not be tracked. --- .github/ansible/.gitignore | 3 ++ .github/ansible/ansible.cfg | 1 + .github/ansible/collections/.keep | 0 .github/ansible/deploy.yaml | 35 ++++++++++++----- .github/ansible/neon-stress.hosts | 20 ---------- .github/ansible/neon-stress.hosts.yaml | 30 +++++++++++++++ .github/ansible/production.hosts | 20 ---------- .github/ansible/production.hosts.yaml | 31 +++++++++++++++ .github/ansible/staging.hosts | 25 ------------ .github/ansible/staging.hosts.yaml | 40 ++++++++++++++++++++ .github/ansible/templates/pageserver.toml.j2 | 1 + .github/workflows/build_and_test.yml | 6 +-- 12 files changed, 134 insertions(+), 78 deletions(-) create mode 100644 .github/ansible/collections/.keep delete mode 100644 .github/ansible/neon-stress.hosts create mode 100644 .github/ansible/neon-stress.hosts.yaml delete mode 100644 .github/ansible/production.hosts create mode 100644 .github/ansible/production.hosts.yaml delete mode 100644 .github/ansible/staging.hosts create mode 100644 .github/ansible/staging.hosts.yaml create mode 100644 .github/ansible/templates/pageserver.toml.j2 diff --git a/.github/ansible/.gitignore b/.github/ansible/.gitignore index 441d9a8b82..e3454fd43c 100644 --- a/.github/ansible/.gitignore +++ b/.github/ansible/.gitignore @@ -2,3 +2,6 @@ zenith_install.tar.gz .zenith_current_version neon_install.tar.gz .neon_current_version + +collections/* +!collections/.keep diff --git a/.github/ansible/ansible.cfg b/.github/ansible/ansible.cfg index 5818a64455..0497ee401d 100644 --- a/.github/ansible/ansible.cfg +++ b/.github/ansible/ansible.cfg @@ -3,6 +3,7 @@ localhost_warning = False host_key_checking = False timeout = 30 +collections_paths = ./collections [ssh_connection] ssh_args = -F ./ansible.ssh.cfg diff --git a/.github/ansible/collections/.keep b/.github/ansible/collections/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.github/ansible/deploy.yaml b/.github/ansible/deploy.yaml index e206f9d5ba..bfd3fd123d 100644 --- a/.github/ansible/deploy.yaml +++ b/.github/ansible/deploy.yaml @@ -14,7 +14,8 @@ - safekeeper - name: inform about versions - debug: msg="Version to deploy - {{ current_version }}" + debug: + msg: "Version to deploy - {{ current_version }}" tags: - pageserver - safekeeper @@ -63,15 +64,29 @@ tags: - pageserver - - name: update remote storage (s3) config - lineinfile: - path: /storage/pageserver/data/pageserver.toml - line: "{{ item }}" - loop: - - "[remote_storage]" - - "bucket_name = '{{ bucket_name }}'" - - "bucket_region = '{{ bucket_region }}'" - - "prefix_in_bucket = '{{ inventory_hostname }}'" + - name: read the existing remote pageserver config + ansible.builtin.slurp: + src: /storage/pageserver/data/pageserver.toml + register: _remote_ps_config + tags: + - pageserver + + - name: parse the existing pageserver configuration + ansible.builtin.set_fact: + _existing_ps_config: "{{ _remote_ps_config['content'] | b64decode | sivel.toiletwater.from_toml }}" + tags: + - pageserver + + - name: construct the final pageserver configuration dict + ansible.builtin.set_fact: + pageserver_config: "{{ pageserver_config_stub | combine({'id': _existing_ps_config.id }) }}" + tags: + - pageserver + + - name: template the pageserver config + template: + src: templates/pageserver.toml.j2 + dest: /storage/pageserver/data/pageserver.toml become: true tags: - pageserver diff --git a/.github/ansible/neon-stress.hosts b/.github/ansible/neon-stress.hosts deleted file mode 100644 index c1bc8243f8..0000000000 --- a/.github/ansible/neon-stress.hosts +++ /dev/null @@ -1,20 +0,0 @@ -[pageservers] -neon-stress-ps-1 console_region_id=1 -neon-stress-ps-2 console_region_id=1 - -[safekeepers] -neon-stress-sk-1 console_region_id=1 -neon-stress-sk-2 console_region_id=1 -neon-stress-sk-3 console_region_id=1 - -[storage:children] -pageservers -safekeepers - -[storage:vars] -env_name = neon-stress -console_mgmt_base_url = http://neon-stress-console.local -bucket_name = neon-storage-ireland -bucket_region = eu-west-1 -etcd_endpoints = neon-stress-etcd.local:2379 -safekeeper_enable_s3_offload = false diff --git a/.github/ansible/neon-stress.hosts.yaml b/.github/ansible/neon-stress.hosts.yaml new file mode 100644 index 0000000000..d4c77e7ada --- /dev/null +++ b/.github/ansible/neon-stress.hosts.yaml @@ -0,0 +1,30 @@ +storage: + vars: + bucket_name: neon-storage-ireland + bucket_region: eu-west-1 + console_mgmt_base_url: http://neon-stress-console.local + env_name: neon-stress + etcd_endpoints: neon-stress-etcd.local:2379 + safekeeper_enable_s3_offload: 'false' + pageserver_config_stub: + pg_distrib_dir: /usr/local + remote_storage: + bucket_name: "{{ bucket_name }}" + bucket_region: "{{ bucket_region }}" + prefix_in_bucket: "{{ inventory_hostname }}" + + children: + pageservers: + hosts: + neon-stress-ps-1: + console_region_id: 1 + neon-stress-ps-2: + console_region_id: 1 + safekeepers: + hosts: + neon-stress-sk-1: + console_region_id: 1 + neon-stress-sk-2: + console_region_id: 1 + neon-stress-sk-3: + console_region_id: 1 diff --git a/.github/ansible/production.hosts b/.github/ansible/production.hosts deleted file mode 100644 index 364e8ed50e..0000000000 --- a/.github/ansible/production.hosts +++ /dev/null @@ -1,20 +0,0 @@ -[pageservers] -#zenith-1-ps-1 console_region_id=1 -zenith-1-ps-2 console_region_id=1 -zenith-1-ps-3 console_region_id=1 - -[safekeepers] -zenith-1-sk-1 console_region_id=1 -zenith-1-sk-2 console_region_id=1 -zenith-1-sk-3 console_region_id=1 - -[storage:children] -pageservers -safekeepers - -[storage:vars] -env_name = prod-1 -console_mgmt_base_url = http://console-release.local -bucket_name = zenith-storage-oregon -bucket_region = us-west-2 -etcd_endpoints = zenith-1-etcd.local:2379 diff --git a/.github/ansible/production.hosts.yaml b/.github/ansible/production.hosts.yaml new file mode 100644 index 0000000000..c276ca3805 --- /dev/null +++ b/.github/ansible/production.hosts.yaml @@ -0,0 +1,31 @@ +--- +storage: + vars: + env_name: prod-1 + console_mgmt_base_url: http://console-release.local + bucket_name: zenith-storage-oregon + bucket_region: us-west-2 + etcd_endpoints: zenith-1-etcd.local:2379 + pageserver_config_stub: + pg_distrib_dir: /usr/local + remote_storage: + bucket_name: "{{ bucket_name }}" + bucket_region: "{{ bucket_region }}" + prefix_in_bucket: "{{ inventory_hostname }}" + + children: + pageservers: + hosts: + zenith-1-ps-2: + console_region_id: 1 + zenith-1-ps-3: + console_region_id: 1 + + safekeepers: + hosts: + zenith-1-sk-1: + console_region_id: 1 + zenith-1-sk-2: + console_region_id: 1 + zenith-1-sk-3: + console_region_id: 1 diff --git a/.github/ansible/staging.hosts b/.github/ansible/staging.hosts deleted file mode 100644 index f5accc188a..0000000000 --- a/.github/ansible/staging.hosts +++ /dev/null @@ -1,25 +0,0 @@ -[pageservers] -#zenith-us-stage-ps-1 console_region_id=27 -zenith-us-stage-ps-2 console_region_id=27 -zenith-us-stage-ps-3 console_region_id=27 -zenith-us-stage-ps-4 console_region_id=27 -zenith-us-stage-test-ps-1 console_region_id=28 - -[safekeepers] -zenith-us-stage-sk-4 console_region_id=27 -zenith-us-stage-sk-5 console_region_id=27 -zenith-us-stage-sk-6 console_region_id=27 -zenith-us-stage-test-sk-1 console_region_id=28 -zenith-us-stage-test-sk-2 console_region_id=28 -zenith-us-stage-test-sk-3 console_region_id=28 - -[storage:children] -pageservers -safekeepers - -[storage:vars] -env_name = us-stage -console_mgmt_base_url = http://console-staging.local -bucket_name = zenith-staging-storage-us-east-1 -bucket_region = us-east-1 -etcd_endpoints = zenith-us-stage-etcd.local:2379 diff --git a/.github/ansible/staging.hosts.yaml b/.github/ansible/staging.hosts.yaml new file mode 100644 index 0000000000..a3534ed5ce --- /dev/null +++ b/.github/ansible/staging.hosts.yaml @@ -0,0 +1,40 @@ +storage: + vars: + bucket_name: zenith-staging-storage-us-east-1 + bucket_region: us-east-1 + console_mgmt_base_url: http://console-staging.local + env_name: us-stage + etcd_endpoints: zenith-us-stage-etcd.local:2379 + pageserver_config_stub: + pg_distrib_dir: /usr/local + remote_storage: + bucket_name: "{{ bucket_name }}" + bucket_region: "{{ bucket_region }}" + prefix_in_bucket: "{{ inventory_hostname }}" + + children: + pageservers: + hosts: + zenith-us-stage-ps-2: + console_region_id: 27 + zenith-us-stage-ps-3: + console_region_id: 27 + zenith-us-stage-ps-4: + console_region_id: 27 + zenith-us-stage-test-ps-1: + console_region_id: 28 + + safekeepers: + hosts: + zenith-us-stage-sk-4: + console_region_id: 27 + zenith-us-stage-sk-5: + console_region_id: 27 + zenith-us-stage-sk-6: + console_region_id: 27 + zenith-us-stage-test-sk-1: + console_region_id: 28 + zenith-us-stage-test-sk-2: + console_region_id: 28 + zenith-us-stage-test-sk-3: + console_region_id: 28 diff --git a/.github/ansible/templates/pageserver.toml.j2 b/.github/ansible/templates/pageserver.toml.j2 new file mode 100644 index 0000000000..7b0857d5e0 --- /dev/null +++ b/.github/ansible/templates/pageserver.toml.j2 @@ -0,0 +1 @@ +{{ pageserver_config | sivel.toiletwater.to_toml }} diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 69b17113ed..e8d724581d 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -712,7 +712,7 @@ jobs: - name: Setup ansible run: | export PATH="/root/.local/bin:$PATH" - pip install --progress-bar off --user ansible boto3 + pip install --progress-bar off --user ansible boto3 toml - name: Redeploy run: | @@ -734,8 +734,8 @@ jobs: chmod 0600 ssh-key ssh-add ssh-key rm -f ssh-key ssh-key-cert.pub - - ansible-playbook deploy.yaml -i ${{ matrix.env_name }}.hosts + ansible-galaxy collection install sivel.toiletwater + ansible-playbook deploy.yaml -i ${{ matrix.env_name }}.hosts.yaml rm -f neon_install.tar.gz .neon_current_version deploy-proxy: From c7093545794e5a1072fa358d1aa38c87031bce7e Mon Sep 17 00:00:00 2001 From: Joonas Koivunen Date: Mon, 17 Oct 2022 12:21:04 +0300 Subject: [PATCH 30/64] Add layer sizes to index_part.json (#2582) This is the first step in verifying layer files. Next up on the road is hashing the files and verifying the hashes. The metadata additions do not require any migration. The idea is that the change is backward and forward-compatible with regard to `index_part.json` due to the softness of JSON schema and the deserialization options in use. New types added: - LayerFileMetadata for tracking the file metadata - starting with only the file size - in future hopefully a sha256 as well - IndexLayerMetadata, the serialized counterpart of LayerFileMetadata LayerFileMetadata needing to have all fields Option is a problem but that is not possible to handle without conflicting a lot more with other ongoing work. Co-authored-by: Kirill Bulatov --- pageserver/src/http/routes.rs | 2 +- pageserver/src/storage_sync.rs | 384 ++++++++++++++---- pageserver/src/storage_sync/delete.rs | 2 +- pageserver/src/storage_sync/download.rs | 267 +++++++----- pageserver/src/storage_sync/index.rs | 293 ++++++++++--- pageserver/src/storage_sync/upload.rs | 52 ++- pageserver/src/tenant/timeline.rs | 57 ++- pageserver/src/tenant_mgr.rs | 33 +- .../test_tenants_with_remote_storage.py | 246 +++++++++++ 9 files changed, 1057 insertions(+), 279 deletions(-) diff --git a/pageserver/src/http/routes.rs b/pageserver/src/http/routes.rs index 4d7339ec13..91a385bf77 100644 --- a/pageserver/src/http/routes.rs +++ b/pageserver/src/http/routes.rs @@ -386,7 +386,7 @@ async fn tenant_attach_handler(request: Request) -> Result, } return json_response(StatusCode::ACCEPTED, ()); } - // no tenant in the index, release the lock to make the potentially lengthy download opetation + // no tenant in the index, release the lock to make the potentially lengthy download operation drop(index_accessor); // download index parts for every tenant timeline diff --git a/pageserver/src/storage_sync.rs b/pageserver/src/storage_sync.rs index e8844baf5d..037fe76d7f 100644 --- a/pageserver/src/storage_sync.rs +++ b/pageserver/src/storage_sync.rs @@ -171,7 +171,7 @@ use self::{ use crate::{ config::PageServerConf, exponential_backoff, - storage_sync::index::RemoteIndex, + storage_sync::index::{LayerFileMetadata, RemoteIndex}, task_mgr, task_mgr::TaskKind, task_mgr::BACKGROUND_RUNTIME, @@ -193,7 +193,7 @@ static SYNC_QUEUE: OnceCell = OnceCell::new(); /// A timeline status to share with pageserver's sync counterpart, /// after comparing local and remote timeline state. -#[derive(Clone)] +#[derive(Clone, PartialEq, Eq)] pub enum LocalTimelineInitStatus { /// The timeline has every remote layer present locally. /// There could be some layers requiring uploading, @@ -316,7 +316,7 @@ impl SyncQueue { /// A task to run in the async download/upload loop. /// Limited by the number of retries, after certain threshold the failing task gets evicted and the timeline disabled. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] enum SyncTask { /// A checkpoint outcome with possible local file updates that need actualization in the remote storage. /// Not necessary more fresh than the one already uploaded. @@ -427,7 +427,7 @@ impl SyncTaskBatch { .extend(new_delete.data.deleted_layers.iter().cloned()); } if let Some(batch_upload) = &mut self.upload { - let not_deleted = |layer: &PathBuf| { + let not_deleted = |layer: &PathBuf, _: &mut LayerFileMetadata| { !new_delete.data.layers_to_delete.contains(layer) && !new_delete.data.deleted_layers.contains(layer) }; @@ -455,21 +455,35 @@ impl SyncTaskBatch { #[derive(Debug, Clone, PartialEq, Eq)] struct LayersUpload { /// Layer file path in the pageserver workdir, that were added for the corresponding checkpoint. - layers_to_upload: HashSet, + layers_to_upload: HashMap, /// Already uploaded layers. Used to store the data about the uploads between task retries /// and to record the data into the remote index after the task got completed or evicted. - uploaded_layers: HashSet, + uploaded_layers: HashMap, metadata: Option, } /// A timeline download task. /// Does not contain the file list to download, to allow other /// parts of the pageserer code to schedule the task -/// without using the remote index or any other ways to list the remote timleine files. +/// without using the remote index or any other ways to list the remote timeline files. /// Skips the files that are already downloaded. #[derive(Debug, Clone, PartialEq, Eq)] struct LayersDownload { layers_to_skip: HashSet, + + /// Paths which have been downloaded, and had their metadata verified or generated. + /// + /// Metadata generation happens when upgrading from past version of `IndexPart`. + gathered_metadata: HashMap, +} + +impl LayersDownload { + fn from_skipped_layers(layers_to_skip: HashSet) -> Self { + LayersDownload { + layers_to_skip, + gathered_metadata: HashMap::default(), + } + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -491,7 +505,7 @@ struct LayersDeletion { pub fn schedule_layer_upload( tenant_id: TenantId, timeline_id: TimelineId, - layers_to_upload: HashSet, + layers_to_upload: HashMap, metadata: Option, ) { let sync_queue = match SYNC_QUEUE.get() { @@ -508,7 +522,7 @@ pub fn schedule_layer_upload( }, SyncTask::upload(LayersUpload { layers_to_upload, - uploaded_layers: HashSet::new(), + uploaded_layers: HashMap::new(), metadata, }), ); @@ -566,21 +580,44 @@ pub fn schedule_layer_download(tenant_id: TenantId, timeline_id: TimelineId) { tenant_id, timeline_id, }, - SyncTask::download(LayersDownload { - layers_to_skip: HashSet::new(), - }), + SyncTask::download(LayersDownload::from_skipped_layers(HashSet::new())), ); debug!("Download task for tenant {tenant_id}, timeline {timeline_id} sent") } +/// Local existing timeline files +/// +/// Values of this type serve different meanings in different contexts. On startup, collected +/// timelines come with the full collected information and when signalling readyness to attach +/// after completed download. After the download the file information is no longer carried, because +/// it is already merged into [`RemoteTimeline`]. +#[derive(Debug)] +pub struct TimelineLocalFiles(TimelineMetadata, HashMap); + +impl TimelineLocalFiles { + pub fn metadata(&self) -> &TimelineMetadata { + &self.0 + } + + /// Called during startup, for all of the local files with full metadata. + pub(crate) fn collected( + metadata: TimelineMetadata, + timeline_files: HashMap, + ) -> TimelineLocalFiles { + TimelineLocalFiles(metadata, timeline_files) + } + + /// Called near the end of tenant initialization, to signal readyness to attach tenants. + pub(crate) fn ready(metadata: TimelineMetadata) -> Self { + TimelineLocalFiles(metadata, HashMap::new()) + } +} + /// Launch a thread to perform remote storage sync tasks. /// See module docs for loop step description. pub fn spawn_storage_sync_task( conf: &'static PageServerConf, - local_timeline_files: HashMap< - TenantId, - HashMap)>, - >, + local_timeline_files: HashMap>, storage: GenericRemoteStorage, max_concurrent_timelines_sync: NonZeroUsize, max_sync_errors: NonZeroU32, @@ -738,7 +775,7 @@ async fn storage_sync_loop( tenant_entry .iter() .map(|(&id, entry)| { - (id, (entry.metadata.clone(), HashSet::new())) + (id, TimelineLocalFiles::ready(entry.metadata.clone())) }) .collect(), ), @@ -983,15 +1020,27 @@ async fn download_timeline_data( } DownloadedTimeline::Successful(mut download_data) => { match update_local_metadata(conf, sync_id, current_remote_timeline).await { - Ok(()) => match index.write().await.set_awaits_download(&sync_id, false) { - Ok(()) => { - register_sync_status(sync_id, sync_start, TASK_NAME, Some(true)); - return DownloadStatus::Downloaded; - } - Err(e) => { - error!("Timeline {sync_id} was expected to be in the remote index after a successful download, but it's absent: {e:?}"); - } - }, + Ok(()) => { + let mut g = index.write().await; + + match g.set_awaits_download(&sync_id, false) { + Ok(()) => { + let timeline = g + .timeline_entry_mut(&sync_id) + .expect("set_awaits_download verified existence"); + + timeline.merge_metadata_from_downloaded( + &download_data.data.gathered_metadata, + ); + + register_sync_status(sync_id, sync_start, TASK_NAME, Some(true)); + return DownloadStatus::Downloaded; + } + Err(e) => { + error!("Timeline {sync_id} was expected to be in the remote index after a successful download, but it's absent: {e:?}"); + } + }; + } Err(e) => { error!("Failed to update local timeline metadata: {e:?}"); download_data.retries += 1; @@ -1194,11 +1243,18 @@ async fn update_remote_data( } if upload_failed { existing_entry.add_upload_failures( - uploaded_data.layers_to_upload.iter().cloned(), + uploaded_data + .layers_to_upload + .iter() + .map(|(k, v)| (k.to_owned(), v.to_owned())), ); } else { - existing_entry - .add_timeline_layers(uploaded_data.uploaded_layers.iter().cloned()); + existing_entry.add_timeline_layers( + uploaded_data + .uploaded_layers + .iter() + .map(|(k, v)| (k.to_owned(), v.to_owned())), + ); } } RemoteDataUpdate::Delete(layers_to_remove) => { @@ -1218,11 +1274,19 @@ async fn update_remote_data( }; let mut new_remote_timeline = RemoteTimeline::new(new_metadata.clone()); if upload_failed { - new_remote_timeline - .add_upload_failures(uploaded_data.layers_to_upload.iter().cloned()); + new_remote_timeline.add_upload_failures( + uploaded_data + .layers_to_upload + .iter() + .map(|(k, v)| (k.to_owned(), v.to_owned())), + ); } else { - new_remote_timeline - .add_timeline_layers(uploaded_data.uploaded_layers.iter().cloned()); + new_remote_timeline.add_timeline_layers( + uploaded_data + .uploaded_layers + .iter() + .map(|(k, v)| (k.to_owned(), v.to_owned())), + ); } index_accessor.add_timeline_entry(sync_id, new_remote_timeline.clone()); @@ -1270,13 +1334,14 @@ async fn validate_task_retries( fn schedule_first_sync_tasks( index: &mut RemoteTimelineIndex, sync_queue: &SyncQueue, - local_timeline_files: HashMap)>, + local_timeline_files: HashMap, ) -> TenantTimelineValues { let mut local_timeline_init_statuses = TenantTimelineValues::new(); let mut new_sync_tasks = VecDeque::with_capacity(local_timeline_files.len()); - for (sync_id, (local_metadata, local_files)) in local_timeline_files { + for (sync_id, local_timeline) in local_timeline_files { + let TimelineLocalFiles(local_metadata, local_files) = local_timeline; match index.timeline_entry_mut(&sync_id) { Some(remote_timeline) => { let (timeline_status, awaits_download) = compare_local_and_remote_timeline( @@ -1320,7 +1385,7 @@ fn schedule_first_sync_tasks( sync_id, SyncTask::upload(LayersUpload { layers_to_upload: local_files, - uploaded_layers: HashSet::new(), + uploaded_layers: HashMap::new(), metadata: Some(local_metadata.clone()), }), )); @@ -1347,20 +1412,46 @@ fn compare_local_and_remote_timeline( new_sync_tasks: &mut VecDeque<(TenantTimelineId, SyncTask)>, sync_id: TenantTimelineId, local_metadata: TimelineMetadata, - local_files: HashSet, + local_files: HashMap, remote_entry: &RemoteTimeline, ) -> (LocalTimelineInitStatus, bool) { let _entered = info_span!("compare_local_and_remote_timeline", sync_id = %sync_id).entered(); - let remote_files = remote_entry.stored_files(); + let needed_to_download_files = remote_entry + .stored_files() + .iter() + .filter_map(|(layer_file, remote_metadata)| { + if let Some(local_metadata) = local_files.get(layer_file) { + match (remote_metadata.file_size(), local_metadata.file_size()) { + (Some(x), Some(y)) if x == y => { None }, + (None, Some(_)) => { + // upgrading from an earlier IndexPart without metadata + None + }, + _ => { + // having to deal with other than (Some(x), Some(y)) where x != y here is a + // bummer, but see #2582 and #2610 for attempts and discussion. + warn!("Redownloading locally existing {layer_file:?} due to size mismatch, size on index: {:?}, on disk: {:?}", remote_metadata.file_size(), local_metadata.file_size()); + Some(layer_file) + }, + } + } else { + // doesn't exist locally + Some(layer_file) + } + }) + .collect::>(); - let number_of_layers_to_download = remote_files.difference(&local_files).count(); - let (initial_timeline_status, awaits_download) = if number_of_layers_to_download > 0 { + let (initial_timeline_status, awaits_download) = if !needed_to_download_files.is_empty() { new_sync_tasks.push_back(( sync_id, - SyncTask::download(LayersDownload { - layers_to_skip: local_files.clone(), - }), + SyncTask::download(LayersDownload::from_skipped_layers( + local_files + .keys() + .filter(|path| !needed_to_download_files.contains(path)) + .cloned() + .collect(), + )), )); info!("NeedsSync"); (LocalTimelineInitStatus::NeedsSync, true) @@ -1375,15 +1466,22 @@ fn compare_local_and_remote_timeline( }; let layers_to_upload = local_files - .difference(remote_files) - .cloned() - .collect::>(); + .iter() + .filter_map(|(local_file, metadata)| { + if !remote_entry.stored_files().contains_key(local_file) { + Some((local_file.to_owned(), metadata.to_owned())) + } else { + None + } + }) + .collect::>(); + if !layers_to_upload.is_empty() { new_sync_tasks.push_back(( sync_id, SyncTask::upload(LayersUpload { layers_to_upload, - uploaded_layers: HashSet::new(), + uploaded_layers: HashMap::new(), metadata: Some(local_metadata), }), )); @@ -1439,11 +1537,12 @@ mod test_utils { let timeline_path = harness.timeline_path(&timeline_id); fs::create_dir_all(&timeline_path).await?; - let mut layers_to_upload = HashSet::with_capacity(filenames.len()); + let mut layers_to_upload = HashMap::with_capacity(filenames.len()); for &file in filenames { let file_path = timeline_path.join(file); fs::write(&file_path, dummy_contents(file).into_bytes()).await?; - layers_to_upload.insert(file_path); + let metadata = LayerFileMetadata::new(file_path.metadata()?.len()); + layers_to_upload.insert(file_path, metadata); } fs::write( @@ -1454,7 +1553,7 @@ mod test_utils { Ok(LayersUpload { layers_to_upload, - uploaded_layers: HashSet::new(), + uploaded_layers: HashMap::new(), metadata: Some(metadata), }) } @@ -1509,12 +1608,13 @@ mod tests { assert!(sync_id_2 != sync_id_3); assert!(sync_id_3 != TEST_SYNC_ID); - let download_task = SyncTask::download(LayersDownload { - layers_to_skip: HashSet::from([PathBuf::from("sk")]), - }); + let download_task = + SyncTask::download(LayersDownload::from_skipped_layers(HashSet::from([ + PathBuf::from("sk"), + ]))); let upload_task = SyncTask::upload(LayersUpload { - layers_to_upload: HashSet::from([PathBuf::from("up")]), - uploaded_layers: HashSet::from([PathBuf::from("upl")]), + layers_to_upload: HashMap::from([(PathBuf::from("up"), LayerFileMetadata::new(123))]), + uploaded_layers: HashMap::from([(PathBuf::from("upl"), LayerFileMetadata::new(123))]), metadata: Some(dummy_metadata(Lsn(2))), }); let delete_task = SyncTask::delete(LayersDeletion { @@ -1558,12 +1658,10 @@ mod tests { let sync_queue = SyncQueue::new(NonZeroUsize::new(100).unwrap()); assert_eq!(sync_queue.len(), 0); - let download = LayersDownload { - layers_to_skip: HashSet::from([PathBuf::from("sk")]), - }; + let download = LayersDownload::from_skipped_layers(HashSet::from([PathBuf::from("sk")])); let upload = LayersUpload { - layers_to_upload: HashSet::from([PathBuf::from("up")]), - uploaded_layers: HashSet::from([PathBuf::from("upl")]), + layers_to_upload: HashMap::from([(PathBuf::from("up"), LayerFileMetadata::new(123))]), + uploaded_layers: HashMap::from([(PathBuf::from("upl"), LayerFileMetadata::new(123))]), metadata: Some(dummy_metadata(Lsn(2))), }; let delete = LayersDeletion { @@ -1611,18 +1709,10 @@ mod tests { #[tokio::test] async fn same_task_id_same_tasks_batch() { let sync_queue = SyncQueue::new(NonZeroUsize::new(1).unwrap()); - let download_1 = LayersDownload { - layers_to_skip: HashSet::from([PathBuf::from("sk1")]), - }; - let download_2 = LayersDownload { - layers_to_skip: HashSet::from([PathBuf::from("sk2")]), - }; - let download_3 = LayersDownload { - layers_to_skip: HashSet::from([PathBuf::from("sk3")]), - }; - let download_4 = LayersDownload { - layers_to_skip: HashSet::from([PathBuf::from("sk4")]), - }; + let download_1 = LayersDownload::from_skipped_layers(HashSet::from([PathBuf::from("sk1")])); + let download_2 = LayersDownload::from_skipped_layers(HashSet::from([PathBuf::from("sk2")])); + let download_3 = LayersDownload::from_skipped_layers(HashSet::from([PathBuf::from("sk3")])); + let download_4 = LayersDownload::from_skipped_layers(HashSet::from([PathBuf::from("sk4")])); let sync_id_2 = TenantTimelineId { tenant_id: TenantId::from_array(hex!("22223344556677881122334455667788")), @@ -1646,15 +1736,15 @@ mod tests { Some(SyncTaskBatch { download: Some(SyncData { retries: 0, - data: LayersDownload { - layers_to_skip: { + data: LayersDownload::from_skipped_layers( + { let mut set = HashSet::new(); set.extend(download_1.layers_to_skip.into_iter()); set.extend(download_2.layers_to_skip.into_iter()); set.extend(download_4.layers_to_skip.into_iter()); set }, - } + ) }), upload: None, delete: None, @@ -1670,4 +1760,148 @@ mod tests { "Should have one task left out of the batch" ); } + + mod local_and_remote_comparisons { + use super::*; + + #[test] + fn ready() { + let mut new_sync_tasks = VecDeque::default(); + let sync_id = TenantTimelineId::generate(); + let local_metadata = dummy_metadata(0x02.into()); + let local_files = + HashMap::from([(PathBuf::from("first_file"), LayerFileMetadata::new(123))]); + let mut remote_entry = RemoteTimeline::new(local_metadata.clone()); + remote_entry + .add_timeline_layers([(PathBuf::from("first_file"), LayerFileMetadata::new(123))]); + + let (status, sync_needed) = compare_local_and_remote_timeline( + &mut new_sync_tasks, + sync_id, + local_metadata.clone(), + local_files, + &remote_entry, + ); + + assert_eq!( + status, + LocalTimelineInitStatus::LocallyComplete(local_metadata) + ); + assert!(!sync_needed); + + assert!(new_sync_tasks.is_empty(), "{:?}", new_sync_tasks); + } + + #[test] + fn needs_download() { + let mut new_sync_tasks = VecDeque::default(); + let sync_id = TenantTimelineId::generate(); + let local_metadata = dummy_metadata(0x02.into()); + let local_files = HashMap::default(); + let mut remote_entry = RemoteTimeline::new(local_metadata.clone()); + remote_entry + .add_timeline_layers([(PathBuf::from("first_file"), LayerFileMetadata::new(123))]); + + let (status, sync_needed) = compare_local_and_remote_timeline( + &mut new_sync_tasks, + sync_id, + local_metadata, + local_files.clone(), + &remote_entry, + ); + + assert_eq!(status, LocalTimelineInitStatus::NeedsSync); + assert!(sync_needed); + + let new_sync_tasks = new_sync_tasks.into_iter().collect::>(); + + assert_eq!( + &new_sync_tasks, + &[( + sync_id, + SyncTask::download(LayersDownload::from_skipped_layers( + local_files.keys().cloned().collect() + )) + )] + ); + } + + #[test] + fn redownload_is_not_needed_on_upgrade() { + // originally the implementation missed the `(None, Some(_))` case in the match, and + // proceeded to always redownload if the remote metadata was not available. + + let mut new_sync_tasks = VecDeque::default(); + let sync_id = TenantTimelineId::generate(); + + let local_metadata = dummy_metadata(0x02.into()); + + // type system would in general allow that LayerFileMetadata would be created with + // file_size: None, however `LayerFileMetadata::default` is only allowed from tests, + // and so everywhere within the system valid LayerFileMetadata is being created, it is + // created through `::new`. + let local_files = + HashMap::from([(PathBuf::from("first_file"), LayerFileMetadata::new(123))]); + + let mut remote_entry = RemoteTimeline::new(local_metadata.clone()); + + // RemoteTimeline is constructed out of an older version IndexPart, which didn't carry + // any metadata. + remote_entry + .add_timeline_layers([(PathBuf::from("first_file"), LayerFileMetadata::default())]); + + let (status, sync_needed) = compare_local_and_remote_timeline( + &mut new_sync_tasks, + sync_id, + local_metadata.clone(), + local_files, + &remote_entry, + ); + + assert_eq!( + status, + LocalTimelineInitStatus::LocallyComplete(local_metadata) + ); + assert!(!sync_needed); + } + + #[test] + fn needs_upload() { + let mut new_sync_tasks = VecDeque::default(); + let sync_id = TenantTimelineId::generate(); + let local_metadata = dummy_metadata(0x02.into()); + let local_files = + HashMap::from([(PathBuf::from("first_file"), LayerFileMetadata::new(123))]); + let mut remote_entry = RemoteTimeline::new(local_metadata.clone()); + remote_entry.add_timeline_layers([]); + + let (status, sync_needed) = compare_local_and_remote_timeline( + &mut new_sync_tasks, + sync_id, + local_metadata.clone(), + local_files.clone(), + &remote_entry, + ); + + assert_eq!( + status, + LocalTimelineInitStatus::LocallyComplete(local_metadata.clone()) + ); + assert!(!sync_needed); + + let new_sync_tasks = new_sync_tasks.into_iter().collect::>(); + + assert_eq!( + &new_sync_tasks, + &[( + sync_id, + SyncTask::upload(LayersUpload { + layers_to_upload: local_files, + uploaded_layers: HashMap::default(), + metadata: Some(local_metadata), + }) + )] + ); + } + } } diff --git a/pageserver/src/storage_sync/delete.rs b/pageserver/src/storage_sync/delete.rs index 21a3372e70..39846f0da3 100644 --- a/pageserver/src/storage_sync/delete.rs +++ b/pageserver/src/storage_sync/delete.rs @@ -171,7 +171,7 @@ mod tests { let local_timeline_path = harness.timeline_path(&TIMELINE_ID); let timeline_upload = create_local_timeline(&harness, TIMELINE_ID, &layer_files, metadata.clone()).await?; - for local_path in timeline_upload.layers_to_upload { + for (local_path, _metadata) in timeline_upload.layers_to_upload { let remote_path = local_storage.resolve_in_storage(&local_storage.remote_object_id(&local_path)?)?; let remote_parent_dir = remote_path.parent().unwrap(); diff --git a/pageserver/src/storage_sync/download.rs b/pageserver/src/storage_sync/download.rs index 3e850443d8..61ef164f14 100644 --- a/pageserver/src/storage_sync/download.rs +++ b/pageserver/src/storage_sync/download.rs @@ -16,7 +16,11 @@ use tokio::{ }; use tracing::{debug, error, info, warn}; -use crate::{config::PageServerConf, storage_sync::SyncTask, TEMP_FILE_SUFFIX}; +use crate::{ + config::PageServerConf, + storage_sync::{index::LayerFileMetadata, SyncTask}, + TEMP_FILE_SUFFIX, +}; use utils::{ crashsafe_dir::path_with_suffix_extension, id::{TenantId, TenantTimelineId, TimelineId}, @@ -219,8 +223,14 @@ pub(super) async fn download_timeline_layers<'a>( let layers_to_download = remote_timeline .stored_files() - .difference(&download.layers_to_skip) - .cloned() + .iter() + .filter_map(|(layer_path, metadata)| { + if !download.layers_to_skip.contains(layer_path) { + Some((layer_path.to_owned(), metadata.to_owned())) + } else { + None + } + }) .collect::>(); debug!("Layers to download: {layers_to_download:?}"); @@ -233,89 +243,129 @@ pub(super) async fn download_timeline_layers<'a>( let mut download_tasks = layers_to_download .into_iter() - .map(|layer_destination_path| async move { - if layer_destination_path.exists() { - debug!( - "Layer already exists locally, skipping download: {}", - layer_destination_path.display() - ); - } else { - // Perform a rename inspired by durable_rename from file_utils.c. - // The sequence: - // write(tmp) - // fsync(tmp) - // rename(tmp, new) - // fsync(new) - // fsync(parent) - // For more context about durable_rename check this email from postgres mailing list: - // https://www.postgresql.org/message-id/56583BDD.9060302@2ndquadrant.com - // If pageserver crashes the temp file will be deleted on startup and re-downloaded. - let temp_file_path = - path_with_suffix_extension(&layer_destination_path, TEMP_FILE_SUFFIX); + .map(|(layer_destination_path, metadata)| async move { - let mut destination_file = - fs::File::create(&temp_file_path).await.with_context(|| { - format!( - "Failed to create a destination file for layer '{}'", - temp_file_path.display() - ) - })?; + match layer_destination_path.metadata() { + Ok(m) if m.is_file() => { + // the file exists from earlier round when we failed after renaming it as + // layer_destination_path + let verified = if let Some(expected) = metadata.file_size() { + m.len() == expected + } else { + // behaviour before recording metadata was to accept any existing + true + }; - let mut layer_download = storage.download_storage_object(None, &layer_destination_path) - .await - .with_context(|| { - format!( - "Failed to initiate the download the layer for {sync_id} into file '{}'", - temp_file_path.display() - ) - })?; - io::copy(&mut layer_download.download_stream, &mut destination_file) - .await - .with_context(|| { - format!( - "Failed to download the layer for {sync_id} into file '{}'", - temp_file_path.display() - ) - })?; - - // Tokio doc here: https://docs.rs/tokio/1.17.0/tokio/fs/struct.File.html states that: - // A file will not be closed immediately when it goes out of scope if there are any IO operations - // that have not yet completed. To ensure that a file is closed immediately when it is dropped, - // you should call flush before dropping it. - // - // From the tokio code I see that it waits for pending operations to complete. There shouldn't be any because - // we assume that `destination_file` file is fully written. I.e there is no pending .write(...).await operations. - // But for additional safety let's check/wait for any pending operations. - destination_file.flush().await.with_context(|| { - format!( - "failed to flush source file at {}", - temp_file_path.display() - ) - })?; - - // not using sync_data because it can lose file size update - destination_file.sync_all().await.with_context(|| { - format!( - "failed to fsync source file at {}", - temp_file_path.display() - ) - })?; - drop(destination_file); - - fail::fail_point!("remote-storage-download-pre-rename", |_| { - anyhow::bail!("remote-storage-download-pre-rename failpoint triggered") - }); - - fs::rename(&temp_file_path, &layer_destination_path).await?; - - fsync_path(&layer_destination_path).await.with_context(|| { - format!( - "Cannot fsync layer destination path {}", - layer_destination_path.display(), - ) - })?; + if verified { + debug!( + "Layer already exists locally, skipping download: {}", + layer_destination_path.display() + ); + return Ok((layer_destination_path, LayerFileMetadata::new(m.len()))) + } else { + // no need to remove it, it will be overwritten by fs::rename + // after successful download + warn!("Downloaded layer exists already but layer file metadata mismatches: {}, metadata {:?}", layer_destination_path.display(), metadata); + } + } + Ok(m) => { + return Err(anyhow::anyhow!("Downloaded layer destination exists but is not a file: {m:?}, target needs to be removed/archived manually: {layer_destination_path:?}")); + } + Err(_) => { + // behave as the file didn't exist + } } - Ok::<_, anyhow::Error>(layer_destination_path) + + // Perform a rename inspired by durable_rename from file_utils.c. + // The sequence: + // write(tmp) + // fsync(tmp) + // rename(tmp, new) + // fsync(new) + // fsync(parent) + // For more context about durable_rename check this email from postgres mailing list: + // https://www.postgresql.org/message-id/56583BDD.9060302@2ndquadrant.com + // If pageserver crashes the temp file will be deleted on startup and re-downloaded. + let temp_file_path = + path_with_suffix_extension(&layer_destination_path, TEMP_FILE_SUFFIX); + + // TODO: this doesn't use the cached fd for some reason? + let mut destination_file = + fs::File::create(&temp_file_path).await.with_context(|| { + format!( + "Failed to create a destination file for layer '{}'", + temp_file_path.display() + ) + })?; + + let mut layer_download = storage.download_storage_object(None, &layer_destination_path) + .await + .with_context(|| { + format!( + "Failed to initiate the download the layer for {sync_id} into file '{}'", + temp_file_path.display() + ) + })?; + + let bytes_amount = io::copy(&mut layer_download.download_stream, &mut destination_file) + .await + .with_context(|| { + format!( + "Failed to download the layer for {sync_id} into file '{}'", + temp_file_path.display() + ) + })?; + + // Tokio doc here: https://docs.rs/tokio/1.17.0/tokio/fs/struct.File.html states that: + // A file will not be closed immediately when it goes out of scope if there are any IO operations + // that have not yet completed. To ensure that a file is closed immediately when it is dropped, + // you should call flush before dropping it. + // + // From the tokio code I see that it waits for pending operations to complete. There shouldn't be any because + // we assume that `destination_file` file is fully written. I.e there is no pending .write(...).await operations. + // But for additional safety let's check/wait for any pending operations. + destination_file.flush().await.with_context(|| { + format!( + "failed to flush source file at {}", + temp_file_path.display() + ) + })?; + + match metadata.file_size() { + Some(expected) if expected != bytes_amount => { + anyhow::bail!( + "According to layer file metadata should had downloaded {expected} bytes but downloaded {bytes_amount} bytes into file '{}'", + temp_file_path.display() + ); + }, + Some(_) | None => { + // matches, or upgrading from an earlier IndexPart version + } + } + + // not using sync_data because it can lose file size update + destination_file.sync_all().await.with_context(|| { + format!( + "failed to fsync source file at {}", + temp_file_path.display() + ) + })?; + drop(destination_file); + + fail::fail_point!("remote-storage-download-pre-rename", |_| { + anyhow::bail!("remote-storage-download-pre-rename failpoint triggered") + }); + + fs::rename(&temp_file_path, &layer_destination_path).await?; + + fsync_path(&layer_destination_path).await.with_context(|| { + format!( + "Cannot fsync layer destination path {}", + layer_destination_path.display(), + ) + })?; + + Ok::<_, anyhow::Error>((layer_destination_path, LayerFileMetadata::new(bytes_amount))) }) .collect::>(); @@ -324,9 +374,12 @@ pub(super) async fn download_timeline_layers<'a>( let mut undo = HashSet::new(); while let Some(download_result) = download_tasks.next().await { match download_result { - Ok(downloaded_path) => { + Ok((downloaded_path, metadata)) => { undo.insert(downloaded_path.clone()); - download.layers_to_skip.insert(downloaded_path); + download.layers_to_skip.insert(downloaded_path.clone()); + // what if the key existed already? ignore, because then we would had + // downloaded a partial file, and had to retry + download.gathered_metadata.insert(downloaded_path, metadata); } Err(e) => { errors_happened = true; @@ -349,6 +402,8 @@ pub(super) async fn download_timeline_layers<'a>( ); for item in undo { download.layers_to_skip.remove(&item); + // intentionally don't clear the gathered_metadata because it exists for fsync_path + // failure on parent directory } errors_happened = true; } @@ -453,9 +508,9 @@ mod tests { let timeline_upload = create_local_timeline(&harness, TIMELINE_ID, &layer_files, metadata.clone()).await?; - for local_path in timeline_upload.layers_to_upload { + for local_path in timeline_upload.layers_to_upload.keys() { let remote_path = - local_storage.resolve_in_storage(&storage.remote_object_id(&local_path)?)?; + local_storage.resolve_in_storage(&storage.remote_object_id(local_path)?)?; let remote_parent_dir = remote_path.parent().unwrap(); if !remote_parent_dir.exists() { fs::create_dir_all(&remote_parent_dir).await?; @@ -473,11 +528,19 @@ mod tests { let mut remote_timeline = RemoteTimeline::new(metadata.clone()); remote_timeline.awaits_download = true; - remote_timeline.add_timeline_layers( - layer_files - .iter() - .map(|layer| local_timeline_path.join(layer)), - ); + remote_timeline.add_timeline_layers(layer_files.iter().map(|layer| { + let layer_path = local_timeline_path.join(layer); + + // this could had also been LayerFileMetadata::default(), but since in this test we + // don't do the merge operation done by storage_sync::download_timeline_data, it would + // not be merged back to timeline. + let metadata_from_upload = timeline_upload + .layers_to_upload + .get(&layer_path) + .expect("layer must exist in previously uploaded paths") + .to_owned(); + (layer_path, metadata_from_upload) + })); let download_data = match download_timeline_layers( harness.conf, @@ -487,9 +550,9 @@ mod tests { sync_id, SyncData::new( current_retries, - LayersDownload { - layers_to_skip: HashSet::from([local_timeline_path.join("layer_to_skip")]), - }, + LayersDownload::from_skipped_layers(HashSet::from([ + local_timeline_path.join("layer_to_skip") + ])), ), ) .await @@ -552,12 +615,7 @@ mod tests { &sync_queue, None, sync_id, - SyncData::new( - 0, - LayersDownload { - layers_to_skip: HashSet::new(), - }, - ), + SyncData::new(0, LayersDownload::from_skipped_layers(HashSet::new())), ) .await; assert!( @@ -576,12 +634,7 @@ mod tests { &sync_queue, Some(¬_expecting_download_remote_timeline), sync_id, - SyncData::new( - 0, - LayersDownload { - layers_to_skip: HashSet::new(), - }, - ), + SyncData::new(0, LayersDownload::from_skipped_layers(HashSet::new())), ) .await; assert!( diff --git a/pageserver/src/storage_sync/index.rs b/pageserver/src/storage_sync/index.rs index db37c7b411..0779d95e8e 100644 --- a/pageserver/src/storage_sync/index.rs +++ b/pageserver/src/storage_sync/index.rs @@ -212,8 +212,8 @@ impl RemoteTimelineIndex { /// Restored index part data about the timeline, stored in the remote index. #[derive(Debug, Clone)] pub struct RemoteTimeline { - timeline_layers: HashSet, - missing_layers: HashSet, + timeline_layers: HashMap, + missing_layers: HashMap, pub metadata: TimelineMetadata, pub awaits_download: bool, @@ -222,62 +222,161 @@ pub struct RemoteTimeline { impl RemoteTimeline { pub fn new(metadata: TimelineMetadata) -> Self { Self { - timeline_layers: HashSet::new(), - missing_layers: HashSet::new(), + timeline_layers: HashMap::default(), + missing_layers: HashMap::default(), metadata, awaits_download: false, } } - pub fn add_timeline_layers(&mut self, new_layers: impl IntoIterator) { - self.timeline_layers.extend(new_layers.into_iter()); + pub fn add_timeline_layers( + &mut self, + new_layers: impl IntoIterator, + ) { + self.timeline_layers.extend(new_layers); } - pub fn add_upload_failures(&mut self, upload_failures: impl IntoIterator) { - self.missing_layers.extend(upload_failures.into_iter()); + pub fn add_upload_failures( + &mut self, + upload_failures: impl IntoIterator, + ) { + self.missing_layers.extend(upload_failures); } pub fn remove_layers(&mut self, layers_to_remove: &HashSet) { self.timeline_layers - .retain(|layer| !layers_to_remove.contains(layer)); + .retain(|layer, _| !layers_to_remove.contains(layer)); self.missing_layers - .retain(|layer| !layers_to_remove.contains(layer)); + .retain(|layer, _| !layers_to_remove.contains(layer)); } /// Lists all layer files in the given remote timeline. Omits the metadata file. - pub fn stored_files(&self) -> &HashSet { + pub fn stored_files(&self) -> &HashMap { &self.timeline_layers } + /// Combines metadata gathered or verified during downloading needed layer files to metadata on + /// the [`RemoteIndex`], so it can be uploaded later. + pub fn merge_metadata_from_downloaded( + &mut self, + downloaded: &HashMap, + ) { + downloaded.iter().for_each(|(path, metadata)| { + if let Some(upgraded) = self.timeline_layers.get_mut(path) { + upgraded.merge(metadata); + } + }); + } + pub fn from_index_part(timeline_path: &Path, index_part: IndexPart) -> anyhow::Result { let metadata = TimelineMetadata::from_bytes(&index_part.metadata_bytes)?; + let default_metadata = &IndexLayerMetadata::default(); + + let find_metadata = |key: &RelativePath| -> LayerFileMetadata { + index_part + .layer_metadata + .get(key) + .unwrap_or(default_metadata) + .into() + }; + Ok(Self { - timeline_layers: to_local_paths(timeline_path, index_part.timeline_layers), - missing_layers: to_local_paths(timeline_path, index_part.missing_layers), + timeline_layers: index_part + .timeline_layers + .iter() + .map(|layer_path| (layer_path.as_path(timeline_path), find_metadata(layer_path))) + .collect(), + missing_layers: index_part + .missing_layers + .iter() + .map(|layer_path| (layer_path.as_path(timeline_path), find_metadata(layer_path))) + .collect(), metadata, awaits_download: false, }) } } +/// Metadata gathered for each of the layer files. +/// +/// Fields have to be `Option`s because remote [`IndexPart`]'s can be from different version, which +/// might have less or more metadata depending if upgrading or rolling back an upgrade. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[cfg_attr(test, derive(Default))] +pub struct LayerFileMetadata { + file_size: Option, +} + +impl From<&'_ IndexLayerMetadata> for LayerFileMetadata { + fn from(other: &IndexLayerMetadata) -> Self { + LayerFileMetadata { + file_size: other.file_size, + } + } +} + +impl LayerFileMetadata { + pub fn new(file_size: u64) -> Self { + LayerFileMetadata { + file_size: Some(file_size), + } + } + + pub fn file_size(&self) -> Option { + self.file_size + } + + /// Metadata has holes due to version upgrades. This method is called to upgrade self with the + /// other value. + /// + /// This is called on the possibly outdated version. + pub fn merge(&mut self, other: &Self) { + self.file_size = other.file_size.or(self.file_size); + } +} + /// Part of the remote index, corresponding to a certain timeline. /// Contains the data about all files in the timeline, present remotely and its metadata. +/// +/// This type needs to be backwards and forwards compatible. When changing the fields, +/// remember to add a test case for the changed version. #[serde_as] #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct IndexPart { + /// Debugging aid describing the version of this type. + #[serde(default)] + version: usize, + + /// Each of the layers present on remote storage. + /// + /// Additional metadata can might exist in `layer_metadata`. timeline_layers: HashSet, + /// Currently is not really used in pageserver, /// present to manually keep track of the layer files that pageserver might never retrieve. /// /// Such "holes" might appear if any upload task was evicted on an error threshold: /// the this layer will only be rescheduled for upload on pageserver restart. missing_layers: HashSet, + + /// Per layer file metadata, which can be present for a present or missing layer file. + /// + /// Older versions of `IndexPart` will not have this property or have only a part of metadata + /// that latest version stores. + #[serde(default)] + layer_metadata: HashMap, + #[serde_as(as = "DisplayFromStr")] disk_consistent_lsn: Lsn, metadata_bytes: Vec, } impl IndexPart { + /// When adding or modifying any parts of `IndexPart`, increment the version so that it can be + /// used to understand later versions. + /// + /// Version is currently informative only. + const LATEST_VERSION: usize = 1; pub const FILE_NAME: &'static str = "index_part.json"; #[cfg(test)] @@ -288,8 +387,10 @@ impl IndexPart { metadata_bytes: Vec, ) -> Self { Self { + version: Self::LATEST_VERSION, timeline_layers, missing_layers, + layer_metadata: HashMap::default(), disk_consistent_lsn, metadata_bytes, } @@ -304,35 +405,68 @@ impl IndexPart { remote_timeline: RemoteTimeline, ) -> anyhow::Result { let metadata_bytes = remote_timeline.metadata.to_bytes()?; + + let mut layer_metadata = HashMap::new(); + + let mut missing_layers = HashSet::new(); + + separate_paths_and_metadata( + timeline_path, + &remote_timeline.missing_layers, + &mut missing_layers, + &mut layer_metadata, + ) + .context("Failed to convert missing layers' paths to relative ones")?; + + let mut timeline_layers = HashSet::new(); + + separate_paths_and_metadata( + timeline_path, + &remote_timeline.timeline_layers, + &mut timeline_layers, + &mut layer_metadata, + ) + .context("Failed to convert timeline layers' paths to relative ones")?; + Ok(Self { - timeline_layers: to_relative_paths(timeline_path, remote_timeline.timeline_layers) - .context("Failed to convert timeline layers' paths to relative ones")?, - missing_layers: to_relative_paths(timeline_path, remote_timeline.missing_layers) - .context("Failed to convert missing layers' paths to relative ones")?, + version: Self::LATEST_VERSION, + timeline_layers, + missing_layers, + layer_metadata, disk_consistent_lsn: remote_timeline.metadata.disk_consistent_lsn(), metadata_bytes, }) } } -fn to_local_paths( - timeline_path: &Path, - paths: impl IntoIterator, -) -> HashSet { - paths - .into_iter() - .map(|path| path.as_path(timeline_path)) - .collect() +/// Serialized form of [`LayerFileMetadata`]. +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Default)] +pub struct IndexLayerMetadata { + file_size: Option, } -fn to_relative_paths( +impl From<&'_ LayerFileMetadata> for IndexLayerMetadata { + fn from(other: &'_ LayerFileMetadata) -> Self { + IndexLayerMetadata { + file_size: other.file_size, + } + } +} + +fn separate_paths_and_metadata( timeline_path: &Path, - paths: impl IntoIterator, -) -> anyhow::Result> { - paths - .into_iter() - .map(|path| RelativePath::new(timeline_path, path)) - .collect() + input: &HashMap, + output: &mut HashSet, + layer_metadata: &mut HashMap, +) -> anyhow::Result<()> { + for (path, metadata) in input { + let rel_path = RelativePath::new(timeline_path, path)?; + let metadata = IndexLayerMetadata::from(metadata); + + layer_metadata.insert(rel_path.clone(), metadata); + output.insert(rel_path); + } + Ok(()) } #[cfg(test)] @@ -357,13 +491,13 @@ mod tests { DEFAULT_PG_VERSION, ); let remote_timeline = RemoteTimeline { - timeline_layers: HashSet::from([ - timeline_path.join("layer_1"), - timeline_path.join("layer_2"), + timeline_layers: HashMap::from([ + (timeline_path.join("layer_1"), LayerFileMetadata::new(1)), + (timeline_path.join("layer_2"), LayerFileMetadata::new(2)), ]), - missing_layers: HashSet::from([ - timeline_path.join("missing_1"), - timeline_path.join("missing_2"), + missing_layers: HashMap::from([ + (timeline_path.join("missing_1"), LayerFileMetadata::new(3)), + (timeline_path.join("missing_2"), LayerFileMetadata::new(4)), ]), metadata: metadata.clone(), awaits_download: false, @@ -485,13 +619,13 @@ mod tests { let conversion_result = IndexPart::from_remote_timeline( &timeline_path, RemoteTimeline { - timeline_layers: HashSet::from([ - PathBuf::from("bad_path"), - timeline_path.join("layer_2"), + timeline_layers: HashMap::from([ + (PathBuf::from("bad_path"), LayerFileMetadata::new(1)), + (timeline_path.join("layer_2"), LayerFileMetadata::new(2)), ]), - missing_layers: HashSet::from([ - timeline_path.join("missing_1"), - timeline_path.join("missing_2"), + missing_layers: HashMap::from([ + (timeline_path.join("missing_1"), LayerFileMetadata::new(3)), + (timeline_path.join("missing_2"), LayerFileMetadata::new(4)), ]), metadata: metadata.clone(), awaits_download: false, @@ -502,13 +636,13 @@ mod tests { let conversion_result = IndexPart::from_remote_timeline( &timeline_path, RemoteTimeline { - timeline_layers: HashSet::from([ - timeline_path.join("layer_1"), - timeline_path.join("layer_2"), + timeline_layers: HashMap::from([ + (timeline_path.join("layer_1"), LayerFileMetadata::new(1)), + (timeline_path.join("layer_2"), LayerFileMetadata::new(2)), ]), - missing_layers: HashSet::from([ - PathBuf::from("bad_path"), - timeline_path.join("missing_2"), + missing_layers: HashMap::from([ + (PathBuf::from("bad_path"), LayerFileMetadata::new(3)), + (timeline_path.join("missing_2"), LayerFileMetadata::new(4)), ]), metadata, awaits_download: false, @@ -516,4 +650,63 @@ mod tests { ); assert!(conversion_result.is_err(), "Should not be able to convert metadata with missing layer paths that are not in the timeline directory"); } + + #[test] + fn v0_indexpart_is_parsed() { + let example = r#"{ + "timeline_layers":["000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__0000000001696070-00000000016960E9"], + "missing_layers":["not_a_real_layer_but_adding_coverage"], + "disk_consistent_lsn":"0/16960E8", + "metadata_bytes":[113,11,159,210,0,54,0,4,0,0,0,0,1,105,96,232,1,0,0,0,0,1,105,96,112,0,0,0,0,0,0,0,0,0,0,0,0,0,1,105,96,112,0,0,0,0,1,105,96,112,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + }"#; + + let expected = IndexPart { + version: 0, + timeline_layers: [RelativePath("000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__0000000001696070-00000000016960E9".to_owned())].into_iter().collect(), + missing_layers: [RelativePath("not_a_real_layer_but_adding_coverage".to_owned())].into_iter().collect(), + layer_metadata: HashMap::default(), + disk_consistent_lsn: "0/16960E8".parse::().unwrap(), + metadata_bytes: [113,11,159,210,0,54,0,4,0,0,0,0,1,105,96,232,1,0,0,0,0,1,105,96,112,0,0,0,0,0,0,0,0,0,0,0,0,0,1,105,96,112,0,0,0,0,1,105,96,112,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0].to_vec(), + }; + + let part = serde_json::from_str::(example).unwrap(); + assert_eq!(part, expected); + } + + #[test] + fn v1_indexpart_is_parsed() { + let example = r#"{ + "version":1, + "timeline_layers":["000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__0000000001696070-00000000016960E9"], + "missing_layers":["not_a_real_layer_but_adding_coverage"], + "layer_metadata":{ + "000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__0000000001696070-00000000016960E9": { "file_size": 25600000 }, + "not_a_real_layer_but_adding_coverage": { "file_size": 9007199254741001 } + }, + "disk_consistent_lsn":"0/16960E8", + "metadata_bytes":[113,11,159,210,0,54,0,4,0,0,0,0,1,105,96,232,1,0,0,0,0,1,105,96,112,0,0,0,0,0,0,0,0,0,0,0,0,0,1,105,96,112,0,0,0,0,1,105,96,112,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + }"#; + + let expected = IndexPart { + // note this is not verified, could be anything, but exists for humans debugging.. could be the git version instead? + version: 1, + timeline_layers: [RelativePath("000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__0000000001696070-00000000016960E9".to_owned())].into_iter().collect(), + missing_layers: [RelativePath("not_a_real_layer_but_adding_coverage".to_owned())].into_iter().collect(), + layer_metadata: HashMap::from([ + (RelativePath("000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__0000000001696070-00000000016960E9".to_owned()), IndexLayerMetadata { + file_size: Some(25600000), + }), + (RelativePath("not_a_real_layer_but_adding_coverage".to_owned()), IndexLayerMetadata { + // serde_json should always parse this but this might be a double with jq for + // example. + file_size: Some(9007199254741001), + }) + ]), + disk_consistent_lsn: "0/16960E8".parse::().unwrap(), + metadata_bytes: [113,11,159,210,0,54,0,4,0,0,0,0,1,105,96,232,1,0,0,0,0,1,105,96,112,0,0,0,0,0,0,0,0,0,0,0,0,0,1,105,96,112,0,0,0,0,1,105,96,112,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0].to_vec(), + }; + + let part = serde_json::from_str::(example).unwrap(); + assert_eq!(part, expected); + } } diff --git a/pageserver/src/storage_sync/upload.rs b/pageserver/src/storage_sync/upload.rs index 75657915c0..f91105052b 100644 --- a/pageserver/src/storage_sync/upload.rs +++ b/pageserver/src/storage_sync/upload.rs @@ -69,14 +69,25 @@ pub(super) async fn upload_timeline_layers<'a>( .map(|meta| meta.disk_consistent_lsn()); let already_uploaded_layers = remote_timeline - .map(|timeline| timeline.stored_files()) - .cloned() + .map(|timeline| { + timeline + .stored_files() + .keys() + .cloned() + .collect::>() + }) .unwrap_or_default(); let layers_to_upload = upload .layers_to_upload - .difference(&already_uploaded_layers) - .cloned() + .iter() + .filter_map(|(k, v)| { + if !already_uploaded_layers.contains(k) { + Some((k.to_owned(), v.to_owned())) + } else { + None + } + }) .collect::>(); if layers_to_upload.is_empty() { @@ -98,7 +109,7 @@ pub(super) async fn upload_timeline_layers<'a>( let mut upload_tasks = layers_to_upload .into_iter() - .map(|source_path| async move { + .map(|(source_path, known_metadata)| async move { let source_file = match fs::File::open(&source_path).await.with_context(|| { format!( "Failed to upen a source file for layer '{}'", @@ -109,7 +120,7 @@ pub(super) async fn upload_timeline_layers<'a>( Err(e) => return Err(UploadError::MissingLocalFile(source_path, e)), }; - let source_size = source_file + let fs_size = source_file .metadata() .await .with_context(|| { @@ -119,10 +130,24 @@ pub(super) async fn upload_timeline_layers<'a>( ) }) .map_err(UploadError::Other)? - .len() as usize; + .len(); + + // FIXME: this looks bad + if let Some(metadata_size) = known_metadata.file_size() { + if metadata_size != fs_size { + return Err(UploadError::Other(anyhow::anyhow!( + "File {source_path:?} has its current FS size {fs_size} diferent from initially determined {metadata_size}" + ))); + } + } else { + // this is a silly state we would like to avoid + } + + let fs_size = usize::try_from(fs_size).with_context(|| format!("File {source_path:?} size {fs_size} could not be converted to usize")) + .map_err(UploadError::Other)?; match storage - .upload_storage_object(Box::new(source_file), source_size, &source_path) + .upload_storage_object(Box::new(source_file), fs_size, &source_path) .await .with_context(|| format!("Failed to upload layer file for {sync_id}")) { @@ -136,8 +161,11 @@ pub(super) async fn upload_timeline_layers<'a>( while let Some(upload_result) = upload_tasks.next().await { match upload_result { Ok(uploaded_path) => { - upload.layers_to_upload.remove(&uploaded_path); - upload.uploaded_layers.insert(uploaded_path); + let metadata = upload + .layers_to_upload + .remove(&uploaded_path) + .expect("metadata should always exist, assuming no double uploads"); + upload.uploaded_layers.insert(uploaded_path, metadata); } Err(e) => match e { UploadError::Other(e) => { @@ -262,7 +290,7 @@ mod tests { assert_eq!( upload .uploaded_layers - .iter() + .keys() .cloned() .collect::>(), layer_files @@ -357,7 +385,7 @@ mod tests { assert_eq!( upload .uploaded_layers - .iter() + .keys() .cloned() .collect::>(), layer_files diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index 3639e30fee..0f8e60f8d3 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -52,7 +52,10 @@ use crate::task_mgr::TaskKind; use crate::walreceiver::{is_etcd_client_initialized, spawn_connection_manager_task}; use crate::walredo::WalRedoManager; use crate::CheckpointConfig; -use crate::{page_cache, storage_sync}; +use crate::{ + page_cache, + storage_sync::{self, index::LayerFileMetadata}, +}; pub struct Timeline { conf: &'static PageServerConf, @@ -1190,8 +1193,8 @@ impl Timeline { self.create_image_layers(&partitioning, self.initdb_lsn, true)? } else { // normal case, write out a L0 delta layer file. - let delta_path = self.create_delta_layer(&frozen_layer)?; - HashSet::from([delta_path]) + let (delta_path, metadata) = self.create_delta_layer(&frozen_layer)?; + HashMap::from([(delta_path, metadata)]) }; fail_point!("flush-frozen-before-sync"); @@ -1226,7 +1229,7 @@ impl Timeline { fn update_disk_consistent_lsn( &self, disk_consistent_lsn: Lsn, - layer_paths_to_upload: HashSet, + layer_paths_to_upload: HashMap, ) -> Result<()> { // If we were able to advance 'disk_consistent_lsn', save it the metadata file. // After crash, we will restart WAL streaming and processing from that point. @@ -1295,7 +1298,10 @@ impl Timeline { } // Write out the given frozen in-memory layer as a new L0 delta file - fn create_delta_layer(&self, frozen_layer: &InMemoryLayer) -> Result { + fn create_delta_layer( + &self, + frozen_layer: &InMemoryLayer, + ) -> Result<(PathBuf, LayerFileMetadata)> { // Write it out let new_delta = frozen_layer.write_to_disk()?; let new_delta_path = new_delta.path(); @@ -1321,12 +1327,13 @@ impl Timeline { // update the timeline's physical size let sz = new_delta_path.metadata()?.len(); + self.metrics.current_physical_size_gauge.add(sz); // update metrics self.metrics.num_persistent_files_created.inc_by(1); self.metrics.persistent_bytes_written.inc_by(sz); - Ok(new_delta_path) + Ok((new_delta_path, LayerFileMetadata::new(sz))) } pub fn compact(&self) -> anyhow::Result<()> { @@ -1392,7 +1399,7 @@ impl Timeline { storage_sync::schedule_layer_upload( self.tenant_id, self.timeline_id, - HashSet::from_iter(layer_paths_to_upload), + layer_paths_to_upload, None, ); } @@ -1473,10 +1480,9 @@ impl Timeline { partitioning: &KeyPartitioning, lsn: Lsn, force: bool, - ) -> Result> { + ) -> Result> { let timer = self.metrics.create_images_time_histo.start_timer(); let mut image_layers: Vec = Vec::new(); - let mut layer_paths_to_upload = HashSet::new(); for partition in partitioning.parts.iter() { if force || self.time_for_new_image_layer(partition, lsn)? { let img_range = @@ -1498,7 +1504,6 @@ impl Timeline { } } let image_layer = image_layer_writer.finish()?; - layer_paths_to_upload.insert(image_layer.path()); image_layers.push(image_layer); } } @@ -1512,15 +1517,25 @@ impl Timeline { // // Compaction creates multiple image layers. It would be better to create them all // and fsync them all in parallel. - let mut all_paths = Vec::from_iter(layer_paths_to_upload.clone()); - all_paths.push(self.conf.timeline_path(&self.timeline_id, &self.tenant_id)); + let all_paths = image_layers + .iter() + .map(|layer| layer.path()) + .chain(std::iter::once( + self.conf.timeline_path(&self.timeline_id, &self.tenant_id), + )) + .collect::>(); par_fsync::par_fsync(&all_paths)?; + let mut layer_paths_to_upload = HashMap::with_capacity(image_layers.len()); + let mut layers = self.layers.write().unwrap(); for l in image_layers { - self.metrics - .current_physical_size_gauge - .add(l.path().metadata()?.len()); + let path = l.path(); + let metadata = path.metadata()?; + + layer_paths_to_upload.insert(path, LayerFileMetadata::new(metadata.len())); + + self.metrics.current_physical_size_gauge.add(metadata.len()); layers.insert_historic(Arc::new(l)); } drop(layers); @@ -1771,16 +1786,16 @@ impl Timeline { } let mut layers = self.layers.write().unwrap(); - let mut new_layer_paths = HashSet::with_capacity(new_layers.len()); + let mut new_layer_paths = HashMap::with_capacity(new_layers.len()); for l in new_layers { let new_delta_path = l.path(); - // update the timeline's physical size - self.metrics - .current_physical_size_gauge - .add(new_delta_path.metadata()?.len()); + let metadata = new_delta_path.metadata()?; - new_layer_paths.insert(new_delta_path); + // update the timeline's physical size + self.metrics.current_physical_size_gauge.add(metadata.len()); + + new_layer_paths.insert(new_delta_path, LayerFileMetadata::new(metadata.len())); layers.insert_historic(Arc::new(l)); } diff --git a/pageserver/src/tenant_mgr.rs b/pageserver/src/tenant_mgr.rs index c6698ee22f..b2c927d4fc 100644 --- a/pageserver/src/tenant_mgr.rs +++ b/pageserver/src/tenant_mgr.rs @@ -1,7 +1,7 @@ //! This module acts as a switchboard to access different repositories managed by this //! page server. -use std::collections::{hash_map, HashMap, HashSet}; +use std::collections::{hash_map, HashMap}; use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; @@ -14,8 +14,8 @@ use remote_storage::GenericRemoteStorage; use crate::config::{PageServerConf, METADATA_FILE_NAME}; use crate::http::models::TenantInfo; -use crate::storage_sync::index::{RemoteIndex, RemoteTimelineIndex}; -use crate::storage_sync::{self, LocalTimelineInitStatus, SyncStartupData}; +use crate::storage_sync::index::{LayerFileMetadata, RemoteIndex, RemoteTimelineIndex}; +use crate::storage_sync::{self, LocalTimelineInitStatus, SyncStartupData, TimelineLocalFiles}; use crate::task_mgr::{self, TaskKind}; use crate::tenant::{ ephemeral_file::is_ephemeral_file, metadata::TimelineMetadata, Tenant, TenantState, @@ -104,7 +104,7 @@ pub fn init_tenant_mgr( if let TenantAttachData::Ready(t) = new_timeline_values { for (timeline_id, old_value) in old_values { if let LocalTimelineInitStatus::LocallyComplete(metadata) = old_value { - t.insert(timeline_id, (metadata, HashSet::new())); + t.insert(timeline_id, TimelineLocalFiles::ready(metadata)); } } } @@ -189,7 +189,7 @@ pub fn attach_local_tenants( let has_timelines = !timelines.is_empty(); let timelines_to_attach = timelines .iter() - .map(|(&k, (v, _))| (k, v.clone())) + .map(|(&k, v)| (k, v.metadata().to_owned())) .collect(); match tenant.init_attach_timelines(timelines_to_attach) { Ok(()) => { @@ -483,7 +483,7 @@ pub fn list_tenant_info(remote_index: &RemoteTimelineIndex) -> Vec { #[derive(Debug)] pub enum TenantAttachData { - Ready(HashMap)>), + Ready(HashMap), Broken(anyhow::Error), } /// Attempts to collect information about all tenant and timelines, existing on the local FS. @@ -602,7 +602,6 @@ fn is_temporary(path: &Path) -> bool { } } -#[allow(clippy::type_complexity)] fn collect_timelines_for_tenant( config: &'static PageServerConf, tenant_path: &Path, @@ -648,7 +647,10 @@ fn collect_timelines_for_tenant( } else { match collect_timeline_files(&timeline_dir) { Ok((timeline_id, metadata, timeline_files)) => { - tenant_timelines.insert(timeline_id, (metadata, timeline_files)); + tenant_timelines.insert( + timeline_id, + TimelineLocalFiles::collected(metadata, timeline_files), + ); } Err(e) => { error!( @@ -690,8 +692,12 @@ fn collect_timelines_for_tenant( // NOTE: ephemeral files are excluded from the list fn collect_timeline_files( timeline_dir: &Path, -) -> anyhow::Result<(TimelineId, TimelineMetadata, HashSet)> { - let mut timeline_files = HashSet::new(); +) -> anyhow::Result<( + TimelineId, + TimelineMetadata, + HashMap, +)> { + let mut timeline_files = HashMap::new(); let mut timeline_metadata_path = None; let timeline_id = timeline_dir @@ -704,7 +710,9 @@ fn collect_timeline_files( fs::read_dir(&timeline_dir).context("Failed to list timeline dir contents")?; for entry in timeline_dir_entries { let entry_path = entry.context("Failed to list timeline dir entry")?.path(); - if entry_path.is_file() { + let metadata = entry_path.metadata()?; + + if metadata.is_file() { if entry_path.file_name().and_then(OsStr::to_str) == Some(METADATA_FILE_NAME) { timeline_metadata_path = Some(entry_path); } else if is_ephemeral_file(&entry_path.file_name().unwrap().to_string_lossy()) { @@ -719,7 +727,8 @@ fn collect_timeline_files( ) })?; } else { - timeline_files.insert(entry_path); + let layer_metadata = LayerFileMetadata::new(metadata.len()); + timeline_files.insert(entry_path, layer_metadata); } } } diff --git a/test_runner/regress/test_tenants_with_remote_storage.py b/test_runner/regress/test_tenants_with_remote_storage.py index d8424e22c8..a7c2e7ace0 100644 --- a/test_runner/regress/test_tenants_with_remote_storage.py +++ b/test_runner/regress/test_tenants_with_remote_storage.py @@ -7,13 +7,16 @@ # import asyncio +import json import os +import shutil from pathlib import Path from typing import List, Tuple import pytest from fixtures.log_helper import log from fixtures.neon_fixtures import ( + LocalFsStorage, NeonEnv, NeonEnvBuilder, NeonPageserverHttpClient, @@ -189,3 +192,246 @@ def expect_tenant_to_download_timeline( ), f"Tenant {tenant_id} should have no downloads in progress" return assert False, f"Tenant {tenant_id} is missing on pageserver" + + +@pytest.mark.parametrize("remote_storage_kind", [RemoteStorageKind.LOCAL_FS]) +def test_tenant_upgrades_index_json_from_v0( + neon_env_builder: NeonEnvBuilder, remote_storage_kind: RemoteStorageKind +): + # the "image" for the v0 index_part.json. the fields themselves are + # replaced with values read from the later version because of #2592 (initdb + # lsn not reproducible). + v0_skeleton = json.loads( + """{ + "timeline_layers":[ + "000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__0000000001696070-00000000016960E9" + ], + "missing_layers":[], + "disk_consistent_lsn":"0/16960E8", + "metadata_bytes":[] + }""" + ) + + # getting a too eager compaction happening for this test would not play + # well with the strict assertions. + neon_env_builder.pageserver_config_override = "tenant_config.compaction_period='1h'" + + neon_env_builder.enable_remote_storage( + remote_storage_kind, "test_tenant_upgrades_index_json_from_v0" + ) + + # launch pageserver, populate the default tenants timeline, wait for it to be uploaded, + # then go ahead and modify the "remote" version as if it was downgraded, needing upgrade + env = neon_env_builder.init_start() + pageserver_http = env.pageserver.http_client() + pg = env.postgres.create_start("main") + + tenant_id = TenantId(pg.safe_psql("show neon.tenant_id")[0][0]) + timeline_id = TimelineId(pg.safe_psql("show neon.timeline_id")[0][0]) + + with pg.cursor() as cur: + cur.execute("CREATE TABLE t0 AS VALUES (123, 'second column as text');") + current_lsn = Lsn(query_scalar(cur, "SELECT pg_current_wal_flush_lsn()")) + + # flush, wait until in remote storage + wait_for_last_record_lsn(pageserver_http, tenant_id, timeline_id, current_lsn) + pageserver_http.timeline_checkpoint(tenant_id, timeline_id) + wait_for_upload(pageserver_http, tenant_id, timeline_id, current_lsn) + + env.postgres.stop_all() + env.pageserver.stop() + + # remove all local data for the tenant to force redownloading and subsequent upgrade + shutil.rmtree(Path(env.repo_dir) / "tenants" / str(tenant_id)) + + # downgrade the remote file + timeline_path = local_fs_index_part_path(env, tenant_id, timeline_id) + with open(timeline_path, "r+") as timeline_file: + # keep the deserialized for later inspection + orig_index_part = json.load(timeline_file) + + v0_index_part = {key: orig_index_part[key] for key in v0_skeleton} + + timeline_file.seek(0) + json.dump(v0_index_part, timeline_file) + + env.pageserver.start() + pageserver_http = env.pageserver.http_client() + pageserver_http.tenant_attach(tenant_id) + + wait_until( + number_of_iterations=5, + interval=1, + func=lambda: expect_tenant_to_download_timeline(pageserver_http, tenant_id), + ) + + pg = env.postgres.create_start("main") + + with pg.cursor() as cur: + cur.execute("INSERT INTO t0 VALUES (234, 'test data');") + current_lsn = Lsn(query_scalar(cur, "SELECT pg_current_wal_flush_lsn()")) + + wait_for_last_record_lsn(pageserver_http, tenant_id, timeline_id, current_lsn) + pageserver_http.timeline_checkpoint(tenant_id, timeline_id) + wait_for_upload(pageserver_http, tenant_id, timeline_id, current_lsn) + + # not needed anymore + env.postgres.stop_all() + env.pageserver.stop() + + # make sure the file has been upgraded back to how it started + index_part = local_fs_index_part(env, tenant_id, timeline_id) + assert index_part["version"] == orig_index_part["version"] + assert index_part["missing_layers"] == orig_index_part["missing_layers"] + + # expect one more layer because of the forced checkpoint + assert len(index_part["timeline_layers"]) == len(orig_index_part["timeline_layers"]) + 1 + + # all of the same layer files are there, but they might be shuffled around + orig_layers = set(orig_index_part["timeline_layers"]) + later_layers = set(index_part["timeline_layers"]) + assert later_layers.issuperset(orig_layers) + + added_layers = later_layers - orig_layers + assert len(added_layers) == 1 + + # all of metadata has been regenerated (currently just layer file size) + all_metadata_keys = set() + for layer in orig_layers: + orig_metadata = orig_index_part["layer_metadata"][layer] + new_metadata = index_part["layer_metadata"][layer] + assert ( + orig_metadata == new_metadata + ), f"metadata for layer {layer} should not have changed {orig_metadata} vs. {new_metadata}" + all_metadata_keys |= set(orig_metadata.keys()) + + one_new_layer = next(iter(added_layers)) + assert one_new_layer in index_part["layer_metadata"], "new layer should have metadata" + + only_new_metadata = index_part["layer_metadata"][one_new_layer] + + assert ( + set(only_new_metadata.keys()).symmetric_difference(all_metadata_keys) == set() + ), "new layer metadata has same metadata as others" + + +# FIXME: test index_part.json getting downgraded from imaginary new version + + +@pytest.mark.parametrize("remote_storage_kind", [RemoteStorageKind.LOCAL_FS]) +def test_tenant_redownloads_truncated_file_on_startup( + neon_env_builder: NeonEnvBuilder, remote_storage_kind: RemoteStorageKind +): + # since we now store the layer file length metadata, we notice on startup that a layer file is of wrong size, and proceed to redownload it. + neon_env_builder.enable_remote_storage( + remote_storage_kind=remote_storage_kind, + test_name="test_tenant_redownloads_truncated_file_on_startup", + ) + + env = neon_env_builder.init_start() + pageserver_http = env.pageserver.http_client() + pg = env.postgres.create_start("main") + + tenant_id = TenantId(pg.safe_psql("show neon.tenant_id")[0][0]) + timeline_id = TimelineId(pg.safe_psql("show neon.timeline_id")[0][0]) + + with pg.cursor() as cur: + cur.execute("CREATE TABLE t1 AS VALUES (123, 'foobar');") + current_lsn = Lsn(query_scalar(cur, "SELECT pg_current_wal_flush_lsn()")) + + wait_for_last_record_lsn(pageserver_http, tenant_id, timeline_id, current_lsn) + pageserver_http.timeline_checkpoint(tenant_id, timeline_id) + wait_for_upload(pageserver_http, tenant_id, timeline_id, current_lsn) + + env.postgres.stop_all() + env.pageserver.stop() + + timeline_dir = Path(env.repo_dir) / "tenants" / str(tenant_id) / "timelines" / str(timeline_id) + local_layer_truncated = None + for path in Path.iterdir(timeline_dir): + if path.name.startswith("00000"): + correct_size = os.stat(path).st_size + os.truncate(path, 0) + local_layer_truncated = (path, correct_size) + break + assert ( + local_layer_truncated is not None + ), f"Found no local layer files to delete in directory {timeline_dir}" + + (path, expected_size) = local_layer_truncated + + # ensure the same size is found from the index_part.json + index_part = local_fs_index_part(env, tenant_id, timeline_id) + assert index_part["layer_metadata"][path.name]["file_size"] == expected_size + + ##### Start the pageserver, forcing it to download the layer file and load the timeline into memory + env.pageserver.start() + client = env.pageserver.http_client() + + wait_until( + number_of_iterations=5, + interval=1, + func=lambda: expect_tenant_to_download_timeline(client, tenant_id), + ) + + restored_timelines = client.timeline_list(tenant_id) + assert ( + len(restored_timelines) == 1 + ), f"Tenant {tenant_id} should have its timeline reattached after its layer is downloaded from the remote storage" + retored_timeline = restored_timelines[0] + assert retored_timeline["timeline_id"] == str( + timeline_id + ), f"Tenant {tenant_id} should have its old timeline {timeline_id} restored from the remote storage" + + assert os.stat(path).st_size == expected_size, "truncated layer should had been re-downloaded" + + # the remote side of local_layer_truncated + remote_layer_path = local_fs_index_part_path(env, tenant_id, timeline_id).parent / path.name + + # if the upload ever was ongoing, this check would be racy, but at least one + # extra http request has been made in between so assume it's enough delay + assert ( + os.stat(remote_layer_path).st_size == expected_size + ), "truncated file should not had been uploaded around re-download" + + pg = env.postgres.create_start("main") + + with pg.cursor() as cur: + cur.execute("INSERT INTO t1 VALUES (234, 'test data');") + current_lsn = Lsn(query_scalar(cur, "SELECT pg_current_wal_flush_lsn()")) + + wait_for_last_record_lsn(pageserver_http, tenant_id, timeline_id, current_lsn) + pageserver_http.timeline_checkpoint(tenant_id, timeline_id) + wait_for_upload(pageserver_http, tenant_id, timeline_id, current_lsn) + + # now that the upload is complete, make sure the file hasn't been + # re-uploaded truncated. this is a rather bogus check given the current + # implementation, but it's critical it doesn't happen so wasting a few + # lines of python to do this. + assert ( + os.stat(remote_layer_path).st_size == expected_size + ), "truncated file should not had been uploaded after next checkpoint" + + +def local_fs_index_part(env, tenant_id, timeline_id): + """ + Return json.load parsed index_part.json of tenant and timeline from LOCAL_FS + """ + timeline_path = local_fs_index_part_path(env, tenant_id, timeline_id) + with open(timeline_path, "r") as timeline_file: + return json.load(timeline_file) + + +def local_fs_index_part_path(env, tenant_id, timeline_id): + """ + Return path to the LOCAL_FS index_part.json of the tenant and timeline. + """ + assert isinstance(env.remote_storage, LocalFsStorage) + return ( + env.remote_storage.root + / "tenants" + / str(tenant_id) + / "timelines" + / str(timeline_id) + / "index_part.json" + ) From c4ee62d427622d2d576db0e3b2ac3035ea37cd04 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 17 Oct 2022 12:58:40 +0300 Subject: [PATCH 31/64] Bump clap and other minor dependencies (#2623) --- Cargo.lock | 172 ++++-- compute_tools/Cargo.toml | 2 +- compute_tools/src/bin/compute_ctl.rs | 95 +-- control_plane/Cargo.toml | 2 +- control_plane/src/bin/neon_local.rs | 580 +++++++++--------- libs/postgres_ffi/Cargo.toml | 4 +- libs/postgres_ffi/wal_craft/Cargo.toml | 2 +- .../wal_craft/src/bin/wal_craft.rs | 163 ++--- pageserver/Cargo.toml | 2 +- pageserver/src/bin/pageserver.rs | 121 ++-- pageserver/src/bin/pageserver_binutils.rs | 88 +-- proxy/Cargo.toml | 20 +- proxy/src/main.rs | 160 ++--- safekeeper/Cargo.toml | 2 +- safekeeper/src/bin/safekeeper.rs | 242 ++++---- workspace_hack/Cargo.toml | 7 +- 16 files changed, 893 insertions(+), 769 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7659be6c92..131d9a8aa2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,9 +75,9 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "asn1-rs" -version = "0.3.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ff05a702273012438132f449575dbc804e27b2f3cbe3069aa237d26c98fa33" +checksum = "cf6690c370453db30743b373a60ba498fc0d6d83b11f4abfd87a84a075db5dd4" dependencies = [ "asn1-rs-derive", "asn1-rs-impl", @@ -91,9 +91,9 @@ dependencies = [ [[package]] name = "asn1-rs-derive" -version = "0.1.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8b7511298d5b7784b40b092d9e9dcd3a627a5707e4b5e507931ab0d44eeebf" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ "proc-macro2", "quote", @@ -262,15 +262,13 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.60.1" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" +checksum = "8a022e58a142a46fea340d68012b9201c094e93ec3d033a944a24f8fd4a4f09a" dependencies = [ "bitflags", "cexpr", "clang-sys", - "clap", - "env_logger", "lazy_static", "lazycell", "log", @@ -280,6 +278,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", + "syn", "which", ] @@ -327,13 +326,14 @@ checksum = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426" [[package]] name = "bstr" -version = "0.2.17" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd" dependencies = [ - "lazy_static", "memchr", + "once_cell", "regex-automata", + "serde", ] [[package]] @@ -449,14 +449,24 @@ name = "clap" version = "3.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" +dependencies = [ + "bitflags", + "clap_lex 0.2.4", + "indexmap", + "textwrap", +] + +[[package]] +name = "clap" +version = "4.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f" dependencies = [ "atty", "bitflags", - "clap_lex", - "indexmap", + "clap_lex 0.3.0", "strsim", "termcolor", - "textwrap", ] [[package]] @@ -468,6 +478,15 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "close_fds" version = "0.3.2" @@ -525,7 +544,7 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", - "clap", + "clap 4.0.15", "env_logger", "futures", "hyper", @@ -567,7 +586,7 @@ name = "control_plane" version = "0.1.0" dependencies = [ "anyhow", - "clap", + "clap 4.0.15", "comfy-table", "git-version", "nix 0.25.0", @@ -660,7 +679,7 @@ dependencies = [ "atty", "cast", "ciborium", - "clap", + "clap 3.2.22", "criterion-plot", "itertools", "lazy_static", @@ -728,7 +747,7 @@ dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "memoffset", + "memoffset 0.6.5", "scopeguard", ] @@ -789,9 +808,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f39818dcfc97d45b03953c1292efc4e80954e1583c4aa770bac1383e2310a4" +checksum = "3f83d0ebf42c6eafb8d7c52f7e5f2d3003b89c7aa4fd2b79229209459a849af8" dependencies = [ "cc", "cxxbridge-flags", @@ -801,9 +820,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e580d70777c116df50c390d1211993f62d40302881e54d4b79727acb83d0199" +checksum = "07d050484b55975889284352b0ffc2ecbda25c0c55978017c132b29ba0818a86" dependencies = [ "cc", "codespan-reporting", @@ -816,15 +835,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56a46460b88d1cec95112c8c363f0e2c39afdb237f60583b0b36343bf627ea9c" +checksum = "99d2199b00553eda8012dfec8d3b1c75fce747cf27c169a270b3b99e3448ab78" [[package]] name = "cxxbridge-macro" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747b608fecf06b0d72d440f27acc99288207324b793be2c17991839f3d4995ea" +checksum = "dcb67a6de1f602736dd7eaead0080cf3435df806c61b24b13328db128c58868f" dependencies = [ "proc-macro2", "quote", @@ -888,14 +907,14 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6ee87af31d84ef885378aebca32be3d682b0e0dc119d5b4860a2c5bb5046730" dependencies = [ - "uuid", + "uuid 0.8.2", ] [[package]] name = "der-parser" -version = "7.0.0" +version = "8.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe398ac75057914d7d07307bf67dc7f3f574a26783b4fc7805a20ffa9f506e82" +checksum = "42d4bc9b0db0a0df9ae64634ac5bdefb7afcb534e182275ca0beadbe486701c1" dependencies = [ "asn1-rs", "displaydoc", @@ -1204,6 +1223,12 @@ version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + [[package]] name = "futures-util" version = "0.3.24" @@ -1516,9 +1541,9 @@ dependencies = [ [[package]] name = "iana-time-zone-haiku" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde6edd6cef363e9359ed3c98ba64590ba9eecba2293eb5a723ab32aee8926aa" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" dependencies = [ "cxx", "cxx-build", @@ -1644,9 +1669,9 @@ dependencies = [ [[package]] name = "kqueue" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6112e8f37b59803ac47a42d14f1f3a59bbf72fc6857ffc5be455e28a691f8e" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" dependencies = [ "kqueue-sys", "libc", @@ -1790,6 +1815,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "metrics" version = "0.1.0" @@ -1882,7 +1916,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -1895,7 +1929,7 @@ dependencies = [ "bitflags", "cfg-if", "libc", - "memoffset", + "memoffset 0.6.5", "pin-utils", ] @@ -2008,9 +2042,9 @@ dependencies = [ [[package]] name = "oid-registry" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e20717fa0541f39bd146692035c37bedfa532b3e5071b35761082407546b2a" +checksum = "7d4bda43fd1b844cbc6e6e54b5444e2b1bc7838bce59ad205902cccbb26d6761" dependencies = [ "asn1-rs", ] @@ -2101,7 +2135,7 @@ dependencies = [ "byteorder", "bytes", "chrono", - "clap", + "clap 4.0.15", "close_fds", "const_format", "crc32c", @@ -2377,7 +2411,7 @@ dependencies = [ "env_logger", "hex", "log", - "memoffset", + "memoffset 0.7.1", "once_cell", "postgres", "rand", @@ -2416,9 +2450,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "prettyplease" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fead41e178796ef8274dc612a7d8ce4c7e10ca35cd2c5b5ad24cac63aeb6c0" +checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" dependencies = [ "proc-macro2", "syn", @@ -2432,9 +2466,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.46" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] @@ -2533,7 +2567,7 @@ dependencies = [ "base64", "bstr", "bytes", - "clap", + "clap 4.0.15", "futures", "git-version", "hashbrown", @@ -2567,7 +2601,7 @@ dependencies = [ "tracing-subscriber", "url", "utils", - "uuid", + "uuid 1.2.1", "workspace_hack", "x509-parser", ] @@ -2656,13 +2690,13 @@ dependencies = [ [[package]] name = "rcgen" -version = "0.8.14" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5911d1403f4143c9d56a702069d593e8d0f3fab880a85e103604d0893ea31ba7" +checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ - "chrono", "pem", "ring", + "time 0.3.15", "yasna", ] @@ -2852,9 +2886,21 @@ dependencies = [ [[package]] name = "rstest" -version = "0.12.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d912f35156a3f99a66ee3e11ac2e0b3f34ac85a07e05263d05a7e2c8810d616f" +checksum = "e9c9dc66cc29792b663ffb5269be669f1613664e69ad56441fdb895c2347b930" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version 0.4.0", +] + +[[package]] +name = "rstest_macros" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5015e68a0685a95ade3eee617ff7101ab6a3fc689203101ca16ebc16f2b89c66" dependencies = [ "cfg-if", "proc-macro2", @@ -3034,7 +3080,7 @@ dependencies = [ "async-trait", "byteorder", "bytes", - "clap", + "clap 4.0.15", "const_format", "crc32c", "daemonize", @@ -3424,7 +3470,7 @@ dependencies = [ "debugid", "memmap2", "stable_deref_trait", - "uuid", + "uuid 0.8.2", ] [[package]] @@ -4010,6 +4056,12 @@ name = "uuid" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" + +[[package]] +name = "uuid" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feb41e78f93363bb2df8b0e86a2ca30eed7806ea16ea0c790d757cf93f79be83" dependencies = [ "getrandom", "serde", @@ -4059,7 +4111,7 @@ name = "wal_craft" version = "0.1.0" dependencies = [ "anyhow", - "clap", + "clap 4.0.15", "env_logger", "log", "once_cell", @@ -4299,7 +4351,7 @@ dependencies = [ "anyhow", "bytes", "chrono", - "clap", + "clap 4.0.15", "crossbeam-utils", "either", "fail", @@ -4307,6 +4359,7 @@ dependencies = [ "indexmap", "libc", "log", + "memchr", "nom", "num-bigint", "num-integer", @@ -4324,14 +4377,13 @@ dependencies = [ "tokio-util", "tracing", "tracing-core", - "uuid", ] [[package]] name = "x509-parser" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb9bace5b5589ffead1afb76e43e34cff39cd0f3ce7e170ae0c29e53b88eb1c" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" dependencies = [ "asn1-rs", "base64", @@ -4362,11 +4414,11 @@ checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" [[package]] name = "yasna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e262a29d0e61ccf2b6190d7050d4b237535fc76ce4c1210d9caa316f71dffa75" +checksum = "346d34a236c9d3e5f3b9b74563f238f955bbd05fa0b8b4efa53c130c43982f4c" dependencies = [ - "chrono", + "time 0.3.15", ] [[package]] diff --git a/compute_tools/Cargo.toml b/compute_tools/Cargo.toml index 43cf7ae2dd..d6f8fae34c 100644 --- a/compute_tools/Cargo.toml +++ b/compute_tools/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0" chrono = "0.4" -clap = "3.0" +clap = "4.0" env_logger = "0.9" futures = "0.3.13" hyper = { version = "0.14", features = ["full"] } diff --git a/compute_tools/src/bin/compute_ctl.rs b/compute_tools/src/bin/compute_ctl.rs index fc5bbc5fd2..7786d7af9c 100644 --- a/compute_tools/src/bin/compute_ctl.rs +++ b/compute_tools/src/bin/compute_ctl.rs @@ -51,53 +51,19 @@ fn main() -> Result<()> { // TODO: re-use `utils::logging` later init_logger(DEFAULT_LOG_LEVEL)?; - // Env variable is set by `cargo` - let version: Option<&str> = option_env!("CARGO_PKG_VERSION"); - let matches = clap::App::new("compute_ctl") - .version(version.unwrap_or("unknown")) - .arg( - Arg::new("connstr") - .short('C') - .long("connstr") - .value_name("DATABASE_URL") - .required(true), - ) - .arg( - Arg::new("pgdata") - .short('D') - .long("pgdata") - .value_name("DATADIR") - .required(true), - ) - .arg( - Arg::new("pgbin") - .short('b') - .long("pgbin") - .value_name("POSTGRES_PATH"), - ) - .arg( - Arg::new("spec") - .short('s') - .long("spec") - .value_name("SPEC_JSON"), - ) - .arg( - Arg::new("spec-path") - .short('S') - .long("spec-path") - .value_name("SPEC_PATH"), - ) - .get_matches(); + let matches = cli().get_matches(); - let pgdata = matches.value_of("pgdata").expect("PGDATA path is required"); + let pgdata = matches + .get_one::("pgdata") + .expect("PGDATA path is required"); let connstr = matches - .value_of("connstr") + .get_one::("connstr") .expect("Postgres connection string is required"); - let spec = matches.value_of("spec"); - let spec_path = matches.value_of("spec-path"); + let spec = matches.get_one::("spec"); + let spec_path = matches.get_one::("spec-path"); // Try to use just 'postgres' if no path is provided - let pgbin = matches.value_of("pgbin").unwrap_or("postgres"); + let pgbin = matches.get_one::("pgbin").unwrap(); let spec: ComputeSpec = match spec { // First, try to get cluster spec from the cli argument @@ -173,3 +139,48 @@ fn main() -> Result<()> { } } } + +fn cli() -> clap::Command { + // Env variable is set by `cargo` + let version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"); + clap::Command::new("compute_ctl") + .version(version) + .arg( + Arg::new("connstr") + .short('C') + .long("connstr") + .value_name("DATABASE_URL") + .required(true), + ) + .arg( + Arg::new("pgdata") + .short('D') + .long("pgdata") + .value_name("DATADIR") + .required(true), + ) + .arg( + Arg::new("pgbin") + .short('b') + .long("pgbin") + .default_value("postgres") + .value_name("POSTGRES_PATH"), + ) + .arg( + Arg::new("spec") + .short('s') + .long("spec") + .value_name("SPEC_JSON"), + ) + .arg( + Arg::new("spec-path") + .short('S') + .long("spec-path") + .value_name("SPEC_PATH"), + ) +} + +#[test] +fn verify_cli() { + cli().debug_assert() +} diff --git a/control_plane/Cargo.toml b/control_plane/Cargo.toml index 690b63613a..287385c709 100644 --- a/control_plane/Cargo.toml +++ b/control_plane/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -clap = "3.0" +clap = "4.0" comfy-table = "6.1" git-version = "0.3.5" tar = "0.4.38" diff --git a/control_plane/src/bin/neon_local.rs b/control_plane/src/bin/neon_local.rs index 08797fe907..70a2c97a9e 100644 --- a/control_plane/src/bin/neon_local.rs +++ b/control_plane/src/bin/neon_local.rs @@ -6,7 +6,7 @@ //! rely on `neon_local` to set up the environment for each test. //! use anyhow::{anyhow, bail, Context, Result}; -use clap::{App, AppSettings, Arg, ArgMatches}; +use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; use control_plane::compute::ComputeControlPlane; use control_plane::local_env::{EtcdBroker, LocalEnv}; use control_plane::safekeeper::SafekeeperNode; @@ -85,212 +85,7 @@ struct TimelineTreeEl { // * Providing CLI api to the pageserver // * TODO: export/import to/from usual postgres fn main() -> Result<()> { - let branch_name_arg = Arg::new("branch-name") - .long("branch-name") - .takes_value(true) - .help("Name of the branch to be created or used as an alias for other services") - .required(false); - - let pg_node_arg = Arg::new("node").help("Postgres node name").required(false); - - let safekeeper_id_arg = Arg::new("id").help("safekeeper id").required(false); - - let tenant_id_arg = Arg::new("tenant-id") - .long("tenant-id") - .help("Tenant id. Represented as a hexadecimal string 32 symbols length") - .takes_value(true) - .required(false); - - let timeline_id_arg = Arg::new("timeline-id") - .long("timeline-id") - .help("Timeline id. Represented as a hexadecimal string 32 symbols length") - .takes_value(true) - .required(false); - - let pg_version_arg = Arg::new("pg-version") - .long("pg-version") - .help("Postgres version to use for the initial tenant") - .required(false) - .takes_value(true) - .default_value(DEFAULT_PG_VERSION); - - let port_arg = Arg::new("port") - .long("port") - .required(false) - .value_name("port"); - - let stop_mode_arg = Arg::new("stop-mode") - .short('m') - .takes_value(true) - .possible_values(&["fast", "immediate"]) - .help("If 'immediate', don't flush repository data at shutdown") - .required(false) - .value_name("stop-mode"); - - let pageserver_config_args = Arg::new("pageserver-config-override") - .long("pageserver-config-override") - .takes_value(true) - .number_of_values(1) - .multiple_occurrences(true) - .help("Additional pageserver's configuration options or overrides, refer to pageserver's 'config-override' CLI parameter docs for more") - .required(false); - - let lsn_arg = Arg::new("lsn") - .long("lsn") - .help("Specify Lsn on the timeline to start from. By default, end of the timeline would be used.") - .takes_value(true) - .required(false); - - let matches = App::new("Neon CLI") - .setting(AppSettings::ArgRequiredElseHelp) - .version(GIT_VERSION) - .subcommand( - App::new("init") - .about("Initialize a new Neon repository") - .arg(pageserver_config_args.clone()) - .arg(timeline_id_arg.clone().help("Use a specific timeline id when creating a tenant and its initial timeline")) - .arg( - Arg::new("config") - .long("config") - .required(false) - .value_name("config"), - ) - .arg(pg_version_arg.clone()) - ) - .subcommand( - App::new("timeline") - .about("Manage timelines") - .subcommand(App::new("list") - .about("List all timelines, available to this pageserver") - .arg(tenant_id_arg.clone())) - .subcommand(App::new("branch") - .about("Create a new timeline, using another timeline as a base, copying its data") - .arg(tenant_id_arg.clone()) - .arg(branch_name_arg.clone()) - .arg(Arg::new("ancestor-branch-name").long("ancestor-branch-name").takes_value(true) - .help("Use last Lsn of another timeline (and its data) as base when creating the new timeline. The timeline gets resolved by its branch name.").required(false)) - .arg(Arg::new("ancestor-start-lsn").long("ancestor-start-lsn").takes_value(true) - .help("When using another timeline as base, use a specific Lsn in it instead of the latest one").required(false))) - .subcommand(App::new("create") - .about("Create a new blank timeline") - .arg(tenant_id_arg.clone()) - .arg(branch_name_arg.clone()) - .arg(pg_version_arg.clone()) - ) - .subcommand(App::new("import") - .about("Import timeline from basebackup directory") - .arg(tenant_id_arg.clone()) - .arg(timeline_id_arg.clone()) - .arg(Arg::new("node-name").long("node-name").takes_value(true) - .help("Name to assign to the imported timeline")) - .arg(Arg::new("base-tarfile").long("base-tarfile").takes_value(true) - .help("Basebackup tarfile to import")) - .arg(Arg::new("base-lsn").long("base-lsn").takes_value(true) - .help("Lsn the basebackup starts at")) - .arg(Arg::new("wal-tarfile").long("wal-tarfile").takes_value(true) - .help("Wal to add after base")) - .arg(Arg::new("end-lsn").long("end-lsn").takes_value(true) - .help("Lsn the basebackup ends at")) - .arg(pg_version_arg.clone()) - ) - ).subcommand( - App::new("tenant") - .setting(AppSettings::ArgRequiredElseHelp) - .about("Manage tenants") - .subcommand(App::new("list")) - .subcommand(App::new("create") - .arg(tenant_id_arg.clone()) - .arg(timeline_id_arg.clone().help("Use a specific timeline id when creating a tenant and its initial timeline")) - .arg(Arg::new("config").short('c').takes_value(true).multiple_occurrences(true).required(false)) - .arg(pg_version_arg.clone()) - ) - .subcommand(App::new("config") - .arg(tenant_id_arg.clone()) - .arg(Arg::new("config").short('c').takes_value(true).multiple_occurrences(true).required(false)) - ) - ) - .subcommand( - App::new("pageserver") - .setting(AppSettings::ArgRequiredElseHelp) - .about("Manage pageserver") - .subcommand(App::new("status")) - .subcommand(App::new("start").about("Start local pageserver").arg(pageserver_config_args.clone())) - .subcommand(App::new("stop").about("Stop local pageserver") - .arg(stop_mode_arg.clone())) - .subcommand(App::new("restart").about("Restart local pageserver").arg(pageserver_config_args.clone())) - ) - .subcommand( - App::new("safekeeper") - .setting(AppSettings::ArgRequiredElseHelp) - .about("Manage safekeepers") - .subcommand(App::new("start") - .about("Start local safekeeper") - .arg(safekeeper_id_arg.clone()) - ) - .subcommand(App::new("stop") - .about("Stop local safekeeper") - .arg(safekeeper_id_arg.clone()) - .arg(stop_mode_arg.clone()) - ) - .subcommand(App::new("restart") - .about("Restart local safekeeper") - .arg(safekeeper_id_arg.clone()) - .arg(stop_mode_arg.clone()) - ) - ) - .subcommand( - App::new("pg") - .setting(AppSettings::ArgRequiredElseHelp) - .about("Manage postgres instances") - .subcommand(App::new("list").arg(tenant_id_arg.clone())) - .subcommand(App::new("create") - .about("Create a postgres compute node") - .arg(pg_node_arg.clone()) - .arg(branch_name_arg.clone()) - .arg(tenant_id_arg.clone()) - .arg(lsn_arg.clone()) - .arg(port_arg.clone()) - .arg( - Arg::new("config-only") - .help("Don't do basebackup, create compute node with only config files") - .long("config-only") - .required(false)) - .arg(pg_version_arg.clone()) - ) - .subcommand(App::new("start") - .about("Start a postgres compute node.\n This command actually creates new node from scratch, but preserves existing config files") - .arg(pg_node_arg.clone()) - .arg(tenant_id_arg.clone()) - .arg(branch_name_arg.clone()) - .arg(timeline_id_arg.clone()) - .arg(lsn_arg.clone()) - .arg(port_arg.clone()) - .arg(pg_version_arg.clone()) - ) - .subcommand( - App::new("stop") - .arg(pg_node_arg.clone()) - .arg(tenant_id_arg.clone()) - .arg( - Arg::new("destroy") - .help("Also delete data directory (now optional, should be default in future)") - .long("destroy") - .required(false) - ) - ) - - ) - .subcommand( - App::new("start") - .about("Start page server and safekeepers") - .arg(pageserver_config_args) - ) - .subcommand( - App::new("stop") - .about("Stop page server and safekeepers") - .arg(stop_mode_arg.clone()) - ) - .get_matches(); + let matches = cli().get_matches(); let (sub_name, sub_args) = match matches.subcommand() { Some(subcommand_data) => subcommand_data, @@ -475,16 +270,16 @@ fn get_tenant_id(sub_match: &ArgMatches, env: &local_env::LocalEnv) -> anyhow::R fn parse_tenant_id(sub_match: &ArgMatches) -> anyhow::Result> { sub_match - .value_of("tenant-id") - .map(TenantId::from_str) + .get_one::("tenant-id") + .map(|tenant_id| TenantId::from_str(tenant_id)) .transpose() .context("Failed to parse tenant id from the argument string") } fn parse_timeline_id(sub_match: &ArgMatches) -> anyhow::Result> { sub_match - .value_of("timeline-id") - .map(TimelineId::from_str) + .get_one::("timeline-id") + .map(|timeline_id| TimelineId::from_str(timeline_id)) .transpose() .context("Failed to parse timeline id from the argument string") } @@ -493,19 +288,22 @@ fn handle_init(init_match: &ArgMatches) -> anyhow::Result { let initial_timeline_id_arg = parse_timeline_id(init_match)?; // Create config file - let toml_file: String = if let Some(config_path) = init_match.value_of("config") { + let toml_file: String = if let Some(config_path) = init_match.get_one::("config") { // load and parse the file - std::fs::read_to_string(std::path::Path::new(config_path)) - .with_context(|| format!("Could not read configuration file '{config_path}'"))? + std::fs::read_to_string(config_path).with_context(|| { + format!( + "Could not read configuration file '{}'", + config_path.display() + ) + })? } else { // Built-in default config default_conf(&EtcdBroker::locate_etcd()?) }; let pg_version = init_match - .value_of("pg-version") - .unwrap() - .parse::() + .get_one::("pg-version") + .copied() .context("Failed to parse postgres version from the argument string")?; let mut env = @@ -541,9 +339,10 @@ fn handle_init(init_match: &ArgMatches) -> anyhow::Result { fn pageserver_config_overrides(init_match: &ArgMatches) -> Vec<&str> { init_match - .values_of("pageserver-config-override") + .get_many::("pageserver-config-override") .into_iter() .flatten() + .map(|s| s.as_str()) .collect() } @@ -558,7 +357,7 @@ fn handle_tenant(tenant_match: &ArgMatches, env: &mut local_env::LocalEnv) -> an Some(("create", create_match)) => { let initial_tenant_id = parse_tenant_id(create_match)?; let tenant_conf: HashMap<_, _> = create_match - .values_of("config") + .get_many::("config") .map(|vals| vals.flat_map(|c| c.split_once(':')).collect()) .unwrap_or_default(); let new_tenant_id = pageserver.tenant_create(initial_tenant_id, tenant_conf)?; @@ -567,9 +366,8 @@ fn handle_tenant(tenant_match: &ArgMatches, env: &mut local_env::LocalEnv) -> an // Create an initial timeline for the new tenant let new_timeline_id = parse_timeline_id(create_match)?; let pg_version = create_match - .value_of("pg-version") - .unwrap() - .parse::() + .get_one::("pg-version") + .copied() .context("Failed to parse postgres version from the argument string")?; let timeline_info = pageserver.timeline_create( @@ -595,7 +393,7 @@ fn handle_tenant(tenant_match: &ArgMatches, env: &mut local_env::LocalEnv) -> an Some(("config", create_match)) => { let tenant_id = get_tenant_id(create_match, env)?; let tenant_conf: HashMap<_, _> = create_match - .values_of("config") + .get_many::("config") .map(|vals| vals.flat_map(|c| c.split_once(':')).collect()) .unwrap_or_default(); @@ -622,13 +420,12 @@ fn handle_timeline(timeline_match: &ArgMatches, env: &mut local_env::LocalEnv) - Some(("create", create_match)) => { let tenant_id = get_tenant_id(create_match, env)?; let new_branch_name = create_match - .value_of("branch-name") + .get_one::("branch-name") .ok_or_else(|| anyhow!("No branch name provided"))?; let pg_version = create_match - .value_of("pg-version") - .unwrap() - .parse::() + .get_one::("pg-version") + .copied() .context("Failed to parse postgres version from the argument string")?; let timeline_info = @@ -647,35 +444,32 @@ fn handle_timeline(timeline_match: &ArgMatches, env: &mut local_env::LocalEnv) - let tenant_id = get_tenant_id(import_match, env)?; let timeline_id = parse_timeline_id(import_match)?.expect("No timeline id provided"); let name = import_match - .value_of("node-name") + .get_one::("node-name") .ok_or_else(|| anyhow!("No node name provided"))?; // Parse base inputs let base_tarfile = import_match - .value_of("base-tarfile") - .map(|s| PathBuf::from_str(s).unwrap()) - .ok_or_else(|| anyhow!("No base-tarfile provided"))?; + .get_one::("base-tarfile") + .ok_or_else(|| anyhow!("No base-tarfile provided"))? + .to_owned(); let base_lsn = Lsn::from_str( import_match - .value_of("base-lsn") + .get_one::("base-lsn") .ok_or_else(|| anyhow!("No base-lsn provided"))?, )?; let base = (base_lsn, base_tarfile); // Parse pg_wal inputs - let wal_tarfile = import_match - .value_of("wal-tarfile") - .map(|s| PathBuf::from_str(s).unwrap()); + let wal_tarfile = import_match.get_one::("wal-tarfile").cloned(); let end_lsn = import_match - .value_of("end-lsn") + .get_one::("end-lsn") .map(|s| Lsn::from_str(s).unwrap()); // TODO validate both or none are provided let pg_wal = end_lsn.zip(wal_tarfile); let pg_version = import_match - .value_of("pg-version") - .unwrap() - .parse::() + .get_one::("pg-version") + .copied() .context("Failed to parse postgres version from the argument string")?; let mut cplane = ComputeControlPlane::load(env.clone())?; @@ -690,10 +484,11 @@ fn handle_timeline(timeline_match: &ArgMatches, env: &mut local_env::LocalEnv) - Some(("branch", branch_match)) => { let tenant_id = get_tenant_id(branch_match, env)?; let new_branch_name = branch_match - .value_of("branch-name") + .get_one::("branch-name") .ok_or_else(|| anyhow!("No branch name provided"))?; let ancestor_branch_name = branch_match - .value_of("ancestor-branch-name") + .get_one::("ancestor-branch-name") + .map(|s| s.as_str()) .unwrap_or(DEFAULT_BRANCH_NAME); let ancestor_timeline_id = env .get_branch_timeline_id(ancestor_branch_name, tenant_id) @@ -702,8 +497,8 @@ fn handle_timeline(timeline_match: &ArgMatches, env: &mut local_env::LocalEnv) - })?; let start_lsn = branch_match - .value_of("ancestor-start-lsn") - .map(Lsn::from_str) + .get_one::("ancestor-start-lsn") + .map(|lsn_str| Lsn::from_str(lsn_str)) .transpose() .context("Failed to parse ancestor start Lsn from the request")?; let timeline_info = pageserver.timeline_create( @@ -804,45 +599,39 @@ fn handle_pg(pg_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<()> { } "create" => { let branch_name = sub_args - .value_of("branch-name") + .get_one::("branch-name") + .map(|s| s.as_str()) .unwrap_or(DEFAULT_BRANCH_NAME); let node_name = sub_args - .value_of("node") - .map(ToString::to_string) - .unwrap_or_else(|| format!("{}_node", branch_name)); + .get_one::("node") + .map(|node_name| node_name.to_string()) + .unwrap_or_else(|| format!("{branch_name}_node")); let lsn = sub_args - .value_of("lsn") - .map(Lsn::from_str) + .get_one::("lsn") + .map(|lsn_str| Lsn::from_str(lsn_str)) .transpose() .context("Failed to parse Lsn from the request")?; let timeline_id = env .get_branch_timeline_id(branch_name, tenant_id) - .ok_or_else(|| anyhow!("Found no timeline id for branch name '{}'", branch_name))?; + .ok_or_else(|| anyhow!("Found no timeline id for branch name '{branch_name}'"))?; - let port: Option = match sub_args.value_of("port") { - Some(p) => Some(p.parse()?), - None => None, - }; + let port: Option = sub_args.get_one::("port").copied(); let pg_version = sub_args - .value_of("pg-version") - .unwrap() - .parse::() + .get_one::("pg-version") + .copied() .context("Failed to parse postgres version from the argument string")?; cplane.new_node(tenant_id, &node_name, timeline_id, lsn, port, pg_version)?; } "start" => { - let port: Option = match sub_args.value_of("port") { - Some(p) => Some(p.parse()?), - None => None, - }; + let port: Option = sub_args.get_one::("port").copied(); let node_name = sub_args - .value_of("node") + .get_one::("node") .ok_or_else(|| anyhow!("No node name was provided to start"))?; - let node = cplane.nodes.get(&(tenant_id, node_name.to_owned())); + let node = cplane.nodes.get(&(tenant_id, node_name.to_string())); let auth_token = if matches!(env.pageserver.auth_type, AuthType::NeonJWT) { let claims = Claims::new(Some(tenant_id), Scope::Tenant); @@ -853,36 +642,33 @@ fn handle_pg(pg_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<()> { }; if let Some(node) = node { - println!("Starting existing postgres {}...", node_name); + println!("Starting existing postgres {node_name}..."); node.start(&auth_token)?; } else { let branch_name = sub_args - .value_of("branch-name") + .get_one::("branch-name") + .map(|s| s.as_str()) .unwrap_or(DEFAULT_BRANCH_NAME); let timeline_id = env .get_branch_timeline_id(branch_name, tenant_id) .ok_or_else(|| { - anyhow!("Found no timeline id for branch name '{}'", branch_name) + anyhow!("Found no timeline id for branch name '{branch_name}'") })?; let lsn = sub_args - .value_of("lsn") - .map(Lsn::from_str) + .get_one::("lsn") + .map(|lsn_str| Lsn::from_str(lsn_str)) .transpose() .context("Failed to parse Lsn from the request")?; let pg_version = sub_args - .value_of("pg-version") - .unwrap() - .parse::() - .context("Failed to parse postgres version from the argument string")?; + .get_one::("pg-version") + .copied() + .context("Failed to `pg-version` from the argument string")?; // when used with custom port this results in non obvious behaviour // port is remembered from first start command, i e // start --port X // stop // start <-- will also use port X even without explicit port argument - println!( - "Starting new postgres (v{}) {} on timeline {} ...", - pg_version, node_name, timeline_id - ); + println!("Starting new postgres (v{pg_version}) {node_name} on timeline {timeline_id} ..."); let node = cplane.new_node(tenant_id, node_name, timeline_id, lsn, port, pg_version)?; @@ -891,18 +677,18 @@ fn handle_pg(pg_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<()> { } "stop" => { let node_name = sub_args - .value_of("node") + .get_one::("node") .ok_or_else(|| anyhow!("No node name was provided to stop"))?; - let destroy = sub_args.is_present("destroy"); + let destroy = sub_args.get_flag("destroy"); let node = cplane .nodes - .get(&(tenant_id, node_name.to_owned())) - .with_context(|| format!("postgres {} is not found", node_name))?; + .get(&(tenant_id, node_name.to_string())) + .with_context(|| format!("postgres {node_name} is not found"))?; node.stop(destroy)?; } - _ => bail!("Unexpected pg subcommand '{}'", sub_name), + _ => bail!("Unexpected pg subcommand '{sub_name}'"), } Ok(()) @@ -920,7 +706,10 @@ fn handle_pageserver(sub_match: &ArgMatches, env: &local_env::LocalEnv) -> Resul } Some(("stop", stop_match)) => { - let immediate = stop_match.value_of("stop-mode") == Some("immediate"); + let immediate = stop_match + .get_one::("stop-mode") + .map(|s| s.as_str()) + == Some("immediate"); if let Err(e) = pageserver.stop(immediate) { eprintln!("pageserver stop failed: {}", e); @@ -970,7 +759,7 @@ fn handle_safekeeper(sub_match: &ArgMatches, env: &local_env::LocalEnv) -> Resul }; // All the commands take an optional safekeeper name argument - let sk_id = if let Some(id_str) = sub_args.value_of("id") { + let sk_id = if let Some(id_str) = sub_args.get_one::("id") { NodeId(id_str.parse().context("while parsing safekeeper id")?) } else { DEFAULT_SAFEKEEPER_ID @@ -986,7 +775,8 @@ fn handle_safekeeper(sub_match: &ArgMatches, env: &local_env::LocalEnv) -> Resul } "stop" => { - let immediate = sub_args.value_of("stop-mode") == Some("immediate"); + let immediate = + sub_args.get_one::("stop-mode").map(|s| s.as_str()) == Some("immediate"); if let Err(e) = safekeeper.stop(immediate) { eprintln!("safekeeper stop failed: {}", e); @@ -995,7 +785,8 @@ fn handle_safekeeper(sub_match: &ArgMatches, env: &local_env::LocalEnv) -> Resul } "restart" => { - let immediate = sub_args.value_of("stop-mode") == Some("immediate"); + let immediate = + sub_args.get_one::("stop-mode").map(|s| s.as_str()) == Some("immediate"); if let Err(e) = safekeeper.stop(immediate) { eprintln!("safekeeper stop failed: {}", e); @@ -1039,7 +830,8 @@ fn handle_start_all(sub_match: &ArgMatches, env: &local_env::LocalEnv) -> anyhow } fn handle_stop_all(sub_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<()> { - let immediate = sub_match.value_of("stop-mode") == Some("immediate"); + let immediate = + sub_match.get_one::("stop-mode").map(|s| s.as_str()) == Some("immediate"); let pageserver = PageServerNode::from_env(env); @@ -1072,3 +864,219 @@ fn try_stop_etcd_process(env: &local_env::LocalEnv) { eprintln!("etcd stop failed: {e}"); } } + +fn cli() -> Command { + let branch_name_arg = Arg::new("branch-name") + .long("branch-name") + .help("Name of the branch to be created or used as an alias for other services") + .required(false); + + let pg_node_arg = Arg::new("node").help("Postgres node name").required(false); + + let safekeeper_id_arg = Arg::new("id").help("safekeeper id").required(false); + + let tenant_id_arg = Arg::new("tenant-id") + .long("tenant-id") + .help("Tenant id. Represented as a hexadecimal string 32 symbols length") + .required(false); + + let timeline_id_arg = Arg::new("timeline-id") + .long("timeline-id") + .help("Timeline id. Represented as a hexadecimal string 32 symbols length") + .required(false); + + let pg_version_arg = Arg::new("pg-version") + .long("pg-version") + .help("Postgres version to use for the initial tenant") + .required(false) + .value_parser(value_parser!(u32)) + .default_value(DEFAULT_PG_VERSION); + + let port_arg = Arg::new("port") + .long("port") + .required(false) + .value_parser(value_parser!(u16)) + .value_name("port"); + + let stop_mode_arg = Arg::new("stop-mode") + .short('m') + .value_parser(["fast", "immediate"]) + .help("If 'immediate', don't flush repository data at shutdown") + .required(false) + .value_name("stop-mode"); + + let pageserver_config_args = Arg::new("pageserver-config-override") + .long("pageserver-config-override") + .num_args(1) + .action(ArgAction::Append) + .help("Additional pageserver's configuration options or overrides, refer to pageserver's 'config-override' CLI parameter docs for more") + .required(false); + + let lsn_arg = Arg::new("lsn") + .long("lsn") + .help("Specify Lsn on the timeline to start from. By default, end of the timeline would be used.") + .required(false); + + Command::new("Neon CLI") + .arg_required_else_help(true) + .version(GIT_VERSION) + .subcommand( + Command::new("init") + .about("Initialize a new Neon repository") + .arg(pageserver_config_args.clone()) + .arg(timeline_id_arg.clone().help("Use a specific timeline id when creating a tenant and its initial timeline")) + .arg( + Arg::new("config") + .long("config") + .required(false) + .value_parser(value_parser!(PathBuf)) + .value_name("config"), + ) + .arg(pg_version_arg.clone()) + ) + .subcommand( + Command::new("timeline") + .about("Manage timelines") + .subcommand(Command::new("list") + .about("List all timelines, available to this pageserver") + .arg(tenant_id_arg.clone())) + .subcommand(Command::new("branch") + .about("Create a new timeline, using another timeline as a base, copying its data") + .arg(tenant_id_arg.clone()) + .arg(branch_name_arg.clone()) + .arg(Arg::new("ancestor-branch-name").long("ancestor-branch-name") + .help("Use last Lsn of another timeline (and its data) as base when creating the new timeline. The timeline gets resolved by its branch name.").required(false)) + .arg(Arg::new("ancestor-start-lsn").long("ancestor-start-lsn") + .help("When using another timeline as base, use a specific Lsn in it instead of the latest one").required(false))) + .subcommand(Command::new("create") + .about("Create a new blank timeline") + .arg(tenant_id_arg.clone()) + .arg(branch_name_arg.clone()) + .arg(pg_version_arg.clone()) + ) + .subcommand(Command::new("import") + .about("Import timeline from basebackup directory") + .arg(tenant_id_arg.clone()) + .arg(timeline_id_arg.clone()) + .arg(Arg::new("node-name").long("node-name") + .help("Name to assign to the imported timeline")) + .arg(Arg::new("base-tarfile") + .long("base-tarfile") + .value_parser(value_parser!(PathBuf)) + .help("Basebackup tarfile to import") + ) + .arg(Arg::new("base-lsn").long("base-lsn") + .help("Lsn the basebackup starts at")) + .arg(Arg::new("wal-tarfile") + .long("wal-tarfile") + .value_parser(value_parser!(PathBuf)) + .help("Wal to add after base") + ) + .arg(Arg::new("end-lsn").long("end-lsn") + .help("Lsn the basebackup ends at")) + .arg(pg_version_arg.clone()) + ) + ).subcommand( + Command::new("tenant") + .arg_required_else_help(true) + .about("Manage tenants") + .subcommand(Command::new("list")) + .subcommand(Command::new("create") + .arg(tenant_id_arg.clone()) + .arg(timeline_id_arg.clone().help("Use a specific timeline id when creating a tenant and its initial timeline")) + .arg(Arg::new("config").short('c').num_args(1).action(ArgAction::Append).required(false)) + .arg(pg_version_arg.clone()) + ) + .subcommand(Command::new("config") + .arg(tenant_id_arg.clone()) + .arg(Arg::new("config").short('c').num_args(1).action(ArgAction::Append).required(false)) + ) + ) + .subcommand( + Command::new("pageserver") + .arg_required_else_help(true) + .about("Manage pageserver") + .subcommand(Command::new("status")) + .subcommand(Command::new("start").about("Start local pageserver").arg(pageserver_config_args.clone())) + .subcommand(Command::new("stop").about("Stop local pageserver") + .arg(stop_mode_arg.clone())) + .subcommand(Command::new("restart").about("Restart local pageserver").arg(pageserver_config_args.clone())) + ) + .subcommand( + Command::new("safekeeper") + .arg_required_else_help(true) + .about("Manage safekeepers") + .subcommand(Command::new("start") + .about("Start local safekeeper") + .arg(safekeeper_id_arg.clone()) + ) + .subcommand(Command::new("stop") + .about("Stop local safekeeper") + .arg(safekeeper_id_arg.clone()) + .arg(stop_mode_arg.clone()) + ) + .subcommand(Command::new("restart") + .about("Restart local safekeeper") + .arg(safekeeper_id_arg) + .arg(stop_mode_arg.clone()) + ) + ) + .subcommand( + Command::new("pg") + .arg_required_else_help(true) + .about("Manage postgres instances") + .subcommand(Command::new("list").arg(tenant_id_arg.clone())) + .subcommand(Command::new("create") + .about("Create a postgres compute node") + .arg(pg_node_arg.clone()) + .arg(branch_name_arg.clone()) + .arg(tenant_id_arg.clone()) + .arg(lsn_arg.clone()) + .arg(port_arg.clone()) + .arg( + Arg::new("config-only") + .help("Don't do basebackup, create compute node with only config files") + .long("config-only") + .required(false)) + .arg(pg_version_arg.clone()) + ) + .subcommand(Command::new("start") + .about("Start a postgres compute node.\n This command actually creates new node from scratch, but preserves existing config files") + .arg(pg_node_arg.clone()) + .arg(tenant_id_arg.clone()) + .arg(branch_name_arg) + .arg(timeline_id_arg) + .arg(lsn_arg) + .arg(port_arg) + .arg(pg_version_arg) + ) + .subcommand( + Command::new("stop") + .arg(pg_node_arg) + .arg(tenant_id_arg) + .arg( + Arg::new("destroy") + .help("Also delete data directory (now optional, should be default in future)") + .long("destroy") + .action(ArgAction::SetTrue) + .required(false) + ) + ) + + ) + .subcommand( + Command::new("start") + .about("Start page server and safekeepers") + .arg(pageserver_config_args) + ) + .subcommand( + Command::new("stop") + .about("Stop page server and safekeepers") + .arg(stop_mode_arg) + ) +} + +#[test] +fn verify_cli() { + cli().debug_assert(); +} diff --git a/libs/postgres_ffi/Cargo.toml b/libs/postgres_ffi/Cargo.toml index 60caca76b8..01ff6ab60e 100644 --- a/libs/postgres_ffi/Cargo.toml +++ b/libs/postgres_ffi/Cargo.toml @@ -13,7 +13,7 @@ crc32c = "0.6.0" hex = "0.4.3" once_cell = "1.13.0" log = "0.4.14" -memoffset = "0.6.2" +memoffset = "0.7" thiserror = "1.0" serde = { version = "1.0", features = ["derive"] } utils = { path = "../utils" } @@ -26,4 +26,4 @@ wal_craft = { path = "wal_craft" } [build-dependencies] anyhow = "1.0" -bindgen = "0.60.1" +bindgen = "0.61" diff --git a/libs/postgres_ffi/wal_craft/Cargo.toml b/libs/postgres_ffi/wal_craft/Cargo.toml index 88466737ed..4c35c5a650 100644 --- a/libs/postgres_ffi/wal_craft/Cargo.toml +++ b/libs/postgres_ffi/wal_craft/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0" -clap = "3.0" +clap = "4.0" env_logger = "0.9" log = "0.4" once_cell = "1.13.0" diff --git a/libs/postgres_ffi/wal_craft/src/bin/wal_craft.rs b/libs/postgres_ffi/wal_craft/src/bin/wal_craft.rs index 9563298cd8..e87ca27e90 100644 --- a/libs/postgres_ffi/wal_craft/src/bin/wal_craft.rs +++ b/libs/postgres_ffi/wal_craft/src/bin/wal_craft.rs @@ -1,68 +1,19 @@ use anyhow::*; -use clap::{App, Arg, ArgMatches}; -use std::str::FromStr; +use clap::{value_parser, Arg, ArgMatches, Command}; +use std::{path::PathBuf, str::FromStr}; use wal_craft::*; fn main() -> Result<()> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("wal_craft=info")) .init(); - let type_arg = &Arg::new("type") - .takes_value(true) - .help("Type of WAL to craft") - .possible_values([ - Simple::NAME, - LastWalRecordXlogSwitch::NAME, - LastWalRecordXlogSwitchEndsOnPageBoundary::NAME, - WalRecordCrossingSegmentFollowedBySmallOne::NAME, - LastWalRecordCrossingSegment::NAME, - ]) - .required(true); - let arg_matches = App::new("Postgres WAL crafter") - .about("Crafts Postgres databases with specific WAL properties") - .subcommand( - App::new("print-postgres-config") - .about("Print the configuration required for PostgreSQL server before running this script") - ) - .subcommand( - App::new("with-initdb") - .about("Craft WAL in a new data directory first initialized with initdb") - .arg(type_arg) - .arg( - Arg::new("datadir") - .takes_value(true) - .help("Data directory for the Postgres server") - .required(true) - ) - .arg( - Arg::new("pg-distrib-dir") - .long("pg-distrib-dir") - .takes_value(true) - .help("Directory with Postgres distributions (bin and lib directories, e.g. pg_install containing subpath `v14/bin/postgresql`)") - .default_value("/usr/local") - ) - .arg( - Arg::new("pg-version") - .long("pg-version") - .help("Postgres version to use for the initial tenant") - .required(true) - .takes_value(true) - ) - ) - .subcommand( - App::new("in-existing") - .about("Craft WAL at an existing recently created Postgres database. Note that server may append new WAL entries on shutdown.") - .arg(type_arg) - .arg( - Arg::new("connection") - .takes_value(true) - .help("Connection string to the Postgres database to populate") - .required(true) - ) - ) - .get_matches(); + let arg_matches = cli().get_matches(); let wal_craft = |arg_matches: &ArgMatches, client| { - let (intermediate_lsns, end_of_wal_lsn) = match arg_matches.value_of("type").unwrap() { + let (intermediate_lsns, end_of_wal_lsn) = match arg_matches + .get_one::("type") + .map(|s| s.as_str()) + .context("'type' is required")? + { Simple::NAME => Simple::craft(client)?, LastWalRecordXlogSwitch::NAME => LastWalRecordXlogSwitch::craft(client)?, LastWalRecordXlogSwitchEndsOnPageBoundary::NAME => { @@ -72,12 +23,12 @@ fn main() -> Result<()> { WalRecordCrossingSegmentFollowedBySmallOne::craft(client)? } LastWalRecordCrossingSegment::NAME => LastWalRecordCrossingSegment::craft(client)?, - a => panic!("Unknown --type argument: {}", a), + a => panic!("Unknown --type argument: {a}"), }; for lsn in intermediate_lsns { - println!("intermediate_lsn = {}", lsn); + println!("intermediate_lsn = {lsn}"); } - println!("end_of_wal = {}", end_of_wal_lsn); + println!("end_of_wal = {end_of_wal_lsn}"); Ok(()) }; @@ -85,20 +36,24 @@ fn main() -> Result<()> { None => panic!("No subcommand provided"), Some(("print-postgres-config", _)) => { for cfg in REQUIRED_POSTGRES_CONFIG.iter() { - println!("{}", cfg); + println!("{cfg}"); } Ok(()) } Some(("with-initdb", arg_matches)) => { let cfg = Conf { - pg_version: arg_matches - .value_of("pg-version") - .unwrap() - .parse::() - .context("Failed to parse postgres version from the argument string")?, - pg_distrib_dir: arg_matches.value_of("pg-distrib-dir").unwrap().into(), - datadir: arg_matches.value_of("datadir").unwrap().into(), + pg_version: *arg_matches + .get_one::("pg-version") + .context("'pg-version' is required")?, + pg_distrib_dir: arg_matches + .get_one::("pg-distrib-dir") + .context("'pg-distrib-dir' is required")? + .to_owned(), + datadir: arg_matches + .get_one::("datadir") + .context("'datadir' is required")? + .to_owned(), }; cfg.initdb()?; let srv = cfg.start_server()?; @@ -108,9 +63,77 @@ fn main() -> Result<()> { } Some(("in-existing", arg_matches)) => wal_craft( arg_matches, - &mut postgres::Config::from_str(arg_matches.value_of("connection").unwrap())? - .connect(postgres::NoTls)?, + &mut postgres::Config::from_str( + arg_matches + .get_one::("connection") + .context("'connection' is required")?, + ) + .context( + "'connection' argument value could not be parsed as a postgres connection string", + )? + .connect(postgres::NoTls)?, ), Some(_) => panic!("Unknown subcommand"), } } + +fn cli() -> Command { + let type_arg = &Arg::new("type") + .help("Type of WAL to craft") + .value_parser([ + Simple::NAME, + LastWalRecordXlogSwitch::NAME, + LastWalRecordXlogSwitchEndsOnPageBoundary::NAME, + WalRecordCrossingSegmentFollowedBySmallOne::NAME, + LastWalRecordCrossingSegment::NAME, + ]) + .required(true); + + Command::new("Postgres WAL crafter") + .about("Crafts Postgres databases with specific WAL properties") + .subcommand( + Command::new("print-postgres-config") + .about("Print the configuration required for PostgreSQL server before running this script") + ) + .subcommand( + Command::new("with-initdb") + .about("Craft WAL in a new data directory first initialized with initdb") + .arg(type_arg) + .arg( + Arg::new("datadir") + .help("Data directory for the Postgres server") + .value_parser(value_parser!(PathBuf)) + .required(true) + ) + .arg( + Arg::new("pg-distrib-dir") + .long("pg-distrib-dir") + .value_parser(value_parser!(PathBuf)) + .help("Directory with Postgres distributions (bin and lib directories, e.g. pg_install containing subpath `v14/bin/postgresql`)") + .default_value("/usr/local") + ) + .arg( + Arg::new("pg-version") + .long("pg-version") + .help("Postgres version to use for the initial tenant") + .value_parser(value_parser!(u32)) + .required(true) + + ) + ) + .subcommand( + Command::new("in-existing") + .about("Craft WAL at an existing recently created Postgres database. Note that server may append new WAL entries on shutdown.") + .arg(type_arg) + .arg( + Arg::new("connection") + .help("Connection string to the Postgres database to populate") + .required(true) + ) + ) +} + +#[test] +fn verify_cli() { + cli().debug_assert(); +} diff --git a/pageserver/Cargo.toml b/pageserver/Cargo.toml index ea0cf3f18a..ebdda5c6da 100644 --- a/pageserver/Cargo.toml +++ b/pageserver/Cargo.toml @@ -23,7 +23,7 @@ futures = "0.3.13" hex = "0.4.3" hyper = "0.14" itertools = "0.10.3" -clap = "3.0" +clap = { version = "4.0", features = ["string"] } daemonize = "0.4.1" tokio = { version = "1.17", features = ["process", "sync", "macros", "fs", "rt", "io-util", "time"] } tokio-util = { version = "0.7.3", features = ["io", "io-util"] } diff --git a/pageserver/src/bin/pageserver.rs b/pageserver/src/bin/pageserver.rs index 4cd82e37b1..12f594077e 100644 --- a/pageserver/src/bin/pageserver.rs +++ b/pageserver/src/bin/pageserver.rs @@ -6,7 +6,7 @@ use tracing::*; use anyhow::{anyhow, bail, Context, Result}; -use clap::{App, Arg}; +use clap::{Arg, ArgAction, Command}; use daemonize::Daemonize; use fail::FailScenario; @@ -51,57 +51,17 @@ fn version() -> String { } fn main() -> anyhow::Result<()> { - let arg_matches = App::new("Neon page server") - .about("Materializes WAL stream to pages and serves them to the postgres") - .version(&*version()) - .arg( + let arg_matches = cli().get_matches(); - Arg::new("daemonize") - .short('d') - .long("daemonize") - .takes_value(false) - .help("Run in the background"), - ) - .arg( - Arg::new("init") - .long("init") - .takes_value(false) - .help("Initialize pageserver with all given config overrides"), - ) - .arg( - Arg::new("workdir") - .short('D') - .long("workdir") - .takes_value(true) - .help("Working directory for the pageserver"), - ) - // See `settings.md` for more details on the extra configuration patameters pageserver can process - .arg( - Arg::new("config-override") - .short('c') - .takes_value(true) - .number_of_values(1) - .multiple_occurrences(true) - .help("Additional configuration overrides of the ones from the toml config file (or new ones to add there). - Any option has to be a valid toml document, example: `-c=\"foo='hey'\"` `-c=\"foo={value=1}\"`"), - ) - .arg(Arg::new("update-config").long("update-config").takes_value(false).help( - "Update the config file when started", - )) - .arg( - Arg::new("enabled-features") - .long("enabled-features") - .takes_value(false) - .help("Show enabled compile time features"), - ) - .get_matches(); - - if arg_matches.is_present("enabled-features") { + if arg_matches.get_flag("enabled-features") { println!("{{\"features\": {FEATURES:?} }}"); return Ok(()); } - let workdir = Path::new(arg_matches.value_of("workdir").unwrap_or(".neon")); + let workdir = arg_matches + .get_one::("workdir") + .map(Path::new) + .unwrap_or_else(|| Path::new(".neon")); let workdir = workdir .canonicalize() .with_context(|| format!("Error opening workdir '{}'", workdir.display()))?; @@ -115,7 +75,7 @@ fn main() -> anyhow::Result<()> { ) })?; - let daemonize = arg_matches.is_present("daemonize"); + let daemonize = arg_matches.get_flag("daemonize"); let conf = match initialize_config(&cfg_file_path, arg_matches, &workdir)? { ControlFlow::Continue(conf) => conf, @@ -153,8 +113,8 @@ fn initialize_config( arg_matches: clap::ArgMatches, workdir: &Path, ) -> anyhow::Result> { - let init = arg_matches.is_present("init"); - let update_config = init || arg_matches.is_present("update-config"); + let init = arg_matches.get_flag("init"); + let update_config = init || arg_matches.get_flag("update-config"); let (mut toml, config_file_exists) = if cfg_file_path.is_file() { if init { @@ -196,13 +156,10 @@ fn initialize_config( ) }; - if let Some(values) = arg_matches.values_of("config-override") { + if let Some(values) = arg_matches.get_many::("config-override") { for option_line in values { let doc = toml_edit::Document::from_str(option_line).with_context(|| { - format!( - "Option '{}' could not be parsed as a toml document", - option_line - ) + format!("Option '{option_line}' could not be parsed as a toml document") })?; for (key, item) in doc.iter() { @@ -244,7 +201,7 @@ fn start_pageserver(conf: &'static PageServerConf, daemonize: bool) -> Result<() // Initialize logger let log_file = logging::init(LOG_FILE_NAME, daemonize)?; - info!("version: {GIT_VERSION}"); + info!("version: {}", version()); // TODO: Check that it looks like a valid repository before going further @@ -385,3 +342,55 @@ fn start_pageserver(conf: &'static PageServerConf, daemonize: bool) -> Result<() } }) } + +fn cli() -> Command { + Command::new("Neon page server") + .about("Materializes WAL stream to pages and serves them to the postgres") + .version(version()) + .arg( + + Arg::new("daemonize") + .short('d') + .long("daemonize") + .action(ArgAction::SetTrue) + .help("Run in the background"), + ) + .arg( + Arg::new("init") + .long("init") + .action(ArgAction::SetTrue) + .help("Initialize pageserver with all given config overrides"), + ) + .arg( + Arg::new("workdir") + .short('D') + .long("workdir") + .help("Working directory for the pageserver"), + ) + // See `settings.md` for more details on the extra configuration patameters pageserver can process + .arg( + Arg::new("config-override") + .short('c') + .num_args(1) + .action(ArgAction::Append) + .help("Additional configuration overrides of the ones from the toml config file (or new ones to add there). \ + Any option has to be a valid toml document, example: `-c=\"foo='hey'\"` `-c=\"foo={value=1}\"`"), + ) + .arg( + Arg::new("update-config") + .long("update-config") + .action(ArgAction::SetTrue) + .help("Update the config file when started"), + ) + .arg( + Arg::new("enabled-features") + .long("enabled-features") + .action(ArgAction::SetTrue) + .help("Show enabled compile time features"), + ) +} + +#[test] +fn verify_cli() { + cli().debug_assert(); +} diff --git a/pageserver/src/bin/pageserver_binutils.rs b/pageserver/src/bin/pageserver_binutils.rs index ec7699f194..b1484ac45a 100644 --- a/pageserver/src/bin/pageserver_binutils.rs +++ b/pageserver/src/bin/pageserver_binutils.rs @@ -9,7 +9,7 @@ use std::{ }; use anyhow::Context; -use clap::{App, Arg}; +use clap::{value_parser, Arg, Command}; use pageserver::{ page_cache, @@ -24,40 +24,14 @@ project_git_version!(GIT_VERSION); const METADATA_SUBCOMMAND: &str = "metadata"; fn main() -> anyhow::Result<()> { - let arg_matches = App::new("Neon Pageserver binutils") - .about("Reads pageserver (and related) binary files management utility") - .version(GIT_VERSION) - .arg(Arg::new("path").help("Input file path").required(false)) - .subcommand( - App::new(METADATA_SUBCOMMAND) - .about("Read and update pageserver metadata file") - .arg( - Arg::new("metadata_path") - .help("Input metadata file path") - .required(false), - ) - .arg( - Arg::new("disk_consistent_lsn") - .long("disk_consistent_lsn") - .takes_value(true) - .help("Replace disk consistent Lsn"), - ) - .arg( - Arg::new("prev_record_lsn") - .long("prev_record_lsn") - .takes_value(true) - .help("Replace previous record Lsn"), - ), - ) - .get_matches(); + let arg_matches = cli().get_matches(); match arg_matches.subcommand() { Some((subcommand_name, subcommand_matches)) => { - let path = PathBuf::from( - subcommand_matches - .value_of("metadata_path") - .context("'metadata_path' argument is missing")?, - ); + let path = subcommand_matches + .get_one::("metadata_path") + .context("'metadata_path' argument is missing")? + .to_path_buf(); anyhow::ensure!( subcommand_name == METADATA_SUBCOMMAND, "Unknown subcommand {subcommand_name}" @@ -65,11 +39,10 @@ fn main() -> anyhow::Result<()> { handle_metadata(&path, subcommand_matches)?; } None => { - let path = PathBuf::from( - arg_matches - .value_of("path") - .context("'path' argument is missing")?, - ); + let path = arg_matches + .get_one::("path") + .context("'path' argument is missing")? + .to_path_buf(); println!( "No subcommand specified, attempting to guess the format for file {}", path.display() @@ -110,7 +83,7 @@ fn handle_metadata(path: &Path, arg_matches: &clap::ArgMatches) -> Result<(), an let mut meta = TimelineMetadata::from_bytes(&metadata_bytes)?; println!("Current metadata:\n{meta:?}"); let mut update_meta = false; - if let Some(disk_consistent_lsn) = arg_matches.value_of("disk_consistent_lsn") { + if let Some(disk_consistent_lsn) = arg_matches.get_one::("disk_consistent_lsn") { meta = TimelineMetadata::new( Lsn::from_str(disk_consistent_lsn)?, meta.prev_record_lsn(), @@ -122,7 +95,7 @@ fn handle_metadata(path: &Path, arg_matches: &clap::ArgMatches) -> Result<(), an ); update_meta = true; } - if let Some(prev_record_lsn) = arg_matches.value_of("prev_record_lsn") { + if let Some(prev_record_lsn) = arg_matches.get_one::("prev_record_lsn") { meta = TimelineMetadata::new( meta.disk_consistent_lsn(), Some(Lsn::from_str(prev_record_lsn)?), @@ -142,3 +115,40 @@ fn handle_metadata(path: &Path, arg_matches: &clap::ArgMatches) -> Result<(), an Ok(()) } + +fn cli() -> Command { + Command::new("Neon Pageserver binutils") + .about("Reads pageserver (and related) binary files management utility") + .version(GIT_VERSION) + .arg( + Arg::new("path") + .help("Input file path") + .value_parser(value_parser!(PathBuf)) + .required(false), + ) + .subcommand( + Command::new(METADATA_SUBCOMMAND) + .about("Read and update pageserver metadata file") + .arg( + Arg::new("metadata_path") + .help("Input metadata file path") + .value_parser(value_parser!(PathBuf)) + .required(false), + ) + .arg( + Arg::new("disk_consistent_lsn") + .long("disk_consistent_lsn") + .help("Replace disk consistent Lsn"), + ) + .arg( + Arg::new("prev_record_lsn") + .long("prev_record_lsn") + .help("Replace previous record Lsn"), + ), + ) +} + +#[test] +fn verify_cli() { + cli().debug_assert(); +} diff --git a/proxy/Cargo.toml b/proxy/Cargo.toml index 8049737989..395c22b8bc 100644 --- a/proxy/Cargo.toml +++ b/proxy/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0" atty = "0.2.14" base64 = "0.13.0" -bstr = "0.2.17" +bstr = "1.0" bytes = { version = "1.0.1", features = ['serde'] } -clap = "3.0" +clap = "4.0" futures = "0.3.13" git-version = "0.3.5" hashbrown = "0.12" @@ -22,7 +22,11 @@ once_cell = "1.13.0" parking_lot = "0.12" pin-project-lite = "0.2.7" rand = "0.8.3" -reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "rustls-tls"] } +reqwest = { version = "0.11", default-features = false, features = [ + "blocking", + "json", + "rustls-tls", +] } routerify = "3" rustls = "0.20.0" rustls-pemfile = "1" @@ -33,13 +37,13 @@ sha2 = "0.10.2" socket2 = "0.4.4" thiserror = "1.0.30" tokio = { version = "1.17", features = ["macros"] } -tokio-postgres = { git = "https://github.com/neondatabase/rust-postgres.git", rev="d052ee8b86fff9897c77b0fe89ea9daba0e1fa38" } +tokio-postgres = { git = "https://github.com/neondatabase/rust-postgres.git", rev = "d052ee8b86fff9897c77b0fe89ea9daba0e1fa38" } tokio-rustls = "0.23.0" tracing = "0.1.36" tracing-subscriber = { version = "0.3", features = ["env-filter"] } url = "2.2.2" -uuid = { version = "0.8.2", features = ["v4", "serde"]} -x509-parser = "0.13.2" +uuid = { version = "1.2", features = ["v4", "serde"] } +x509-parser = "0.14" utils = { path = "../libs/utils" } metrics = { path = "../libs/metrics" } @@ -47,6 +51,6 @@ workspace_hack = { version = "0.1", path = "../workspace_hack" } [dev-dependencies] async-trait = "0.1" -rcgen = "0.8.14" -rstest = "0.12" +rcgen = "0.10" +rstest = "0.15" tokio-postgres-rustls = "0.9.0" diff --git a/proxy/src/main.rs b/proxy/src/main.rs index 91ef26a37f..2055616a6e 100644 --- a/proxy/src/main.rs +++ b/proxy/src/main.rs @@ -45,98 +45,43 @@ async fn main() -> anyhow::Result<()> { .with_target(false) .init(); - let arg_matches = clap::App::new("Neon proxy/router") - .version(GIT_VERSION) - .arg( - Arg::new("proxy") - .short('p') - .long("proxy") - .takes_value(true) - .help("listen for incoming client connections on ip:port") - .default_value("127.0.0.1:4432"), - ) - .arg( - Arg::new("auth-backend") - .long("auth-backend") - .takes_value(true) - .possible_values(["console", "postgres", "link"]) - .default_value("link"), - ) - .arg( - Arg::new("mgmt") - .short('m') - .long("mgmt") - .takes_value(true) - .help("listen for management callback connection on ip:port") - .default_value("127.0.0.1:7000"), - ) - .arg( - Arg::new("http") - .short('h') - .long("http") - .takes_value(true) - .help("listen for incoming http connections (metrics, etc) on ip:port") - .default_value("127.0.0.1:7001"), - ) - .arg( - Arg::new("uri") - .short('u') - .long("uri") - .takes_value(true) - .help("redirect unauthenticated users to the given uri in case of link auth") - .default_value("http://localhost:3000/psql_session/"), - ) - .arg( - Arg::new("auth-endpoint") - .short('a') - .long("auth-endpoint") - .takes_value(true) - .help("cloud API endpoint for authenticating users") - .default_value("http://localhost:3000/authenticate_proxy_request/"), - ) - .arg( - Arg::new("tls-key") - .short('k') - .long("tls-key") - .alias("ssl-key") // backwards compatibility - .takes_value(true) - .help("path to TLS key for client postgres connections"), - ) - .arg( - Arg::new("tls-cert") - .short('c') - .long("tls-cert") - .alias("ssl-cert") // backwards compatibility - .takes_value(true) - .help("path to TLS cert for client postgres connections"), - ) - .get_matches(); + let arg_matches = cli().get_matches(); let tls_config = match ( - arg_matches.value_of("tls-key"), - arg_matches.value_of("tls-cert"), + arg_matches.get_one::("tls-key"), + arg_matches.get_one::("tls-cert"), ) { (Some(key_path), Some(cert_path)) => Some(config::configure_tls(key_path, cert_path)?), (None, None) => None, _ => bail!("either both or neither tls-key and tls-cert must be specified"), }; - let proxy_address: SocketAddr = arg_matches.value_of("proxy").unwrap().parse()?; - let mgmt_address: SocketAddr = arg_matches.value_of("mgmt").unwrap().parse()?; - let http_address: SocketAddr = arg_matches.value_of("http").unwrap().parse()?; + let proxy_address: SocketAddr = arg_matches.get_one::("proxy").unwrap().parse()?; + let mgmt_address: SocketAddr = arg_matches.get_one::("mgmt").unwrap().parse()?; + let http_address: SocketAddr = arg_matches.get_one::("http").unwrap().parse()?; - let auth_backend = match arg_matches.value_of("auth-backend").unwrap() { + let auth_backend = match arg_matches + .get_one::("auth-backend") + .unwrap() + .as_str() + { "console" => { - let url = arg_matches.value_of("auth-endpoint").unwrap().parse()?; + let url = arg_matches + .get_one::("auth-endpoint") + .unwrap() + .parse()?; let endpoint = http::Endpoint::new(url, reqwest::Client::new()); auth::BackendType::Console(Cow::Owned(endpoint), ()) } "postgres" => { - let url = arg_matches.value_of("auth-endpoint").unwrap().parse()?; + let url = arg_matches + .get_one::("auth-endpoint") + .unwrap() + .parse()?; auth::BackendType::Postgres(Cow::Owned(url), ()) } "link" => { - let url = arg_matches.value_of("uri").unwrap().parse()?; + let url = arg_matches.get_one::("uri").unwrap().parse()?; auth::BackendType::Link(Cow::Owned(url)) } other => bail!("unsupported auth backend: {other}"), @@ -174,3 +119,68 @@ async fn main() -> anyhow::Result<()> { Ok(()) } + +fn cli() -> clap::Command { + clap::Command::new("Neon proxy/router") + .disable_help_flag(true) + .version(GIT_VERSION) + .arg( + Arg::new("proxy") + .short('p') + .long("proxy") + .help("listen for incoming client connections on ip:port") + .default_value("127.0.0.1:4432"), + ) + .arg( + Arg::new("auth-backend") + .long("auth-backend") + .value_parser(["console", "postgres", "link"]) + .default_value("link"), + ) + .arg( + Arg::new("mgmt") + .short('m') + .long("mgmt") + .help("listen for management callback connection on ip:port") + .default_value("127.0.0.1:7000"), + ) + .arg( + Arg::new("http") + .long("http") + .help("listen for incoming http connections (metrics, etc) on ip:port") + .default_value("127.0.0.1:7001"), + ) + .arg( + Arg::new("uri") + .short('u') + .long("uri") + .help("redirect unauthenticated users to the given uri in case of link auth") + .default_value("http://localhost:3000/psql_session/"), + ) + .arg( + Arg::new("auth-endpoint") + .short('a') + .long("auth-endpoint") + .help("cloud API endpoint for authenticating users") + .default_value("http://localhost:3000/authenticate_proxy_request/"), + ) + .arg( + Arg::new("tls-key") + .short('k') + .long("tls-key") + .alias("ssl-key") // backwards compatibility + .help("path to TLS key for client postgres connections"), + ) + .arg( + Arg::new("tls-cert") + .short('c') + .long("tls-cert") + .alias("ssl-cert") // backwards compatibility + .help("path to TLS cert for client postgres connections"), + ) +} + +#[test] +fn verify_cli() { + cli().debug_assert(); +} diff --git a/safekeeper/Cargo.toml b/safekeeper/Cargo.toml index ddc3956d74..64c541ddef 100644 --- a/safekeeper/Cargo.toml +++ b/safekeeper/Cargo.toml @@ -11,7 +11,7 @@ hyper = "0.14" fs2 = "0.4.3" serde_json = "1" tracing = "0.1.27" -clap = "3.0" +clap = "4.0" daemonize = "0.4.1" tokio = { version = "1.17", features = ["macros", "fs"] } postgres-protocol = { git = "https://github.com/neondatabase/rust-postgres.git", rev="d052ee8b86fff9897c77b0fe89ea9daba0e1fa38" } diff --git a/safekeeper/src/bin/safekeeper.rs b/safekeeper/src/bin/safekeeper.rs index 3f55d823cc..9422b55d60 100644 --- a/safekeeper/src/bin/safekeeper.rs +++ b/safekeeper/src/bin/safekeeper.rs @@ -2,7 +2,7 @@ // Main entry point for the safekeeper executable // use anyhow::{bail, Context, Result}; -use clap::{App, Arg}; +use clap::{value_parser, Arg, ArgAction, Command}; use const_format::formatcp; use daemonize::Daemonize; use fs2::FileExt; @@ -40,145 +40,44 @@ const ID_FILE_NAME: &str = "safekeeper.id"; project_git_version!(GIT_VERSION); fn main() -> anyhow::Result<()> { - let arg_matches = App::new("Neon safekeeper") - .about("Store WAL stream to local file system and push it to WAL receivers") - .version(GIT_VERSION) - .arg( - Arg::new("datadir") - .short('D') - .long("dir") - .takes_value(true) - .help("Path to the safekeeper data directory"), - ) - .arg( - Arg::new("init") - .long("init") - .takes_value(false) - .help("Initialize safekeeper with ID"), - ) - .arg( - Arg::new("listen-pg") - .short('l') - .long("listen-pg") - .alias("listen") // for compatibility - .takes_value(true) - .help(formatcp!("listen for incoming WAL data connections on ip:port (default: {DEFAULT_PG_LISTEN_ADDR})")), - ) - .arg( - Arg::new("listen-http") - .long("listen-http") - .takes_value(true) - .help(formatcp!("http endpoint address for metrics on ip:port (default: {DEFAULT_HTTP_LISTEN_ADDR})")), - ) - // FIXME this argument is no longer needed since pageserver address is forwarded from compute. - // However because this argument is in use by console's e2e tests let's keep it for now and remove separately. - // So currently it is a noop. - .arg( - Arg::new("pageserver") - .short('p') - .long("pageserver") - .takes_value(true), - ) - .arg( - Arg::new("recall") - .long("recall") - .takes_value(true) - .help("Period for requestion pageserver to call for replication"), - ) - .arg( - Arg::new("daemonize") - .short('d') - .long("daemonize") - .takes_value(false) - .help("Run in the background"), - ) - .arg( - Arg::new("no-sync") - .short('n') - .long("no-sync") - .takes_value(false) - .help("Do not wait for changes to be written safely to disk"), - ) - .arg( - Arg::new("dump-control-file") - .long("dump-control-file") - .takes_value(true) - .help("Dump control file at path specified by this argument and exit"), - ) - .arg( - Arg::new("id").long("id").takes_value(true).help("safekeeper node id: integer") - ).arg( - Arg::new("broker-endpoints") - .long("broker-endpoints") - .takes_value(true) - .help("a comma separated broker (etcd) endpoints for storage nodes coordination, e.g. 'http://127.0.0.1:2379'"), - ) - .arg( - Arg::new("broker-etcd-prefix") - .long("broker-etcd-prefix") - .takes_value(true) - .help("a prefix to always use when polling/pusing data in etcd from this safekeeper"), - ) - .arg( - Arg::new("wal-backup-threads").long("backup-threads").takes_value(true).help(formatcp!("number of threads for wal backup (default {DEFAULT_WAL_BACKUP_RUNTIME_THREADS}")), - ).arg( - Arg::new("remote-storage") - .long("remote-storage") - .takes_value(true) - .help("Remote storage configuration for WAL backup (offloading to s3) as TOML inline table, e.g. {\"max_concurrent_syncs\" = 17, \"max_sync_errors\": 13, \"bucket_name\": \"\", \"bucket_region\":\"\", \"concurrency_limit\": 119}.\nSafekeeper offloads WAL to [prefix_in_bucket/]//, mirroring structure on the file system.") - ) - .arg( - Arg::new("enable-wal-backup") - .long("enable-wal-backup") - .takes_value(true) - .default_value("true") - .default_missing_value("true") - .help("Enable/disable WAL backup to s3. When disabled, safekeeper removes WAL ignoring WAL backup horizon."), - ) - .arg( - Arg::new("auth-validation-public-key-path") - .long("auth-validation-public-key-path") - .takes_value(true) - .help("Path to an RSA .pem public key which is used to check JWT tokens") - ) - .get_matches(); + let arg_matches = cli().get_matches(); - if let Some(addr) = arg_matches.value_of("dump-control-file") { + if let Some(addr) = arg_matches.get_one::("dump-control-file") { let state = control_file::FileStorage::load_control_file(Path::new(addr))?; let json = serde_json::to_string(&state)?; - print!("{}", json); + print!("{json}"); return Ok(()); } let mut conf = SafeKeeperConf::default(); - if let Some(dir) = arg_matches.value_of("datadir") { + if let Some(dir) = arg_matches.get_one::("datadir") { // change into the data directory. - std::env::set_current_dir(PathBuf::from(dir))?; + std::env::set_current_dir(dir)?; } - if arg_matches.is_present("no-sync") { + if arg_matches.get_flag("no-sync") { conf.no_sync = true; } - if arg_matches.is_present("daemonize") { + if arg_matches.get_flag("daemonize") { conf.daemonize = true; } - if let Some(addr) = arg_matches.value_of("listen-pg") { - conf.listen_pg_addr = addr.to_owned(); + if let Some(addr) = arg_matches.get_one::("listen-pg") { + conf.listen_pg_addr = addr.to_string(); } - if let Some(addr) = arg_matches.value_of("listen-http") { - conf.listen_http_addr = addr.to_owned(); + if let Some(addr) = arg_matches.get_one::("listen-http") { + conf.listen_http_addr = addr.to_string(); } - if let Some(recall) = arg_matches.value_of("recall") { + if let Some(recall) = arg_matches.get_one::("recall") { conf.recall_period = humantime::parse_duration(recall)?; } let mut given_id = None; - if let Some(given_id_str) = arg_matches.value_of("id") { + if let Some(given_id_str) = arg_matches.get_one::("id") { given_id = Some(NodeId( given_id_str .parse() @@ -186,20 +85,20 @@ fn main() -> anyhow::Result<()> { )); } - if let Some(addr) = arg_matches.value_of("broker-endpoints") { + if let Some(addr) = arg_matches.get_one::("broker-endpoints") { let collected_ep: Result, ParseError> = addr.split(',').map(Url::parse).collect(); conf.broker_endpoints = collected_ep.context("Failed to parse broker endpoint urls")?; } - if let Some(prefix) = arg_matches.value_of("broker-etcd-prefix") { + if let Some(prefix) = arg_matches.get_one::("broker-etcd-prefix") { conf.broker_etcd_prefix = prefix.to_string(); } - if let Some(backup_threads) = arg_matches.value_of("wal-backup-threads") { + if let Some(backup_threads) = arg_matches.get_one::("wal-backup-threads") { conf.backup_runtime_threads = backup_threads .parse() .with_context(|| format!("Failed to parse backup threads {}", backup_threads))?; } - if let Some(storage_conf) = arg_matches.value_of("remote-storage") { + if let Some(storage_conf) = arg_matches.get_one::("remote-storage") { // funny toml doesn't consider plain inline table as valid document, so wrap in a key to parse let storage_conf_toml = format!("remote_storage = {}", storage_conf); let parsed_toml = storage_conf_toml.parse::()?; // parse @@ -208,16 +107,16 @@ fn main() -> anyhow::Result<()> { } // Seems like there is no better way to accept bool values explicitly in clap. conf.wal_backup_enabled = arg_matches - .value_of("enable-wal-backup") + .get_one::("enable-wal-backup") .unwrap() .parse() .context("failed to parse bool enable-s3-offload bool")?; conf.auth_validation_public_key_path = arg_matches - .value_of("auth-validation-public-key-path") + .get_one::("auth-validation-public-key-path") .map(PathBuf::from); - start_safekeeper(conf, given_id, arg_matches.is_present("init")) + start_safekeeper(conf, given_id, arg_matches.get_flag("init")) } fn start_safekeeper(mut conf: SafeKeeperConf, given_id: Option, init: bool) -> Result<()> { @@ -424,3 +323,102 @@ fn set_id(conf: &mut SafeKeeperConf, given_id: Option) -> Result<()> { conf.my_id = my_id; Ok(()) } + +fn cli() -> Command { + Command::new("Neon safekeeper") + .about("Store WAL stream to local file system and push it to WAL receivers") + .version(GIT_VERSION) + .arg( + Arg::new("datadir") + .short('D') + .long("dir") + .value_parser(value_parser!(PathBuf)) + .help("Path to the safekeeper data directory"), + ) + .arg( + Arg::new("init") + .long("init") + .action(ArgAction::SetTrue) + .help("Initialize safekeeper with ID"), + ) + .arg( + Arg::new("listen-pg") + .short('l') + .long("listen-pg") + .alias("listen") // for compatibility + .help(formatcp!("listen for incoming WAL data connections on ip:port (default: {DEFAULT_PG_LISTEN_ADDR})")), + ) + .arg( + Arg::new("listen-http") + .long("listen-http") + .help(formatcp!("http endpoint address for metrics on ip:port (default: {DEFAULT_HTTP_LISTEN_ADDR})")), + ) + // FIXME this argument is no longer needed since pageserver address is forwarded from compute. + // However because this argument is in use by console's e2e tests let's keep it for now and remove separately. + // So currently it is a noop. + .arg( + Arg::new("pageserver") + .short('p') + .long("pageserver"), + ) + .arg( + Arg::new("recall") + .long("recall") + .help("Period for requestion pageserver to call for replication"), + ) + .arg( + Arg::new("daemonize") + .short('d') + .long("daemonize") + .action(ArgAction::SetTrue) + .help("Run in the background"), + ) + .arg( + Arg::new("no-sync") + .short('n') + .long("no-sync") + .action(ArgAction::SetTrue) + .help("Do not wait for changes to be written safely to disk"), + ) + .arg( + Arg::new("dump-control-file") + .long("dump-control-file") + .help("Dump control file at path specified by this argument and exit"), + ) + .arg( + Arg::new("id").long("id").help("safekeeper node id: integer") + ).arg( + Arg::new("broker-endpoints") + .long("broker-endpoints") + .help("a comma separated broker (etcd) endpoints for storage nodes coordination, e.g. 'http://127.0.0.1:2379'"), + ) + .arg( + Arg::new("broker-etcd-prefix") + .long("broker-etcd-prefix") + .help("a prefix to always use when polling/pusing data in etcd from this safekeeper"), + ) + .arg( + Arg::new("wal-backup-threads").long("backup-threads").help(formatcp!("number of threads for wal backup (default {DEFAULT_WAL_BACKUP_RUNTIME_THREADS}")), + ).arg( + Arg::new("remote-storage") + .long("remote-storage") + .help("Remote storage configuration for WAL backup (offloading to s3) as TOML inline table, e.g. {\"max_concurrent_syncs\" = 17, \"max_sync_errors\": 13, \"bucket_name\": \"\", \"bucket_region\":\"\", \"concurrency_limit\": 119}.\nSafekeeper offloads WAL to [prefix_in_bucket/]//, mirroring structure on the file system.") + ) + .arg( + Arg::new("enable-wal-backup") + .long("enable-wal-backup") + .default_value("true") + .default_missing_value("true") + .help("Enable/disable WAL backup to s3. When disabled, safekeeper removes WAL ignoring WAL backup horizon."), + ) + .arg( + Arg::new("auth-validation-public-key-path") + .long("auth-validation-public-key-path") + .help("Path to an RSA .pem public key which is used to check JWT tokens") + ) +} + +#[test] +fn verify_cli() { + cli().debug_assert(); +} diff --git a/workspace_hack/Cargo.toml b/workspace_hack/Cargo.toml index af055ed9a4..f4468d85f0 100644 --- a/workspace_hack/Cargo.toml +++ b/workspace_hack/Cargo.toml @@ -8,7 +8,6 @@ version = "0.1.0" description = "workspace-hack package, managed by hakari" # You can choose to publish this crate: see https://docs.rs/cargo-hakari/latest/cargo_hakari/publishing. publish = false - # The parts of the file between the BEGIN HAKARI SECTION and END HAKARI SECTION comments # are managed by hakari. @@ -18,7 +17,7 @@ ahash = { version = "0.7", features = ["std"] } anyhow = { version = "1", features = ["backtrace", "std"] } bytes = { version = "1", features = ["serde", "std"] } chrono = { version = "0.4", features = ["clock", "iana-time-zone", "js-sys", "oldtime", "serde", "std", "time", "wasm-bindgen", "wasmbind", "winapi"] } -clap = { version = "3", features = ["atty", "color", "std", "strsim", "suggestions", "termcolor"] } +clap = { version = "4", features = ["color", "error-context", "help", "std", "string", "suggestions", "usage"] } crossbeam-utils = { version = "0.8", features = ["once_cell", "std"] } either = { version = "1", features = ["use_std"] } fail = { version = "0.5", default-features = false, features = ["failpoints"] } @@ -26,6 +25,7 @@ hashbrown = { version = "0.12", features = ["ahash", "inline-more", "raw"] } indexmap = { version = "1", default-features = false, features = ["std"] } libc = { version = "0.2", features = ["extra_traits", "std"] } log = { version = "0.4", default-features = false, features = ["serde", "std"] } +memchr = { version = "2", features = ["std"] } nom = { version = "7", features = ["alloc", "std"] } num-bigint = { version = "0.4", features = ["std"] } num-integer = { version = "0.1", default-features = false, features = ["i128", "std"] } @@ -42,18 +42,17 @@ tokio = { version = "1", features = ["bytes", "fs", "io-std", "io-util", "libc", tokio-util = { version = "0.7", features = ["codec", "io", "io-util", "tracing"] } tracing = { version = "0.1", features = ["attributes", "log", "std", "tracing-attributes"] } tracing-core = { version = "0.1", features = ["once_cell", "std"] } -uuid = { version = "0.8", features = ["getrandom", "serde", "std", "v4"] } [build-dependencies] ahash = { version = "0.7", features = ["std"] } anyhow = { version = "1", features = ["backtrace", "std"] } bytes = { version = "1", features = ["serde", "std"] } -clap = { version = "3", features = ["atty", "color", "std", "strsim", "suggestions", "termcolor"] } either = { version = "1", features = ["use_std"] } hashbrown = { version = "0.12", features = ["ahash", "inline-more", "raw"] } indexmap = { version = "1", default-features = false, features = ["std"] } libc = { version = "0.2", features = ["extra_traits", "std"] } log = { version = "0.4", default-features = false, features = ["serde", "std"] } +memchr = { version = "2", features = ["std"] } nom = { version = "7", features = ["alloc", "std"] } prost = { version = "0.10", features = ["prost-derive", "std"] } regex = { version = "1", features = ["aho-corasick", "memchr", "perf", "perf-cache", "perf-dfa", "perf-inline", "perf-literal", "std", "unicode", "unicode-age", "unicode-bool", "unicode-case", "unicode-gencat", "unicode-perl", "unicode-script", "unicode-segment"] } From 0ec5ddea0b855908ca3bda60cc0778d906e4bb9e Mon Sep 17 00:00:00 2001 From: Anastasia Lubennikova Date: Mon, 17 Oct 2022 19:21:36 +0300 Subject: [PATCH 32/64] GRANT CREATE ON SCHEMA public TO web_access --- compute_tools/src/spec.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compute_tools/src/spec.rs b/compute_tools/src/spec.rs index bd47614386..89a6a93510 100644 --- a/compute_tools/src/spec.rs +++ b/compute_tools/src/spec.rs @@ -380,6 +380,10 @@ pub fn handle_grants(node: &ComputeNode, client: &mut Client) -> Result<()> { info!("grant query {}", &query); client.execute(query.as_str(), &[])?; + + // Explicitly grant CREATE ON SCHEMA PUBLIC to the web_access user. + // This is needed since postgres 15, where this privilege is removed by default. + client.execute("GRANT CREATE ON SCHEMA public TO web_access", &[])?; } // Do some per-database access adjustments. We'd better do this at db creation time, From 129f7c82b7d29faa985b9f507cfe7c5758b7f7c5 Mon Sep 17 00:00:00 2001 From: Dmitry Rodionov Date: Mon, 17 Oct 2022 21:36:30 +0300 Subject: [PATCH 33/64] remove redundant expect_tenant_to_download_timeline --- test_runner/regress/test_remote_storage.py | 17 ++------------- .../test_tenants_with_remote_storage.py | 21 ++++--------------- 2 files changed, 6 insertions(+), 32 deletions(-) diff --git a/test_runner/regress/test_remote_storage.py b/test_runner/regress/test_remote_storage.py index 0a02a80de5..56b14dc42b 100644 --- a/test_runner/regress/test_remote_storage.py +++ b/test_runner/regress/test_remote_storage.py @@ -10,8 +10,8 @@ import pytest from fixtures.log_helper import log from fixtures.neon_fixtures import ( NeonEnvBuilder, - NeonPageserverHttpClient, RemoteStorageKind, + assert_no_in_progress_downloads_for_tenant, available_remote_storages, wait_for_last_record_lsn, wait_for_upload, @@ -125,7 +125,7 @@ def test_remote_storage_backup_and_restore( wait_until( number_of_iterations=20, interval=1, - func=lambda: expect_tenant_to_download_timeline(client, tenant_id), + func=lambda: assert_no_in_progress_downloads_for_tenant(client, tenant_id), ) detail = client.timeline_detail(tenant_id, timeline_id) @@ -142,16 +142,3 @@ def test_remote_storage_backup_and_restore( query_scalar(cur, f"SELECT secret FROM t{checkpoint_number} WHERE id = {data_id};") == f"{data_secret}|{checkpoint_number}" ) - - -def expect_tenant_to_download_timeline( - client: NeonPageserverHttpClient, - tenant_id: TenantId, -): - for tenant in client.tenant_list(): - if tenant["id"] == str(tenant_id): - assert not tenant.get( - "has_in_progress_downloads", True - ), f"Tenant {tenant_id} should have no downloads in progress" - return - assert False, f"Tenant {tenant_id} is missing on pageserver" diff --git a/test_runner/regress/test_tenants_with_remote_storage.py b/test_runner/regress/test_tenants_with_remote_storage.py index a7c2e7ace0..96c1fc25db 100644 --- a/test_runner/regress/test_tenants_with_remote_storage.py +++ b/test_runner/regress/test_tenants_with_remote_storage.py @@ -19,9 +19,9 @@ from fixtures.neon_fixtures import ( LocalFsStorage, NeonEnv, NeonEnvBuilder, - NeonPageserverHttpClient, Postgres, RemoteStorageKind, + assert_no_in_progress_downloads_for_tenant, available_remote_storages, wait_for_last_record_lsn, wait_for_upload, @@ -168,7 +168,7 @@ def test_tenants_attached_after_download( wait_until( number_of_iterations=5, interval=1, - func=lambda: expect_tenant_to_download_timeline(client, tenant_id), + func=lambda: assert_no_in_progress_downloads_for_tenant(client, tenant_id), ) restored_timelines = client.timeline_list(tenant_id) @@ -181,19 +181,6 @@ def test_tenants_attached_after_download( ), f"Tenant {tenant_id} should have its old timeline {timeline_id} restored from the remote storage" -def expect_tenant_to_download_timeline( - client: NeonPageserverHttpClient, - tenant_id: TenantId, -): - for tenant in client.tenant_list(): - if tenant["id"] == str(tenant_id): - assert not tenant.get( - "has_in_progress_downloads", True - ), f"Tenant {tenant_id} should have no downloads in progress" - return - assert False, f"Tenant {tenant_id} is missing on pageserver" - - @pytest.mark.parametrize("remote_storage_kind", [RemoteStorageKind.LOCAL_FS]) def test_tenant_upgrades_index_json_from_v0( neon_env_builder: NeonEnvBuilder, remote_storage_kind: RemoteStorageKind @@ -262,7 +249,7 @@ def test_tenant_upgrades_index_json_from_v0( wait_until( number_of_iterations=5, interval=1, - func=lambda: expect_tenant_to_download_timeline(pageserver_http, tenant_id), + func=lambda: assert_no_in_progress_downloads_for_tenant(pageserver_http, tenant_id), ) pg = env.postgres.create_start("main") @@ -371,7 +358,7 @@ def test_tenant_redownloads_truncated_file_on_startup( wait_until( number_of_iterations=5, interval=1, - func=lambda: expect_tenant_to_download_timeline(client, tenant_id), + func=lambda: assert_no_in_progress_downloads_for_tenant(client, tenant_id), ) restored_timelines = client.timeline_list(tenant_id) From 80746b1c7a0627ab36ad850832d49bdd22a1755f Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Mon, 17 Oct 2022 16:44:32 +0300 Subject: [PATCH 34/64] Add micro-benchmark for layer map search function The test data was extracted from our pgbench benchmark project on the captest environment, the one we use for the 'neon-captest-reuse' test. --- Cargo.lock | 1 + pageserver/Cargo.toml | 5 + pageserver/benches/bench_layer_map.rs | 5866 +++++++++++++++++++++++++ pageserver/src/tenant.rs | 7 +- 4 files changed, 5876 insertions(+), 3 deletions(-) create mode 100644 pageserver/benches/bench_layer_map.rs diff --git a/Cargo.lock b/Cargo.lock index 131d9a8aa2..d02ec1f5a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2139,6 +2139,7 @@ dependencies = [ "close_fds", "const_format", "crc32c", + "criterion", "crossbeam-utils", "daemonize", "etcd_broker", diff --git a/pageserver/Cargo.toml b/pageserver/Cargo.toml index ebdda5c6da..75aa6e93eb 100644 --- a/pageserver/Cargo.toml +++ b/pageserver/Cargo.toml @@ -69,5 +69,10 @@ close_fds = "0.3.2" walkdir = "2.3.2" [dev-dependencies] +criterion = "0.4" hex-literal = "0.3" tempfile = "3.2" + +[[bench]] +name = "bench_layer_map" +harness = false diff --git a/pageserver/benches/bench_layer_map.rs b/pageserver/benches/bench_layer_map.rs new file mode 100644 index 0000000000..25d5ecd643 --- /dev/null +++ b/pageserver/benches/bench_layer_map.rs @@ -0,0 +1,5866 @@ +use anyhow::Result; +use pageserver::repository::{Key, Value}; +use pageserver::tenant::filename::{DeltaFileName, ImageFileName}; +use pageserver::tenant::layer_map::LayerMap; +use pageserver::tenant::storage_layer::Layer; +use pageserver::tenant::storage_layer::ValueReconstructResult; +use pageserver::tenant::storage_layer::ValueReconstructState; +use std::cmp::{max, min}; +use std::ops::Range; +use std::path::PathBuf; +use std::str::FromStr; +use std::sync::Arc; +use utils::id::{TenantId, TimelineId}; +use utils::lsn::Lsn; + +use criterion::{criterion_group, criterion_main, Criterion}; + +struct DummyDelta { + key_range: Range, + lsn_range: Range, +} + +impl Layer for DummyDelta { + fn get_tenant_id(&self) -> TenantId { + TenantId::from_str("00000000000000000000000000000000").unwrap() + } + + fn get_timeline_id(&self) -> TimelineId { + TimelineId::from_str("00000000000000000000000000000000").unwrap() + } + + fn get_key_range(&self) -> Range { + self.key_range.clone() + } + + fn get_lsn_range(&self) -> Range { + self.lsn_range.clone() + } + + fn filename(&self) -> PathBuf { + todo!() + } + + fn local_path(&self) -> Option { + todo!() + } + + fn get_value_reconstruct_data( + &self, + _key: Key, + _lsn_range: Range, + _reconstruct_data: &mut ValueReconstructState, + ) -> Result { + panic!() + } + + fn is_incremental(&self) -> bool { + true + } + + fn is_in_memory(&self) -> bool { + false + } + + fn iter(&self) -> Box> + '_> { + panic!() + } + + fn key_iter(&self) -> Box + '_> { + panic!("Not implemented") + } + + fn delete(&self) -> Result<()> { + panic!() + } + + fn dump(&self, _verbose: bool) -> Result<()> { + todo!() + } +} + +struct DummyImage { + key_range: Range, + lsn: Lsn, +} + +impl Layer for DummyImage { + fn get_tenant_id(&self) -> TenantId { + TenantId::from_str("00000000000000000000000000000000").unwrap() + } + + fn get_timeline_id(&self) -> TimelineId { + TimelineId::from_str("00000000000000000000000000000000").unwrap() + } + + fn get_key_range(&self) -> Range { + self.key_range.clone() + } + + fn get_lsn_range(&self) -> Range { + // End-bound is exclusive + self.lsn..(self.lsn + 1) + } + + fn filename(&self) -> PathBuf { + todo!() + } + + fn local_path(&self) -> Option { + todo!() + } + + fn get_value_reconstruct_data( + &self, + _key: Key, + _lsn_range: Range, + _reconstruct_data: &mut ValueReconstructState, + ) -> Result { + panic!() + } + + fn is_incremental(&self) -> bool { + false + } + + fn is_in_memory(&self) -> bool { + false + } + + fn iter(&self) -> Box> + '_> { + panic!() + } + + fn key_iter(&self) -> Box + '_> { + panic!("Not implemented") + } + + fn delete(&self) -> Result<()> { + panic!() + } + + fn dump(&self, _verbose: bool) -> Result<()> { + todo!() + } +} + +fn build_layer_map() -> LayerMap { + let mut layer_map = LayerMap::default(); + + let mut min_lsn = Lsn(u64::MAX); + let mut max_lsn = Lsn(0); + + for fname in TEST_LAYER_FILENAMES { + if let Some(imgfilename) = ImageFileName::parse_str(fname) { + let layer = DummyImage { + key_range: imgfilename.key_range, + lsn: imgfilename.lsn, + }; + layer_map.insert_historic(Arc::new(layer)); + min_lsn = min(min_lsn, imgfilename.lsn); + max_lsn = max(max_lsn, imgfilename.lsn); + } else if let Some(deltafilename) = DeltaFileName::parse_str(fname) { + let layer = DummyDelta { + key_range: deltafilename.key_range, + lsn_range: deltafilename.lsn_range.clone(), + }; + layer_map.insert_historic(Arc::new(layer)); + min_lsn = min(min_lsn, deltafilename.lsn_range.start); + max_lsn = max(max_lsn, deltafilename.lsn_range.end); + } else { + panic!("unexpected filename {fname}"); + } + } + + println!("min: {min_lsn}, max: {max_lsn}"); + + layer_map +} + +fn large_layer_map(c: &mut Criterion) { + let layer_map = build_layer_map(); + + c.bench_function("search", |b| { + b.iter(|| { + let result = layer_map.search( + // Just an arbitrary point + Key::from_hex("000000067F000080000009E014000001B011").unwrap(), + // This LSN is higher than any of the LSNs in the tree + Lsn::from_str("D0/80208AE1").unwrap(), + ); + result.unwrap(); + }); + }); + + // test with a key that corresponds to the RelDir entry. See pgdatadir_mapping.rs. + c.bench_function("search_rel_dir", |b| { + b.iter(|| { + let result = layer_map.search( + Key::from_hex("000000067F00008000000000000000000001").unwrap(), + // This LSN is higher than any of the LSNs in the tree + Lsn::from_str("D0/80208AE1").unwrap(), + ); + result.unwrap(); + }); + }); +} + +criterion_group!(benches, large_layer_map); +criterion_main!(benches); + +// A list of layer filenames, extracted from our performance test environment, from +// a project where we have run pgbench many timmes. The pgbench database was initialized +// between each test run. +const TEST_LAYER_FILENAMES: &[&str] = &[ +"000000000000000000000000000000000000-000000067F00008000000032090100000000__0000006CF69CD8B0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__0000006F949B7C08", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__00000071F15CF6B0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__00000072AEE2BFE0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000756884A510", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__00000077B1836CA0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__0000007D41715570", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__0000007F12B83FE8", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__00000083D5DE3FD0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000873B520940", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000890CF51FE0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__0000008C71903720", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__0000008E43487FF0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__0000009445A06DC8", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__00000096187D1FC8", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__00000096E85806C0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__0000009921F3B4A8", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__0000009B5229DFE8", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__0000009EBB11FFC0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000A93DDE5FE0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000AD3698E000", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000B3AC039FE8", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000B8606C92A0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000BC59629F98", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000BD25E66810", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000BEF683BFD0", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000C14270A078", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000C3687EDFE8", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000C6C7BD8140", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000C896B8DFD8", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000CB82C2FF68", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000CD51009FE8", +"000000000000000000000000000000000000-000000067F00008000000032090100000000__000000CF7E08BFD0", +"000000000000000000000000000000000000-000000067F00008000000540090100000000__0000006AEF261AF8", +"000000000000000000000000000000000000-000000067F00008000000560090100000000__0000006DA30DA180", +"000000000000000000000000000000000000-000000067F00008000000580090100000000__0000006FAFE25518", +"000000000000000000000000000000000000-000000067F000080000005E0090100000000__00000073AF75E930", +"000000000000000000000000000000000000-000000067F00008000000620090100000000__00000078B2CB1C68", +"000000000000000000000000000000000000-000000067F00008000000640090100000000__0000007B9877EF40", +"000000000000000000000000000000000000-000000067F00008000000680090100000000__00000080E477E868", +"000000000000000000000000000000000000-000000067F000080000006C0090100000000__00000085BE169568", +"000000000000000000000000000000000000-000000067F00008000000700090100000000__0000008AF15FEF50", +"000000000000000000000000000000000000-000000067F00008000000740090100000000__000000902186B1D0", +"000000000000000000000000000000000000-000000067F00008000000760090100000000__00000092CA5E4EA8", +"000000000000000000000000000000000000-000000067F000080000007E0090100000000__0000009D34F8D4D8", +"000000000000000000000000000000000000-000000067F00008000000820090100000000__000000A29F1D8950", +"000000000000000000000000000000000000-000000067F00008000000860090100000000__000000A434813A68", +"000000000000000000000000000000000000-000000067F000080000008C0090100000000__000000AAEBE534F8", +"000000000000000000000000000000000000-000000067F00008000000960090100000000__000000B6C2E92A88", +"000000000000000000000000000000000000-000000067F00008000000A20090100000000__000000C5745579F0", +"000000000000000000000000000000000000-000000067F00008000000A60090100000000__000000CA2C877DC8", +"000000000000000000000000000000000000-030000000000000000000000000000000002__000000AFB4666000", +"000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__000000CF7DC97FD1-000000CF801FC221", +"000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__000000CF801FC221-000000CF801FDB61", +"000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__000000CF801FDB61-000000CF80201FA1", +"000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__000000CF80201FA1-000000CF80203CC1", +"000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__000000CF80203CC1-000000CF802067C1", +"000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__000000CF802067C1-000000CF80208AE1", +"000000067F000032AC000040040000000000-000000067F000080000005400C0000007DD8__0000006A5C770149-0000006ACEF98449", +"000000067F000032AC000040040000000000-000000067F000080000005600C0000008077__0000006CF7781D19-0000006D69B48989", +"000000067F000032AC000040040000000000-000000067F000080000005800C0000007A49__0000006F95E72491-0000006FA8EDF3B9", +"000000067F000032AC000040040000000000-000000067F000080000005A00C0000007614__000000723877FF21-00000072A0D7CEA1", +"000000067F000032AC000040040000000000-000000067F000080000005C00C0000016516__00000072A0D7CEA1-0000007318DDE691", +"000000067F000032AC000040040000000000-000000067F000080000006000C0000008FB7__00000075687C3009-00000075E915EBC9", +"000000067F000032AC000040040000000000-000000067F000080000006200C0000009441__0000007805801C41-00000078859FEA11", +"000000067F000032AC000040040000000000-000000067F000080000006400C0000007987__0000007AA1DF6639-0000007B14D5C521", +"000000067F000032AC000040040000000000-000000067F000080000006600C0000009381__0000007D41EA8D51-0000007DC21DE569", +"000000067F000032AC000040040000000000-000000067F000080000006800C0000007D6A__0000007FDCDCE659-000000804F6BFFC1", +"000000067F000032AC000040040000000000-000000067F000080000006801400000044E4__00000081AFAF5FD1-0000008215AFE5A9", +"000000067F000032AC000040040000000000-000000067F000080000006C00C00000090F5__00000084A325AA01-00000085239DFB81", +"000000067F000032AC000040040000000000-000000067F000080000006E00C00000096C8__000000873C9A2551-00000087BC75E5B1", +"000000067F000032AC000040040000000000-000000067F000080000007000C000000955C__00000089D6B8EE99-0000008A56BBF739", +"000000067F000032AC000040040000000000-000000067F000080000007200C000000933D__0000008C72843D41-0000008CF2BFFC89", +"000000067F000032AC000040040000000000-000000067F000080000007400C00000090E9__0000008F10E3E189-0000008F915DE591", +"000000067F000032AC000040040000000000-000000067F000080000007600C0000008180__00000091A6DD7A79-0000009228F7FA79", +"000000067F000032AC000040040000000000-000000067F000080000007800C000000974C__0000009446B52FD1-00000094D67DF4F9", +"000000067F000032AC000040040000000000-000000067F000080000007A00C000000974B__00000096E85829C9-00000098A7ADFC91", +"000000067F000032AC000040040000000000-000000067F000080000007C00C0000007EA5__000000997F5D23C9-00000099F1C9FC71", +"000000067F000032AC000040040000000000-000000067F000080000007E00C00000092CD__0000009C1E8CC879-0000009C9ED3F059", +"000000067F000032AC000040040000000000-000000067F000080000008000C00000081F6__0000009EBBC72771-000000A154401909", +"000000067F000032AC000040040000000000-000000067F000080000008200C000000974D__000000A154401909-000000A1E407F839", +"000000067F000032AC000040040000000000-000000067F0000800000082014000000393C__000000A323C9E001-000000A37A60B1A9", +"000000067F000032AC000040040000000000-000000067F000080000008600C0000009747__000000A37A60B1A9-000000A3CA47ECA9", +"000000067F000032AC000040040000000000-000000067F000080000008801C0000009703__000000A5A081B661-000000A6503DE919", +"000000067F000032AC000040040000000000-000000067F000080000008801C00000CF6B0__000000A6F001F909-000000A91D97FD49", +"000000067F000032AC000040040000000000-000000067F000080000008C00C0000002330__000000A98AB7EE49-000000AA2597E9A1", +"000000067F000032AC000040040000000000-000000067F000080000008E00C00000077B3__000000AB6533BFD9-000000ABF63DF511", +"000000067F000032AC000040040000000000-000000067F000080000008E02A000000529F__000000AF5D587FE1-000000AFB4666001", +"000000067F000032AC000040040000000000-000000067F000080000009004000000047E0__000000B18495C001-000000B1FA75F501", +"000000067F000032AC000040040000000000-000000067F00008000000920140000005289__000000B3AB3B7FC9-000000B4208FF3D1", +"000000067F000032AC000040040000000000-000000067F000080000009400C000008DEA4__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000032AC000040040000000000-000000067F000080000009600C000000974F__000000B5CED8CF79-000000B63EADE5B9", +"000000067F000032AC000040040000000000-000000067F000080000009600C0000055A74__000000B808718889-000000B8606C92A1", +"000000067F000032AC000040040000000000-000000067F000080000009800C0000009748__000000B8606C92A1-000000B8E03BF0B9", +"000000067F000032AC000040040000000000-000000067F000080000009800C000010EC71__000000BA1FC3FB39-000000BA9685E7C1", +"000000067F000032AC000040040000000000-000000067F000080000009A00C0000071F6F__000000BCEF79BE91-000000BD263A5849", +"000000067F000032AC000040040000000000-000000067F000080000009C00C0000009749__000000BD263A5849-000000BDA607F261", +"000000067F000032AC000040040000000000-000000067F000080000009E00C0000004916__000000BEF5F47FD1-000000BF48FFEB11", +"000000067F000032AC000040040000000000-000000067F00008000000A000C0000008EF9__000000C19744E959-000000C217F3F379", +"000000067F000032AC000040040000000000-000000067F00008000000A200C0000009748__000000C430961E71-000000C4C05DDB29", +"000000067F000032AC000040040000000000-000000067F00008000000A400C0000009743__000000C6C87B6329-000000C74849FAE1", +"000000067F000032AC000040040000000000-000000067F00008000000A600C0000009746__000000C90726D0D9-000000C986F5F0D9", +"000000067F000032AC000040040000000000-000000067F00008000000A600C000007A149__000000CB40C16489-000000CB82C37859", +"000000067F000032AC000040040000000000-000000067F00008000000A800C0000009748__000000CB82C37859-000000CC11F5EDC9", +"000000067F000032AC000040040000000000-000000067F00008000000A800F0100000003__000000CD51344F89-000000CDCC7BF889", +"000000067F00008000000000000000000001-000000067F000080000005400C000004B479__0000006C98B77D29-0000006CF7781D19", +"000000067F00008000000000000000000001-000000067F000080000005400C0000104BE4__0000006C1E7C73C1-0000006C98B77D29", +"000000067F00008000000000000000000001-000000067F000080000005600C0000048643__0000006F3370DD59-0000006F95E72491", +"000000067F00008000000000000000000001-000000067F000080000005600C0000100001__0000006EB935F989-0000006F3370DD59", +"000000067F00008000000000000000000001-000000067F000080000005800C000005CF06__00000071F21624D1-000000723877FF21", +"000000067F00008000000000000000000001-000000067F000080000005800C000009D78D__000000716A103FC9-00000071F21624D1", +"000000067F00008000000000000000000001-000000067F000080000005800C00000CDE2D__00000070E8761431-000000716A103FC9", +"000000067F00008000000000000000000001-000000067F000080000005E00C00000385D9__0000007318DDE691-0000007497B01FF9", +"000000067F00008000000000000000000001-000000067F000080000005E00C0000050175__000000751253A4C1-00000075687C3009", +"000000067F00008000000000000000000001-000000067F000080000005E00C00000AF576__0000007497B01FF9-000000751253A4C1", +"000000067F00008000000000000000000001-000000067F000080000006000C0000051A02__00000077B2AD0F91-0000007805801C41", +"000000067F00008000000000000000000001-000000067F000080000006000C00000C3C38__00000077391A8001-00000077B2AD0F91", +"000000067F00008000000000000000000001-000000067F000080000006000C00000C56C1__00000076A8CDE8F9-00000077391A8001", +"000000067F00008000000000000000000001-000000067F000080000006200C000004811C__0000007A3F679FA1-0000007AA1DF6639", +"000000067F00008000000000000000000001-000000067F000080000006200C0000107883__00000079C527F0D9-0000007A3F679FA1", +"000000067F00008000000000000000000001-000000067F000080000006400C000004B4C9__0000007B14D5C521-0000007C73B53FC9", +"000000067F00008000000000000000000001-000000067F000080000006400C000005258F__0000007CEE5A0B91-0000007D41EA8D51", +"000000067F00008000000000000000000001-000000067F000080000006400C00000A887C__0000007C73B53FC9-0000007CEE5A0B91", +"000000067F00008000000000000000000001-000000067F000080000006600C0000049742__0000007F7BE4E6F1-0000007FDCDCE659", +"000000067F00008000000000000000000001-000000067F000080000006600C00000BC29F__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F00008000000000000000000001-000000067F000080000006600C0000111C82__0000007F11E4BFE9-0000007F7BE4E6F1", +"000000067F00008000000000000000000001-000000067F000080000006800C00000A8D4C__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F00008000000000000000000001-000000067F000080000006A00C0000051984__000000844F1A6789-00000084A325AA01", +"000000067F00008000000000000000000001-000000067F000080000006A00C00000703EC__00000082B573F579-00000083D5901FD9", +"000000067F00008000000000000000000001-000000067F000080000006A00C00000C4CC8__00000083D5901FD9-000000844F1A6789", +"000000067F00008000000000000000000001-000000067F000080000006C00C0000055EA3__00000086ED29E361-000000873C9A2551", +"000000067F00008000000000000000000001-000000067F000080000006C00C00000BC102__00000085D35BF439-0000008673817FC9", +"000000067F00008000000000000000000001-000000067F000080000006C00C00000BFB6E__0000008673817FC9-00000086ED29E361", +"000000067F00008000000000000000000001-000000067F000080000006E00C0000054244__0000008985FD3611-00000089D6B8EE99", +"000000067F00008000000000000000000001-000000067F000080000006E00C00000B6F42__000000890C5B6001-0000008985FD3611", +"000000067F00008000000000000000000001-000000067F000080000006E00C00000C5883__000000887C2DFE59-000000890C5B6001", +"000000067F00008000000000000000000001-000000067F000080000007000C0000053C20__0000008C2045B721-0000008C72843D41", +"000000067F00008000000000000000000001-000000067F000080000007000C00000B2B06__0000008AF67FEC19-0000008BA6803FC9", +"000000067F00008000000000000000000001-000000067F000080000007000C00000BF157__0000008BA6803FC9-0000008C2045B721", +"000000067F00008000000000000000000001-000000067F000080000007200C0000051312__0000008EBC4827C1-0000008F10E3E189", +"000000067F00008000000000000000000001-000000067F000080000007200C00000BA086__0000008E42A19FD1-0000008EBC4827C1", +"000000067F00008000000000000000000001-000000067F000080000007200C00000C58B0__0000008DB277FA49-0000008E42A19FD1", +"000000067F00008000000000000000000001-000000067F000080000007400C000004DF08__000000914B2393B1-00000091A6DD7A79", +"000000067F00008000000000000000000001-000000067F000080000007400C00000FCCA8__00000090D0E5EA29-000000914B2393B1", +"000000067F00008000000000000000000001-000000067F000080000007600C00000544BA__0000009228F7FA79-00000093786F8001", +"000000067F00008000000000000000000001-000000067F000080000007600C0000061028__0000009402435A49-0000009446B52FD1", +"000000067F00008000000000000000000001-000000067F000080000007600C000008C52F__00000093786F8001-0000009402435A49", +"000000067F00008000000000000000000001-000000067F000080000007800C000006D445__00000096AEF27399-00000096E85829C9", +"000000067F00008000000000000000000001-000000067F000080000007800C000007B8BC__00000096193A8001-00000096AEF27399", +"000000067F00008000000000000000000001-000000067F000080000007800C00000CD6B6__000000959635F2A9-00000096193A8001", +"000000067F00008000000000000000000001-000000067F000080000007A00C000004B9A5__0000009921E47AA1-000000997F5D23C9", +"000000067F00008000000000000000000001-000000067F000080000007A00C00000F720F__00000098A7ADFC91-0000009921E47AA1", +"000000067F00008000000000000000000001-000000067F000080000007C00C0000052A9D__0000009BCB4E4461-0000009C1E8CC879", +"000000067F00008000000000000000000001-000000067F000080000007C00C00000A9244__0000009A918DF181-0000009B51A8BBB9", +"000000067F00008000000000000000000001-000000067F000080000007C00C00000BA258__0000009B51A8BBB9-0000009BCB4E4461", +"000000067F00008000000000000000000001-000000067F000080000007E00C0000061ADC__0000009E781A9731-0000009EBBC72771", +"000000067F00008000000000000000000001-000000067F000080000007E00C0000093E3A__0000009DEEE6BFF9-0000009E781A9731", +"000000067F00008000000000000000000001-000000067F000080000007E00C00000B2704__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F00008000000000000000000001-000000067F000080000008200C000005D8FE__000000A1E407F839-000000A323C9E001", +"000000067F00008000000000000000000001-000000067F000080000008600C000010ECC4__000000A539BDE561-000000A5A081B661", +"000000067F00008000000000000000000001-000000067F000080000008A00C0000104A0C__000000A91D97FD49-000000A98AB7EE49", +"000000067F00008000000000000000000001-000000067F000080000008C00C000005DA8C__000000AA2597E9A1-000000AB6533BFD9", +"000000067F00008000000000000000000001-000000067F000080000008E00C00000BC018__000000AC9601EA19-000000AD36393FE9", +"000000067F00008000000000000000000001-000000067F000080000008E0140000003E33__000000AD36393FE9-000000ADB047EAB9", +"000000067F00008000000000000000000001-000000067F000080000008E022000008E3D1__000000AE6FFFE799-000000AF5D587FE1", +"000000067F00008000000000000000000001-000000067F000080000009003800000C5213__000000B0F3EDEAC9-000000B18495C001", +"000000067F00008000000000000000000001-000000067F000080000009200C000009567A__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F00008000000000000000000001-000000067F000080000009600C00000A93FD__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F00008000000000000000000001-000000067F000080000009600C020000000B__000000B79E68FFF9-000000B808718889", +"000000067F00008000000000000000000001-000000067F000080000009A00C00000794DC__000000BC596B5D59-000000BCEF79BE91", +"000000067F00008000000000000000000001-000000067F000080000009A00C00000D6C06__000000BBE607E8F1-000000BC596B5D59", +"000000067F00008000000000000000000001-000000067F000080000009C00C00000B2921__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F00008000000000000000000001-000000067F000080000009E00C0000050E55__000000C1426D92E1-000000C19744E959", +"000000067F00008000000000000000000001-000000067F000080000009E00C000009FB21__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F00008000000000000000000001-000000067F000080000009E00C00000C0C74__000000C0C8CA5FF1-000000C1426D92E1", +"000000067F00008000000000000000000001-000000067F00008000000A000C000005635B__000000C3E17E01A1-000000C430961E71", +"000000067F00008000000000000000000001-000000067F00008000000A000C00000B8B52__000000C367E48001-000000C3E17E01A1", +"000000067F00008000000000000000000001-000000067F00008000000A000C00000BC072__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000000000000000001-000000067F00008000000A200C00000677D8__000000C689AF4AC1-000000C6C87B6329", +"000000067F00008000000000000000000001-000000067F00008000000A200C00000933F0__000000C600A8FFF9-000000C689AF4AC1", +"000000067F00008000000000000000000001-000000067F00008000000A200C00000BBC1F__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000000000000000001-000000067F00008000000A400C00000C4AE6__000000C80801E859-000000C8993EBFF9", +"000000067F00008000000000000000000001-000000067F00008000000A400C0000107F8F__000000C8993EBFF9-000000C90726D0D9", +"000000067F00008000000000000000000001-000000067F00008000000A600C0000054BFB__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000000000000000001-000000067F00008000000A600C00001117CB__000000CAD5D7FFF1-000000CB40C16489", +"000000067F00008000000000000000000001-000000067F00008000000A800C00000BCB46__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000000000000000001-000000067F00008000000AA00C0000078E97__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000004E10100000002-000000067F000080000005400C000004BA9C__0000006ACEF98449-0000006C1E7C73C1", +"000000067F00008000000004E10100000002-000000067F000080000005800C0000071854__0000007048B1EC09-00000070E8761431", +"000000067F00008000000004E10200000000-000000067F000080000005600C000004BA9D__0000006D69B48989-0000006EB935F989", +"000000067F00008000000004EB0100000002-000000067F00008000000A400C00000551FC__000000C74849FAE1-000000C80801E859", +"000000067F000080000005200C000006C000-030000000000000000000000000000000002__000000687B67FC58", +"000000067F00008000000520140000028A69-030000000000000000000000000000000002__0000006981B5FDC9-00000069FBEEB099", +"000000067F0000800000052014000002C260-030000000000000000000000000000000002__00000069FBEEB099-0000006A5C770149", +"000000067F000080000005400C0000000000-000000067F000080000005400C0000004000__0000006CF69CD8B0", +"000000067F000080000005400C0000004000-000000067F000080000005400C0000008000__0000006CF69CD8B0", +"000000067F000080000005400C0000008000-000000067F000080000005400C000000C000__0000006CF69CD8B0", +"000000067F000080000005400C000000C000-000000067F000080000005400C0000010000__0000006CF69CD8B0", +"000000067F000080000005400C0000010000-000000067F000080000005400C0000014000__0000006CF69CD8B0", +"000000067F000080000005400C0000014000-000000067F000080000005400C0000018000__0000006CF69CD8B0", +"000000067F000080000005400C0000018000-000000067F000080000005400C000001C000__0000006CF69CD8B0", +"000000067F000080000005400C000001C000-000000067F000080000005400C0000020000__0000006CF69CD8B0", +"000000067F000080000005400C0000020000-000000067F000080000005400C0000024000__0000006CF69CD8B0", +"000000067F000080000005400C0000024000-000000067F000080000005400C0000028000__0000006CF69CD8B0", +"000000067F000080000005400C0000028000-000000067F000080000005400C000002C000__0000006CF69CD8B0", +"000000067F000080000005400C000002C000-000000067F000080000005400C0000030000__0000006CF69CD8B0", +"000000067F000080000005400C0000030000-000000067F000080000005400C0000034000__0000006CF69CD8B0", +"000000067F000080000005400C0000034000-000000067F000080000005400C0000038000__0000006CF69CD8B0", +"000000067F000080000005400C0000038000-000000067F000080000005400C000003C000__0000006CF69CD8B0", +"000000067F000080000005400C000003C000-000000067F000080000005400C0000040000__0000006CF69CD8B0", +"000000067F000080000005400C0000040000-000000067F000080000005400C0000044000__0000006CF69CD8B0", +"000000067F000080000005400C0000044000-000000067F000080000005400C0000048000__0000006CF69CD8B0", +"000000067F000080000005400C0000048000-000000067F000080000005400C000004C000__0000006CF69CD8B0", +"000000067F000080000005400C000004B483-000000067F000080000005400C00000967AD__0000006C98B77D29-0000006CF7781D19", +"000000067F000080000005400C000004C000-000000067F000080000005400C0000050000__0000006CF69CD8B0", +"000000067F000080000005400C0000050000-000000067F000080000005400C0000054000__0000006CF69CD8B0", +"000000067F000080000005400C0000054000-000000067F000080000005400C0000058000__0000006CF69CD8B0", +"000000067F000080000005400C0000054000-030000000000000000000000000000000002__0000006AEF261AF8", +"000000067F000080000005400C0000058000-000000067F000080000005400C000005C000__0000006CF69CD8B0", +"000000067F000080000005400C000005C000-000000067F000080000005400C0000060000__0000006CF69CD8B0", +"000000067F000080000005400C0000060000-000000067F000080000005400C0000064000__0000006CF69CD8B0", +"000000067F000080000005400C0000064000-000000067F000080000005400C0000068000__0000006CF69CD8B0", +"000000067F000080000005400C0000068000-000000067F000080000005400C000006C000__0000006CF69CD8B0", +"000000067F000080000005400C000006C000-000000067F000080000005400C0000070000__0000006CF69CD8B0", +"000000067F000080000005400C0000070000-000000067F000080000005400C0000074000__0000006CF69CD8B0", +"000000067F000080000005400C0000074000-000000067F000080000005400C0000078000__0000006CF69CD8B0", +"000000067F000080000005400C0000078000-000000067F000080000005400C000007C000__0000006CF69CD8B0", +"000000067F000080000005400C000007C000-000000067F000080000005400C0000080000__0000006CF69CD8B0", +"000000067F000080000005400C0000080000-000000067F000080000005400C0000084000__0000006CF69CD8B0", +"000000067F000080000005400C0000084000-000000067F000080000005400C0000088000__0000006CF69CD8B0", +"000000067F000080000005400C0000088000-000000067F000080000005400C000008C000__0000006CF69CD8B0", +"000000067F000080000005400C000008C000-000000067F000080000005400C0000090000__0000006CF69CD8B0", +"000000067F000080000005400C0000090000-000000067F000080000005400C0000094000__0000006CF69CD8B0", +"000000067F000080000005400C0000094000-000000067F000080000005400C0000098000__0000006CF69CD8B0", +"000000067F000080000005400C00000967BA-000000067F000080000005400C00000E2771__0000006C98B77D29-0000006CF7781D19", +"000000067F000080000005400C0000098000-000000067F000080000005400C000009C000__0000006CF69CD8B0", +"000000067F000080000005400C000009C000-000000067F000080000005400C00000A0000__0000006CF69CD8B0", +"000000067F000080000005400C00000A0000-000000067F000080000005400C00000A4000__0000006CF69CD8B0", +"000000067F000080000005400C00000A4000-000000067F000080000005400C00000A8000__0000006CF69CD8B0", +"000000067F000080000005400C00000A8000-000000067F000080000005400C00000AC000__0000006CF69CD8B0", +"000000067F000080000005400C00000AC000-000000067F000080000005400C00000B0000__0000006CF69CD8B0", +"000000067F000080000005400C00000B0000-000000067F000080000005400C00000B4000__0000006CF69CD8B0", +"000000067F000080000005400C00000B4000-000000067F000080000005400C00000B8000__0000006CF69CD8B0", +"000000067F000080000005400C00000B8000-000000067F000080000005400C00000BC000__0000006CF69CD8B0", +"000000067F000080000005400C00000BC000-000000067F000080000005400C00000C0000__0000006CF69CD8B0", +"000000067F000080000005400C00000C0000-000000067F000080000005400C00000C4000__0000006CF69CD8B0", +"000000067F000080000005400C00000C4000-000000067F000080000005400C00000C8000__0000006CF69CD8B0", +"000000067F000080000005400C00000C8000-000000067F000080000005400C00000CC000__0000006CF69CD8B0", +"000000067F000080000005400C00000CC000-000000067F000080000005400C00000D0000__0000006CF69CD8B0", +"000000067F000080000005400C00000D0000-000000067F000080000005400C00000D4000__0000006CF69CD8B0", +"000000067F000080000005400C00000D4000-000000067F000080000005400C00000D8000__0000006CF69CD8B0", +"000000067F000080000005400C00000D8000-000000067F000080000005400C00000DC000__0000006CF69CD8B0", +"000000067F000080000005400C00000DC000-000000067F000080000005400C00000E0000__0000006CF69CD8B0", +"000000067F000080000005400C00000E0000-000000067F000080000005400C00000E4000__0000006CF69CD8B0", +"000000067F000080000005400C00000E277B-000000067F00008000000540140000005B2E__0000006C98B77D29-0000006CF7781D19", +"000000067F000080000005400C00000E4000-000000067F000080000005400C00000E8000__0000006CF69CD8B0", +"000000067F000080000005400C00000E8000-000000067F000080000005400C00000EC000__0000006CF69CD8B0", +"000000067F000080000005400C00000EC000-000000067F000080000005400C00000F0000__0000006CF69CD8B0", +"000000067F000080000005400C00000F0000-000000067F000080000005400C00000F4000__0000006CF69CD8B0", +"000000067F000080000005400C00000F4000-000000067F000080000005400C00000F8000__0000006CF69CD8B0", +"000000067F000080000005400C00000F8000-000000067F000080000005400C00000FC000__0000006CF69CD8B0", +"000000067F000080000005400C00000FC000-000000067F000080000005400C0000100000__0000006CF69CD8B0", +"000000067F000080000005400C0000100000-000000067F000080000005400C0000104000__0000006CF69CD8B0", +"000000067F000080000005400C0000104000-000000067F000080000005400C0000108000__0000006CF69CD8B0", +"000000067F000080000005400C0000108000-000000067F000080000005400C000010C000__0000006CF69CD8B0", +"000000067F000080000005400C000010C000-000000067F000080000005400C0000110000__0000006CF69CD8B0", +"000000067F000080000005400C0000110000-000000067F00008000000540120100000000__0000006CF69CD8B0", +"000000067F000080000005400C0100000000-000000067F00008000000540140000004760__0000006C1E7C73C1-0000006C98B77D29", +"000000067F00008000000540140000004760-000000067F0000800000054014000000BB51__0000006C1E7C73C1-0000006C98B77D29", +"000000067F00008000000540140000005B2F-000000067F0000800000054014000001A04C__0000006C98B77D29-0000006CF7781D19", +"000000067F0000800000054014000000BB51-000000067F00008000000540140000012EFA__0000006C1E7C73C1-0000006C98B77D29", +"000000067F00008000000540140000012EFA-000000067F0000800000054014000001A2E5__0000006C1E7C73C1-0000006C98B77D29", +"000000067F0000800000054014000001A04E-000000067F0000800000054016000000022B__0000006C98B77D29-0000006CF7781D19", +"000000067F0000800000054014000001A2E5-000000067F000080000005401400000216D5__0000006C1E7C73C1-0000006C98B77D29", +"000000067F000080000005401400000216D5-000000067F00008000000540140000028AD9__0000006C1E7C73C1-0000006C98B77D29", +"000000067F00008000000540140000028AD9-030000000000000000000000000000000002__0000006C1E7C73C1-0000006C98B77D29", +"000000067F0000800000054016000000022B-030000000000000000000000000000000002__0000006C98B77D29-0000006CF7781D19", +"000000067F000080000005600C0000000000-000000067F000080000005600C0000004000__0000006DA30DA180", +"000000067F000080000005600C0000000000-000000067F000080000005600C0000004000__0000006F949B7C08", +"000000067F000080000005600C0000004000-000000067F000080000005600C0000008000__0000006DA30DA180", +"000000067F000080000005600C0000004000-000000067F000080000005600C0000008000__0000006F949B7C08", +"000000067F000080000005600C0000008000-000000067F000080000005600C000000C000__0000006DA30DA180", +"000000067F000080000005600C0000008000-000000067F000080000005600C000000C000__0000006F949B7C08", +"000000067F000080000005600C0000008077-000000067F000080000005600C00000117CE__0000006CF7781D19-0000006D69B48989", +"000000067F000080000005600C000000C000-000000067F000080000005600C0000010000__0000006DA30DA180", +"000000067F000080000005600C000000C000-000000067F000080000005600C0000010000__0000006F949B7C08", +"000000067F000080000005600C0000010000-000000067F000080000005600C0000014000__0000006DA30DA180", +"000000067F000080000005600C0000010000-000000067F000080000005600C0000014000__0000006F949B7C08", +"000000067F000080000005600C00000117CE-000000067F000080000005600C000001AF0A__0000006CF7781D19-0000006D69B48989", +"000000067F000080000005600C0000014000-000000067F000080000005600C0000018000__0000006DA30DA180", +"000000067F000080000005600C0000014000-000000067F000080000005600C0000018000__0000006F949B7C08", +"000000067F000080000005600C0000018000-000000067F000080000005600C000001C000__0000006DA30DA180", +"000000067F000080000005600C0000018000-000000067F000080000005600C000001C000__0000006F949B7C08", +"000000067F000080000005600C000001AF0A-000000067F000080000005600C0000024670__0000006CF7781D19-0000006D69B48989", +"000000067F000080000005600C000001C000-000000067F000080000005600C0000020000__0000006DA30DA180", +"000000067F000080000005600C000001C000-000000067F000080000005600C0000020000__0000006F949B7C08", +"000000067F000080000005600C0000020000-000000067F000080000005600C0000024000__0000006DA30DA180", +"000000067F000080000005600C0000020000-000000067F000080000005600C0000024000__0000006F949B7C08", +"000000067F000080000005600C0000024000-000000067F000080000005600C0000028000__0000006DA30DA180", +"000000067F000080000005600C0000024000-000000067F000080000005600C0000028000__0000006F949B7C08", +"000000067F000080000005600C0000024670-000000067F000080000005600C000002DDD6__0000006CF7781D19-0000006D69B48989", +"000000067F000080000005600C0000028000-000000067F000080000005600C000002C000__0000006DA30DA180", +"000000067F000080000005600C0000028000-000000067F000080000005600C000002C000__0000006F949B7C08", +"000000067F000080000005600C000002C000-000000067F000080000005600C0000030000__0000006DA30DA180", +"000000067F000080000005600C000002C000-000000067F000080000005600C0000030000__0000006F949B7C08", +"000000067F000080000005600C000002DDD6-000000067F000080000005600C000003752A__0000006CF7781D19-0000006D69B48989", +"000000067F000080000005600C0000030000-000000067F000080000005600C0000034000__0000006DA30DA180", +"000000067F000080000005600C0000030000-000000067F000080000005600C0000034000__0000006F949B7C08", +"000000067F000080000005600C0000034000-000000067F000080000005600C0000038000__0000006DA30DA180", +"000000067F000080000005600C0000034000-000000067F000080000005600C0000038000__0000006F949B7C08", +"000000067F000080000005600C000003752A-000000067F000080000005600C0000040C90__0000006CF7781D19-0000006D69B48989", +"000000067F000080000005600C0000038000-000000067F000080000005600C000003C000__0000006DA30DA180", +"000000067F000080000005600C0000038000-000000067F000080000005600C000003C000__0000006F949B7C08", +"000000067F000080000005600C000003C000-000000067F000080000005600C0000040000__0000006DA30DA180", +"000000067F000080000005600C000003C000-000000067F000080000005600C0000040000__0000006F949B7C08", +"000000067F000080000005600C0000040000-000000067F000080000005600C0000044000__0000006DA30DA180", +"000000067F000080000005600C0000040000-000000067F000080000005600C0000044000__0000006F949B7C08", +"000000067F000080000005600C0000040C90-030000000000000000000000000000000002__0000006CF7781D19-0000006D69B48989", +"000000067F000080000005600C0000044000-000000067F000080000005600C0000048000__0000006DA30DA180", +"000000067F000080000005600C0000044000-000000067F000080000005600C0000048000__0000006F949B7C08", +"000000067F000080000005600C0000048000-000000067F000080000005600C000004C000__0000006DA30DA180", +"000000067F000080000005600C0000048000-000000067F000080000005600C000004C000__0000006F949B7C08", +"000000067F000080000005600C0000048643-000000067F000080000005600C00000907F3__0000006F3370DD59-0000006F95E72491", +"000000067F000080000005600C000004BA9D-000000067F000080000005600C00000551D2__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C000004C000-000000067F000080000005600C0000050000__0000006DA30DA180", +"000000067F000080000005600C000004C000-000000067F000080000005600C0000050000__0000006F949B7C08", +"000000067F000080000005600C0000050000-000000067F000080000005600C0000054000__0000006DA30DA180", +"000000067F000080000005600C0000050000-000000067F000080000005600C0000054000__0000006F949B7C08", +"000000067F000080000005600C0000054000-000000067F000080000005600C0000058000__0000006DA30DA180", +"000000067F000080000005600C0000054000-000000067F000080000005600C0000058000__0000006F949B7C08", +"000000067F000080000005600C00000551D2-000000067F000080000005600C000005E90B__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C0000058000-000000067F000080000005600C000005C000__0000006DA30DA180", +"000000067F000080000005600C0000058000-000000067F000080000005600C000005C000__0000006F949B7C08", +"000000067F000080000005600C000005C000-000000067F000080000005600C0000060000__0000006DA30DA180", +"000000067F000080000005600C000005C000-000000067F000080000005600C0000060000__0000006F949B7C08", +"000000067F000080000005600C000005E90B-000000067F000080000005600C000006802B__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C0000060000-000000067F000080000005600C0000064000__0000006DA30DA180", +"000000067F000080000005600C0000060000-000000067F000080000005600C0000064000__0000006F949B7C08", +"000000067F000080000005600C0000064000-000000067F000080000005600C0000068000__0000006F949B7C08", +"000000067F000080000005600C0000064000-030000000000000000000000000000000002__0000006DA30DA180", +"000000067F000080000005600C0000068000-000000067F000080000005600C000006C000__0000006F949B7C08", +"000000067F000080000005600C000006802B-000000067F000080000005600C0000071782__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C000006C000-000000067F000080000005600C0000070000__0000006F949B7C08", +"000000067F000080000005600C0000070000-000000067F000080000005600C0000074000__0000006F949B7C08", +"000000067F000080000005600C0000071782-000000067F000080000005600C000007AEE8__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C0000074000-000000067F000080000005600C0000078000__0000006F949B7C08", +"000000067F000080000005600C0000078000-000000067F000080000005600C000007C000__0000006F949B7C08", +"000000067F000080000005600C000007AEE8-000000067F000080000005600C000008460B__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C000007C000-000000067F000080000005600C0000080000__0000006F949B7C08", +"000000067F000080000005600C0000080000-000000067F000080000005600C0000084000__0000006F949B7C08", +"000000067F000080000005600C0000084000-000000067F000080000005600C0000088000__0000006F949B7C08", +"000000067F000080000005600C000008460B-000000067F000080000005600C000008DD71__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C0000088000-000000067F000080000005600C000008C000__0000006F949B7C08", +"000000067F000080000005600C000008C000-000000067F000080000005600C0000090000__0000006F949B7C08", +"000000067F000080000005600C000008DD71-000000067F000080000005600C00000974D7__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C0000090000-000000067F000080000005600C0000094000__0000006F949B7C08", +"000000067F000080000005600C00000907F5-000000067F000080000005600C00000D90E0__0000006F3370DD59-0000006F95E72491", +"000000067F000080000005600C0000094000-000000067F000080000005600C0000098000__0000006F949B7C08", +"000000067F000080000005600C00000974D7-000000067F000080000005600C00000A0C0B__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C0000098000-000000067F000080000005600C000009C000__0000006F949B7C08", +"000000067F000080000005600C000009C000-000000067F000080000005600C00000A0000__0000006F949B7C08", +"000000067F000080000005600C00000A0000-000000067F000080000005600C00000A4000__0000006F949B7C08", +"000000067F000080000005600C00000A0C0B-000000067F000080000005600C00000AA371__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C00000A4000-000000067F000080000005600C00000A8000__0000006F949B7C08", +"000000067F000080000005600C00000A8000-000000067F000080000005600C00000AC000__0000006F949B7C08", +"000000067F000080000005600C00000AA371-000000067F000080000005600C00000B3AD7__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C00000AC000-000000067F000080000005600C00000B0000__0000006F949B7C08", +"000000067F000080000005600C00000B0000-000000067F000080000005600C00000B4000__0000006F949B7C08", +"000000067F000080000005600C00000B3AD7-000000067F000080000005600C00000BD20B__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C00000B4000-000000067F000080000005600C00000B8000__0000006F949B7C08", +"000000067F000080000005600C00000B8000-000000067F000080000005600C00000BC000__0000006F949B7C08", +"000000067F000080000005600C00000BC000-000000067F000080000005600C00000C0000__0000006F949B7C08", +"000000067F000080000005600C00000BD20B-000000067F000080000005600C00000C6932__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C00000C0000-000000067F000080000005600C00000C4000__0000006F949B7C08", +"000000067F000080000005600C00000C4000-000000067F000080000005600C00000C8000__0000006F949B7C08", +"000000067F000080000005600C00000C6932-000000067F000080000005600C00000D0098__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C00000C8000-000000067F000080000005600C00000CC000__0000006F949B7C08", +"000000067F000080000005600C00000CC000-000000067F000080000005600C00000D0000__0000006F949B7C08", +"000000067F000080000005600C00000D0000-000000067F000080000005600C00000D4000__0000006F949B7C08", +"000000067F000080000005600C00000D0098-000000067F000080000005600C00000D97FE__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C00000D4000-000000067F000080000005600C00000D8000__0000006F949B7C08", +"000000067F000080000005600C00000D8000-000000067F000080000005600C00000DC000__0000006F949B7C08", +"000000067F000080000005600C00000D90F8-000000067F00008000000560140000002A9A__0000006F3370DD59-0000006F95E72491", +"000000067F000080000005600C00000D97FE-000000067F000080000005600C00000E2F0B__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C00000DC000-000000067F000080000005600C00000E0000__0000006F949B7C08", +"000000067F000080000005600C00000E0000-000000067F000080000005600C00000E4000__0000006F949B7C08", +"000000067F000080000005600C00000E2F0B-000000067F000080000005600C00000EC671__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C00000E4000-000000067F000080000005600C00000E8000__0000006F949B7C08", +"000000067F000080000005600C00000E8000-000000067F000080000005600C00000EC000__0000006F949B7C08", +"000000067F000080000005600C00000EC000-000000067F000080000005600C00000F0000__0000006F949B7C08", +"000000067F000080000005600C00000EC671-000000067F000080000005600C00000F5D9F__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C00000F0000-000000067F000080000005600C00000F4000__0000006F949B7C08", +"000000067F000080000005600C00000F4000-000000067F000080000005600C00000F8000__0000006F949B7C08", +"000000067F000080000005600C00000F5D9F-000000067F000080000005600C00000FF505__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C00000F8000-000000067F000080000005600C00000FC000__0000006F949B7C08", +"000000067F000080000005600C00000FC000-000000067F000080000005600C0000100000__0000006F949B7C08", +"000000067F000080000005600C00000FF505-000000067F000080000005600C0000108C10__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C0000100000-000000067F000080000005600C0000104000__0000006F949B7C08", +"000000067F000080000005600C0000100001-000000067F000080000005600C0000111BF7__0000006EB935F989-0000006F3370DD59", +"000000067F000080000005600C0000104000-000000067F000080000005600C0000108000__0000006F949B7C08", +"000000067F000080000005600C0000108000-000000067F000080000005600C000010C000__0000006F949B7C08", +"000000067F000080000005600C0000108C10-000000067F000080000005600C0100000000__0000006D69B48989-0000006EB935F989", +"000000067F000080000005600C000010C000-000000067F000080000005600C0000110000__0000006F949B7C08", +"000000067F000080000005600C0000110000-000000067F00008000000560120100000000__0000006F949B7C08", +"000000067F000080000005600C0000111BF7-000000067F0000800000056014000000451D__0000006EB935F989-0000006F3370DD59", +"000000067F00008000000560140000002A9A-000000067F00008000000560140000016143__0000006F3370DD59-0000006F95E72491", +"000000067F0000800000056014000000451D-000000067F0000800000056014000000B9A7__0000006EB935F989-0000006F3370DD59", +"000000067F0000800000056014000000B9A7-000000067F00008000000560140000012DE3__0000006EB935F989-0000006F3370DD59", +"000000067F00008000000560140000012DE3-000000067F0000800000056014000001A213__0000006EB935F989-0000006F3370DD59", +"000000067F00008000000560140000016143-000000067F00008000000560140000029CE0__0000006F3370DD59-0000006F95E72491", +"000000067F0000800000056014000001A213-000000067F00008000000560140000021666__0000006EB935F989-0000006F3370DD59", +"000000067F00008000000560140000021666-000000067F00008000000560140000028A7C__0000006EB935F989-0000006F3370DD59", +"000000067F00008000000560140000028A7C-030000000000000000000000000000000002__0000006EB935F989-0000006F3370DD59", +"000000067F00008000000560140000029CE2-030000000000000000000000000000000002__0000006F3370DD59-0000006F95E72491", +"000000067F000080000005800C0000000000-000000067F000080000005800C0000004000__0000006FAFE25518", +"000000067F000080000005800C0000000000-000000067F000080000005800C0000004000__00000071F15CF6B0", +"000000067F000080000005800C0000004000-000000067F000080000005800C0000008000__0000006FAFE25518", +"000000067F000080000005800C0000004000-000000067F000080000005800C0000008000__00000071F15CF6B0", +"000000067F000080000005800C0000007A49-030000000000000000000000000000000002__0000006F95E72491-0000006FA8EDF3B9", +"000000067F000080000005800C0000008000-000000067F000080000005800C000000C000__0000006FAFE25518", +"000000067F000080000005800C0000008000-000000067F000080000005800C000000C000__0000007168C9DFF8", +"000000067F000080000005800C0000008000-000000067F000080000005800C000000C000__00000072377CDB60", +"000000067F000080000005800C00000096DE-000000067F000080000005800C0000012E0C__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C000000C000-000000067F000080000005800C0000010000__0000007168C9DFF8", +"000000067F000080000005800C000000C000-000000067F000080000005800C0000010000__00000072377CDB60", +"000000067F000080000005800C000000C000-030000000000000000000000000000000002__0000006FAFE25518", +"000000067F000080000005800C0000010000-000000067F000080000005800C0000014000__0000007168C9DFF8", +"000000067F000080000005800C0000010000-000000067F000080000005800C0000014000__00000072377CDB60", +"000000067F000080000005800C0000012E0C-000000067F000080000005800C000001C572__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C0000014000-000000067F000080000005800C0000018000__0000007168C9DFF8", +"000000067F000080000005800C0000014000-000000067F000080000005800C0000018000__00000072377CDB60", +"000000067F000080000005800C0000018000-000000067F000080000005800C000001C000__0000007168C9DFF8", +"000000067F000080000005800C0000018000-000000067F000080000005800C000001C000__00000072377CDB60", +"000000067F000080000005800C000001C000-000000067F000080000005800C0000020000__0000007168C9DFF8", +"000000067F000080000005800C000001C000-000000067F000080000005800C0000020000__00000072377CDB60", +"000000067F000080000005800C000001C572-000000067F000080000005800C0000025CD8__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C0000020000-000000067F000080000005800C0000024000__0000007168C9DFF8", +"000000067F000080000005800C0000020000-000000067F000080000005800C0000024000__00000072377CDB60", +"000000067F000080000005800C0000024000-000000067F000080000005800C0000028000__0000007168C9DFF8", +"000000067F000080000005800C0000024000-000000067F000080000005800C0000028000__00000072377CDB60", +"000000067F000080000005800C0000025CD8-000000067F000080000005800C000002F40B__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C0000028000-000000067F000080000005800C000002C000__0000007168C9DFF8", +"000000067F000080000005800C0000028000-000000067F000080000005800C000002C000__00000072377CDB60", +"000000067F000080000005800C000002C000-000000067F000080000005800C0000030000__0000007168C9DFF8", +"000000067F000080000005800C000002C000-000000067F000080000005800C0000030000__00000072377CDB60", +"000000067F000080000005800C000002F40B-000000067F000080000005800C0000038B1E__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C0000030000-000000067F000080000005800C0000034000__0000007168C9DFF8", +"000000067F000080000005800C0000030000-000000067F000080000005800C0000034000__00000072377CDB60", +"000000067F000080000005800C0000034000-000000067F000080000005800C0000038000__0000007168C9DFF8", +"000000067F000080000005800C0000034000-000000067F000080000005800C0000038000__00000072377CDB60", +"000000067F000080000005800C0000038000-000000067F000080000005800C000003C000__0000007168C9DFF8", +"000000067F000080000005800C0000038000-000000067F000080000005800C000003C000__00000072377CDB60", +"000000067F000080000005800C0000038B1E-000000067F000080000005800C0000042284__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C000003C000-000000067F000080000005800C0000040000__0000007168C9DFF8", +"000000067F000080000005800C000003C000-000000067F000080000005800C0000040000__00000072377CDB60", +"000000067F000080000005800C0000040000-000000067F000080000005800C0000044000__0000007168C9DFF8", +"000000067F000080000005800C0000040000-000000067F000080000005800C0000044000__00000072377CDB60", +"000000067F000080000005800C0000042284-000000067F000080000005800C000004B9EA__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C0000044000-000000067F000080000005800C0000048000__0000007168C9DFF8", +"000000067F000080000005800C0000044000-000000067F000080000005800C0000048000__00000072377CDB60", +"000000067F000080000005800C0000048000-000000067F000080000005800C000004C000__0000007168C9DFF8", +"000000067F000080000005800C0000048000-000000067F000080000005800C000004C000__00000072377CDB60", +"000000067F000080000005800C000004B9EA-000000067F000080000005800C000005510B__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C000004C000-000000067F000080000005800C0000050000__0000007168C9DFF8", +"000000067F000080000005800C000004C000-000000067F000080000005800C0000050000__00000072377CDB60", +"000000067F000080000005800C0000050000-000000067F000080000005800C0000054000__0000007168C9DFF8", +"000000067F000080000005800C0000050000-000000067F000080000005800C0000054000__00000072377CDB60", +"000000067F000080000005800C0000054000-000000067F000080000005800C0000058000__0000007168C9DFF8", +"000000067F000080000005800C0000054000-000000067F000080000005800C0000058000__00000072377CDB60", +"000000067F000080000005800C000005510B-000000067F000080000005800C000005E871__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C0000058000-000000067F000080000005800C000005C000__0000007168C9DFF8", +"000000067F000080000005800C0000058000-000000067F000080000005800C000005C000__00000072377CDB60", +"000000067F000080000005800C000005C000-000000067F000080000005800C0000060000__0000007168C9DFF8", +"000000067F000080000005800C000005C000-000000067F000080000005800C0000060000__00000072377CDB60", +"000000067F000080000005800C000005CF08-000000067F000080000005800C00000BAF56__00000071F21624D1-000000723877FF21", +"000000067F000080000005800C000005E871-000000067F000080000005800C0000067F8B__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C0000060000-000000067F000080000005800C0000064000__0000007168C9DFF8", +"000000067F000080000005800C0000060000-000000067F000080000005800C0000064000__00000072377CDB60", +"000000067F000080000005800C0000064000-000000067F000080000005800C0000068000__0000007168C9DFF8", +"000000067F000080000005800C0000064000-000000067F000080000005800C0000068000__00000072377CDB60", +"000000067F000080000005800C0000067F8B-000000067F000080000005800C0100000000__0000006FA8EDF3B9-0000007048B1EC09", +"000000067F000080000005800C0000068000-000000067F000080000005800C000006C000__0000007168C9DFF8", +"000000067F000080000005800C0000068000-000000067F000080000005800C000006C000__00000072377CDB60", +"000000067F000080000005800C000006C000-000000067F000080000005800C0000070000__0000007168C9DFF8", +"000000067F000080000005800C000006C000-000000067F000080000005800C0000070000__00000072377CDB60", +"000000067F000080000005800C0000070000-000000067F000080000005800C0000074000__0000007168C9DFF8", +"000000067F000080000005800C0000070000-000000067F000080000005800C0000074000__00000072377CDB60", +"000000067F000080000005800C0000071854-000000067F000080000005800C000007AFBA__0000007048B1EC09-00000070E8761431", +"000000067F000080000005800C0000074000-000000067F000080000005800C0000078000__0000007168C9DFF8", +"000000067F000080000005800C0000074000-000000067F000080000005800C0000078000__00000072377CDB60", +"000000067F000080000005800C0000078000-000000067F000080000005800C000007C000__0000007168C9DFF8", +"000000067F000080000005800C0000078000-000000067F000080000005800C000007C000__00000072377CDB60", +"000000067F000080000005800C000007AFBA-000000067F000080000005800C0000084720__0000007048B1EC09-00000070E8761431", +"000000067F000080000005800C000007C000-000000067F000080000005800C0000080000__0000007168C9DFF8", +"000000067F000080000005800C000007C000-000000067F000080000005800C0000080000__00000072377CDB60", +"000000067F000080000005800C0000080000-000000067F000080000005800C0000084000__0000007168C9DFF8", +"000000067F000080000005800C0000080000-000000067F000080000005800C0000084000__00000072377CDB60", +"000000067F000080000005800C0000084000-000000067F000080000005800C0000088000__0000007168C9DFF8", +"000000067F000080000005800C0000084000-000000067F000080000005800C0000088000__00000072377CDB60", +"000000067F000080000005800C0000084720-000000067F000080000005800C000008DE86__0000007048B1EC09-00000070E8761431", +"000000067F000080000005800C0000088000-000000067F000080000005800C000008C000__0000007168C9DFF8", +"000000067F000080000005800C0000088000-000000067F000080000005800C000008C000__00000072377CDB60", +"000000067F000080000005800C000008C000-000000067F000080000005800C0000090000__0000007168C9DFF8", +"000000067F000080000005800C000008C000-000000067F000080000005800C0000090000__00000072377CDB60", +"000000067F000080000005800C000008DE86-000000067F000080000005800C00000975A6__0000007048B1EC09-00000070E8761431", +"000000067F000080000005800C0000090000-000000067F000080000005800C0000094000__0000007168C9DFF8", +"000000067F000080000005800C0000090000-000000067F000080000005800C0000094000__00000072377CDB60", +"000000067F000080000005800C0000094000-000000067F000080000005800C0000098000__0000007168C9DFF8", +"000000067F000080000005800C0000094000-000000067F000080000005800C0000098000__00000072377CDB60", +"000000067F000080000005800C00000975A6-000000067F000080000005800C00000A0D0C__0000007048B1EC09-00000070E8761431", +"000000067F000080000005800C0000098000-000000067F000080000005800C000009C000__0000007168C9DFF8", +"000000067F000080000005800C0000098000-000000067F000080000005800C000009C000__00000072377CDB60", +"000000067F000080000005800C000009C000-000000067F000080000005800C00000A0000__0000007168C9DFF8", +"000000067F000080000005800C000009C000-000000067F000080000005800C00000A0000__00000072377CDB60", +"000000067F000080000005800C000009D78D-000000067F000080000005800C0200000018__000000716A103FC9-00000071F21624D1", +"000000067F000080000005800C00000A0000-000000067F000080000005800C00000A4000__0000007168C9DFF8", +"000000067F000080000005800C00000A0000-000000067F000080000005800C00000A4000__00000072377CDB60", +"000000067F000080000005800C00000A0D0C-000000067F000080000005800C00000AA472__0000007048B1EC09-00000070E8761431", +"000000067F000080000005800C00000A4000-000000067F000080000005800C00000A8000__0000007168C9DFF8", +"000000067F000080000005800C00000A4000-000000067F000080000005800C00000A8000__00000072377CDB60", +"000000067F000080000005800C00000A8000-000000067F000080000005800C00000AC000__0000007168C9DFF8", +"000000067F000080000005800C00000A8000-000000067F000080000005800C00000AC000__00000072377CDB60", +"000000067F000080000005800C00000AA472-000000067F000080000005800C00000B3BB4__0000007048B1EC09-00000070E8761431", +"000000067F000080000005800C00000AC000-000000067F000080000005800C00000B0000__0000007168C9DFF8", +"000000067F000080000005800C00000AC000-000000067F000080000005800C00000B0000__00000072377CDB60", +"000000067F000080000005800C00000B0000-000000067F000080000005800C00000B4000__0000007168C9DFF8", +"000000067F000080000005800C00000B0000-000000067F000080000005800C00000B4000__00000072377CDB60", +"000000067F000080000005800C00000B3BB4-000000067F000080000005800C00000BD30B__0000007048B1EC09-00000070E8761431", +"000000067F000080000005800C00000B4000-000000067F000080000005800C00000B8000__0000007168C9DFF8", +"000000067F000080000005800C00000B4000-000000067F000080000005800C00000B8000__00000072377CDB60", +"000000067F000080000005800C00000B8000-000000067F000080000005800C00000BC000__0000007168C9DFF8", +"000000067F000080000005800C00000B8000-000000067F000080000005800C00000BC000__00000072377CDB60", +"000000067F000080000005800C00000BAF5F-000000067F000080000005801400000007C1__00000071F21624D1-000000723877FF21", +"000000067F000080000005800C00000BC000-000000067F000080000005800C00000C0000__0000007168C9DFF8", +"000000067F000080000005800C00000BC000-000000067F000080000005800C00000C0000__00000072377CDB60", +"000000067F000080000005800C00000BD30B-000000067F000080000005800C00000C6A32__0000007048B1EC09-00000070E8761431", +"000000067F000080000005800C00000C0000-000000067F000080000005800C00000C4000__0000007168C9DFF8", +"000000067F000080000005800C00000C0000-000000067F000080000005800C00000C4000__00000072377CDB60", +"000000067F000080000005800C00000C4000-000000067F000080000005800C00000C8000__0000007168C9DFF8", +"000000067F000080000005800C00000C4000-000000067F000080000005800C00000C8000__00000072377CDB60", +"000000067F000080000005800C00000C6A32-000000067F000080000005800C0100000000__0000007048B1EC09-00000070E8761431", +"000000067F000080000005800C00000C8000-000000067F000080000005800C00000CC000__0000007168C9DFF8", +"000000067F000080000005800C00000C8000-000000067F000080000005800C00000CC000__00000072377CDB60", +"000000067F000080000005800C00000CC000-000000067F000080000005800C00000D0000__0000007168C9DFF8", +"000000067F000080000005800C00000CC000-000000067F000080000005800C00000D0000__00000072377CDB60", +"000000067F000080000005800C00000CDE2D-000000067F000080000005800C00000D754D__00000070E8761431-000000716A103FC9", +"000000067F000080000005800C00000D0000-000000067F000080000005800C00000D4000__0000007168C9DFF8", +"000000067F000080000005800C00000D0000-000000067F000080000005800C00000D4000__00000072377CDB60", +"000000067F000080000005800C00000D4000-000000067F000080000005800C00000D8000__0000007168C9DFF8", +"000000067F000080000005800C00000D4000-000000067F000080000005800C00000D8000__00000072377CDB60", +"000000067F000080000005800C00000D754D-000000067F000080000005800C00000E0CB3__00000070E8761431-000000716A103FC9", +"000000067F000080000005800C00000D8000-000000067F000080000005800C00000DC000__0000007168C9DFF8", +"000000067F000080000005800C00000D8000-000000067F000080000005800C00000DC000__00000072377CDB60", +"000000067F000080000005800C00000DC000-000000067F000080000005800C00000E0000__0000007168C9DFF8", +"000000067F000080000005800C00000DC000-000000067F000080000005800C00000E0000__00000072377CDB60", +"000000067F000080000005800C00000E0000-000000067F000080000005800C00000E4000__0000007168C9DFF8", +"000000067F000080000005800C00000E0000-000000067F000080000005800C00000E4000__00000072377CDB60", +"000000067F000080000005800C00000E0CB3-000000067F000080000005800C00000EA409__00000070E8761431-000000716A103FC9", +"000000067F000080000005800C00000E4000-000000067F000080000005800C00000E8000__0000007168C9DFF8", +"000000067F000080000005800C00000E4000-000000067F000080000005800C00000E8000__00000072377CDB60", +"000000067F000080000005800C00000E8000-000000067F000080000005800C00000EC000__0000007168C9DFF8", +"000000067F000080000005800C00000E8000-000000067F000080000005800C00000EC000__00000072377CDB60", +"000000067F000080000005800C00000EA409-000000067F000080000005800C00000F3B4B__00000070E8761431-000000716A103FC9", +"000000067F000080000005800C00000EC000-000000067F000080000005800C00000F0000__0000007168C9DFF8", +"000000067F000080000005800C00000EC000-000000067F000080000005800C00000F0000__00000072377CDB60", +"000000067F000080000005800C00000F0000-000000067F000080000005800C00000F4000__0000007168C9DFF8", +"000000067F000080000005800C00000F0000-000000067F000080000005800C00000F4000__00000072377CDB60", +"000000067F000080000005800C00000F3B4B-000000067F000080000005800C00000FD2B1__00000070E8761431-000000716A103FC9", +"000000067F000080000005800C00000F4000-000000067F000080000005800C00000F8000__0000007168C9DFF8", +"000000067F000080000005800C00000F4000-000000067F000080000005800C00000F8000__00000072377CDB60", +"000000067F000080000005800C00000F8000-000000067F000080000005800C00000FC000__0000007168C9DFF8", +"000000067F000080000005800C00000F8000-000000067F000080000005800C00000FC000__00000072377CDB60", +"000000067F000080000005800C00000FC000-000000067F000080000005800C0000100000__0000007168C9DFF8", +"000000067F000080000005800C00000FC000-000000067F000080000005800C0000100000__00000072377CDB60", +"000000067F000080000005800C00000FD2B1-000000067F000080000005800C00001069D8__00000070E8761431-000000716A103FC9", +"000000067F000080000005800C0000100000-000000067F000080000005800C0000104000__0000007168C9DFF8", +"000000067F000080000005800C0000100000-000000067F000080000005800C0000104000__00000072377CDB60", +"000000067F000080000005800C0000104000-000000067F000080000005800C0000108000__0000007168C9DFF8", +"000000067F000080000005800C0000104000-000000067F000080000005800C0000108000__00000072377CDB60", +"000000067F000080000005800C00001069D8-000000067F000080000005800C000011010C__00000070E8761431-000000716A103FC9", +"000000067F000080000005800C0000108000-000000067F000080000005800C000010C000__0000007168C9DFF8", +"000000067F000080000005800C0000108000-000000067F000080000005800C000010C000__00000072377CDB60", +"000000067F000080000005800C000010C000-000000067F000080000005800C0000110000__0000007168C9DFF8", +"000000067F000080000005800C000010C000-000000067F000080000005800C0000110000__00000072377CDB60", +"000000067F000080000005800C0000110000-000000067F00008000000580120100000000__00000072377CDB60", +"000000067F000080000005800C0000110000-030000000000000000000000000000000002__0000007168C9DFF8", +"000000067F000080000005800C000011010C-01000000000000000100000002000000001E__00000070E8761431-000000716A103FC9", +"000000067F000080000005800C0200000018-000000067F000080000005801400000059BE__000000716A103FC9-00000071F21624D1", +"000000067F00008000000580140000000000-000000067F00008000000580140000004000__00000072377CDB60", +"000000067F000080000005801400000007C3-000000067F00008000000580140000020462__00000071F21624D1-000000723877FF21", +"000000067F00008000000580140000004000-000000067F00008000000580140000008000__00000072377CDB60", +"000000067F000080000005801400000059BE-000000067F0000800000058014000000BF38__000000716A103FC9-00000071F21624D1", +"000000067F00008000000580140000008000-000000067F0000800000058014000000C000__00000072377CDB60", +"000000067F0000800000058014000000BF38-000000067F00008000000580140000012530__000000716A103FC9-00000071F21624D1", +"000000067F0000800000058014000000C000-000000067F00008000000580140000010000__00000072377CDB60", +"000000067F00008000000580140000010000-000000067F00008000000580140000014000__00000072377CDB60", +"000000067F00008000000580140000012530-000000067F00008000000580140000018B50__000000716A103FC9-00000071F21624D1", +"000000067F00008000000580140000014000-000000067F00008000000580140000018000__00000072377CDB60", +"000000067F00008000000580140000018000-000000067F0000800000058014000001C000__00000072377CDB60", +"000000067F00008000000580140000018B50-000000067F0000800000058014000001F0D3__000000716A103FC9-00000071F21624D1", +"000000067F0000800000058014000001C000-000000067F00008000000580140000020000__00000072377CDB60", +"000000067F0000800000058014000001F0D3-000000067F0000800000058014000002562B__000000716A103FC9-00000071F21624D1", +"000000067F00008000000580140000020000-000000067F00008000000580140000024000__00000072377CDB60", +"000000067F00008000000580140000020464-030000000000000000000000000000000002__00000071F21624D1-000000723877FF21", +"000000067F00008000000580140000024000-000000067F00008000000580140000028000__00000072377CDB60", +"000000067F0000800000058014000002562B-000000067F0000800000058014000002BC37__000000716A103FC9-00000071F21624D1", +"000000067F00008000000580140000028000-000000067F0000800000058014000002C000__00000072377CDB60", +"000000067F0000800000058014000002BC37-030000000000000000000000000000000002__000000716A103FC9-00000071F21624D1", +"000000067F0000800000058014000002C000-030000000000000000000000000000000002__00000072377CDB60", +"000000067F000080000005A00C0000007614-000000067F000080000005A00C000000ED44__000000723877FF21-00000072A0D7CEA1", +"000000067F000080000005A00C000000ED44-000000067F000080000005A00C0000016337__000000723877FF21-00000072A0D7CEA1", +"000000067F000080000005A00C0000016337-000000067F000080000005A014000000148C__000000723877FF21-00000072A0D7CEA1", +"000000067F000080000005A014000000148C-000000067F000080000005C00C0000003207__000000723877FF21-00000072A0D7CEA1", +"000000067F000080000005C00C0000003207-000000067F000080000005C00C000000C96D__000000723877FF21-00000072A0D7CEA1", +"000000067F000080000005C00C000000C96D-030000000000000000000000000000000002__000000723877FF21-00000072A0D7CEA1", +"000000067F000080000005C00C0000016516-000000067F000080000005C0140000001694__00000072A0D7CEA1-0000007318DDE691", +"000000067F000080000005C0140000001694-000000067F000080000005E00C000000360C__00000072A0D7CEA1-0000007318DDE691", +"000000067F000080000005E00C0000000000-000000067F000080000005E00C0000004000__00000073AF75E930", +"000000067F000080000005E00C0000000000-000000067F000080000005E00C0000004000__000000756884A510", +"000000067F000080000005E00C000000360C-000000067F000080000005E00C000000CD72__00000072A0D7CEA1-0000007318DDE691", +"000000067F000080000005E00C0000004000-000000067F000080000005E00C0000008000__00000073AF75E930", +"000000067F000080000005E00C0000004000-000000067F000080000005E00C0000008000__000000756884A510", +"000000067F000080000005E00C0000008000-000000067F000080000005E00C000000C000__00000073AF75E930", +"000000067F000080000005E00C0000008000-000000067F000080000005E00C000000C000__000000756884A510", +"000000067F000080000005E00C000000C000-000000067F000080000005E00C0000010000__00000073AF75E930", +"000000067F000080000005E00C000000C000-000000067F000080000005E00C0000010000__000000756884A510", +"000000067F000080000005E00C000000CD72-000000067F000080000005E00C00000164D8__00000072A0D7CEA1-0000007318DDE691", +"000000067F000080000005E00C0000010000-000000067F000080000005E00C0000014000__00000073AF75E930", +"000000067F000080000005E00C0000010000-000000067F000080000005E00C0000014000__000000756884A510", +"000000067F000080000005E00C0000014000-000000067F000080000005E00C0000018000__00000073AF75E930", +"000000067F000080000005E00C0000014000-000000067F000080000005E00C0000018000__000000756884A510", +"000000067F000080000005E00C00000164D8-000000067F000080000005E00C000001FC0B__00000072A0D7CEA1-0000007318DDE691", +"000000067F000080000005E00C0000018000-000000067F000080000005E00C000001C000__00000073AF75E930", +"000000067F000080000005E00C0000018000-000000067F000080000005E00C000001C000__000000756884A510", +"000000067F000080000005E00C000001C000-000000067F000080000005E00C0000020000__00000073AF75E930", +"000000067F000080000005E00C000001C000-000000067F000080000005E00C0000020000__000000756884A510", +"000000067F000080000005E00C000001FC0B-000000067F000080000005E00C0000029319__00000072A0D7CEA1-0000007318DDE691", +"000000067F000080000005E00C0000020000-000000067F000080000005E00C0000024000__00000073AF75E930", +"000000067F000080000005E00C0000020000-000000067F000080000005E00C0000024000__000000756884A510", +"000000067F000080000005E00C0000024000-000000067F000080000005E00C0000028000__00000073AF75E930", +"000000067F000080000005E00C0000024000-000000067F000080000005E00C0000028000__000000756884A510", +"000000067F000080000005E00C0000028000-000000067F000080000005E00C000002C000__00000073AF75E930", +"000000067F000080000005E00C0000028000-000000067F000080000005E00C000002C000__000000756884A510", +"000000067F000080000005E00C0000029319-030000000000000000000000000000000002__00000072A0D7CEA1-0000007318DDE691", +"000000067F000080000005E00C000002C000-000000067F000080000005E00C0000030000__00000073AF75E930", +"000000067F000080000005E00C000002C000-000000067F000080000005E00C0000030000__000000756884A510", +"000000067F000080000005E00C0000030000-000000067F000080000005E00C0000034000__00000073AF75E930", +"000000067F000080000005E00C0000030000-000000067F000080000005E00C0000034000__000000756884A510", +"000000067F000080000005E00C0000034000-000000067F000080000005E00C0000038000__00000073AF75E930", +"000000067F000080000005E00C0000034000-000000067F000080000005E00C0000038000__000000756884A510", +"000000067F000080000005E00C0000038000-000000067F000080000005E00C000003C000__00000073AF75E930", +"000000067F000080000005E00C0000038000-000000067F000080000005E00C000003C000__000000756884A510", +"000000067F000080000005E00C00000385D9-000000067F000080000005E00C0000041D0A__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C000003C000-000000067F000080000005E00C0000040000__00000073AF75E930", +"000000067F000080000005E00C000003C000-000000067F000080000005E00C0000040000__000000756884A510", +"000000067F000080000005E00C0000040000-000000067F000080000005E00C0000044000__00000073AF75E930", +"000000067F000080000005E00C0000040000-000000067F000080000005E00C0000044000__000000756884A510", +"000000067F000080000005E00C0000041D0A-000000067F000080000005E00C000004B470__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C0000044000-000000067F000080000005E00C0000048000__00000073AF75E930", +"000000067F000080000005E00C0000044000-000000067F000080000005E00C0000048000__000000756884A510", +"000000067F000080000005E00C0000048000-000000067F000080000005E00C000004C000__00000073AF75E930", +"000000067F000080000005E00C0000048000-000000067F000080000005E00C000004C000__000000756884A510", +"000000067F000080000005E00C000004B470-000000067F000080000005E00C0000054BA9__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C000004C000-000000067F000080000005E00C0000050000__00000073AF75E930", +"000000067F000080000005E00C000004C000-000000067F000080000005E00C0000050000__000000756884A510", +"000000067F000080000005E00C0000050000-000000067F000080000005E00C0000054000__00000073AF75E930", +"000000067F000080000005E00C0000050000-000000067F000080000005E00C0000054000__000000756884A510", +"000000067F000080000005E00C000005017A-000000067F000080000005E00C000009FEAD__000000751253A4C1-00000075687C3009", +"000000067F000080000005E00C0000054000-000000067F000080000005E00C0000058000__00000073AF75E930", +"000000067F000080000005E00C0000054000-000000067F000080000005E00C0000058000__000000756884A510", +"000000067F000080000005E00C0000054BA9-000000067F000080000005E00C000005E30B__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C0000058000-000000067F000080000005E00C000005C000__00000073AF75E930", +"000000067F000080000005E00C0000058000-000000067F000080000005E00C000005C000__000000756884A510", +"000000067F000080000005E00C000005C000-000000067F000080000005E00C0000060000__00000073AF75E930", +"000000067F000080000005E00C000005C000-000000067F000080000005E00C0000060000__000000756884A510", +"000000067F000080000005E00C000005E30B-000000067F000080000005E00C0000067A2C__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C0000060000-000000067F000080000005E00C0000064000__00000073AF75E930", +"000000067F000080000005E00C0000060000-000000067F000080000005E00C0000064000__000000756884A510", +"000000067F000080000005E00C0000064000-000000067F000080000005E00C0000068000__00000073AF75E930", +"000000067F000080000005E00C0000064000-000000067F000080000005E00C0000068000__000000756884A510", +"000000067F000080000005E00C0000067A2C-000000067F000080000005E00C0000071187__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C0000068000-000000067F000080000005E00C000006C000__00000073AF75E930", +"000000067F000080000005E00C0000068000-000000067F000080000005E00C000006C000__000000756884A510", +"000000067F000080000005E00C000006C000-000000067F000080000005E00C0000070000__00000073AF75E930", +"000000067F000080000005E00C000006C000-000000067F000080000005E00C0000070000__000000756884A510", +"000000067F000080000005E00C0000070000-000000067F000080000005E00C0000074000__00000073AF75E930", +"000000067F000080000005E00C0000070000-000000067F000080000005E00C0000074000__000000756884A510", +"000000067F000080000005E00C0000071187-000000067F000080000005E00C000007A8ED__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C0000074000-000000067F000080000005E00C0000078000__00000073AF75E930", +"000000067F000080000005E00C0000074000-000000067F000080000005E00C0000078000__000000756884A510", +"000000067F000080000005E00C0000078000-000000067F000080000005E00C000007C000__00000073AF75E930", +"000000067F000080000005E00C0000078000-000000067F000080000005E00C000007C000__000000756884A510", +"000000067F000080000005E00C000007A8ED-000000067F000080000005E00C000008400B__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C000007C000-000000067F000080000005E00C0000080000__00000073AF75E930", +"000000067F000080000005E00C000007C000-000000067F000080000005E00C0000080000__000000756884A510", +"000000067F000080000005E00C0000080000-000000067F000080000005E00C0000084000__00000073AF75E930", +"000000067F000080000005E00C0000080000-000000067F000080000005E00C0000084000__000000756884A510", +"000000067F000080000005E00C0000084000-000000067F000080000005E00C0000088000__00000073AF75E930", +"000000067F000080000005E00C0000084000-000000067F000080000005E00C0000088000__000000756884A510", +"000000067F000080000005E00C000008400B-000000067F000080000005E00C000008D771__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C0000088000-000000067F000080000005E00C000008C000__000000756884A510", +"000000067F000080000005E00C0000088000-030000000000000000000000000000000002__00000073AF75E930", +"000000067F000080000005E00C000008C000-000000067F000080000005E00C0000090000__000000756884A510", +"000000067F000080000005E00C000008D771-000000067F000080000005E00C0000096ED7__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C0000090000-000000067F000080000005E00C0000094000__000000756884A510", +"000000067F000080000005E00C0000094000-000000067F000080000005E00C0000098000__000000756884A510", +"000000067F000080000005E00C0000096ED7-000000067F000080000005E00C00000A060B__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C0000098000-000000067F000080000005E00C000009C000__000000756884A510", +"000000067F000080000005E00C000009C000-000000067F000080000005E00C00000A0000__000000756884A510", +"000000067F000080000005E00C000009FEB2-000000067F000080000005E00C00000EF4ED__000000751253A4C1-00000075687C3009", +"000000067F000080000005E00C00000A0000-000000067F000080000005E00C00000A4000__000000756884A510", +"000000067F000080000005E00C00000A060B-000000067F000080000005E00C00000A9D71__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C00000A4000-000000067F000080000005E00C00000A8000__000000756884A510", +"000000067F000080000005E00C00000A8000-000000067F000080000005E00C00000AC000__000000756884A510", +"000000067F000080000005E00C00000A9D71-000000067F000080000005E00C00000B34D7__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C00000AC000-000000067F000080000005E00C00000B0000__000000756884A510", +"000000067F000080000005E00C00000AF576-000000067F000080000005E00C0200000023__0000007497B01FF9-000000751253A4C1", +"000000067F000080000005E00C00000B0000-000000067F000080000005E00C00000B4000__000000756884A510", +"000000067F000080000005E00C00000B34D7-000000067F000080000005E00C00000BCC0C__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C00000B4000-000000067F000080000005E00C00000B8000__000000756884A510", +"000000067F000080000005E00C00000B8000-000000067F000080000005E00C00000BC000__000000756884A510", +"000000067F000080000005E00C00000BC000-000000067F000080000005E00C00000C0000__000000756884A510", +"000000067F000080000005E00C00000BCC0C-000000067F000080000005E00C00000C6336__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C00000C0000-000000067F000080000005E00C00000C4000__000000756884A510", +"000000067F000080000005E00C00000C4000-000000067F000080000005E00C00000C8000__000000756884A510", +"000000067F000080000005E00C00000C6336-000000067F000080000005E00C00000CFA9C__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C00000C8000-000000067F000080000005E00C00000CC000__000000756884A510", +"000000067F000080000005E00C00000CC000-000000067F000080000005E00C00000D0000__000000756884A510", +"000000067F000080000005E00C00000CFA9C-000000067F000080000005E00C00000D91AB__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C00000D0000-000000067F000080000005E00C00000D4000__000000756884A510", +"000000067F000080000005E00C00000D4000-000000067F000080000005E00C00000D8000__000000756884A510", +"000000067F000080000005E00C00000D8000-000000067F000080000005E00C00000DC000__000000756884A510", +"000000067F000080000005E00C00000D91AB-000000067F000080000005E00C00000E2911__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C00000DC000-000000067F000080000005E00C00000E0000__000000756884A510", +"000000067F000080000005E00C00000E0000-000000067F000080000005E00C00000E4000__000000756884A510", +"000000067F000080000005E00C00000E2911-000000067F000080000005E00C00000EC077__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C00000E4000-000000067F000080000005E00C00000E8000__000000756884A510", +"000000067F000080000005E00C00000E8000-000000067F000080000005E00C00000EC000__000000756884A510", +"000000067F000080000005E00C00000EC000-000000067F000080000005E00C00000F0000__000000756884A510", +"000000067F000080000005E00C00000EC077-000000067F000080000005E00C00000F57A8__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C00000EF4F1-000000067F000080000005E014000000BDDE__000000751253A4C1-00000075687C3009", +"000000067F000080000005E00C00000F0000-000000067F000080000005E00C00000F4000__000000756884A510", +"000000067F000080000005E00C00000F4000-000000067F000080000005E00C00000F8000__000000756884A510", +"000000067F000080000005E00C00000F57A8-000000067F000080000005E00C00000FEF0A__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C00000F8000-000000067F000080000005E00C00000FC000__000000756884A510", +"000000067F000080000005E00C00000FC000-000000067F000080000005E00C0000100000__000000756884A510", +"000000067F000080000005E00C00000FEF0A-000000067F000080000005E00C000010862B__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C0000100000-000000067F000080000005E00C0000104000__000000756884A510", +"000000067F000080000005E00C0000104000-000000067F000080000005E00C0000108000__000000756884A510", +"000000067F000080000005E00C0000108000-000000067F000080000005E00C000010C000__000000756884A510", +"000000067F000080000005E00C000010862B-000000067F000080000005E00C0000111C20__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C000010C000-000000067F000080000005E00C0000110000__000000756884A510", +"000000067F000080000005E00C0000110000-000000067F000080000005E0120100000000__000000756884A510", +"000000067F000080000005E00C00FFFFFFFF-010000000000000001000000030000000002__0000007318DDE691-0000007497B01FF9", +"000000067F000080000005E00C02FFFFFFFF-000000067F000080000005E0140000006C41__0000007497B01FF9-000000751253A4C1", +"000000067F000080000005E0140000000000-000000067F000080000005E0140000004000__000000756884A510", +"000000067F000080000005E0140000004000-000000067F000080000005E0140000008000__000000756884A510", +"000000067F000080000005E0140000006C41-000000067F000080000005E014000000D890__0000007497B01FF9-000000751253A4C1", +"000000067F000080000005E0140000008000-000000067F000080000005E014000000C000__000000756884A510", +"000000067F000080000005E014000000BDDE-000000067F000080000005E0140000023A18__000000751253A4C1-00000075687C3009", +"000000067F000080000005E014000000C000-000000067F000080000005E0140000010000__000000756884A510", +"000000067F000080000005E014000000D890-000000067F000080000005E01400000144C8__0000007497B01FF9-000000751253A4C1", +"000000067F000080000005E0140000010000-000000067F000080000005E0140000014000__000000756884A510", +"000000067F000080000005E0140000014000-000000067F000080000005E0140000018000__000000756884A510", +"000000067F000080000005E01400000144C8-000000067F000080000005E014000001B1AC__0000007497B01FF9-000000751253A4C1", +"000000067F000080000005E0140000018000-000000067F000080000005E014000001C000__000000756884A510", +"000000067F000080000005E014000001B1AC-000000067F000080000005E0140000021E03__0000007497B01FF9-000000751253A4C1", +"000000067F000080000005E014000001C000-000000067F000080000005E0140000020000__000000756884A510", +"000000067F000080000005E0140000020000-000000067F000080000005E0140000024000__000000756884A510", +"000000067F000080000005E0140000021E03-000000067F000080000005E0140000028A36__0000007497B01FF9-000000751253A4C1", +"000000067F000080000005E0140000023A18-030000000000000000000000000000000002__000000751253A4C1-00000075687C3009", +"000000067F000080000005E0140000024000-000000067F000080000005E0140000028000__000000756884A510", +"000000067F000080000005E0140000028000-000000067F000080000005E014000002C000__000000756884A510", +"000000067F000080000005E0140000028A36-030000000000000000000000000000000002__0000007497B01FF9-000000751253A4C1", +"000000067F000080000005E014000002C000-030000000000000000000000000000000002__000000756884A510", +"000000067F000080000006000C0000000000-000000067F000080000006000C0000004000__00000077B1836CA0", +"000000067F000080000006000C0000004000-000000067F000080000006000C0000008000__00000077B1836CA0", +"000000067F000080000006000C0000008000-000000067F000080000006000C000000C000__00000077B1836CA0", +"000000067F000080000006000C0000008FB7-000000067F000080000006000C000001271D__00000075687C3009-00000075E915EBC9", +"000000067F000080000006000C000000C000-000000067F000080000006000C0000010000__00000077B1836CA0", +"000000067F000080000006000C0000010000-000000067F000080000006000C0000014000__00000077B1836CA0", +"000000067F000080000006000C000001271D-000000067F000080000006000C000001BE83__00000075687C3009-00000075E915EBC9", +"000000067F000080000006000C0000014000-000000067F000080000006000C0000018000__00000077B1836CA0", +"000000067F000080000006000C0000018000-000000067F000080000006000C000001C000__00000077B1836CA0", +"000000067F000080000006000C000001BE83-000000067F000080000006000C00000255B6__00000075687C3009-00000075E915EBC9", +"000000067F000080000006000C000001C000-000000067F000080000006000C0000020000__00000077B1836CA0", +"000000067F000080000006000C0000020000-000000067F000080000006000C0000024000__00000077B1836CA0", +"000000067F000080000006000C0000024000-000000067F000080000006000C0000028000__00000077B1836CA0", +"000000067F000080000006000C00000255B6-000000067F000080000006000C000002ED0B__00000075687C3009-00000075E915EBC9", +"000000067F000080000006000C0000028000-000000067F000080000006000C000002C000__00000077B1836CA0", +"000000067F000080000006000C000002C000-000000067F000080000006000C0000030000__00000077B1836CA0", +"000000067F000080000006000C000002ED0B-000000067F000080000006000C000003842B__00000075687C3009-00000075E915EBC9", +"000000067F000080000006000C0000030000-000000067F000080000006000C0000034000__00000077B1836CA0", +"000000067F000080000006000C0000034000-000000067F000080000006000C0000038000__00000077B1836CA0", +"000000067F000080000006000C0000038000-000000067F000080000006000C000003C000__00000077B1836CA0", +"000000067F000080000006000C000003842B-000000067F000080000006000C0000041B80__00000075687C3009-00000075E915EBC9", +"000000067F000080000006000C000003C000-000000067F000080000006000C0000040000__00000077B1836CA0", +"000000067F000080000006000C0000040000-000000067F000080000006000C0000044000__00000077B1836CA0", +"000000067F000080000006000C0000041B80-000000067F000080000006000C000004B2E6__00000075687C3009-00000075E915EBC9", +"000000067F000080000006000C0000044000-000000067F000080000006000C0000048000__00000077B1836CA0", +"000000067F000080000006000C0000048000-000000067F000080000006000C000004C000__0000007739203FF0", +"000000067F000080000006000C000004B2E6-030000000000000000000000000000000002__00000075687C3009-00000075E915EBC9", +"000000067F000080000006000C000004BAC2-000000067F000080000006000C00000551F7__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C000004C000-000000067F000080000006000C0000050000__0000007739203FF0", +"000000067F000080000006000C0000050000-000000067F000080000006000C0000054000__0000007739203FF0", +"000000067F000080000006000C0000051A05-000000067F000080000006000C00000A4D93__00000077B2AD0F91-0000007805801C41", +"000000067F000080000006000C0000054000-000000067F000080000006000C0000058000__0000007739203FF0", +"000000067F000080000006000C00000551F7-000000067F000080000006000C000005E90B__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C0000058000-000000067F000080000006000C000005C000__0000007739203FF0", +"000000067F000080000006000C000005C000-000000067F000080000006000C0000060000__0000007739203FF0", +"000000067F000080000006000C000005E90B-000000067F000080000006000C000006802B__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C0000060000-000000067F000080000006000C0000064000__0000007739203FF0", +"000000067F000080000006000C0000064000-000000067F000080000006000C0000068000__0000007739203FF0", +"000000067F000080000006000C0000068000-000000067F000080000006000C000006C000__0000007739203FF0", +"000000067F000080000006000C000006802B-000000067F000080000006000C0000071782__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C000006C000-000000067F000080000006000C0000070000__0000007739203FF0", +"000000067F000080000006000C0000070000-000000067F000080000006000C0000074000__0000007739203FF0", +"000000067F000080000006000C0000071782-000000067F000080000006000C000007AEE8__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C0000074000-000000067F000080000006000C0000078000__0000007739203FF0", +"000000067F000080000006000C0000078000-000000067F000080000006000C000007C000__0000007739203FF0", +"000000067F000080000006000C000007AEE8-000000067F000080000006000C000008460B__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C000007C000-000000067F000080000006000C0000080000__0000007739203FF0", +"000000067F000080000006000C0000080000-000000067F000080000006000C0000084000__0000007739203FF0", +"000000067F000080000006000C0000084000-000000067F000080000006000C0000088000__0000007739203FF0", +"000000067F000080000006000C000008460B-000000067F000080000006000C000008DD71__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C0000088000-000000067F000080000006000C000008C000__0000007739203FF0", +"000000067F000080000006000C000008C000-000000067F000080000006000C0000090000__0000007739203FF0", +"000000067F000080000006000C000008DD71-000000067F000080000006000C00000974D7__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C0000090000-000000067F000080000006000C0000094000__0000007739203FF0", +"000000067F000080000006000C0000094000-000000067F000080000006000C0000098000__0000007739203FF0", +"000000067F000080000006000C00000974D7-000000067F000080000006000C00000A0C0B__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C0000098000-000000067F000080000006000C000009C000__0000007739203FF0", +"000000067F000080000006000C000009C000-000000067F000080000006000C00000A0000__0000007739203FF0", +"000000067F000080000006000C00000A0000-000000067F000080000006000C00000A4000__0000007739203FF0", +"000000067F000080000006000C00000A0C0B-000000067F000080000006000C00000AA371__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C00000A4000-000000067F000080000006000C00000A8000__0000007739203FF0", +"000000067F000080000006000C00000A4D95-000000067F000080000006000C00000F7C7B__00000077B2AD0F91-0000007805801C41", +"000000067F000080000006000C00000A8000-000000067F000080000006000C00000AC000__0000007739203FF0", +"000000067F000080000006000C00000AA371-000000067F000080000006000C00000B3AD7__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C00000AC000-000000067F000080000006000C00000B0000__0000007739203FF0", +"000000067F000080000006000C00000B0000-000000067F000080000006000C00000B4000__0000007739203FF0", +"000000067F000080000006000C00000B3AD7-000000067F000080000006000C00000BD20B__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C00000B4000-000000067F000080000006000C00000B8000__0000007739203FF0", +"000000067F000080000006000C00000B8000-000000067F000080000006000C00000BC000__0000007739203FF0", +"000000067F000080000006000C00000BC000-000000067F000080000006000C00000C0000__0000007739203FF0", +"000000067F000080000006000C00000BD20B-000000067F000080000006000C0100000000__00000075E915EBC9-00000076A8CDE8F9", +"000000067F000080000006000C00000C0000-000000067F000080000006000C00000C4000__0000007739203FF0", +"000000067F000080000006000C00000C3C38-000000067F00008000000600140000001B38__00000077391A8001-00000077B2AD0F91", +"000000067F000080000006000C00000C4000-000000067F000080000006000C00000C8000__0000007739203FF0", +"000000067F000080000006000C00000C56C1-000000067F000080000006000C00000CEE0A__00000076A8CDE8F9-00000077391A8001", +"000000067F000080000006000C00000C8000-000000067F000080000006000C00000CC000__0000007739203FF0", +"000000067F000080000006000C00000CC000-000000067F000080000006000C00000D0000__0000007739203FF0", +"000000067F000080000006000C00000CEE0A-000000067F000080000006000C00000D8520__00000076A8CDE8F9-00000077391A8001", +"000000067F000080000006000C00000D0000-000000067F000080000006000C00000D4000__0000007739203FF0", +"000000067F000080000006000C00000D4000-000000067F000080000006000C00000D8000__0000007739203FF0", +"000000067F000080000006000C00000D8000-000000067F000080000006000C00000DC000__0000007739203FF0", +"000000067F000080000006000C00000D8520-000000067F000080000006000C00000E1C86__00000076A8CDE8F9-00000077391A8001", +"000000067F000080000006000C00000DC000-000000067F000080000006000C00000E0000__0000007739203FF0", +"000000067F000080000006000C00000E0000-000000067F000080000006000C00000E4000__0000007739203FF0", +"000000067F000080000006000C00000E1C86-000000067F000080000006000C00000EB3EC__00000076A8CDE8F9-00000077391A8001", +"000000067F000080000006000C00000E4000-000000067F000080000006000C00000E8000__0000007739203FF0", +"000000067F000080000006000C00000E8000-000000067F000080000006000C00000EC000__0000007739203FF0", +"000000067F000080000006000C00000EB3EC-000000067F000080000006000C00000F4B0C__00000076A8CDE8F9-00000077391A8001", +"000000067F000080000006000C00000EC000-000000067F000080000006000C00000F0000__0000007739203FF0", +"000000067F000080000006000C00000F0000-000000067F000080000006000C00000F4000__0000007739203FF0", +"000000067F000080000006000C00000F4000-000000067F000080000006000C00000F8000__0000007739203FF0", +"000000067F000080000006000C00000F4B0C-000000067F000080000006000C00000FE272__00000076A8CDE8F9-00000077391A8001", +"000000067F000080000006000C00000F7C96-000000067F0000800000060014000000F3A9__00000077B2AD0F91-0000007805801C41", +"000000067F000080000006000C00000F8000-000000067F000080000006000C00000FC000__0000007739203FF0", +"000000067F000080000006000C00000FC000-000000067F000080000006000C0000100000__0000007739203FF0", +"000000067F000080000006000C00000FE272-000000067F000080000006000C000010798F__00000076A8CDE8F9-00000077391A8001", +"000000067F000080000006000C0000100000-000000067F000080000006000C0000104000__0000007739203FF0", +"000000067F000080000006000C0000104000-000000067F000080000006000C0000108000__0000007739203FF0", +"000000067F000080000006000C000010798F-000000067F000080000006000C00001110F5__00000076A8CDE8F9-00000077391A8001", +"000000067F000080000006000C0000108000-000000067F000080000006000C000010C000__0000007739203FF0", +"000000067F000080000006000C000010C000-000000067F000080000006000C0000110000__0000007739203FF0", +"000000067F000080000006000C0000110000-030000000000000000000000000000000002__0000007739203FF0", +"000000067F000080000006000C00001110F5-010000000000000001000000030000000006__00000076A8CDE8F9-00000077391A8001", +"000000067F00008000000600140000001B38-000000067F00008000000600140000008758__00000077391A8001-00000077B2AD0F91", +"000000067F00008000000600140000008758-000000067F0000800000060014000000F32F__00000077391A8001-00000077B2AD0F91", +"000000067F0000800000060014000000F32F-000000067F00008000000600140000015EDC__00000077391A8001-00000077B2AD0F91", +"000000067F0000800000060014000000F3A9-000000067F00008000000600140000028656__00000077B2AD0F91-0000007805801C41", +"000000067F00008000000600140000015EDC-000000067F0000800000060014000001CB12__00000077391A8001-00000077B2AD0F91", +"000000067F0000800000060014000001CB12-000000067F000080000006001400000236BC__00000077391A8001-00000077B2AD0F91", +"000000067F000080000006001400000236BC-000000067F0000800000060014000002A294__00000077391A8001-00000077B2AD0F91", +"000000067F00008000000600140000028657-030000000000000000000000000000000002__00000077B2AD0F91-0000007805801C41", +"000000067F0000800000060014000002A294-030000000000000000000000000000000002__00000077391A8001-00000077B2AD0F91", +"000000067F000080000006200C0000000000-000000067F000080000006200C0000004000__00000078B2CB1C68", +"000000067F000080000006200C0000004000-000000067F000080000006200C0000008000__00000078B2CB1C68", +"000000067F000080000006200C0000008000-000000067F000080000006200C000000C000__00000078B2CB1C68", +"000000067F000080000006200C0000009441-000000067F000080000006200C0000012B8D__0000007805801C41-00000078859FEA11", +"000000067F000080000006200C000000C000-000000067F000080000006200C0000010000__00000078B2CB1C68", +"000000067F000080000006200C0000010000-000000067F000080000006200C0000014000__00000078B2CB1C68", +"000000067F000080000006200C0000012B8D-000000067F000080000006200C000001C2F3__0000007805801C41-00000078859FEA11", +"000000067F000080000006200C0000014000-000000067F000080000006200C0000018000__00000078B2CB1C68", +"000000067F000080000006200C0000018000-000000067F000080000006200C000001C000__00000078B2CB1C68", +"000000067F000080000006200C000001C000-000000067F000080000006200C0000020000__00000078B2CB1C68", +"000000067F000080000006200C000001C2F3-000000067F000080000006200C0000025A0C__0000007805801C41-00000078859FEA11", +"000000067F000080000006200C0000020000-000000067F000080000006200C0000024000__00000078B2CB1C68", +"000000067F000080000006200C0000024000-000000067F000080000006200C0000028000__00000078B2CB1C68", +"000000067F000080000006200C0000025A0C-000000067F000080000006200C000002F172__0000007805801C41-00000078859FEA11", +"000000067F000080000006200C0000028000-000000067F000080000006200C000002C000__00000078B2CB1C68", +"000000067F000080000006200C000002C000-000000067F000080000006200C0000030000__00000078B2CB1C68", +"000000067F000080000006200C000002F172-000000067F000080000006200C00000388D8__0000007805801C41-00000078859FEA11", +"000000067F000080000006200C0000030000-000000067F000080000006200C0000034000__00000078B2CB1C68", +"000000067F000080000006200C0000034000-000000067F000080000006200C0000038000__00000078B2CB1C68", +"000000067F000080000006200C0000038000-000000067F000080000006200C000003C000__00000078B2CB1C68", +"000000067F000080000006200C00000388D8-000000067F000080000006200C0000042009__0000007805801C41-00000078859FEA11", +"000000067F000080000006200C000003C000-000000067F000080000006200C0000040000__00000078B2CB1C68", +"000000067F000080000006200C0000040000-000000067F000080000006200C0000044000__00000078B2CB1C68", +"000000067F000080000006200C0000042009-000000067F000080000006200C000004B76F__0000007805801C41-00000078859FEA11", +"000000067F000080000006200C0000044000-000000067F000080000006200C0000048000__00000078B2CB1C68", +"000000067F000080000006200C0000048000-000000067F000080000006200C000004C000__00000078B2CB1C68", +"000000067F000080000006200C0000048000-000000067F000080000006200C000004C000__0000007AA0A6FB48", +"000000067F000080000006200C0000048121-000000067F000080000006200C0000090C08__0000007A3F679FA1-0000007AA1DF6639", +"000000067F000080000006200C000004B76F-030000000000000000000000000000000002__0000007805801C41-00000078859FEA11", +"000000067F000080000006200C000004BAC9-000000067F000080000006200C00000551FE__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C000004C000-000000067F000080000006200C0000050000__00000078B2CB1C68", +"000000067F000080000006200C000004C000-000000067F000080000006200C0000050000__0000007AA0A6FB48", +"000000067F000080000006200C0000050000-000000067F000080000006200C0000054000__00000078B2CB1C68", +"000000067F000080000006200C0000050000-000000067F000080000006200C0000054000__0000007AA0A6FB48", +"000000067F000080000006200C0000054000-000000067F000080000006200C0000058000__00000078B2CB1C68", +"000000067F000080000006200C0000054000-000000067F000080000006200C0000058000__0000007AA0A6FB48", +"000000067F000080000006200C00000551FE-000000067F000080000006200C000005E90C__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C0000058000-000000067F000080000006200C000005C000__00000078B2CB1C68", +"000000067F000080000006200C0000058000-000000067F000080000006200C000005C000__0000007AA0A6FB48", +"000000067F000080000006200C000005C000-000000067F000080000006200C0000060000__00000078B2CB1C68", +"000000067F000080000006200C000005C000-000000067F000080000006200C0000060000__0000007AA0A6FB48", +"000000067F000080000006200C000005E90C-000000067F000080000006200C000006802C__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C0000060000-000000067F000080000006200C0000064000__00000078B2CB1C68", +"000000067F000080000006200C0000060000-000000067F000080000006200C0000064000__0000007AA0A6FB48", +"000000067F000080000006200C0000064000-000000067F000080000006200C0000068000__0000007AA0A6FB48", +"000000067F000080000006200C0000064000-030000000000000000000000000000000002__00000078B2CB1C68", +"000000067F000080000006200C0000068000-000000067F000080000006200C000006C000__0000007AA0A6FB48", +"000000067F000080000006200C000006802C-000000067F000080000006200C0000071783__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C000006C000-000000067F000080000006200C0000070000__0000007AA0A6FB48", +"000000067F000080000006200C0000070000-000000067F000080000006200C0000074000__0000007AA0A6FB48", +"000000067F000080000006200C0000071783-000000067F000080000006200C000007AEE9__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C0000074000-000000067F000080000006200C0000078000__0000007AA0A6FB48", +"000000067F000080000006200C0000078000-000000067F000080000006200C000007C000__0000007AA0A6FB48", +"000000067F000080000006200C000007AEE9-000000067F000080000006200C000008460B__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C000007C000-000000067F000080000006200C0000080000__0000007AA0A6FB48", +"000000067F000080000006200C0000080000-000000067F000080000006200C0000084000__0000007AA0A6FB48", +"000000067F000080000006200C0000084000-000000067F000080000006200C0000088000__0000007AA0A6FB48", +"000000067F000080000006200C000008460B-000000067F000080000006200C000008DD71__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C0000088000-000000067F000080000006200C000008C000__0000007AA0A6FB48", +"000000067F000080000006200C000008C000-000000067F000080000006200C0000090000__0000007AA0A6FB48", +"000000067F000080000006200C000008DD71-000000067F000080000006200C00000974D7__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C0000090000-000000067F000080000006200C0000094000__0000007AA0A6FB48", +"000000067F000080000006200C0000090C11-000000067F000080000006200C00000DA35B__0000007A3F679FA1-0000007AA1DF6639", +"000000067F000080000006200C0000094000-000000067F000080000006200C0000098000__0000007AA0A6FB48", +"000000067F000080000006200C00000974D7-000000067F000080000006200C00000A0C0B__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C0000098000-000000067F000080000006200C000009C000__0000007AA0A6FB48", +"000000067F000080000006200C000009C000-000000067F000080000006200C00000A0000__0000007AA0A6FB48", +"000000067F000080000006200C00000A0000-000000067F000080000006200C00000A4000__0000007AA0A6FB48", +"000000067F000080000006200C00000A0C0B-000000067F000080000006200C00000AA371__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C00000A4000-000000067F000080000006200C00000A8000__0000007AA0A6FB48", +"000000067F000080000006200C00000A8000-000000067F000080000006200C00000AC000__0000007AA0A6FB48", +"000000067F000080000006200C00000AA371-000000067F000080000006200C00000B3AD7__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C00000AC000-000000067F000080000006200C00000B0000__0000007AA0A6FB48", +"000000067F000080000006200C00000B0000-000000067F000080000006200C00000B4000__0000007AA0A6FB48", +"000000067F000080000006200C00000B3AD7-000000067F000080000006200C00000BD20B__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C00000B4000-000000067F000080000006200C00000B8000__0000007AA0A6FB48", +"000000067F000080000006200C00000B8000-000000067F000080000006200C00000BC000__0000007AA0A6FB48", +"000000067F000080000006200C00000BC000-000000067F000080000006200C00000C0000__0000007AA0A6FB48", +"000000067F000080000006200C00000BD20B-000000067F000080000006200C00000C6932__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C00000C0000-000000067F000080000006200C00000C4000__0000007AA0A6FB48", +"000000067F000080000006200C00000C4000-000000067F000080000006200C00000C8000__0000007AA0A6FB48", +"000000067F000080000006200C00000C6932-000000067F000080000006200C00000D0098__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C00000C8000-000000067F000080000006200C00000CC000__0000007AA0A6FB48", +"000000067F000080000006200C00000CC000-000000067F000080000006200C00000D0000__0000007AA0A6FB48", +"000000067F000080000006200C00000D0000-000000067F000080000006200C00000D4000__0000007AA0A6FB48", +"000000067F000080000006200C00000D0098-000000067F000080000006200C00000D97FE__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C00000D4000-000000067F000080000006200C00000D8000__0000007AA0A6FB48", +"000000067F000080000006200C00000D8000-000000067F000080000006200C00000DC000__0000007AA0A6FB48", +"000000067F000080000006200C00000D97FE-000000067F000080000006200C00000E2F0B__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C00000DA36C-000000067F00008000000620140000002D07__0000007A3F679FA1-0000007AA1DF6639", +"000000067F000080000006200C00000DC000-000000067F000080000006200C00000E0000__0000007AA0A6FB48", +"000000067F000080000006200C00000E0000-000000067F000080000006200C00000E4000__0000007AA0A6FB48", +"000000067F000080000006200C00000E2F0B-000000067F000080000006200C00000EC671__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C00000E4000-000000067F000080000006200C00000E8000__0000007AA0A6FB48", +"000000067F000080000006200C00000E8000-000000067F000080000006200C00000EC000__0000007AA0A6FB48", +"000000067F000080000006200C00000EC000-000000067F000080000006200C00000F0000__0000007AA0A6FB48", +"000000067F000080000006200C00000EC671-000000067F000080000006200C00000F5D9F__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C00000F0000-000000067F000080000006200C00000F4000__0000007AA0A6FB48", +"000000067F000080000006200C00000F4000-000000067F000080000006200C00000F8000__0000007AA0A6FB48", +"000000067F000080000006200C00000F5D9F-000000067F000080000006200C00000FF505__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C00000F8000-000000067F000080000006200C00000FC000__0000007AA0A6FB48", +"000000067F000080000006200C00000FC000-000000067F000080000006200C0000100000__0000007AA0A6FB48", +"000000067F000080000006200C00000FF505-000000067F000080000006200C0000108C10__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C0000100000-000000067F000080000006200C0000104000__0000007AA0A6FB48", +"000000067F000080000006200C0000104000-000000067F000080000006200C0000108000__0000007AA0A6FB48", +"000000067F000080000006200C0000107883-000000067F000080000006200C01000000AF__00000079C527F0D9-0000007A3F679FA1", +"000000067F000080000006200C0000108000-000000067F000080000006200C000010C000__0000007AA0A6FB48", +"000000067F000080000006200C0000108C10-000000067F000080000006200C0100000000__00000078859FEA11-00000079C527F0D9", +"000000067F000080000006200C000010C000-000000067F000080000006200C0000110000__0000007AA0A6FB48", +"000000067F000080000006200C0000110000-000000067F00008000000620120100000000__0000007AA0A6FB48", +"000000067F000080000006200C01000000AF-000000067F00008000000620140000004888__00000079C527F0D9-0000007A3F679FA1", +"000000067F00008000000620140000002D0A-000000067F00008000000620140000016355__0000007A3F679FA1-0000007AA1DF6639", +"000000067F00008000000620140000004888-000000067F0000800000062014000000BC11__00000079C527F0D9-0000007A3F679FA1", +"000000067F0000800000062014000000BC11-000000067F00008000000620140000012FA7__00000079C527F0D9-0000007A3F679FA1", +"000000067F00008000000620140000012FA7-000000067F0000800000062014000001A33D__00000079C527F0D9-0000007A3F679FA1", +"000000067F00008000000620140000016357-000000067F00008000000620140000029C35__0000007A3F679FA1-0000007AA1DF6639", +"000000067F0000800000062014000001A33D-000000067F000080000006201400000216B4__00000079C527F0D9-0000007A3F679FA1", +"000000067F000080000006201400000216B4-000000067F00008000000620140000028A65__00000079C527F0D9-0000007A3F679FA1", +"000000067F00008000000620140000028A65-030000000000000000000000000000000002__00000079C527F0D9-0000007A3F679FA1", +"000000067F00008000000620140000029C38-030000000000000000000000000000000002__0000007A3F679FA1-0000007AA1DF6639", +"000000067F000080000006400C0000000000-000000067F000080000006400C0000004000__0000007B9877EF40", +"000000067F000080000006400C0000000000-000000067F000080000006400C0000004000__0000007D41715570", +"000000067F000080000006400C0000004000-000000067F000080000006400C0000008000__0000007B9877EF40", +"000000067F000080000006400C0000004000-000000067F000080000006400C0000008000__0000007D41715570", +"000000067F000080000006400C0000007987-000000067F000080000006400C00000110ED__0000007AA1DF6639-0000007B14D5C521", +"000000067F000080000006400C0000008000-000000067F000080000006400C000000C000__0000007B9877EF40", +"000000067F000080000006400C0000008000-000000067F000080000006400C000000C000__0000007D41715570", +"000000067F000080000006400C000000C000-000000067F000080000006400C0000010000__0000007B9877EF40", +"000000067F000080000006400C000000C000-000000067F000080000006400C0000010000__0000007D41715570", +"000000067F000080000006400C0000010000-000000067F000080000006400C0000014000__0000007B9877EF40", +"000000067F000080000006400C0000010000-000000067F000080000006400C0000014000__0000007D41715570", +"000000067F000080000006400C00000110ED-000000067F000080000006400C000001A80A__0000007AA1DF6639-0000007B14D5C521", +"000000067F000080000006400C0000014000-000000067F000080000006400C0000018000__0000007B9877EF40", +"000000067F000080000006400C0000014000-000000067F000080000006400C0000018000__0000007D41715570", +"000000067F000080000006400C0000018000-000000067F000080000006400C000001C000__0000007B9877EF40", +"000000067F000080000006400C0000018000-000000067F000080000006400C000001C000__0000007D41715570", +"000000067F000080000006400C000001A80A-000000067F000080000006400C0000023F4A__0000007AA1DF6639-0000007B14D5C521", +"000000067F000080000006400C000001C000-000000067F000080000006400C0000020000__0000007B9877EF40", +"000000067F000080000006400C000001C000-000000067F000080000006400C0000020000__0000007D41715570", +"000000067F000080000006400C0000020000-000000067F000080000006400C0000024000__0000007B9877EF40", +"000000067F000080000006400C0000020000-000000067F000080000006400C0000024000__0000007D41715570", +"000000067F000080000006400C0000023F4A-000000067F000080000006400C000002D6B0__0000007AA1DF6639-0000007B14D5C521", +"000000067F000080000006400C0000024000-000000067F000080000006400C0000028000__0000007B9877EF40", +"000000067F000080000006400C0000024000-000000067F000080000006400C0000028000__0000007D41715570", +"000000067F000080000006400C0000028000-000000067F000080000006400C000002C000__0000007B9877EF40", +"000000067F000080000006400C0000028000-000000067F000080000006400C000002C000__0000007D41715570", +"000000067F000080000006400C000002C000-000000067F000080000006400C0000030000__0000007B9877EF40", +"000000067F000080000006400C000002C000-000000067F000080000006400C0000030000__0000007D41715570", +"000000067F000080000006400C000002D6B0-000000067F000080000006400C0000036DD4__0000007AA1DF6639-0000007B14D5C521", +"000000067F000080000006400C0000030000-000000067F000080000006400C0000034000__0000007B9877EF40", +"000000067F000080000006400C0000030000-000000067F000080000006400C0000034000__0000007D41715570", +"000000067F000080000006400C0000034000-000000067F000080000006400C0000038000__0000007B9877EF40", +"000000067F000080000006400C0000034000-000000067F000080000006400C0000038000__0000007D41715570", +"000000067F000080000006400C0000036DD4-000000067F000080000006400C000004050A__0000007AA1DF6639-0000007B14D5C521", +"000000067F000080000006400C0000038000-000000067F000080000006400C000003C000__0000007B9877EF40", +"000000067F000080000006400C0000038000-000000067F000080000006400C000003C000__0000007D41715570", +"000000067F000080000006400C000003C000-000000067F000080000006400C0000040000__0000007B9877EF40", +"000000067F000080000006400C000003C000-000000067F000080000006400C0000040000__0000007D41715570", +"000000067F000080000006400C0000040000-000000067F000080000006400C0000044000__0000007B9877EF40", +"000000067F000080000006400C0000040000-000000067F000080000006400C0000044000__0000007D41715570", +"000000067F000080000006400C000004050A-030000000000000000000000000000000002__0000007AA1DF6639-0000007B14D5C521", +"000000067F000080000006400C0000044000-000000067F000080000006400C0000048000__0000007B9877EF40", +"000000067F000080000006400C0000044000-000000067F000080000006400C0000048000__0000007D41715570", +"000000067F000080000006400C0000048000-000000067F000080000006400C000004C000__0000007B9877EF40", +"000000067F000080000006400C0000048000-000000067F000080000006400C000004C000__0000007D41715570", +"000000067F000080000006400C000004B4C9-000000067F000080000006400C0000054C01__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C000004C000-000000067F000080000006400C0000050000__0000007B9877EF40", +"000000067F000080000006400C000004C000-000000067F000080000006400C0000050000__0000007D41715570", +"000000067F000080000006400C0000050000-000000067F000080000006400C0000054000__0000007B9877EF40", +"000000067F000080000006400C0000050000-000000067F000080000006400C0000054000__0000007D41715570", +"000000067F000080000006400C00000525C4-000000067F000080000006400C00000A47A7__0000007CEE5A0B91-0000007D41EA8D51", +"000000067F000080000006400C0000054000-000000067F000080000006400C0000058000__0000007B9877EF40", +"000000067F000080000006400C0000054000-000000067F000080000006400C0000058000__0000007D41715570", +"000000067F000080000006400C0000054C01-000000067F000080000006400C000005E30C__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C0000058000-000000067F000080000006400C000005C000__0000007B9877EF40", +"000000067F000080000006400C0000058000-000000067F000080000006400C000005C000__0000007D41715570", +"000000067F000080000006400C000005C000-000000067F000080000006400C0000060000__0000007B9877EF40", +"000000067F000080000006400C000005C000-000000067F000080000006400C0000060000__0000007D41715570", +"000000067F000080000006400C000005E30C-000000067F000080000006400C0000067A2C__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C0000060000-000000067F000080000006400C0000064000__0000007B9877EF40", +"000000067F000080000006400C0000060000-000000067F000080000006400C0000064000__0000007D41715570", +"000000067F000080000006400C0000064000-000000067F000080000006400C0000068000__0000007B9877EF40", +"000000067F000080000006400C0000064000-000000067F000080000006400C0000068000__0000007D41715570", +"000000067F000080000006400C0000067A2C-000000067F000080000006400C0000071187__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C0000068000-000000067F000080000006400C000006C000__0000007B9877EF40", +"000000067F000080000006400C0000068000-000000067F000080000006400C000006C000__0000007D41715570", +"000000067F000080000006400C000006C000-000000067F000080000006400C0000070000__0000007B9877EF40", +"000000067F000080000006400C000006C000-000000067F000080000006400C0000070000__0000007D41715570", +"000000067F000080000006400C0000070000-000000067F000080000006400C0000074000__0000007B9877EF40", +"000000067F000080000006400C0000070000-000000067F000080000006400C0000074000__0000007D41715570", +"000000067F000080000006400C0000071187-000000067F000080000006400C000007A8ED__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C0000074000-000000067F000080000006400C0000078000__0000007B9877EF40", +"000000067F000080000006400C0000074000-000000067F000080000006400C0000078000__0000007D41715570", +"000000067F000080000006400C0000078000-000000067F000080000006400C000007C000__0000007B9877EF40", +"000000067F000080000006400C0000078000-000000067F000080000006400C000007C000__0000007D41715570", +"000000067F000080000006400C000007A8ED-000000067F000080000006400C000008400B__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C000007C000-000000067F000080000006400C0000080000__0000007B9877EF40", +"000000067F000080000006400C000007C000-000000067F000080000006400C0000080000__0000007D41715570", +"000000067F000080000006400C0000080000-000000067F000080000006400C0000084000__0000007B9877EF40", +"000000067F000080000006400C0000080000-000000067F000080000006400C0000084000__0000007D41715570", +"000000067F000080000006400C0000084000-000000067F000080000006400C0000088000__0000007B9877EF40", +"000000067F000080000006400C0000084000-000000067F000080000006400C0000088000__0000007D41715570", +"000000067F000080000006400C000008400B-000000067F000080000006400C000008D771__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C0000088000-000000067F000080000006400C000008C000__0000007B9877EF40", +"000000067F000080000006400C0000088000-000000067F000080000006400C000008C000__0000007D41715570", +"000000067F000080000006400C000008C000-000000067F000080000006400C0000090000__0000007B9877EF40", +"000000067F000080000006400C000008C000-000000067F000080000006400C0000090000__0000007D41715570", +"000000067F000080000006400C000008D771-000000067F000080000006400C0000096ED7__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C0000090000-000000067F000080000006400C0000094000__0000007D41715570", +"000000067F000080000006400C0000090000-030000000000000000000000000000000002__0000007B9877EF40", +"000000067F000080000006400C0000094000-000000067F000080000006400C0000098000__0000007D41715570", +"000000067F000080000006400C0000096ED7-000000067F000080000006400C00000A060B__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C0000098000-000000067F000080000006400C000009C000__0000007D41715570", +"000000067F000080000006400C000009C000-000000067F000080000006400C00000A0000__0000007D41715570", +"000000067F000080000006400C00000A0000-000000067F000080000006400C00000A4000__0000007D41715570", +"000000067F000080000006400C00000A060B-000000067F000080000006400C00000A9D71__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C00000A4000-000000067F000080000006400C00000A8000__0000007D41715570", +"000000067F000080000006400C00000A47B1-000000067F000080000006400C00000F593E__0000007CEE5A0B91-0000007D41EA8D51", +"000000067F000080000006400C00000A8000-000000067F000080000006400C00000AC000__0000007D41715570", +"000000067F000080000006400C00000A887C-000000067F000080000006400C020000001F__0000007C73B53FC9-0000007CEE5A0B91", +"000000067F000080000006400C00000A9D71-000000067F000080000006400C00000B34D7__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C00000AC000-000000067F000080000006400C00000B0000__0000007D41715570", +"000000067F000080000006400C00000B0000-000000067F000080000006400C00000B4000__0000007D41715570", +"000000067F000080000006400C00000B34D7-000000067F000080000006400C00000BCC0C__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C00000B4000-000000067F000080000006400C00000B8000__0000007D41715570", +"000000067F000080000006400C00000B8000-000000067F000080000006400C00000BC000__0000007D41715570", +"000000067F000080000006400C00000BC000-000000067F000080000006400C00000C0000__0000007D41715570", +"000000067F000080000006400C00000BCC0C-000000067F000080000006400C00000C6336__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C00000C0000-000000067F000080000006400C00000C4000__0000007D41715570", +"000000067F000080000006400C00000C4000-000000067F000080000006400C00000C8000__0000007D41715570", +"000000067F000080000006400C00000C6336-000000067F000080000006400C00000CFA9C__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C00000C8000-000000067F000080000006400C00000CC000__0000007D41715570", +"000000067F000080000006400C00000CC000-000000067F000080000006400C00000D0000__0000007D41715570", +"000000067F000080000006400C00000CFA9C-000000067F000080000006400C00000D91AB__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C00000D0000-000000067F000080000006400C00000D4000__0000007D41715570", +"000000067F000080000006400C00000D4000-000000067F000080000006400C00000D8000__0000007D41715570", +"000000067F000080000006400C00000D8000-000000067F000080000006400C00000DC000__0000007D41715570", +"000000067F000080000006400C00000D91AB-000000067F000080000006400C00000E2911__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C00000DC000-000000067F000080000006400C00000E0000__0000007D41715570", +"000000067F000080000006400C00000E0000-000000067F000080000006400C00000E4000__0000007D41715570", +"000000067F000080000006400C00000E2911-000000067F000080000006400C00000EC077__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C00000E4000-000000067F000080000006400C00000E8000__0000007D41715570", +"000000067F000080000006400C00000E8000-000000067F000080000006400C00000EC000__0000007D41715570", +"000000067F000080000006400C00000EC000-000000067F000080000006400C00000F0000__0000007D41715570", +"000000067F000080000006400C00000EC077-000000067F000080000006400C00000F57A8__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C00000F0000-000000067F000080000006400C00000F4000__0000007D41715570", +"000000067F000080000006400C00000F4000-000000067F000080000006400C00000F8000__0000007D41715570", +"000000067F000080000006400C00000F57A8-000000067F000080000006400C00000FEF0A__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C00000F5940-000000067F0000800000064014000000E7FF__0000007CEE5A0B91-0000007D41EA8D51", +"000000067F000080000006400C00000F8000-000000067F000080000006400C00000FC000__0000007D41715570", +"000000067F000080000006400C00000FC000-000000067F000080000006400C0000100000__0000007D41715570", +"000000067F000080000006400C00000FEF0A-000000067F000080000006400C000010862B__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C0000100000-000000067F000080000006400C0000104000__0000007D41715570", +"000000067F000080000006400C0000104000-000000067F000080000006400C0000108000__0000007D41715570", +"000000067F000080000006400C0000108000-000000067F000080000006400C000010C000__0000007D41715570", +"000000067F000080000006400C000010862B-000000067F000080000006400C0000111C20__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C000010C000-000000067F000080000006400C0000110000__0000007D41715570", +"000000067F000080000006400C0000110000-000000067F00008000000640120100000000__0000007D41715570", +"000000067F000080000006400C00FFFFFFFF-01000000000000000100000003000000000D__0000007B14D5C521-0000007C73B53FC9", +"000000067F000080000006400C020000001F-000000067F0000800000064014000000691F__0000007C73B53FC9-0000007CEE5A0B91", +"000000067F00008000000640140000000000-000000067F00008000000640140000004000__0000007D41715570", +"000000067F00008000000640140000004000-000000067F00008000000640140000008000__0000007D41715570", +"000000067F0000800000064014000000691F-000000067F0000800000064014000000D68F__0000007C73B53FC9-0000007CEE5A0B91", +"000000067F00008000000640140000008000-000000067F0000800000064014000000C000__0000007D41715570", +"000000067F0000800000064014000000C000-000000067F00008000000640140000010000__0000007D41715570", +"000000067F0000800000064014000000D68F-000000067F00008000000640140000014406__0000007C73B53FC9-0000007CEE5A0B91", +"000000067F0000800000064014000000E803-000000067F000080000006401400000274BB__0000007CEE5A0B91-0000007D41EA8D51", +"000000067F00008000000640140000010000-000000067F00008000000640140000014000__0000007D41715570", +"000000067F00008000000640140000014000-000000067F00008000000640140000018000__0000007D41715570", +"000000067F00008000000640140000014406-000000067F0000800000064014000001B192__0000007C73B53FC9-0000007CEE5A0B91", +"000000067F00008000000640140000018000-000000067F0000800000064014000001C000__0000007D41715570", +"000000067F0000800000064014000001B192-000000067F00008000000640140000021F03__0000007C73B53FC9-0000007CEE5A0B91", +"000000067F0000800000064014000001C000-000000067F00008000000640140000020000__0000007D41715570", +"000000067F00008000000640140000020000-000000067F00008000000640140000024000__0000007D41715570", +"000000067F00008000000640140000021F03-000000067F00008000000640140000028C6A__0000007C73B53FC9-0000007CEE5A0B91", +"000000067F00008000000640140000024000-000000067F00008000000640140000028000__0000007D41715570", +"000000067F000080000006401400000274BF-030000000000000000000000000000000002__0000007CEE5A0B91-0000007D41EA8D51", +"000000067F00008000000640140000028000-000000067F0000800000064014000002C000__0000007D41715570", +"000000067F00008000000640140000028C6A-030000000000000000000000000000000002__0000007C73B53FC9-0000007CEE5A0B91", +"000000067F0000800000064014000002C000-030000000000000000000000000000000002__0000007D41715570", +"000000067F000080000006600C0000000000-000000067F000080000006600C0000004000__0000007F12B83FE8", +"000000067F000080000006600C0000004000-000000067F000080000006600C0000008000__0000007F12B83FE8", +"000000067F000080000006600C0000008000-000000067F000080000006600C000000C000__0000007F12B83FE8", +"000000067F000080000006600C0000009381-000000067F000080000006600C0000012AE7__0000007D41EA8D51-0000007DC21DE569", +"000000067F000080000006600C000000C000-000000067F000080000006600C0000010000__0000007F12B83FE8", +"000000067F000080000006600C0000010000-000000067F000080000006600C0000014000__0000007F12B83FE8", +"000000067F000080000006600C0000012AE7-000000067F000080000006600C000001C20B__0000007D41EA8D51-0000007DC21DE569", +"000000067F000080000006600C0000014000-000000067F000080000006600C0000018000__0000007F12B83FE8", +"000000067F000080000006600C0000018000-000000067F000080000006600C000001C000__0000007F12B83FE8", +"000000067F000080000006600C000001C000-000000067F000080000006600C0000020000__0000007F12B83FE8", +"000000067F000080000006600C000001C20B-000000067F000080000006600C000002593B__0000007D41EA8D51-0000007DC21DE569", +"000000067F000080000006600C0000020000-000000067F000080000006600C0000024000__0000007F12B83FE8", +"000000067F000080000006600C0000024000-000000067F000080000006600C0000028000__0000007F12B83FE8", +"000000067F000080000006600C000002593B-000000067F000080000006600C000002F0A1__0000007D41EA8D51-0000007DC21DE569", +"000000067F000080000006600C0000028000-000000067F000080000006600C000002C000__0000007F12B83FE8", +"000000067F000080000006600C000002C000-000000067F000080000006600C0000030000__0000007F12B83FE8", +"000000067F000080000006600C000002F0A1-000000067F000080000006600C00000387B6__0000007D41EA8D51-0000007DC21DE569", +"000000067F000080000006600C0000030000-000000067F000080000006600C0000034000__0000007F12B83FE8", +"000000067F000080000006600C0000034000-000000067F000080000006600C0000038000__0000007F12B83FE8", +"000000067F000080000006600C0000038000-000000067F000080000006600C000003C000__0000007F12B83FE8", +"000000067F000080000006600C00000387B6-000000067F000080000006600C0000041F1C__0000007D41EA8D51-0000007DC21DE569", +"000000067F000080000006600C000003C000-000000067F000080000006600C0000040000__0000007F12B83FE8", +"000000067F000080000006600C0000040000-000000067F000080000006600C0000044000__0000007F12B83FE8", +"000000067F000080000006600C0000041F1C-000000067F000080000006600C000004B682__0000007D41EA8D51-0000007DC21DE569", +"000000067F000080000006600C0000044000-000000067F000080000006600C0000048000__0000007F12B83FE8", +"000000067F000080000006600C0000048000-000000067F000080000006600C000004C000__0000007F108C1FD8", +"000000067F000080000006600C0000048000-000000067F000080000006600C000004C000__0000007FDCA75700", +"000000067F000080000006600C0000049743-000000067F000080000006600C0000093532__0000007F7BE4E6F1-0000007FDCDCE659", +"000000067F000080000006600C000004B682-030000000000000000000000000000000002__0000007D41EA8D51-0000007DC21DE569", +"000000067F000080000006600C000004BAC3-000000067F000080000006600C00000551F8__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C000004C000-000000067F000080000006600C0000050000__0000007F108C1FD8", +"000000067F000080000006600C000004C000-000000067F000080000006600C0000050000__0000007FDCA75700", +"000000067F000080000006600C0000050000-000000067F000080000006600C0000054000__0000007F108C1FD8", +"000000067F000080000006600C0000050000-000000067F000080000006600C0000054000__0000007FDCA75700", +"000000067F000080000006600C0000054000-000000067F000080000006600C0000058000__0000007F108C1FD8", +"000000067F000080000006600C0000054000-000000067F000080000006600C0000058000__0000007FDCA75700", +"000000067F000080000006600C00000551F8-000000067F000080000006600C000005E90C__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C0000058000-000000067F000080000006600C000005C000__0000007F108C1FD8", +"000000067F000080000006600C0000058000-000000067F000080000006600C000005C000__0000007FDCA75700", +"000000067F000080000006600C000005C000-000000067F000080000006600C0000060000__0000007F108C1FD8", +"000000067F000080000006600C000005C000-000000067F000080000006600C0000060000__0000007FDCA75700", +"000000067F000080000006600C000005E90C-000000067F000080000006600C000006802C__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C0000060000-000000067F000080000006600C0000064000__0000007F108C1FD8", +"000000067F000080000006600C0000060000-000000067F000080000006600C0000064000__0000007FDCA75700", +"000000067F000080000006600C0000064000-000000067F000080000006600C0000068000__0000007F108C1FD8", +"000000067F000080000006600C0000064000-000000067F000080000006600C0000068000__0000007FDCA75700", +"000000067F000080000006600C0000068000-000000067F000080000006600C000006C000__0000007F108C1FD8", +"000000067F000080000006600C0000068000-000000067F000080000006600C000006C000__0000007FDCA75700", +"000000067F000080000006600C000006802C-000000067F000080000006600C0000071783__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C000006C000-000000067F000080000006600C0000070000__0000007F108C1FD8", +"000000067F000080000006600C000006C000-000000067F000080000006600C0000070000__0000007FDCA75700", +"000000067F000080000006600C0000070000-000000067F000080000006600C0000074000__0000007F108C1FD8", +"000000067F000080000006600C0000070000-000000067F000080000006600C0000074000__0000007FDCA75700", +"000000067F000080000006600C0000071783-000000067F000080000006600C000007AEE9__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C0000074000-000000067F000080000006600C0000078000__0000007F108C1FD8", +"000000067F000080000006600C0000074000-000000067F000080000006600C0000078000__0000007FDCA75700", +"000000067F000080000006600C0000078000-000000067F000080000006600C000007C000__0000007F108C1FD8", +"000000067F000080000006600C0000078000-000000067F000080000006600C000007C000__0000007FDCA75700", +"000000067F000080000006600C000007AEE9-000000067F000080000006600C000008460B__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C000007C000-000000067F000080000006600C0000080000__0000007F108C1FD8", +"000000067F000080000006600C000007C000-000000067F000080000006600C0000080000__0000007FDCA75700", +"000000067F000080000006600C0000080000-000000067F000080000006600C0000084000__0000007F108C1FD8", +"000000067F000080000006600C0000080000-000000067F000080000006600C0000084000__0000007FDCA75700", +"000000067F000080000006600C0000084000-000000067F000080000006600C0000088000__0000007F108C1FD8", +"000000067F000080000006600C0000084000-000000067F000080000006600C0000088000__0000007FDCA75700", +"000000067F000080000006600C000008460B-000000067F000080000006600C000008DD71__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C0000088000-000000067F000080000006600C000008C000__0000007F108C1FD8", +"000000067F000080000006600C0000088000-000000067F000080000006600C000008C000__0000007FDCA75700", +"000000067F000080000006600C000008C000-000000067F000080000006600C0000090000__0000007F108C1FD8", +"000000067F000080000006600C000008C000-000000067F000080000006600C0000090000__0000007FDCA75700", +"000000067F000080000006600C000008DD71-000000067F000080000006600C00000974D7__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C0000090000-000000067F000080000006600C0000094000__0000007F108C1FD8", +"000000067F000080000006600C0000090000-000000067F000080000006600C0000094000__0000007FDCA75700", +"000000067F000080000006600C0000093532-000000067F000080000006600C00000DD150__0000007F7BE4E6F1-0000007FDCDCE659", +"000000067F000080000006600C0000094000-000000067F000080000006600C0000098000__0000007F108C1FD8", +"000000067F000080000006600C0000094000-000000067F000080000006600C0000098000__0000007FDCA75700", +"000000067F000080000006600C00000974D7-000000067F000080000006600C00000A0C0B__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C0000098000-000000067F000080000006600C000009C000__0000007F108C1FD8", +"000000067F000080000006600C0000098000-000000067F000080000006600C000009C000__0000007FDCA75700", +"000000067F000080000006600C000009C000-000000067F000080000006600C00000A0000__0000007F108C1FD8", +"000000067F000080000006600C000009C000-000000067F000080000006600C00000A0000__0000007FDCA75700", +"000000067F000080000006600C00000A0000-000000067F000080000006600C00000A4000__0000007F108C1FD8", +"000000067F000080000006600C00000A0000-000000067F000080000006600C00000A4000__0000007FDCA75700", +"000000067F000080000006600C00000A0C0B-000000067F000080000006600C00000AA371__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C00000A4000-000000067F000080000006600C00000A8000__0000007F108C1FD8", +"000000067F000080000006600C00000A4000-000000067F000080000006600C00000A8000__0000007FDCA75700", +"000000067F000080000006600C00000A8000-000000067F000080000006600C00000AC000__0000007F108C1FD8", +"000000067F000080000006600C00000A8000-000000067F000080000006600C00000AC000__0000007FDCA75700", +"000000067F000080000006600C00000AA371-000000067F000080000006600C00000B3AD7__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C00000AC000-000000067F000080000006600C00000B0000__0000007F108C1FD8", +"000000067F000080000006600C00000AC000-000000067F000080000006600C00000B0000__0000007FDCA75700", +"000000067F000080000006600C00000B0000-000000067F000080000006600C00000B4000__0000007F108C1FD8", +"000000067F000080000006600C00000B0000-000000067F000080000006600C00000B4000__0000007FDCA75700", +"000000067F000080000006600C00000B3AD7-000000067F000080000006600C0100000000__0000007DC21DE569-0000007E71DBF8F9", +"000000067F000080000006600C00000B4000-000000067F000080000006600C00000B8000__0000007F108C1FD8", +"000000067F000080000006600C00000B4000-000000067F000080000006600C00000B8000__0000007FDCA75700", +"000000067F000080000006600C00000B8000-000000067F000080000006600C00000BC000__0000007F108C1FD8", +"000000067F000080000006600C00000B8000-000000067F000080000006600C00000BC000__0000007FDCA75700", +"000000067F000080000006600C00000BC000-000000067F000080000006600C00000C0000__0000007F108C1FD8", +"000000067F000080000006600C00000BC000-000000067F000080000006600C00000C0000__0000007FDCA75700", +"000000067F000080000006600C00000BC29F-000000067F000080000006600C00000C59CF__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F000080000006600C00000C0000-000000067F000080000006600C00000C4000__0000007F108C1FD8", +"000000067F000080000006600C00000C0000-000000067F000080000006600C00000C4000__0000007FDCA75700", +"000000067F000080000006600C00000C4000-000000067F000080000006600C00000C8000__0000007F108C1FD8", +"000000067F000080000006600C00000C4000-000000067F000080000006600C00000C8000__0000007FDCA75700", +"000000067F000080000006600C00000C59CF-000000067F000080000006600C00000CF10B__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F000080000006600C00000C8000-000000067F000080000006600C00000CC000__0000007F108C1FD8", +"000000067F000080000006600C00000C8000-000000067F000080000006600C00000CC000__0000007FDCA75700", +"000000067F000080000006600C00000CC000-000000067F000080000006600C00000D0000__0000007F108C1FD8", +"000000067F000080000006600C00000CC000-000000067F000080000006600C00000D0000__0000007FDCA75700", +"000000067F000080000006600C00000CF10B-000000067F000080000006600C00000D882C__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F000080000006600C00000D0000-000000067F000080000006600C00000D4000__0000007F108C1FD8", +"000000067F000080000006600C00000D0000-000000067F000080000006600C00000D4000__0000007FDCA75700", +"000000067F000080000006600C00000D4000-000000067F000080000006600C00000D8000__0000007F108C1FD8", +"000000067F000080000006600C00000D4000-000000067F000080000006600C00000D8000__0000007FDCA75700", +"000000067F000080000006600C00000D8000-000000067F000080000006600C00000DC000__0000007F108C1FD8", +"000000067F000080000006600C00000D8000-000000067F000080000006600C00000DC000__0000007FDCA75700", +"000000067F000080000006600C00000D882C-000000067F000080000006600C00000E1F7F__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F000080000006600C00000DC000-000000067F000080000006600C00000E0000__0000007F108C1FD8", +"000000067F000080000006600C00000DC000-000000067F000080000006600C00000E0000__0000007FDCA75700", +"000000067F000080000006600C00000DD152-000000067F00008000000660140000003DA8__0000007F7BE4E6F1-0000007FDCDCE659", +"000000067F000080000006600C00000E0000-000000067F000080000006600C00000E4000__0000007F108C1FD8", +"000000067F000080000006600C00000E0000-000000067F000080000006600C00000E4000__0000007FDCA75700", +"000000067F000080000006600C00000E1F7F-000000067F000080000006600C00000EB6E5__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F000080000006600C00000E4000-000000067F000080000006600C00000E8000__0000007F108C1FD8", +"000000067F000080000006600C00000E4000-000000067F000080000006600C00000E8000__0000007FDCA75700", +"000000067F000080000006600C00000E8000-000000067F000080000006600C00000EC000__0000007F108C1FD8", +"000000067F000080000006600C00000E8000-000000067F000080000006600C00000EC000__0000007FDCA75700", +"000000067F000080000006600C00000EB6E5-000000067F000080000006600C00000F4E0C__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F000080000006600C00000EC000-000000067F000080000006600C00000F0000__0000007F108C1FD8", +"000000067F000080000006600C00000EC000-000000067F000080000006600C00000F0000__0000007FDCA75700", +"000000067F000080000006600C00000F0000-000000067F000080000006600C00000F4000__0000007F108C1FD8", +"000000067F000080000006600C00000F0000-000000067F000080000006600C00000F4000__0000007FDCA75700", +"000000067F000080000006600C00000F4000-000000067F000080000006600C00000F8000__0000007F108C1FD8", +"000000067F000080000006600C00000F4000-000000067F000080000006600C00000F8000__0000007FDCA75700", +"000000067F000080000006600C00000F4E0C-000000067F000080000006600C00000FE572__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F000080000006600C00000F8000-000000067F000080000006600C00000FC000__0000007F108C1FD8", +"000000067F000080000006600C00000F8000-000000067F000080000006600C00000FC000__0000007FDCA75700", +"000000067F000080000006600C00000FC000-000000067F000080000006600C0000100000__0000007F108C1FD8", +"000000067F000080000006600C00000FC000-000000067F000080000006600C0000100000__0000007FDCA75700", +"000000067F000080000006600C00000FE572-000000067F000080000006600C0000107CD8__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F000080000006600C0000100000-000000067F000080000006600C0000104000__0000007F108C1FD8", +"000000067F000080000006600C0000100000-000000067F000080000006600C0000104000__0000007FDCA75700", +"000000067F000080000006600C0000104000-000000067F000080000006600C0000108000__0000007F108C1FD8", +"000000067F000080000006600C0000104000-000000067F000080000006600C0000108000__0000007FDCA75700", +"000000067F000080000006600C0000107CD8-000000067F000080000006600C000011140B__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F000080000006600C0000108000-000000067F000080000006600C000010C000__0000007F108C1FD8", +"000000067F000080000006600C0000108000-000000067F000080000006600C000010C000__0000007FDCA75700", +"000000067F000080000006600C000010C000-000000067F000080000006600C0000110000__0000007F108C1FD8", +"000000067F000080000006600C000010C000-000000067F000080000006600C0000110000__0000007FDCA75700", +"000000067F000080000006600C0000110000-000000067F00008000000660120100000000__0000007FDCA75700", +"000000067F000080000006600C0000110000-030000000000000000000000000000000002__0000007F108C1FD8", +"000000067F000080000006600C000011140B-010000000000000001000000030000000010__0000007E71DBF8F9-0000007F11E4BFE9", +"000000067F000080000006600C0000111C82-000000067F0000800000066014000000535B__0000007F11E4BFE9-0000007F7BE4E6F1", +"000000067F00008000000660140000000000-000000067F00008000000660140000004000__0000007FDCA75700", +"000000067F00008000000660140000003DAA-000000067F00008000000660140000017C4D__0000007F7BE4E6F1-0000007FDCDCE659", +"000000067F00008000000660140000004000-000000067F00008000000660140000008000__0000007FDCA75700", +"000000067F0000800000066014000000535B-000000067F0000800000066014000000C839__0000007F11E4BFE9-0000007F7BE4E6F1", +"000000067F00008000000660140000008000-000000067F0000800000066014000000C000__0000007FDCA75700", +"000000067F0000800000066014000000C000-000000067F00008000000660140000010000__0000007FDCA75700", +"000000067F0000800000066014000000C839-000000067F00008000000660140000013D42__0000007F11E4BFE9-0000007F7BE4E6F1", +"000000067F00008000000660140000010000-000000067F00008000000660140000014000__0000007FDCA75700", +"000000067F00008000000660140000013D42-000000067F0000800000066014000001B222__0000007F11E4BFE9-0000007F7BE4E6F1", +"000000067F00008000000660140000014000-000000067F00008000000660140000018000__0000007FDCA75700", +"000000067F00008000000660140000017C51-000000067F0000800000066014000002B9D0__0000007F7BE4E6F1-0000007FDCDCE659", +"000000067F00008000000660140000018000-000000067F0000800000066014000001C000__0000007FDCA75700", +"000000067F0000800000066014000001B222-000000067F00008000000660140000022704__0000007F11E4BFE9-0000007F7BE4E6F1", +"000000067F0000800000066014000001C000-000000067F00008000000660140000020000__0000007FDCA75700", +"000000067F00008000000660140000020000-000000067F00008000000660140000024000__0000007FDCA75700", +"000000067F00008000000660140000022704-000000067F00008000000660140000029C2D__0000007F11E4BFE9-0000007F7BE4E6F1", +"000000067F00008000000660140000024000-000000067F00008000000660140000028000__0000007FDCA75700", +"000000067F00008000000660140000028000-000000067F0000800000066014000002C000__0000007FDCA75700", +"000000067F00008000000660140000029C2D-030000000000000000000000000000000002__0000007F11E4BFE9-0000007F7BE4E6F1", +"000000067F0000800000066014000002B9D1-030000000000000000000000000000000002__0000007F7BE4E6F1-0000007FDCDCE659", +"000000067F0000800000066014000002C000-030000000000000000000000000000000002__0000007FDCA75700", +"000000067F000080000006800C0000000000-000000067F000080000006800C0000004000__00000081AFEDBFE0", +"000000067F000080000006800C0000004000-000000067F000080000006800C0000008000__00000081AFEDBFE0", +"000000067F000080000006800C0000007D6A-000000067F000080000006800C00000114D0__0000007FDCDCE659-000000804F6BFFC1", +"000000067F000080000006800C0000008000-000000067F000080000006800C000000C000__00000081AFEDBFE0", +"000000067F000080000006800C000000C000-000000067F000080000006800C0000010000__00000081AFEDBFE0", +"000000067F000080000006800C0000010000-000000067F000080000006800C0000014000__00000081AFEDBFE0", +"000000067F000080000006800C00000114D0-000000067F000080000006800C000001AC0B__0000007FDCDCE659-000000804F6BFFC1", +"000000067F000080000006800C0000014000-000000067F000080000006800C0000018000__00000081AFEDBFE0", +"000000067F000080000006800C0000018000-000000067F000080000006800C000001C000__00000081AFEDBFE0", +"000000067F000080000006800C000001AC0B-000000067F000080000006800C0000024348__0000007FDCDCE659-000000804F6BFFC1", +"000000067F000080000006800C000001C000-000000067F000080000006800C0000020000__00000081AFEDBFE0", +"000000067F000080000006800C0000020000-000000067F000080000006800C0000024000__00000081AFEDBFE0", +"000000067F000080000006800C0000024000-000000067F000080000006800C0000028000__00000081AFEDBFE0", +"000000067F000080000006800C0000024348-000000067F000080000006800C000002DAAE__0000007FDCDCE659-000000804F6BFFC1", +"000000067F000080000006800C0000028000-000000067F000080000006800C000002C000__00000081AFEDBFE0", +"000000067F000080000006800C000002C000-000000067F000080000006800C0000030000__00000081AFEDBFE0", +"000000067F000080000006800C000002DAAE-000000067F000080000006800C00000371D0__0000007FDCDCE659-000000804F6BFFC1", +"000000067F000080000006800C0000030000-000000067F000080000006800C0000034000__00000081AFEDBFE0", +"000000067F000080000006800C0000034000-000000067F000080000006800C0000038000__00000081AFEDBFE0", +"000000067F000080000006800C00000371D0-000000067F000080000006800C000004090B__0000007FDCDCE659-000000804F6BFFC1", +"000000067F000080000006800C0000038000-000000067F000080000006800C000003C000__00000081AFEDBFE0", +"000000067F000080000006800C000003C000-000000067F000080000006800C0000040000__00000081AFEDBFE0", +"000000067F000080000006800C0000040000-000000067F000080000006800C0000044000__00000081A164D628", +"000000067F000080000006800C000004090B-030000000000000000000000000000000002__0000007FDCDCE659-000000804F6BFFC1", +"000000067F000080000006800C0000042368-000000067F000080000006800C000004BACE__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C0000044000-000000067F000080000006800C0000048000__00000081A164D628", +"000000067F000080000006800C0000048000-000000067F000080000006800C000004C000__00000081A164D628", +"000000067F000080000006800C000004BACE-000000067F000080000006800C0000055202__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C000004C000-000000067F000080000006800C0000050000__00000081A164D628", +"000000067F000080000006800C0000050000-000000067F000080000006800C0000054000__00000081A164D628", +"000000067F000080000006800C0000054000-000000067F000080000006800C0000058000__00000081A164D628", +"000000067F000080000006800C0000055202-000000067F000080000006800C000005E90D__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C0000058000-000000067F000080000006800C000005C000__00000081A164D628", +"000000067F000080000006800C000005C000-000000067F000080000006800C0000060000__00000081A164D628", +"000000067F000080000006800C000005E90D-000000067F000080000006800C000006802B__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C0000060000-000000067F000080000006800C0000064000__00000081A164D628", +"000000067F000080000006800C0000064000-000000067F000080000006800C0000068000__00000081A164D628", +"000000067F000080000006800C0000068000-000000067F000080000006800C000006C000__00000081A164D628", +"000000067F000080000006800C000006802B-000000067F000080000006800C0000071782__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C000006C000-000000067F000080000006800C0000070000__00000081A164D628", +"000000067F000080000006800C0000070000-000000067F000080000006800C0000074000__00000081A164D628", +"000000067F000080000006800C0000071782-000000067F000080000006800C000007AEE8__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C0000074000-000000067F000080000006800C0000078000__00000081A164D628", +"000000067F000080000006800C0000078000-000000067F000080000006800C000007C000__00000081A164D628", +"000000067F000080000006800C000007AEE8-000000067F000080000006800C000008460B__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C000007C000-000000067F000080000006800C0000080000__00000081A164D628", +"000000067F000080000006800C0000080000-000000067F000080000006800C0000084000__00000081A164D628", +"000000067F000080000006800C0000084000-000000067F000080000006800C0000088000__00000081A164D628", +"000000067F000080000006800C000008460B-000000067F000080000006800C000008DD71__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C0000088000-000000067F000080000006800C000008C000__00000081A164D628", +"000000067F000080000006800C000008C000-000000067F000080000006800C0000090000__00000081A164D628", +"000000067F000080000006800C000008DD71-000000067F000080000006800C00000974D7__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C0000090000-000000067F000080000006800C0000094000__00000081A164D628", +"000000067F000080000006800C0000094000-000000067F000080000006800C0000098000__00000081A164D628", +"000000067F000080000006800C00000974D7-000000067F000080000006800C00000A0C0B__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C0000098000-000000067F000080000006800C000009C000__00000081A164D628", +"000000067F000080000006800C000009C000-000000067F000080000006800C00000A0000__00000081A164D628", +"000000067F000080000006800C00000A0000-000000067F000080000006800C00000A4000__00000081A164D628", +"000000067F000080000006800C00000A0C0B-000000067F000080000006800C0100000000__000000804F6BFFC1-00000080EF2FF5B9", +"000000067F000080000006800C00000A4000-000000067F000080000006800C00000A8000__00000081A164D628", +"000000067F000080000006800C00000A8000-000000067F000080000006800C00000AC000__00000081A164D628", +"000000067F000080000006800C00000A8D4C-000000067F000080000006800C00000B24B2__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C00000AC000-000000067F000080000006800C00000B0000__00000081A164D628", +"000000067F000080000006800C00000B0000-000000067F000080000006800C00000B4000__00000081A164D628", +"000000067F000080000006800C00000B24B2-000000067F000080000006800C00000BBC0B__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C00000B4000-000000067F000080000006800C00000B8000__00000081A164D628", +"000000067F000080000006800C00000B8000-000000067F000080000006800C00000BC000__00000081A164D628", +"000000067F000080000006800C00000BBC0B-000000067F000080000006800C00000C533F__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C00000BC000-000000067F000080000006800C00000C0000__00000081A164D628", +"000000067F000080000006800C00000C0000-000000067F000080000006800C00000C4000__00000081A164D628", +"000000067F000080000006800C00000C4000-000000067F000080000006800C00000C8000__00000081A164D628", +"000000067F000080000006800C00000C533F-000000067F000080000006800C00000CEAA5__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C00000C8000-000000067F000080000006800C00000CC000__00000081A164D628", +"000000067F000080000006800C00000CC000-000000067F000080000006800C00000D0000__00000081A164D628", +"000000067F000080000006800C00000CEAA5-000000067F000080000006800C00000D81BE__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C00000D0000-000000067F000080000006800C00000D4000__00000081A164D628", +"000000067F000080000006800C00000D4000-000000067F000080000006800C00000D8000__00000081A164D628", +"000000067F000080000006800C00000D8000-000000067F000080000006800C00000DC000__00000081A164D628", +"000000067F000080000006800C00000D81BE-000000067F000080000006800C00000E190B__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C00000DC000-000000067F000080000006800C00000E0000__00000081A164D628", +"000000067F000080000006800C00000E0000-000000067F000080000006800C00000E4000__00000081A164D628", +"000000067F000080000006800C00000E190B-000000067F000080000006800C00000EB071__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C00000E4000-000000067F000080000006800C00000E8000__00000081A164D628", +"000000067F000080000006800C00000E8000-000000067F000080000006800C00000EC000__00000081A164D628", +"000000067F000080000006800C00000EB071-000000067F000080000006800C00000F47AC__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C00000EC000-000000067F000080000006800C00000F0000__00000081A164D628", +"000000067F000080000006800C00000F0000-000000067F000080000006800C00000F4000__00000081A164D628", +"000000067F000080000006800C00000F4000-000000067F000080000006800C00000F8000__00000081A164D628", +"000000067F000080000006800C00000F47AC-000000067F000080000006800C00000FDF0A__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C00000F8000-000000067F000080000006800C00000FC000__00000081A164D628", +"000000067F000080000006800C00000FC000-000000067F000080000006800C0000100000__00000081A164D628", +"000000067F000080000006800C00000FDF0A-000000067F000080000006800C000010762B__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C0000100000-000000067F000080000006800C0000104000__00000081A164D628", +"000000067F000080000006800C0000104000-000000067F000080000006800C0000108000__00000081A164D628", +"000000067F000080000006800C000010762B-000000067F000080000006800C0000110D88__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006800C0000108000-030000000000000000000000000000000002__00000081A164D628", +"000000067F000080000006800C0000110D88-010000000000000001000000030000000014__00000080EF2FF5B9-00000081AFAF5FD1", +"000000067F000080000006801400000044E4-000000067F0000800000068014000000C3F5__00000081AFAF5FD1-0000008215AFE5A9", +"000000067F0000800000068014000000C3F5-000000067F00008000000680140000014303__00000081AFAF5FD1-0000008215AFE5A9", +"000000067F00008000000680140000014303-000000067F0000800000068014000001C214__00000081AFAF5FD1-0000008215AFE5A9", +"000000067F0000800000068014000001C214-000000067F00008000000680140000024125__00000081AFAF5FD1-0000008215AFE5A9", +"000000067F00008000000680140000024125-000000067F0000800000068014000002C035__00000081AFAF5FD1-0000008215AFE5A9", +"000000067F0000800000068014000002C035-000000067F000080000006A00C00000072CA__00000081AFAF5FD1-0000008215AFE5A9", +"000000067F000080000006A00C0000000000-000000067F000080000006A00C0000004000__00000083D5DE3FD0", +"000000067F000080000006A00C0000004000-000000067F000080000006A00C0000008000__00000083D5DE3FD0", +"000000067F000080000006A00C00000072CA-030000000000000000000000000000000002__00000081AFAF5FD1-0000008215AFE5A9", +"000000067F000080000006A00C0000008000-000000067F000080000006A00C000000C000__00000083865C64B8", +"000000067F000080000006A00C0000008000-000000067F000080000006A00C000000C000__00000084A1F03030", +"000000067F000080000006A00C00000096E3-000000067F000080000006A00C0000012E0B__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C000000C000-000000067F000080000006A00C0000010000__00000083865C64B8", +"000000067F000080000006A00C000000C000-000000067F000080000006A00C0000010000__00000084A1F03030", +"000000067F000080000006A00C0000010000-000000067F000080000006A00C0000014000__00000083865C64B8", +"000000067F000080000006A00C0000010000-000000067F000080000006A00C0000014000__00000084A1F03030", +"000000067F000080000006A00C0000012E0B-000000067F000080000006A00C000001C571__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C0000014000-000000067F000080000006A00C0000018000__00000083865C64B8", +"000000067F000080000006A00C0000014000-000000067F000080000006A00C0000018000__00000084A1F03030", +"000000067F000080000006A00C0000018000-000000067F000080000006A00C000001C000__00000083865C64B8", +"000000067F000080000006A00C0000018000-000000067F000080000006A00C000001C000__00000084A1F03030", +"000000067F000080000006A00C000001C000-000000067F000080000006A00C0000020000__00000083865C64B8", +"000000067F000080000006A00C000001C000-000000067F000080000006A00C0000020000__00000084A1F03030", +"000000067F000080000006A00C000001C571-000000067F000080000006A00C0000025CD7__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C0000020000-000000067F000080000006A00C0000024000__00000083865C64B8", +"000000067F000080000006A00C0000020000-000000067F000080000006A00C0000024000__00000084A1F03030", +"000000067F000080000006A00C0000024000-000000067F000080000006A00C0000028000__00000083865C64B8", +"000000067F000080000006A00C0000024000-000000067F000080000006A00C0000028000__00000084A1F03030", +"000000067F000080000006A00C0000025CD7-000000067F000080000006A00C000002F40B__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C0000028000-000000067F000080000006A00C000002C000__00000083865C64B8", +"000000067F000080000006A00C0000028000-000000067F000080000006A00C000002C000__00000084A1F03030", +"000000067F000080000006A00C000002C000-000000067F000080000006A00C0000030000__00000083865C64B8", +"000000067F000080000006A00C000002C000-000000067F000080000006A00C0000030000__00000084A1F03030", +"000000067F000080000006A00C000002F40B-000000067F000080000006A00C0000038B1E__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C0000030000-000000067F000080000006A00C0000034000__00000083865C64B8", +"000000067F000080000006A00C0000030000-000000067F000080000006A00C0000034000__00000084A1F03030", +"000000067F000080000006A00C0000034000-000000067F000080000006A00C0000038000__00000083865C64B8", +"000000067F000080000006A00C0000034000-000000067F000080000006A00C0000038000__00000084A1F03030", +"000000067F000080000006A00C0000038000-000000067F000080000006A00C000003C000__00000083865C64B8", +"000000067F000080000006A00C0000038000-000000067F000080000006A00C000003C000__00000084A1F03030", +"000000067F000080000006A00C0000038B1E-000000067F000080000006A00C0000042284__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C000003C000-000000067F000080000006A00C0000040000__00000083865C64B8", +"000000067F000080000006A00C000003C000-000000067F000080000006A00C0000040000__00000084A1F03030", +"000000067F000080000006A00C0000040000-000000067F000080000006A00C0000044000__00000083865C64B8", +"000000067F000080000006A00C0000040000-000000067F000080000006A00C0000044000__00000084A1F03030", +"000000067F000080000006A00C0000042284-000000067F000080000006A00C000004B9EA__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C0000044000-000000067F000080000006A00C0000048000__00000083865C64B8", +"000000067F000080000006A00C0000044000-000000067F000080000006A00C0000048000__00000084A1F03030", +"000000067F000080000006A00C0000048000-000000067F000080000006A00C000004C000__00000083865C64B8", +"000000067F000080000006A00C0000048000-000000067F000080000006A00C000004C000__00000084A1F03030", +"000000067F000080000006A00C000004B9EA-000000067F000080000006A00C000005510B__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C000004C000-000000067F000080000006A00C0000050000__00000083865C64B8", +"000000067F000080000006A00C000004C000-000000067F000080000006A00C0000050000__00000084A1F03030", +"000000067F000080000006A00C0000050000-000000067F000080000006A00C0000054000__00000083865C64B8", +"000000067F000080000006A00C0000050000-000000067F000080000006A00C0000054000__00000084A1F03030", +"000000067F000080000006A00C000005198B-000000067F000080000006A00C00000A31A6__000000844F1A6789-00000084A325AA01", +"000000067F000080000006A00C0000054000-000000067F000080000006A00C0000058000__00000083865C64B8", +"000000067F000080000006A00C0000054000-000000067F000080000006A00C0000058000__00000084A1F03030", +"000000067F000080000006A00C000005510B-000000067F000080000006A00C000005E871__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C0000058000-000000067F000080000006A00C000005C000__00000083865C64B8", +"000000067F000080000006A00C0000058000-000000067F000080000006A00C000005C000__00000084A1F03030", +"000000067F000080000006A00C000005C000-000000067F000080000006A00C0000060000__00000083865C64B8", +"000000067F000080000006A00C000005C000-000000067F000080000006A00C0000060000__00000084A1F03030", +"000000067F000080000006A00C000005E871-000000067F000080000006A00C0000067F8B__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C0000060000-000000067F000080000006A00C0000064000__00000083865C64B8", +"000000067F000080000006A00C0000060000-000000067F000080000006A00C0000064000__00000084A1F03030", +"000000067F000080000006A00C0000064000-000000067F000080000006A00C0000068000__00000083865C64B8", +"000000067F000080000006A00C0000064000-000000067F000080000006A00C0000068000__00000084A1F03030", +"000000067F000080000006A00C0000067F8B-000000067F000080000006A00C0100000000__0000008215AFE5A9-00000082B573F579", +"000000067F000080000006A00C0000068000-000000067F000080000006A00C000006C000__00000083865C64B8", +"000000067F000080000006A00C0000068000-000000067F000080000006A00C000006C000__00000084A1F03030", +"000000067F000080000006A00C000006C000-000000067F000080000006A00C0000070000__00000083865C64B8", +"000000067F000080000006A00C000006C000-000000067F000080000006A00C0000070000__00000084A1F03030", +"000000067F000080000006A00C0000070000-000000067F000080000006A00C0000074000__00000083865C64B8", +"000000067F000080000006A00C0000070000-000000067F000080000006A00C0000074000__00000084A1F03030", +"000000067F000080000006A00C00000703EC-000000067F000080000006A00C0000079B0C__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C0000074000-000000067F000080000006A00C0000078000__00000083865C64B8", +"000000067F000080000006A00C0000074000-000000067F000080000006A00C0000078000__00000084A1F03030", +"000000067F000080000006A00C0000078000-000000067F000080000006A00C000007C000__00000083865C64B8", +"000000067F000080000006A00C0000078000-000000067F000080000006A00C000007C000__00000084A1F03030", +"000000067F000080000006A00C0000079B0C-000000067F000080000006A00C0000083272__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C000007C000-000000067F000080000006A00C0000080000__00000083865C64B8", +"000000067F000080000006A00C000007C000-000000067F000080000006A00C0000080000__00000084A1F03030", +"000000067F000080000006A00C0000080000-000000067F000080000006A00C0000084000__00000083865C64B8", +"000000067F000080000006A00C0000080000-000000067F000080000006A00C0000084000__00000084A1F03030", +"000000067F000080000006A00C0000083272-000000067F000080000006A00C000008C9D8__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C0000084000-000000067F000080000006A00C0000088000__00000083865C64B8", +"000000067F000080000006A00C0000084000-000000067F000080000006A00C0000088000__00000084A1F03030", +"000000067F000080000006A00C0000088000-000000067F000080000006A00C000008C000__00000083865C64B8", +"000000067F000080000006A00C0000088000-000000067F000080000006A00C000008C000__00000084A1F03030", +"000000067F000080000006A00C000008C000-000000067F000080000006A00C0000090000__00000083865C64B8", +"000000067F000080000006A00C000008C000-000000067F000080000006A00C0000090000__00000084A1F03030", +"000000067F000080000006A00C000008C9D8-000000067F000080000006A00C0000096129__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C0000090000-000000067F000080000006A00C0000094000__00000083865C64B8", +"000000067F000080000006A00C0000090000-000000067F000080000006A00C0000094000__00000084A1F03030", +"000000067F000080000006A00C0000094000-000000067F000080000006A00C0000098000__00000083865C64B8", +"000000067F000080000006A00C0000094000-000000067F000080000006A00C0000098000__00000084A1F03030", +"000000067F000080000006A00C0000096129-000000067F000080000006A00C000009F88F__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C0000098000-000000067F000080000006A00C000009C000__00000083865C64B8", +"000000067F000080000006A00C0000098000-000000067F000080000006A00C000009C000__00000084A1F03030", +"000000067F000080000006A00C000009C000-000000067F000080000006A00C00000A0000__00000083865C64B8", +"000000067F000080000006A00C000009C000-000000067F000080000006A00C00000A0000__00000084A1F03030", +"000000067F000080000006A00C000009F88F-000000067F000080000006A00C00000A8F9F__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C00000A0000-000000067F000080000006A00C00000A4000__00000083865C64B8", +"000000067F000080000006A00C00000A0000-000000067F000080000006A00C00000A4000__00000084A1F03030", +"000000067F000080000006A00C00000A31B0-000000067F000080000006A00C00000F4C19__000000844F1A6789-00000084A325AA01", +"000000067F000080000006A00C00000A4000-000000067F000080000006A00C00000A8000__00000083865C64B8", +"000000067F000080000006A00C00000A4000-000000067F000080000006A00C00000A8000__00000084A1F03030", +"000000067F000080000006A00C00000A8000-000000067F000080000006A00C00000AC000__00000083865C64B8", +"000000067F000080000006A00C00000A8000-000000067F000080000006A00C00000AC000__00000084A1F03030", +"000000067F000080000006A00C00000A8F9F-000000067F000080000006A00C00000B2705__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C00000AC000-000000067F000080000006A00C00000B0000__00000083865C64B8", +"000000067F000080000006A00C00000AC000-000000067F000080000006A00C00000B0000__00000084A1F03030", +"000000067F000080000006A00C00000B0000-000000067F000080000006A00C00000B4000__00000083865C64B8", +"000000067F000080000006A00C00000B0000-000000067F000080000006A00C00000B4000__00000084A1F03030", +"000000067F000080000006A00C00000B2705-000000067F000080000006A00C00000BBE10__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C00000B4000-000000067F000080000006A00C00000B8000__00000083865C64B8", +"000000067F000080000006A00C00000B4000-000000067F000080000006A00C00000B8000__00000084A1F03030", +"000000067F000080000006A00C00000B8000-000000067F000080000006A00C00000BC000__00000083865C64B8", +"000000067F000080000006A00C00000B8000-000000067F000080000006A00C00000BC000__00000084A1F03030", +"000000067F000080000006A00C00000BBE10-000000067F000080000006A00C00000C5543__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C00000BC000-000000067F000080000006A00C00000C0000__00000083865C64B8", +"000000067F000080000006A00C00000BC000-000000067F000080000006A00C00000C0000__00000084A1F03030", +"000000067F000080000006A00C00000C0000-000000067F000080000006A00C00000C4000__00000083865C64B8", +"000000067F000080000006A00C00000C0000-000000067F000080000006A00C00000C4000__00000084A1F03030", +"000000067F000080000006A00C00000C4000-000000067F000080000006A00C00000C8000__00000083865C64B8", +"000000067F000080000006A00C00000C4000-000000067F000080000006A00C00000C8000__00000084A1F03030", +"000000067F000080000006A00C00000C4CC8-000000067F000080000006A0140000001CBC__00000083D5901FD9-000000844F1A6789", +"000000067F000080000006A00C00000C5543-000000067F000080000006A00C00000CECA9__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C00000C8000-000000067F000080000006A00C00000CC000__00000083865C64B8", +"000000067F000080000006A00C00000C8000-000000067F000080000006A00C00000CC000__00000084A1F03030", +"000000067F000080000006A00C00000CC000-000000067F000080000006A00C00000D0000__00000083865C64B8", +"000000067F000080000006A00C00000CC000-000000067F000080000006A00C00000D0000__00000084A1F03030", +"000000067F000080000006A00C00000CECA9-000000067F000080000006A00C00000D83C0__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C00000D0000-000000067F000080000006A00C00000D4000__00000083865C64B8", +"000000067F000080000006A00C00000D0000-000000067F000080000006A00C00000D4000__00000084A1F03030", +"000000067F000080000006A00C00000D4000-000000067F000080000006A00C00000D8000__00000083865C64B8", +"000000067F000080000006A00C00000D4000-000000067F000080000006A00C00000D8000__00000084A1F03030", +"000000067F000080000006A00C00000D8000-000000067F000080000006A00C00000DC000__00000083865C64B8", +"000000067F000080000006A00C00000D8000-000000067F000080000006A00C00000DC000__00000084A1F03030", +"000000067F000080000006A00C00000D83C0-000000067F000080000006A00C00000E1B0A__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C00000DC000-000000067F000080000006A00C00000E0000__00000083865C64B8", +"000000067F000080000006A00C00000DC000-000000067F000080000006A00C00000E0000__00000084A1F03030", +"000000067F000080000006A00C00000E0000-000000067F000080000006A00C00000E4000__00000084A1F03030", +"000000067F000080000006A00C00000E0000-030000000000000000000000000000000002__00000083865C64B8", +"000000067F000080000006A00C00000E1B0A-000000067F000080000006A00C00000EB270__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C00000E4000-000000067F000080000006A00C00000E8000__00000084A1F03030", +"000000067F000080000006A00C00000E8000-000000067F000080000006A00C00000EC000__00000084A1F03030", +"000000067F000080000006A00C00000EB270-000000067F000080000006A00C00000F49AA__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C00000EC000-000000067F000080000006A00C00000F0000__00000084A1F03030", +"000000067F000080000006A00C00000F0000-000000067F000080000006A00C00000F4000__00000084A1F03030", +"000000067F000080000006A00C00000F4000-000000067F000080000006A00C00000F8000__00000084A1F03030", +"000000067F000080000006A00C00000F49AA-000000067F000080000006A00C00000FE10A__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C00000F4C23-000000067F000080000006A014000000E1C2__000000844F1A6789-00000084A325AA01", +"000000067F000080000006A00C00000F8000-000000067F000080000006A00C00000FC000__00000084A1F03030", +"000000067F000080000006A00C00000FC000-000000067F000080000006A00C0000100000__00000084A1F03030", +"000000067F000080000006A00C00000FE10A-000000067F000080000006A00C000010782C__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C0000100000-000000067F000080000006A00C0000104000__00000084A1F03030", +"000000067F000080000006A00C0000104000-000000067F000080000006A00C0000108000__00000084A1F03030", +"000000067F000080000006A00C000010782C-000000067F000080000006A00C0000110F88__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A00C0000108000-000000067F000080000006A00C000010C000__00000084A1F03030", +"000000067F000080000006A00C000010C000-000000067F000080000006A00C0000110000__00000084A1F03030", +"000000067F000080000006A00C0000110000-000000067F000080000006A0120100000000__00000084A1F03030", +"000000067F000080000006A00C0000110F88-010000000000000001000000030000000014__00000082B573F579-00000083D5901FD9", +"000000067F000080000006A0140000000000-000000067F000080000006A0140000004000__00000084A1F03030", +"000000067F000080000006A0140000001CBC-000000067F000080000006A01400000088E1__00000083D5901FD9-000000844F1A6789", +"000000067F000080000006A0140000004000-000000067F000080000006A0140000008000__00000084A1F03030", +"000000067F000080000006A0140000008000-000000067F000080000006A014000000C000__00000084A1F03030", +"000000067F000080000006A01400000088E1-000000067F000080000006A014000000F459__00000083D5901FD9-000000844F1A6789", +"000000067F000080000006A014000000C000-000000067F000080000006A0140000010000__00000084A1F03030", +"000000067F000080000006A014000000E1C2-000000067F000080000006A014000002682C__000000844F1A6789-00000084A325AA01", +"000000067F000080000006A014000000F459-000000067F000080000006A0140000016068__00000083D5901FD9-000000844F1A6789", +"000000067F000080000006A0140000010000-000000067F000080000006A0140000014000__00000084A1F03030", +"000000067F000080000006A0140000014000-000000067F000080000006A0140000018000__00000084A1F03030", +"000000067F000080000006A0140000016068-000000067F000080000006A014000001CC14__00000083D5901FD9-000000844F1A6789", +"000000067F000080000006A0140000018000-000000067F000080000006A014000001C000__00000084A1F03030", +"000000067F000080000006A014000001C000-000000067F000080000006A0140000020000__00000084A1F03030", +"000000067F000080000006A014000001CC14-000000067F000080000006A014000002384E__00000083D5901FD9-000000844F1A6789", +"000000067F000080000006A0140000020000-000000067F000080000006A0140000024000__00000084A1F03030", +"000000067F000080000006A014000002384E-000000067F000080000006A014000002A467__00000083D5901FD9-000000844F1A6789", +"000000067F000080000006A0140000024000-000000067F000080000006A0140000028000__00000084A1F03030", +"000000067F000080000006A0140000026831-030000000000000000000000000000000002__000000844F1A6789-00000084A325AA01", +"000000067F000080000006A0140000028000-000000067F000080000006A014000002C000__00000084A1F03030", +"000000067F000080000006A014000002A467-030000000000000000000000000000000002__00000083D5901FD9-000000844F1A6789", +"000000067F000080000006A014000002C000-030000000000000000000000000000000002__00000084A1F03030", +"000000067F000080000006C00C0000000000-000000067F000080000006C00C0000004000__00000086746BDFE0", +"000000067F000080000006C00C0000004000-000000067F000080000006C00C0000008000__00000086746BDFE0", +"000000067F000080000006C00C0000008000-000000067F000080000006C00C000000C000__00000086746BDFE0", +"000000067F000080000006C00C00000090F5-000000067F000080000006C00C000001280C__00000084A325AA01-00000085239DFB81", +"000000067F000080000006C00C000000C000-000000067F000080000006C00C0000010000__00000086746BDFE0", +"000000067F000080000006C00C0000010000-000000067F000080000006C00C0000014000__00000086746BDFE0", +"000000067F000080000006C00C000001280C-000000067F000080000006C00C000001BF72__00000084A325AA01-00000085239DFB81", +"000000067F000080000006C00C0000014000-000000067F000080000006C00C0000018000__00000086746BDFE0", +"000000067F000080000006C00C0000018000-000000067F000080000006C00C000001C000__00000086746BDFE0", +"000000067F000080000006C00C000001BF72-000000067F000080000006C00C00000256D8__00000084A325AA01-00000085239DFB81", +"000000067F000080000006C00C000001C000-000000067F000080000006C00C0000020000__00000086746BDFE0", +"000000067F000080000006C00C0000020000-000000067F000080000006C00C0000024000__00000086746BDFE0", +"000000067F000080000006C00C0000024000-000000067F000080000006C00C0000028000__00000086746BDFE0", +"000000067F000080000006C00C00000256D8-000000067F000080000006C00C000002EE0B__00000084A325AA01-00000085239DFB81", +"000000067F000080000006C00C0000028000-000000067F000080000006C00C000002C000__00000086746BDFE0", +"000000067F000080000006C00C000002C000-000000067F000080000006C00C0000030000__00000086746BDFE0", +"000000067F000080000006C00C000002EE0B-000000067F000080000006C00C0000038521__00000084A325AA01-00000085239DFB81", +"000000067F000080000006C00C0000030000-000000067F000080000006C00C0000034000__00000086746BDFE0", +"000000067F000080000006C00C0000034000-000000067F000080000006C00C0000038000__00000086746BDFE0", +"000000067F000080000006C00C0000038000-000000067F000080000006C00C000003C000__00000086746BDFE0", +"000000067F000080000006C00C0000038521-000000067F000080000006C00C0000041C87__00000084A325AA01-00000085239DFB81", +"000000067F000080000006C00C000003C000-000000067F000080000006C00C0000040000__00000086746BDFE0", +"000000067F000080000006C00C0000040000-000000067F000080000006C00C0000044000__00000086746BDFE0", +"000000067F000080000006C00C0000041C87-000000067F000080000006C00C000004B3ED__00000084A325AA01-00000085239DFB81", +"000000067F000080000006C00C0000044000-000000067F000080000006C00C0000048000__00000086746BDFE0", +"000000067F000080000006C00C0000048000-000000067F000080000006C00C000004C000__00000086720CFFF0", +"000000067F000080000006C00C0000048000-000000067F000080000006C00C000004C000__000000873B520940", +"000000067F000080000006C00C000004B3ED-030000000000000000000000000000000002__00000084A325AA01-00000085239DFB81", +"000000067F000080000006C00C000004BAC4-000000067F000080000006C00C00000551F9__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C000004C000-000000067F000080000006C00C0000050000__00000086720CFFF0", +"000000067F000080000006C00C000004C000-000000067F000080000006C00C0000050000__000000873B520940", +"000000067F000080000006C00C0000050000-000000067F000080000006C00C0000054000__00000086720CFFF0", +"000000067F000080000006C00C0000050000-000000067F000080000006C00C0000054000__000000873B520940", +"000000067F000080000006C00C0000054000-000000067F000080000006C00C0000058000__00000086720CFFF0", +"000000067F000080000006C00C0000054000-000000067F000080000006C00C0000058000__000000873B520940", +"000000067F000080000006C00C00000551F9-000000067F000080000006C00C000005E90C__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C0000055EB3-000000067F000080000006C00C00000AB316__00000086ED29E361-000000873C9A2551", +"000000067F000080000006C00C0000058000-000000067F000080000006C00C000005C000__00000086720CFFF0", +"000000067F000080000006C00C0000058000-000000067F000080000006C00C000005C000__000000873B520940", +"000000067F000080000006C00C000005C000-000000067F000080000006C00C0000060000__00000086720CFFF0", +"000000067F000080000006C00C000005C000-000000067F000080000006C00C0000060000__000000873B520940", +"000000067F000080000006C00C000005E90C-000000067F000080000006C00C000006802C__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C0000060000-000000067F000080000006C00C0000064000__00000086720CFFF0", +"000000067F000080000006C00C0000060000-000000067F000080000006C00C0000064000__000000873B520940", +"000000067F000080000006C00C0000064000-000000067F000080000006C00C0000068000__00000086720CFFF0", +"000000067F000080000006C00C0000064000-000000067F000080000006C00C0000068000__000000873B520940", +"000000067F000080000006C00C0000068000-000000067F000080000006C00C000006C000__00000086720CFFF0", +"000000067F000080000006C00C0000068000-000000067F000080000006C00C000006C000__000000873B520940", +"000000067F000080000006C00C000006802C-000000067F000080000006C00C0000071783__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C000006C000-000000067F000080000006C00C0000070000__00000086720CFFF0", +"000000067F000080000006C00C000006C000-000000067F000080000006C00C0000070000__000000873B520940", +"000000067F000080000006C00C0000070000-000000067F000080000006C00C0000074000__00000086720CFFF0", +"000000067F000080000006C00C0000070000-000000067F000080000006C00C0000074000__000000873B520940", +"000000067F000080000006C00C0000071783-000000067F000080000006C00C000007AEE9__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C0000074000-000000067F000080000006C00C0000078000__00000086720CFFF0", +"000000067F000080000006C00C0000074000-000000067F000080000006C00C0000078000__000000873B520940", +"000000067F000080000006C00C0000078000-000000067F000080000006C00C000007C000__00000086720CFFF0", +"000000067F000080000006C00C0000078000-000000067F000080000006C00C000007C000__000000873B520940", +"000000067F000080000006C00C000007AEE9-000000067F000080000006C00C000008460B__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C000007C000-000000067F000080000006C00C0000080000__00000086720CFFF0", +"000000067F000080000006C00C000007C000-000000067F000080000006C00C0000080000__000000873B520940", +"000000067F000080000006C00C0000080000-000000067F000080000006C00C0000084000__00000086720CFFF0", +"000000067F000080000006C00C0000080000-000000067F000080000006C00C0000084000__000000873B520940", +"000000067F000080000006C00C0000084000-000000067F000080000006C00C0000088000__00000086720CFFF0", +"000000067F000080000006C00C0000084000-000000067F000080000006C00C0000088000__000000873B520940", +"000000067F000080000006C00C000008460B-000000067F000080000006C00C000008DD71__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C0000088000-000000067F000080000006C00C000008C000__00000086720CFFF0", +"000000067F000080000006C00C0000088000-000000067F000080000006C00C000008C000__000000873B520940", +"000000067F000080000006C00C000008C000-000000067F000080000006C00C0000090000__00000086720CFFF0", +"000000067F000080000006C00C000008C000-000000067F000080000006C00C0000090000__000000873B520940", +"000000067F000080000006C00C000008DD71-000000067F000080000006C00C00000974D7__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C0000090000-000000067F000080000006C00C0000094000__00000086720CFFF0", +"000000067F000080000006C00C0000090000-000000067F000080000006C00C0000094000__000000873B520940", +"000000067F000080000006C00C0000094000-000000067F000080000006C00C0000098000__00000086720CFFF0", +"000000067F000080000006C00C0000094000-000000067F000080000006C00C0000098000__000000873B520940", +"000000067F000080000006C00C00000974D7-000000067F000080000006C00C00000A0C0B__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C0000098000-000000067F000080000006C00C000009C000__00000086720CFFF0", +"000000067F000080000006C00C0000098000-000000067F000080000006C00C000009C000__000000873B520940", +"000000067F000080000006C00C000009C000-000000067F000080000006C00C00000A0000__00000086720CFFF0", +"000000067F000080000006C00C000009C000-000000067F000080000006C00C00000A0000__000000873B520940", +"000000067F000080000006C00C00000A0000-000000067F000080000006C00C00000A4000__00000086720CFFF0", +"000000067F000080000006C00C00000A0000-000000067F000080000006C00C00000A4000__000000873B520940", +"000000067F000080000006C00C00000A0C0B-000000067F000080000006C00C00000AA371__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C00000A4000-000000067F000080000006C00C00000A8000__00000086720CFFF0", +"000000067F000080000006C00C00000A4000-000000067F000080000006C00C00000A8000__000000873B520940", +"000000067F000080000006C00C00000A8000-000000067F000080000006C00C00000AC000__00000086720CFFF0", +"000000067F000080000006C00C00000A8000-000000067F000080000006C00C00000AC000__000000873B520940", +"000000067F000080000006C00C00000AA371-000000067F000080000006C00C00000B3AD7__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C00000AB316-000000067F000080000006C00C00001015F1__00000086ED29E361-000000873C9A2551", +"000000067F000080000006C00C00000AC000-000000067F000080000006C00C00000B0000__00000086720CFFF0", +"000000067F000080000006C00C00000AC000-000000067F000080000006C00C00000B0000__000000873B520940", +"000000067F000080000006C00C00000B0000-000000067F000080000006C00C00000B4000__00000086720CFFF0", +"000000067F000080000006C00C00000B0000-000000067F000080000006C00C00000B4000__000000873B520940", +"000000067F000080000006C00C00000B3AD7-000000067F000080000006C00C0100000000__00000085239DFB81-00000085D35BF439", +"000000067F000080000006C00C00000B4000-000000067F000080000006C00C00000B8000__00000086720CFFF0", +"000000067F000080000006C00C00000B4000-000000067F000080000006C00C00000B8000__000000873B520940", +"000000067F000080000006C00C00000B8000-000000067F000080000006C00C00000BC000__00000086720CFFF0", +"000000067F000080000006C00C00000B8000-000000067F000080000006C00C00000BC000__000000873B520940", +"000000067F000080000006C00C00000BC000-000000067F000080000006C00C00000C0000__00000086720CFFF0", +"000000067F000080000006C00C00000BC000-000000067F000080000006C00C00000C0000__000000873B520940", +"000000067F000080000006C00C00000BC102-000000067F000080000006C00C00000C580D__00000085D35BF439-0000008673817FC9", +"000000067F000080000006C00C00000BFB6E-000000067F000080000006C01400000016BC__0000008673817FC9-00000086ED29E361", +"000000067F000080000006C00C00000C0000-000000067F000080000006C00C00000C4000__00000086720CFFF0", +"000000067F000080000006C00C00000C0000-000000067F000080000006C00C00000C4000__000000873B520940", +"000000067F000080000006C00C00000C4000-000000067F000080000006C00C00000C8000__00000086720CFFF0", +"000000067F000080000006C00C00000C4000-000000067F000080000006C00C00000C8000__000000873B520940", +"000000067F000080000006C00C00000C580D-000000067F000080000006C00C00000CEF73__00000085D35BF439-0000008673817FC9", +"000000067F000080000006C00C00000C8000-000000067F000080000006C00C00000CC000__00000086720CFFF0", +"000000067F000080000006C00C00000C8000-000000067F000080000006C00C00000CC000__000000873B520940", +"000000067F000080000006C00C00000CC000-000000067F000080000006C00C00000D0000__00000086720CFFF0", +"000000067F000080000006C00C00000CC000-000000067F000080000006C00C00000D0000__000000873B520940", +"000000067F000080000006C00C00000CEF73-000000067F000080000006C00C00000D86D9__00000085D35BF439-0000008673817FC9", +"000000067F000080000006C00C00000D0000-000000067F000080000006C00C00000D4000__00000086720CFFF0", +"000000067F000080000006C00C00000D0000-000000067F000080000006C00C00000D4000__000000873B520940", +"000000067F000080000006C00C00000D4000-000000067F000080000006C00C00000D8000__00000086720CFFF0", +"000000067F000080000006C00C00000D4000-000000067F000080000006C00C00000D8000__000000873B520940", +"000000067F000080000006C00C00000D8000-000000067F000080000006C00C00000DC000__00000086720CFFF0", +"000000067F000080000006C00C00000D8000-000000067F000080000006C00C00000DC000__000000873B520940", +"000000067F000080000006C00C00000D86D9-000000067F000080000006C00C00000E1E0C__00000085D35BF439-0000008673817FC9", +"000000067F000080000006C00C00000DC000-000000067F000080000006C00C00000E0000__00000086720CFFF0", +"000000067F000080000006C00C00000DC000-000000067F000080000006C00C00000E0000__000000873B520940", +"000000067F000080000006C00C00000E0000-000000067F000080000006C00C00000E4000__00000086720CFFF0", +"000000067F000080000006C00C00000E0000-000000067F000080000006C00C00000E4000__000000873B520940", +"000000067F000080000006C00C00000E1E0C-000000067F000080000006C00C00000EB572__00000085D35BF439-0000008673817FC9", +"000000067F000080000006C00C00000E4000-000000067F000080000006C00C00000E8000__00000086720CFFF0", +"000000067F000080000006C00C00000E4000-000000067F000080000006C00C00000E8000__000000873B520940", +"000000067F000080000006C00C00000E8000-000000067F000080000006C00C00000EC000__00000086720CFFF0", +"000000067F000080000006C00C00000E8000-000000067F000080000006C00C00000EC000__000000873B520940", +"000000067F000080000006C00C00000EB572-000000067F000080000006C00C00000F4CD8__00000085D35BF439-0000008673817FC9", +"000000067F000080000006C00C00000EC000-000000067F000080000006C00C00000F0000__00000086720CFFF0", +"000000067F000080000006C00C00000EC000-000000067F000080000006C00C00000F0000__000000873B520940", +"000000067F000080000006C00C00000F0000-000000067F000080000006C00C00000F4000__00000086720CFFF0", +"000000067F000080000006C00C00000F0000-000000067F000080000006C00C00000F4000__000000873B520940", +"000000067F000080000006C00C00000F4000-000000067F000080000006C00C00000F8000__00000086720CFFF0", +"000000067F000080000006C00C00000F4000-000000067F000080000006C00C00000F8000__000000873B520940", +"000000067F000080000006C00C00000F4CD8-000000067F000080000006C00C00000FE40B__00000085D35BF439-0000008673817FC9", +"000000067F000080000006C00C00000F8000-000000067F000080000006C00C00000FC000__00000086720CFFF0", +"000000067F000080000006C00C00000F8000-000000067F000080000006C00C00000FC000__000000873B520940", +"000000067F000080000006C00C00000FC000-000000067F000080000006C00C0000100000__00000086720CFFF0", +"000000067F000080000006C00C00000FC000-000000067F000080000006C00C0000100000__000000873B520940", +"000000067F000080000006C00C00000FE40B-000000067F000080000006C00C0000107B27__00000085D35BF439-0000008673817FC9", +"000000067F000080000006C00C0000100000-000000067F000080000006C00C0000104000__00000086720CFFF0", +"000000067F000080000006C00C0000100000-000000067F000080000006C00C0000104000__000000873B520940", +"000000067F000080000006C00C00001015F3-000000067F000080000006C0140000013635__00000086ED29E361-000000873C9A2551", +"000000067F000080000006C00C0000104000-000000067F000080000006C00C0000108000__00000086720CFFF0", +"000000067F000080000006C00C0000104000-000000067F000080000006C00C0000108000__000000873B520940", +"000000067F000080000006C00C0000107B27-000000067F000080000006C00C000011128D__00000085D35BF439-0000008673817FC9", +"000000067F000080000006C00C0000108000-000000067F000080000006C00C000010C000__00000086720CFFF0", +"000000067F000080000006C00C0000108000-000000067F000080000006C00C000010C000__000000873B520940", +"000000067F000080000006C00C000010C000-000000067F000080000006C00C0000110000__00000086720CFFF0", +"000000067F000080000006C00C000010C000-000000067F000080000006C00C0000110000__000000873B520940", +"000000067F000080000006C00C0000110000-000000067F000080000006C0120100000000__000000873B520940", +"000000067F000080000006C00C0000110000-030000000000000000000000000000000002__00000086720CFFF0", +"000000067F000080000006C00C000011128D-010000000000000001000000030000000017__00000085D35BF439-0000008673817FC9", +"000000067F000080000006C0140000000000-000000067F000080000006C0140000004000__000000873B520940", +"000000067F000080000006C01400000016BC-000000067F000080000006C014000000830F__0000008673817FC9-00000086ED29E361", +"000000067F000080000006C0140000004000-000000067F000080000006C0140000008000__000000873B520940", +"000000067F000080000006C0140000008000-000000067F000080000006C014000000C000__000000873B520940", +"000000067F000080000006C014000000830F-000000067F000080000006C014000000EF5B__0000008673817FC9-00000086ED29E361", +"000000067F000080000006C014000000C000-000000067F000080000006C0140000010000__000000873B520940", +"000000067F000080000006C014000000EF5B-000000067F000080000006C0140000015BA7__0000008673817FC9-00000086ED29E361", +"000000067F000080000006C0140000010000-000000067F000080000006C0140000014000__000000873B520940", +"000000067F000080000006C0140000013636-000000067F000080000006C014000002DB5F__00000086ED29E361-000000873C9A2551", +"000000067F000080000006C0140000014000-000000067F000080000006C0140000018000__000000873B520940", +"000000067F000080000006C0140000015BA7-000000067F000080000006C014000001C7F0__0000008673817FC9-00000086ED29E361", +"000000067F000080000006C0140000018000-000000067F000080000006C014000001C000__000000873B520940", +"000000067F000080000006C014000001C000-000000067F000080000006C0140000020000__000000873B520940", +"000000067F000080000006C014000001C7F0-000000067F000080000006C0140000023430__0000008673817FC9-00000086ED29E361", +"000000067F000080000006C0140000020000-000000067F000080000006C0140000024000__000000873B520940", +"000000067F000080000006C0140000023430-000000067F000080000006C014000002A049__0000008673817FC9-00000086ED29E361", +"000000067F000080000006C0140000024000-000000067F000080000006C0140000028000__000000873B520940", +"000000067F000080000006C0140000028000-000000067F000080000006C014000002C000__000000873B520940", +"000000067F000080000006C014000002A049-030000000000000000000000000000000002__0000008673817FC9-00000086ED29E361", +"000000067F000080000006C014000002C000-030000000000000000000000000000000002__000000873B520940", +"000000067F000080000006C014000002DB60-030000000000000000000000000000000002__00000086ED29E361-000000873C9A2551", +"000000067F000080000006E00C0000000000-000000067F000080000006E00C0000004000__000000890CF51FE0", +"000000067F000080000006E00C0000004000-000000067F000080000006E00C0000008000__000000890CF51FE0", +"000000067F000080000006E00C0000008000-000000067F000080000006E00C000000C000__000000890CF51FE0", +"000000067F000080000006E00C00000096C8-000000067F000080000006E00C0000012E0A__000000873C9A2551-00000087BC75E5B1", +"000000067F000080000006E00C000000C000-000000067F000080000006E00C0000010000__000000890CF51FE0", +"000000067F000080000006E00C0000010000-000000067F000080000006E00C0000014000__000000890CF51FE0", +"000000067F000080000006E00C0000012E0A-000000067F000080000006E00C000001C570__000000873C9A2551-00000087BC75E5B1", +"000000067F000080000006E00C0000014000-000000067F000080000006E00C0000018000__000000890CF51FE0", +"000000067F000080000006E00C0000018000-000000067F000080000006E00C000001C000__000000890CF51FE0", +"000000067F000080000006E00C000001C000-000000067F000080000006E00C0000020000__000000890CF51FE0", +"000000067F000080000006E00C000001C570-000000067F000080000006E00C0000025CD6__000000873C9A2551-00000087BC75E5B1", +"000000067F000080000006E00C0000020000-000000067F000080000006E00C0000024000__000000890CF51FE0", +"000000067F000080000006E00C0000024000-000000067F000080000006E00C0000028000__000000890CF51FE0", +"000000067F000080000006E00C0000025CD6-000000067F000080000006E00C000002F40A__000000873C9A2551-00000087BC75E5B1", +"000000067F000080000006E00C0000028000-000000067F000080000006E00C000002C000__000000890CF51FE0", +"000000067F000080000006E00C000002C000-000000067F000080000006E00C0000030000__000000890CF51FE0", +"000000067F000080000006E00C000002F40A-000000067F000080000006E00C0000038B1D__000000873C9A2551-00000087BC75E5B1", +"000000067F000080000006E00C0000030000-000000067F000080000006E00C0000034000__000000890CF51FE0", +"000000067F000080000006E00C0000034000-000000067F000080000006E00C0000038000__000000890CF51FE0", +"000000067F000080000006E00C0000038000-000000067F000080000006E00C000003C000__000000890CF51FE0", +"000000067F000080000006E00C0000038B1D-000000067F000080000006E00C0000042283__000000873C9A2551-00000087BC75E5B1", +"000000067F000080000006E00C000003C000-000000067F000080000006E00C0000040000__000000890CF51FE0", +"000000067F000080000006E00C0000040000-000000067F000080000006E00C0000044000__000000890CF51FE0", +"000000067F000080000006E00C0000042283-000000067F000080000006E00C000004B9E9__000000873C9A2551-00000087BC75E5B1", +"000000067F000080000006E00C0000044000-000000067F000080000006E00C0000048000__000000890CF51FE0", +"000000067F000080000006E00C0000048000-000000067F000080000006E00C000004C000__000000890AE2DFC8", +"000000067F000080000006E00C0000048000-000000067F000080000006E00C000004C000__00000089D5AEF6E8", +"000000067F000080000006E00C000004B9E9-030000000000000000000000000000000002__000000873C9A2551-00000087BC75E5B1", +"000000067F000080000006E00C000004BACB-000000067F000080000006E00C0000055200__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C000004C000-000000067F000080000006E00C0000050000__000000890AE2DFC8", +"000000067F000080000006E00C000004C000-000000067F000080000006E00C0000050000__00000089D5AEF6E8", +"000000067F000080000006E00C0000050000-000000067F000080000006E00C0000054000__000000890AE2DFC8", +"000000067F000080000006E00C0000050000-000000067F000080000006E00C0000054000__00000089D5AEF6E8", +"000000067F000080000006E00C0000054000-000000067F000080000006E00C0000058000__000000890AE2DFC8", +"000000067F000080000006E00C0000054000-000000067F000080000006E00C0000058000__00000089D5AEF6E8", +"000000067F000080000006E00C0000054246-000000067F000080000006E00C00000A83ED__0000008985FD3611-00000089D6B8EE99", +"000000067F000080000006E00C0000055200-000000067F000080000006E00C000005E90B__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C0000058000-000000067F000080000006E00C000005C000__000000890AE2DFC8", +"000000067F000080000006E00C0000058000-000000067F000080000006E00C000005C000__00000089D5AEF6E8", +"000000067F000080000006E00C000005C000-000000067F000080000006E00C0000060000__000000890AE2DFC8", +"000000067F000080000006E00C000005C000-000000067F000080000006E00C0000060000__00000089D5AEF6E8", +"000000067F000080000006E00C000005E90B-000000067F000080000006E00C000006802B__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C0000060000-000000067F000080000006E00C0000064000__000000890AE2DFC8", +"000000067F000080000006E00C0000060000-000000067F000080000006E00C0000064000__00000089D5AEF6E8", +"000000067F000080000006E00C0000064000-000000067F000080000006E00C0000068000__000000890AE2DFC8", +"000000067F000080000006E00C0000064000-000000067F000080000006E00C0000068000__00000089D5AEF6E8", +"000000067F000080000006E00C0000068000-000000067F000080000006E00C000006C000__000000890AE2DFC8", +"000000067F000080000006E00C0000068000-000000067F000080000006E00C000006C000__00000089D5AEF6E8", +"000000067F000080000006E00C000006802B-000000067F000080000006E00C0000071782__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C000006C000-000000067F000080000006E00C0000070000__000000890AE2DFC8", +"000000067F000080000006E00C000006C000-000000067F000080000006E00C0000070000__00000089D5AEF6E8", +"000000067F000080000006E00C0000070000-000000067F000080000006E00C0000074000__000000890AE2DFC8", +"000000067F000080000006E00C0000070000-000000067F000080000006E00C0000074000__00000089D5AEF6E8", +"000000067F000080000006E00C0000071782-000000067F000080000006E00C000007AEE8__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C0000074000-000000067F000080000006E00C0000078000__000000890AE2DFC8", +"000000067F000080000006E00C0000074000-000000067F000080000006E00C0000078000__00000089D5AEF6E8", +"000000067F000080000006E00C0000078000-000000067F000080000006E00C000007C000__000000890AE2DFC8", +"000000067F000080000006E00C0000078000-000000067F000080000006E00C000007C000__00000089D5AEF6E8", +"000000067F000080000006E00C000007AEE8-000000067F000080000006E00C000008460B__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C000007C000-000000067F000080000006E00C0000080000__000000890AE2DFC8", +"000000067F000080000006E00C000007C000-000000067F000080000006E00C0000080000__00000089D5AEF6E8", +"000000067F000080000006E00C0000080000-000000067F000080000006E00C0000084000__000000890AE2DFC8", +"000000067F000080000006E00C0000080000-000000067F000080000006E00C0000084000__00000089D5AEF6E8", +"000000067F000080000006E00C0000084000-000000067F000080000006E00C0000088000__000000890AE2DFC8", +"000000067F000080000006E00C0000084000-000000067F000080000006E00C0000088000__00000089D5AEF6E8", +"000000067F000080000006E00C000008460B-000000067F000080000006E00C000008DD71__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C0000088000-000000067F000080000006E00C000008C000__000000890AE2DFC8", +"000000067F000080000006E00C0000088000-000000067F000080000006E00C000008C000__00000089D5AEF6E8", +"000000067F000080000006E00C000008C000-000000067F000080000006E00C0000090000__000000890AE2DFC8", +"000000067F000080000006E00C000008C000-000000067F000080000006E00C0000090000__00000089D5AEF6E8", +"000000067F000080000006E00C000008DD71-000000067F000080000006E00C00000974D7__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C0000090000-000000067F000080000006E00C0000094000__000000890AE2DFC8", +"000000067F000080000006E00C0000090000-000000067F000080000006E00C0000094000__00000089D5AEF6E8", +"000000067F000080000006E00C0000094000-000000067F000080000006E00C0000098000__000000890AE2DFC8", +"000000067F000080000006E00C0000094000-000000067F000080000006E00C0000098000__00000089D5AEF6E8", +"000000067F000080000006E00C00000974D7-000000067F000080000006E00C00000A0C0B__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C0000098000-000000067F000080000006E00C000009C000__000000890AE2DFC8", +"000000067F000080000006E00C0000098000-000000067F000080000006E00C000009C000__00000089D5AEF6E8", +"000000067F000080000006E00C000009C000-000000067F000080000006E00C00000A0000__000000890AE2DFC8", +"000000067F000080000006E00C000009C000-000000067F000080000006E00C00000A0000__00000089D5AEF6E8", +"000000067F000080000006E00C00000A0000-000000067F000080000006E00C00000A4000__000000890AE2DFC8", +"000000067F000080000006E00C00000A0000-000000067F000080000006E00C00000A4000__00000089D5AEF6E8", +"000000067F000080000006E00C00000A0C0B-000000067F000080000006E00C00000AA371__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C00000A4000-000000067F000080000006E00C00000A8000__000000890AE2DFC8", +"000000067F000080000006E00C00000A4000-000000067F000080000006E00C00000A8000__00000089D5AEF6E8", +"000000067F000080000006E00C00000A8000-000000067F000080000006E00C00000AC000__000000890AE2DFC8", +"000000067F000080000006E00C00000A8000-000000067F000080000006E00C00000AC000__00000089D5AEF6E8", +"000000067F000080000006E00C00000A8407-000000067F000080000006E00C00000FD787__0000008985FD3611-00000089D6B8EE99", +"000000067F000080000006E00C00000AA371-000000067F000080000006E00C00000B3AD7__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C00000AC000-000000067F000080000006E00C00000B0000__000000890AE2DFC8", +"000000067F000080000006E00C00000AC000-000000067F000080000006E00C00000B0000__00000089D5AEF6E8", +"000000067F000080000006E00C00000B0000-000000067F000080000006E00C00000B4000__000000890AE2DFC8", +"000000067F000080000006E00C00000B0000-000000067F000080000006E00C00000B4000__00000089D5AEF6E8", +"000000067F000080000006E00C00000B3AD7-000000067F000080000006E00C00000BD20B__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C00000B4000-000000067F000080000006E00C00000B8000__000000890AE2DFC8", +"000000067F000080000006E00C00000B4000-000000067F000080000006E00C00000B8000__00000089D5AEF6E8", +"000000067F000080000006E00C00000B6F42-000000067F000080000006E0140000000EEF__000000890C5B6001-0000008985FD3611", +"000000067F000080000006E00C00000B8000-000000067F000080000006E00C00000BC000__000000890AE2DFC8", +"000000067F000080000006E00C00000B8000-000000067F000080000006E00C00000BC000__00000089D5AEF6E8", +"000000067F000080000006E00C00000BC000-000000067F000080000006E00C00000C0000__000000890AE2DFC8", +"000000067F000080000006E00C00000BC000-000000067F000080000006E00C00000C0000__00000089D5AEF6E8", +"000000067F000080000006E00C00000BD20B-000000067F000080000006E00C0100000000__00000087BC75E5B1-000000887C2DFE59", +"000000067F000080000006E00C00000C0000-000000067F000080000006E00C00000C4000__000000890AE2DFC8", +"000000067F000080000006E00C00000C0000-000000067F000080000006E00C00000C4000__00000089D5AEF6E8", +"000000067F000080000006E00C00000C4000-000000067F000080000006E00C00000C8000__000000890AE2DFC8", +"000000067F000080000006E00C00000C4000-000000067F000080000006E00C00000C8000__00000089D5AEF6E8", +"000000067F000080000006E00C00000C5883-000000067F000080000006E00C00000CEFE9__000000887C2DFE59-000000890C5B6001", +"000000067F000080000006E00C00000C8000-000000067F000080000006E00C00000CC000__000000890AE2DFC8", +"000000067F000080000006E00C00000C8000-000000067F000080000006E00C00000CC000__00000089D5AEF6E8", +"000000067F000080000006E00C00000CC000-000000067F000080000006E00C00000D0000__000000890AE2DFC8", +"000000067F000080000006E00C00000CC000-000000067F000080000006E00C00000D0000__00000089D5AEF6E8", +"000000067F000080000006E00C00000CEFE9-000000067F000080000006E00C00000D872B__000000887C2DFE59-000000890C5B6001", +"000000067F000080000006E00C00000D0000-000000067F000080000006E00C00000D4000__000000890AE2DFC8", +"000000067F000080000006E00C00000D0000-000000067F000080000006E00C00000D4000__00000089D5AEF6E8", +"000000067F000080000006E00C00000D4000-000000067F000080000006E00C00000D8000__000000890AE2DFC8", +"000000067F000080000006E00C00000D4000-000000067F000080000006E00C00000D8000__00000089D5AEF6E8", +"000000067F000080000006E00C00000D8000-000000067F000080000006E00C00000DC000__000000890AE2DFC8", +"000000067F000080000006E00C00000D8000-000000067F000080000006E00C00000DC000__00000089D5AEF6E8", +"000000067F000080000006E00C00000D872B-000000067F000080000006E00C00000E1E91__000000887C2DFE59-000000890C5B6001", +"000000067F000080000006E00C00000DC000-000000067F000080000006E00C00000E0000__000000890AE2DFC8", +"000000067F000080000006E00C00000DC000-000000067F000080000006E00C00000E0000__00000089D5AEF6E8", +"000000067F000080000006E00C00000E0000-000000067F000080000006E00C00000E4000__000000890AE2DFC8", +"000000067F000080000006E00C00000E0000-000000067F000080000006E00C00000E4000__00000089D5AEF6E8", +"000000067F000080000006E00C00000E1E91-000000067F000080000006E00C00000EB5F7__000000887C2DFE59-000000890C5B6001", +"000000067F000080000006E00C00000E4000-000000067F000080000006E00C00000E8000__000000890AE2DFC8", +"000000067F000080000006E00C00000E4000-000000067F000080000006E00C00000E8000__00000089D5AEF6E8", +"000000067F000080000006E00C00000E8000-000000067F000080000006E00C00000EC000__000000890AE2DFC8", +"000000067F000080000006E00C00000E8000-000000067F000080000006E00C00000EC000__00000089D5AEF6E8", +"000000067F000080000006E00C00000EB5F7-000000067F000080000006E00C00000F4D0C__000000887C2DFE59-000000890C5B6001", +"000000067F000080000006E00C00000EC000-000000067F000080000006E00C00000F0000__000000890AE2DFC8", +"000000067F000080000006E00C00000EC000-000000067F000080000006E00C00000F0000__00000089D5AEF6E8", +"000000067F000080000006E00C00000F0000-000000067F000080000006E00C00000F4000__000000890AE2DFC8", +"000000067F000080000006E00C00000F0000-000000067F000080000006E00C00000F4000__00000089D5AEF6E8", +"000000067F000080000006E00C00000F4000-000000067F000080000006E00C00000F8000__000000890AE2DFC8", +"000000067F000080000006E00C00000F4000-000000067F000080000006E00C00000F8000__00000089D5AEF6E8", +"000000067F000080000006E00C00000F4D0C-000000067F000080000006E00C00000FE472__000000887C2DFE59-000000890C5B6001", +"000000067F000080000006E00C00000F8000-000000067F000080000006E00C00000FC000__000000890AE2DFC8", +"000000067F000080000006E00C00000F8000-000000067F000080000006E00C00000FC000__00000089D5AEF6E8", +"000000067F000080000006E00C00000FC000-000000067F000080000006E00C0000100000__000000890AE2DFC8", +"000000067F000080000006E00C00000FC000-000000067F000080000006E00C0000100000__00000089D5AEF6E8", +"000000067F000080000006E00C00000FD78D-000000067F000080000006E0140000011DB5__0000008985FD3611-00000089D6B8EE99", +"000000067F000080000006E00C00000FE472-000000067F000080000006E00C0000107B8E__000000887C2DFE59-000000890C5B6001", +"000000067F000080000006E00C0000100000-000000067F000080000006E00C0000104000__000000890AE2DFC8", +"000000067F000080000006E00C0000100000-000000067F000080000006E00C0000104000__00000089D5AEF6E8", +"000000067F000080000006E00C0000104000-000000067F000080000006E00C0000108000__000000890AE2DFC8", +"000000067F000080000006E00C0000104000-000000067F000080000006E00C0000108000__00000089D5AEF6E8", +"000000067F000080000006E00C0000107B8E-000000067F000080000006E00C00001112F4__000000887C2DFE59-000000890C5B6001", +"000000067F000080000006E00C0000108000-000000067F000080000006E00C000010C000__000000890AE2DFC8", +"000000067F000080000006E00C0000108000-000000067F000080000006E00C000010C000__00000089D5AEF6E8", +"000000067F000080000006E00C000010C000-000000067F000080000006E00C0000110000__000000890AE2DFC8", +"000000067F000080000006E00C000010C000-000000067F000080000006E00C0000110000__00000089D5AEF6E8", +"000000067F000080000006E00C0000110000-000000067F000080000006E0120100000000__00000089D5AEF6E8", +"000000067F000080000006E00C0000110000-030000000000000000000000000000000002__000000890AE2DFC8", +"000000067F000080000006E00C00001112F4-01000000000000000100000003000000001A__000000887C2DFE59-000000890C5B6001", +"000000067F000080000006E0140000000000-000000067F000080000006E0140000004000__00000089D5AEF6E8", +"000000067F000080000006E0140000000EEF-000000067F000080000006E0140000007C4F__000000890C5B6001-0000008985FD3611", +"000000067F000080000006E0140000004000-000000067F000080000006E0140000008000__00000089D5AEF6E8", +"000000067F000080000006E0140000007C4F-000000067F000080000006E014000000E97E__000000890C5B6001-0000008985FD3611", +"000000067F000080000006E0140000008000-000000067F000080000006E014000000C000__00000089D5AEF6E8", +"000000067F000080000006E014000000C000-000000067F000080000006E0140000010000__00000089D5AEF6E8", +"000000067F000080000006E014000000E97E-000000067F000080000006E01400000156DC__000000890C5B6001-0000008985FD3611", +"000000067F000080000006E0140000010000-000000067F000080000006E0140000014000__00000089D5AEF6E8", +"000000067F000080000006E0140000011DB5-000000067F000080000006E014000002B9CE__0000008985FD3611-00000089D6B8EE99", +"000000067F000080000006E0140000014000-000000067F000080000006E0140000018000__00000089D5AEF6E8", +"000000067F000080000006E01400000156DC-000000067F000080000006E014000001C468__000000890C5B6001-0000008985FD3611", +"000000067F000080000006E0140000018000-000000067F000080000006E014000001C000__00000089D5AEF6E8", +"000000067F000080000006E014000001C000-000000067F000080000006E0140000020000__00000089D5AEF6E8", +"000000067F000080000006E014000001C468-000000067F000080000006E01400000231D5__000000890C5B6001-0000008985FD3611", +"000000067F000080000006E0140000020000-000000067F000080000006E0140000024000__00000089D5AEF6E8", +"000000067F000080000006E01400000231D5-000000067F000080000006E0140000029F96__000000890C5B6001-0000008985FD3611", +"000000067F000080000006E0140000024000-000000067F000080000006E0140000028000__00000089D5AEF6E8", +"000000067F000080000006E0140000028000-000000067F000080000006E014000002C000__00000089D5AEF6E8", +"000000067F000080000006E0140000029F96-030000000000000000000000000000000002__000000890C5B6001-0000008985FD3611", +"000000067F000080000006E014000002B9D0-030000000000000000000000000000000002__0000008985FD3611-00000089D6B8EE99", +"000000067F000080000006E014000002C000-030000000000000000000000000000000002__00000089D5AEF6E8", +"000000067F000080000007000C0000000000-000000067F000080000007000C0000004000__0000008BA730BFE8", +"000000067F000080000007000C0000004000-000000067F000080000007000C0000008000__0000008BA730BFE8", +"000000067F000080000007000C0000008000-000000067F000080000007000C000000C000__0000008BA730BFE8", +"000000067F000080000007000C000000955C-000000067F000080000007000C0000012CC2__00000089D6B8EE99-0000008A56BBF739", +"000000067F000080000007000C000000C000-000000067F000080000007000C0000010000__0000008BA730BFE8", +"000000067F000080000007000C0000010000-000000067F000080000007000C0000014000__0000008BA730BFE8", +"000000067F000080000007000C0000012CC2-000000067F000080000007000C000001C40A__00000089D6B8EE99-0000008A56BBF739", +"000000067F000080000007000C0000014000-000000067F000080000007000C0000018000__0000008BA730BFE8", +"000000067F000080000007000C0000018000-000000067F000080000007000C000001C000__0000008BA730BFE8", +"000000067F000080000007000C000001C000-000000067F000080000007000C0000020000__0000008BA730BFE8", +"000000067F000080000007000C000001C40A-000000067F000080000007000C0000025B39__00000089D6B8EE99-0000008A56BBF739", +"000000067F000080000007000C0000020000-000000067F000080000007000C0000024000__0000008BA730BFE8", +"000000067F000080000007000C0000024000-000000067F000080000007000C0000028000__0000008BA730BFE8", +"000000067F000080000007000C0000025B39-000000067F000080000007000C000002F29F__00000089D6B8EE99-0000008A56BBF739", +"000000067F000080000007000C0000028000-000000067F000080000007000C000002C000__0000008BA730BFE8", +"000000067F000080000007000C000002C000-000000067F000080000007000C0000030000__0000008BA730BFE8", +"000000067F000080000007000C000002F29F-000000067F000080000007000C00000389B3__00000089D6B8EE99-0000008A56BBF739", +"000000067F000080000007000C0000030000-000000067F000080000007000C0000034000__0000008BA730BFE8", +"000000067F000080000007000C0000034000-000000067F000080000007000C0000038000__0000008BA730BFE8", +"000000067F000080000007000C0000038000-000000067F000080000007000C000003C000__0000008BA730BFE8", +"000000067F000080000007000C00000389B3-000000067F000080000007000C0000042119__00000089D6B8EE99-0000008A56BBF739", +"000000067F000080000007000C000003C000-000000067F000080000007000C0000040000__0000008BA730BFE8", +"000000067F000080000007000C0000040000-000000067F000080000007000C0000044000__0000008BA730BFE8", +"000000067F000080000007000C0000042119-000000067F000080000007000C000004B87F__00000089D6B8EE99-0000008A56BBF739", +"000000067F000080000007000C0000044000-000000067F000080000007000C0000048000__0000008BA730BFE8", +"000000067F000080000007000C0000048000-000000067F000080000007000C000004C000__0000008B9669EDB0", +"000000067F000080000007000C0000048000-000000067F000080000007000C000004C000__0000008C71903720", +"000000067F000080000007000C000004B87F-030000000000000000000000000000000002__00000089D6B8EE99-0000008A56BBF739", +"000000067F000080000007000C000004BAD3-000000067F000080000007000C0000055207__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C000004C000-000000067F000080000007000C0000050000__0000008B9669EDB0", +"000000067F000080000007000C000004C000-000000067F000080000007000C0000050000__0000008C71903720", +"000000067F000080000007000C0000050000-000000067F000080000007000C0000054000__0000008B9669EDB0", +"000000067F000080000007000C0000050000-000000067F000080000007000C0000054000__0000008C71903720", +"000000067F000080000007000C0000053C23-000000067F000080000007000C00000A6F76__0000008C2045B721-0000008C72843D41", +"000000067F000080000007000C0000054000-000000067F000080000007000C0000058000__0000008B9669EDB0", +"000000067F000080000007000C0000054000-000000067F000080000007000C0000058000__0000008C71903720", +"000000067F000080000007000C0000055207-000000067F000080000007000C000005E912__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C0000058000-000000067F000080000007000C000005C000__0000008B9669EDB0", +"000000067F000080000007000C0000058000-000000067F000080000007000C000005C000__0000008C71903720", +"000000067F000080000007000C000005C000-000000067F000080000007000C0000060000__0000008B9669EDB0", +"000000067F000080000007000C000005C000-000000067F000080000007000C0000060000__0000008C71903720", +"000000067F000080000007000C000005E912-000000067F000080000007000C000006802C__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C0000060000-000000067F000080000007000C0000064000__0000008B9669EDB0", +"000000067F000080000007000C0000060000-000000067F000080000007000C0000064000__0000008C71903720", +"000000067F000080000007000C0000064000-000000067F000080000007000C0000068000__0000008B9669EDB0", +"000000067F000080000007000C0000064000-000000067F000080000007000C0000068000__0000008C71903720", +"000000067F000080000007000C0000068000-000000067F000080000007000C000006C000__0000008B9669EDB0", +"000000067F000080000007000C0000068000-000000067F000080000007000C000006C000__0000008C71903720", +"000000067F000080000007000C000006802C-000000067F000080000007000C0000071783__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C000006C000-000000067F000080000007000C0000070000__0000008B9669EDB0", +"000000067F000080000007000C000006C000-000000067F000080000007000C0000070000__0000008C71903720", +"000000067F000080000007000C0000070000-000000067F000080000007000C0000074000__0000008B9669EDB0", +"000000067F000080000007000C0000070000-000000067F000080000007000C0000074000__0000008C71903720", +"000000067F000080000007000C0000071783-000000067F000080000007000C000007AEE9__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C0000074000-000000067F000080000007000C0000078000__0000008B9669EDB0", +"000000067F000080000007000C0000074000-000000067F000080000007000C0000078000__0000008C71903720", +"000000067F000080000007000C0000078000-000000067F000080000007000C000007C000__0000008B9669EDB0", +"000000067F000080000007000C0000078000-000000067F000080000007000C000007C000__0000008C71903720", +"000000067F000080000007000C000007AEE9-000000067F000080000007000C000008460B__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C000007C000-000000067F000080000007000C0000080000__0000008B9669EDB0", +"000000067F000080000007000C000007C000-000000067F000080000007000C0000080000__0000008C71903720", +"000000067F000080000007000C0000080000-000000067F000080000007000C0000084000__0000008B9669EDB0", +"000000067F000080000007000C0000080000-000000067F000080000007000C0000084000__0000008C71903720", +"000000067F000080000007000C0000084000-000000067F000080000007000C0000088000__0000008B9669EDB0", +"000000067F000080000007000C0000084000-000000067F000080000007000C0000088000__0000008C71903720", +"000000067F000080000007000C000008460B-000000067F000080000007000C000008DD71__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C0000088000-000000067F000080000007000C000008C000__0000008B9669EDB0", +"000000067F000080000007000C0000088000-000000067F000080000007000C000008C000__0000008C71903720", +"000000067F000080000007000C000008C000-000000067F000080000007000C0000090000__0000008B9669EDB0", +"000000067F000080000007000C000008C000-000000067F000080000007000C0000090000__0000008C71903720", +"000000067F000080000007000C000008DD71-000000067F000080000007000C00000974D7__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C0000090000-000000067F000080000007000C0000094000__0000008B9669EDB0", +"000000067F000080000007000C0000090000-000000067F000080000007000C0000094000__0000008C71903720", +"000000067F000080000007000C0000094000-000000067F000080000007000C0000098000__0000008B9669EDB0", +"000000067F000080000007000C0000094000-000000067F000080000007000C0000098000__0000008C71903720", +"000000067F000080000007000C00000974D7-000000067F000080000007000C00000A0C0B__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C0000098000-000000067F000080000007000C000009C000__0000008B9669EDB0", +"000000067F000080000007000C0000098000-000000067F000080000007000C000009C000__0000008C71903720", +"000000067F000080000007000C000009C000-000000067F000080000007000C00000A0000__0000008B9669EDB0", +"000000067F000080000007000C000009C000-000000067F000080000007000C00000A0000__0000008C71903720", +"000000067F000080000007000C00000A0000-000000067F000080000007000C00000A4000__0000008B9669EDB0", +"000000067F000080000007000C00000A0000-000000067F000080000007000C00000A4000__0000008C71903720", +"000000067F000080000007000C00000A0C0B-000000067F000080000007000C00000AA371__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C00000A4000-000000067F000080000007000C00000A8000__0000008B9669EDB0", +"000000067F000080000007000C00000A4000-000000067F000080000007000C00000A8000__0000008C71903720", +"000000067F000080000007000C00000A6F77-000000067F000080000007000C00000FA170__0000008C2045B721-0000008C72843D41", +"000000067F000080000007000C00000A8000-000000067F000080000007000C00000AC000__0000008B9669EDB0", +"000000067F000080000007000C00000A8000-000000067F000080000007000C00000AC000__0000008C71903720", +"000000067F000080000007000C00000AA371-000000067F000080000007000C0100000000__0000008A56BBF739-0000008AF67FEC19", +"000000067F000080000007000C00000AC000-000000067F000080000007000C00000B0000__0000008B9669EDB0", +"000000067F000080000007000C00000AC000-000000067F000080000007000C00000B0000__0000008C71903720", +"000000067F000080000007000C00000B0000-000000067F000080000007000C00000B4000__0000008B9669EDB0", +"000000067F000080000007000C00000B0000-000000067F000080000007000C00000B4000__0000008C71903720", +"000000067F000080000007000C00000B2B06-000000067F000080000007000C00000BC211__0000008AF67FEC19-0000008BA6803FC9", +"000000067F000080000007000C00000B4000-000000067F000080000007000C00000B8000__0000008B9669EDB0", +"000000067F000080000007000C00000B4000-000000067F000080000007000C00000B8000__0000008C71903720", +"000000067F000080000007000C00000B8000-000000067F000080000007000C00000BC000__0000008B9669EDB0", +"000000067F000080000007000C00000B8000-000000067F000080000007000C00000BC000__0000008C71903720", +"000000067F000080000007000C00000BC000-000000067F000080000007000C00000C0000__0000008B9669EDB0", +"000000067F000080000007000C00000BC000-000000067F000080000007000C00000C0000__0000008C71903720", +"000000067F000080000007000C00000BC211-000000067F000080000007000C00000C5941__0000008AF67FEC19-0000008BA6803FC9", +"000000067F000080000007000C00000BF157-000000067F000080000007001400000016B2__0000008BA6803FC9-0000008C2045B721", +"000000067F000080000007000C00000C0000-000000067F000080000007000C00000C4000__0000008B9669EDB0", +"000000067F000080000007000C00000C0000-000000067F000080000007000C00000C4000__0000008C71903720", +"000000067F000080000007000C00000C4000-000000067F000080000007000C00000C8000__0000008B9669EDB0", +"000000067F000080000007000C00000C4000-000000067F000080000007000C00000C8000__0000008C71903720", +"000000067F000080000007000C00000C5941-000000067F000080000007000C00000CF0A7__0000008AF67FEC19-0000008BA6803FC9", +"000000067F000080000007000C00000C8000-000000067F000080000007000C00000CC000__0000008B9669EDB0", +"000000067F000080000007000C00000C8000-000000067F000080000007000C00000CC000__0000008C71903720", +"000000067F000080000007000C00000CC000-000000067F000080000007000C00000D0000__0000008B9669EDB0", +"000000067F000080000007000C00000CC000-000000067F000080000007000C00000D0000__0000008C71903720", +"000000067F000080000007000C00000CF0A7-000000067F000080000007000C00000D87BC__0000008AF67FEC19-0000008BA6803FC9", +"000000067F000080000007000C00000D0000-000000067F000080000007000C00000D4000__0000008B9669EDB0", +"000000067F000080000007000C00000D0000-000000067F000080000007000C00000D4000__0000008C71903720", +"000000067F000080000007000C00000D4000-000000067F000080000007000C00000D8000__0000008B9669EDB0", +"000000067F000080000007000C00000D4000-000000067F000080000007000C00000D8000__0000008C71903720", +"000000067F000080000007000C00000D8000-000000067F000080000007000C00000DC000__0000008B9669EDB0", +"000000067F000080000007000C00000D8000-000000067F000080000007000C00000DC000__0000008C71903720", +"000000067F000080000007000C00000D87BC-000000067F000080000007000C00000E1F0A__0000008AF67FEC19-0000008BA6803FC9", +"000000067F000080000007000C00000DC000-000000067F000080000007000C00000E0000__0000008B9669EDB0", +"000000067F000080000007000C00000DC000-000000067F000080000007000C00000E0000__0000008C71903720", +"000000067F000080000007000C00000E0000-000000067F000080000007000C00000E4000__0000008B9669EDB0", +"000000067F000080000007000C00000E0000-000000067F000080000007000C00000E4000__0000008C71903720", +"000000067F000080000007000C00000E1F0A-000000067F000080000007000C00000EB670__0000008AF67FEC19-0000008BA6803FC9", +"000000067F000080000007000C00000E4000-000000067F000080000007000C00000E8000__0000008B9669EDB0", +"000000067F000080000007000C00000E4000-000000067F000080000007000C00000E8000__0000008C71903720", +"000000067F000080000007000C00000E8000-000000067F000080000007000C00000EC000__0000008B9669EDB0", +"000000067F000080000007000C00000E8000-000000067F000080000007000C00000EC000__0000008C71903720", +"000000067F000080000007000C00000EB670-000000067F000080000007000C00000F4DA7__0000008AF67FEC19-0000008BA6803FC9", +"000000067F000080000007000C00000EC000-000000067F000080000007000C00000F0000__0000008B9669EDB0", +"000000067F000080000007000C00000EC000-000000067F000080000007000C00000F0000__0000008C71903720", +"000000067F000080000007000C00000F0000-000000067F000080000007000C00000F4000__0000008B9669EDB0", +"000000067F000080000007000C00000F0000-000000067F000080000007000C00000F4000__0000008C71903720", +"000000067F000080000007000C00000F4000-000000067F000080000007000C00000F8000__0000008B9669EDB0", +"000000067F000080000007000C00000F4000-000000067F000080000007000C00000F8000__0000008C71903720", +"000000067F000080000007000C00000F4DA7-000000067F000080000007000C00000FE509__0000008AF67FEC19-0000008BA6803FC9", +"000000067F000080000007000C00000F8000-000000067F000080000007000C00000FC000__0000008B9669EDB0", +"000000067F000080000007000C00000F8000-000000067F000080000007000C00000FC000__0000008C71903720", +"000000067F000080000007000C00000FA175-000000067F00008000000700140000010412__0000008C2045B721-0000008C72843D41", +"000000067F000080000007000C00000FC000-000000067F000080000007000C0000100000__0000008B9669EDB0", +"000000067F000080000007000C00000FC000-000000067F000080000007000C0000100000__0000008C71903720", +"000000067F000080000007000C00000FE509-000000067F000080000007000C0000107C2B__0000008AF67FEC19-0000008BA6803FC9", +"000000067F000080000007000C0000100000-000000067F000080000007000C0000104000__0000008B9669EDB0", +"000000067F000080000007000C0000100000-000000067F000080000007000C0000104000__0000008C71903720", +"000000067F000080000007000C0000104000-000000067F000080000007000C0000108000__0000008B9669EDB0", +"000000067F000080000007000C0000104000-000000067F000080000007000C0000108000__0000008C71903720", +"000000067F000080000007000C0000107C2B-000000067F000080000007000C0000111385__0000008AF67FEC19-0000008BA6803FC9", +"000000067F000080000007000C0000108000-000000067F000080000007000C000010C000__0000008C71903720", +"000000067F000080000007000C0000108000-030000000000000000000000000000000002__0000008B9669EDB0", +"000000067F000080000007000C000010C000-000000067F000080000007000C0000110000__0000008C71903720", +"000000067F000080000007000C0000110000-000000067F00008000000700120100000000__0000008C71903720", +"000000067F000080000007000C0000111385-01000000000000000100000003000000001E__0000008AF67FEC19-0000008BA6803FC9", +"000000067F00008000000700140000000000-000000067F00008000000700140000004000__0000008C71903720", +"000000067F000080000007001400000016B2-000000067F000080000007001400000082A6__0000008BA6803FC9-0000008C2045B721", +"000000067F00008000000700140000004000-000000067F00008000000700140000008000__0000008C71903720", +"000000067F00008000000700140000008000-000000067F0000800000070014000000C000__0000008C71903720", +"000000067F000080000007001400000082A6-000000067F0000800000070014000000EED0__0000008BA6803FC9-0000008C2045B721", +"000000067F0000800000070014000000C000-000000067F00008000000700140000010000__0000008C71903720", +"000000067F0000800000070014000000EED0-000000067F00008000000700140000015ADC__0000008BA6803FC9-0000008C2045B721", +"000000067F00008000000700140000010000-000000067F00008000000700140000014000__0000008C71903720", +"000000067F0000800000070014000001041E-000000067F000080000007001400000294B8__0000008C2045B721-0000008C72843D41", +"000000067F00008000000700140000014000-000000067F00008000000700140000018000__0000008C71903720", +"000000067F00008000000700140000015ADC-000000067F0000800000070014000001C6D6__0000008BA6803FC9-0000008C2045B721", +"000000067F00008000000700140000018000-000000067F0000800000070014000001C000__0000008C71903720", +"000000067F0000800000070014000001C000-000000067F00008000000700140000020000__0000008C71903720", +"000000067F0000800000070014000001C6D6-000000067F000080000007001400000232FD__0000008BA6803FC9-0000008C2045B721", +"000000067F00008000000700140000020000-000000067F00008000000700140000024000__0000008C71903720", +"000000067F000080000007001400000232FD-000000067F00008000000700140000029F07__0000008BA6803FC9-0000008C2045B721", +"000000067F00008000000700140000024000-000000067F00008000000700140000028000__0000008C71903720", +"000000067F00008000000700140000028000-000000067F0000800000070014000002C000__0000008C71903720", +"000000067F000080000007001400000294BA-030000000000000000000000000000000002__0000008C2045B721-0000008C72843D41", +"000000067F00008000000700140000029F07-030000000000000000000000000000000002__0000008BA6803FC9-0000008C2045B721", +"000000067F0000800000070014000002C000-030000000000000000000000000000000002__0000008C71903720", +"000000067F000080000007200C0000000000-000000067F000080000007200C0000004000__0000008E43487FF0", +"000000067F000080000007200C0000004000-000000067F000080000007200C0000008000__0000008E43487FF0", +"000000067F000080000007200C0000008000-000000067F000080000007200C000000C000__0000008E43487FF0", +"000000067F000080000007200C000000933D-000000067F000080000007200C0000012AA3__0000008C72843D41-0000008CF2BFFC89", +"000000067F000080000007200C000000C000-000000067F000080000007200C0000010000__0000008E43487FF0", +"000000067F000080000007200C0000010000-000000067F000080000007200C0000014000__0000008E43487FF0", +"000000067F000080000007200C0000012AA3-000000067F000080000007200C000001C209__0000008C72843D41-0000008CF2BFFC89", +"000000067F000080000007200C0000014000-000000067F000080000007200C0000018000__0000008E43487FF0", +"000000067F000080000007200C0000018000-000000067F000080000007200C000001C000__0000008E43487FF0", +"000000067F000080000007200C000001C000-000000067F000080000007200C0000020000__0000008E43487FF0", +"000000067F000080000007200C000001C209-000000067F000080000007200C0000025939__0000008C72843D41-0000008CF2BFFC89", +"000000067F000080000007200C0000020000-000000067F000080000007200C0000024000__0000008E43487FF0", +"000000067F000080000007200C0000024000-000000067F000080000007200C0000028000__0000008E43487FF0", +"000000067F000080000007200C0000025939-000000067F000080000007200C000002F09F__0000008C72843D41-0000008CF2BFFC89", +"000000067F000080000007200C0000028000-000000067F000080000007200C000002C000__0000008E43487FF0", +"000000067F000080000007200C000002C000-000000067F000080000007200C0000030000__0000008E43487FF0", +"000000067F000080000007200C000002F09F-000000067F000080000007200C00000387B4__0000008C72843D41-0000008CF2BFFC89", +"000000067F000080000007200C0000030000-000000067F000080000007200C0000034000__0000008E43487FF0", +"000000067F000080000007200C0000034000-000000067F000080000007200C0000038000__0000008E43487FF0", +"000000067F000080000007200C0000038000-000000067F000080000007200C000003C000__0000008E43487FF0", +"000000067F000080000007200C00000387B4-000000067F000080000007200C0000041F1A__0000008C72843D41-0000008CF2BFFC89", +"000000067F000080000007200C000003C000-000000067F000080000007200C0000040000__0000008E43487FF0", +"000000067F000080000007200C0000040000-000000067F000080000007200C0000044000__0000008E43487FF0", +"000000067F000080000007200C0000041F1A-000000067F000080000007200C000004B680__0000008C72843D41-0000008CF2BFFC89", +"000000067F000080000007200C0000044000-000000067F000080000007200C0000048000__0000008E43487FF0", +"000000067F000080000007200C0000048000-000000067F000080000007200C000004C000__0000008E3CDF59C0", +"000000067F000080000007200C0000048000-000000067F000080000007200C000004C000__0000008F10EA21C8", +"000000067F000080000007200C000004B680-030000000000000000000000000000000002__0000008C72843D41-0000008CF2BFFC89", +"000000067F000080000007200C000004BACE-000000067F000080000007200C0000055202__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C000004C000-000000067F000080000007200C0000050000__0000008E3CDF59C0", +"000000067F000080000007200C000004C000-000000067F000080000007200C0000050000__0000008F10EA21C8", +"000000067F000080000007200C0000050000-000000067F000080000007200C0000054000__0000008E3CDF59C0", +"000000067F000080000007200C0000050000-000000067F000080000007200C0000054000__0000008F10EA21C8", +"000000067F000080000007200C000005131D-000000067F000080000007200C00000A2138__0000008EBC4827C1-0000008F10E3E189", +"000000067F000080000007200C0000054000-000000067F000080000007200C0000058000__0000008E3CDF59C0", +"000000067F000080000007200C0000054000-000000067F000080000007200C0000058000__0000008F10EA21C8", +"000000067F000080000007200C0000055202-000000067F000080000007200C000005E90D__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C0000058000-000000067F000080000007200C000005C000__0000008E3CDF59C0", +"000000067F000080000007200C0000058000-000000067F000080000007200C000005C000__0000008F10EA21C8", +"000000067F000080000007200C000005C000-000000067F000080000007200C0000060000__0000008E3CDF59C0", +"000000067F000080000007200C000005C000-000000067F000080000007200C0000060000__0000008F10EA21C8", +"000000067F000080000007200C000005E90D-000000067F000080000007200C000006802B__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C0000060000-000000067F000080000007200C0000064000__0000008E3CDF59C0", +"000000067F000080000007200C0000060000-000000067F000080000007200C0000064000__0000008F10EA21C8", +"000000067F000080000007200C0000064000-000000067F000080000007200C0000068000__0000008E3CDF59C0", +"000000067F000080000007200C0000064000-000000067F000080000007200C0000068000__0000008F10EA21C8", +"000000067F000080000007200C0000068000-000000067F000080000007200C000006C000__0000008E3CDF59C0", +"000000067F000080000007200C0000068000-000000067F000080000007200C000006C000__0000008F10EA21C8", +"000000067F000080000007200C000006802B-000000067F000080000007200C0000071782__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C000006C000-000000067F000080000007200C0000070000__0000008E3CDF59C0", +"000000067F000080000007200C000006C000-000000067F000080000007200C0000070000__0000008F10EA21C8", +"000000067F000080000007200C0000070000-000000067F000080000007200C0000074000__0000008E3CDF59C0", +"000000067F000080000007200C0000070000-000000067F000080000007200C0000074000__0000008F10EA21C8", +"000000067F000080000007200C0000071782-000000067F000080000007200C000007AEE8__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C0000074000-000000067F000080000007200C0000078000__0000008E3CDF59C0", +"000000067F000080000007200C0000074000-000000067F000080000007200C0000078000__0000008F10EA21C8", +"000000067F000080000007200C0000078000-000000067F000080000007200C000007C000__0000008E3CDF59C0", +"000000067F000080000007200C0000078000-000000067F000080000007200C000007C000__0000008F10EA21C8", +"000000067F000080000007200C000007AEE8-000000067F000080000007200C000008460B__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C000007C000-000000067F000080000007200C0000080000__0000008E3CDF59C0", +"000000067F000080000007200C000007C000-000000067F000080000007200C0000080000__0000008F10EA21C8", +"000000067F000080000007200C0000080000-000000067F000080000007200C0000084000__0000008E3CDF59C0", +"000000067F000080000007200C0000080000-000000067F000080000007200C0000084000__0000008F10EA21C8", +"000000067F000080000007200C0000084000-000000067F000080000007200C0000088000__0000008E3CDF59C0", +"000000067F000080000007200C0000084000-000000067F000080000007200C0000088000__0000008F10EA21C8", +"000000067F000080000007200C000008460B-000000067F000080000007200C000008DD71__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C0000088000-000000067F000080000007200C000008C000__0000008E3CDF59C0", +"000000067F000080000007200C0000088000-000000067F000080000007200C000008C000__0000008F10EA21C8", +"000000067F000080000007200C000008C000-000000067F000080000007200C0000090000__0000008E3CDF59C0", +"000000067F000080000007200C000008C000-000000067F000080000007200C0000090000__0000008F10EA21C8", +"000000067F000080000007200C000008DD71-000000067F000080000007200C00000974D7__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C0000090000-000000067F000080000007200C0000094000__0000008E3CDF59C0", +"000000067F000080000007200C0000090000-000000067F000080000007200C0000094000__0000008F10EA21C8", +"000000067F000080000007200C0000094000-000000067F000080000007200C0000098000__0000008E3CDF59C0", +"000000067F000080000007200C0000094000-000000067F000080000007200C0000098000__0000008F10EA21C8", +"000000067F000080000007200C00000974D7-000000067F000080000007200C00000A0C0B__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C0000098000-000000067F000080000007200C000009C000__0000008E3CDF59C0", +"000000067F000080000007200C0000098000-000000067F000080000007200C000009C000__0000008F10EA21C8", +"000000067F000080000007200C000009C000-000000067F000080000007200C00000A0000__0000008E3CDF59C0", +"000000067F000080000007200C000009C000-000000067F000080000007200C00000A0000__0000008F10EA21C8", +"000000067F000080000007200C00000A0000-000000067F000080000007200C00000A4000__0000008E3CDF59C0", +"000000067F000080000007200C00000A0000-000000067F000080000007200C00000A4000__0000008F10EA21C8", +"000000067F000080000007200C00000A0C0B-000000067F000080000007200C00000AA371__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C00000A2138-000000067F000080000007200C00000F342E__0000008EBC4827C1-0000008F10E3E189", +"000000067F000080000007200C00000A4000-000000067F000080000007200C00000A8000__0000008E3CDF59C0", +"000000067F000080000007200C00000A4000-000000067F000080000007200C00000A8000__0000008F10EA21C8", +"000000067F000080000007200C00000A8000-000000067F000080000007200C00000AC000__0000008E3CDF59C0", +"000000067F000080000007200C00000A8000-000000067F000080000007200C00000AC000__0000008F10EA21C8", +"000000067F000080000007200C00000AA371-000000067F000080000007200C00000B3AD7__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C00000AC000-000000067F000080000007200C00000B0000__0000008E3CDF59C0", +"000000067F000080000007200C00000AC000-000000067F000080000007200C00000B0000__0000008F10EA21C8", +"000000067F000080000007200C00000B0000-000000067F000080000007200C00000B4000__0000008E3CDF59C0", +"000000067F000080000007200C00000B0000-000000067F000080000007200C00000B4000__0000008F10EA21C8", +"000000067F000080000007200C00000B3AD7-000000067F000080000007200C00000BD20B__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C00000B4000-000000067F000080000007200C00000B8000__0000008E3CDF59C0", +"000000067F000080000007200C00000B4000-000000067F000080000007200C00000B8000__0000008F10EA21C8", +"000000067F000080000007200C00000B8000-000000067F000080000007200C00000BC000__0000008E3CDF59C0", +"000000067F000080000007200C00000B8000-000000067F000080000007200C00000BC000__0000008F10EA21C8", +"000000067F000080000007200C00000BA086-000000067F00008000000720140000001101__0000008E42A19FD1-0000008EBC4827C1", +"000000067F000080000007200C00000BC000-000000067F000080000007200C00000C0000__0000008E3CDF59C0", +"000000067F000080000007200C00000BC000-000000067F000080000007200C00000C0000__0000008F10EA21C8", +"000000067F000080000007200C00000BD20B-000000067F000080000007200C0100000000__0000008CF2BFFC89-0000008DB277FA49", +"000000067F000080000007200C00000C0000-000000067F000080000007200C00000C4000__0000008E3CDF59C0", +"000000067F000080000007200C00000C0000-000000067F000080000007200C00000C4000__0000008F10EA21C8", +"000000067F000080000007200C00000C4000-000000067F000080000007200C00000C8000__0000008E3CDF59C0", +"000000067F000080000007200C00000C4000-000000067F000080000007200C00000C8000__0000008F10EA21C8", +"000000067F000080000007200C00000C58B0-000000067F000080000007200C00000CF00A__0000008DB277FA49-0000008E42A19FD1", +"000000067F000080000007200C00000C8000-000000067F000080000007200C00000CC000__0000008E3CDF59C0", +"000000067F000080000007200C00000C8000-000000067F000080000007200C00000CC000__0000008F10EA21C8", +"000000067F000080000007200C00000CC000-000000067F000080000007200C00000D0000__0000008E3CDF59C0", +"000000067F000080000007200C00000CC000-000000067F000080000007200C00000D0000__0000008F10EA21C8", +"000000067F000080000007200C00000CF00A-000000067F000080000007200C00000D871F__0000008DB277FA49-0000008E42A19FD1", +"000000067F000080000007200C00000D0000-000000067F000080000007200C00000D4000__0000008E3CDF59C0", +"000000067F000080000007200C00000D0000-000000067F000080000007200C00000D4000__0000008F10EA21C8", +"000000067F000080000007200C00000D4000-000000067F000080000007200C00000D8000__0000008E3CDF59C0", +"000000067F000080000007200C00000D4000-000000067F000080000007200C00000D8000__0000008F10EA21C8", +"000000067F000080000007200C00000D8000-000000067F000080000007200C00000DC000__0000008E3CDF59C0", +"000000067F000080000007200C00000D8000-000000067F000080000007200C00000DC000__0000008F10EA21C8", +"000000067F000080000007200C00000D871F-000000067F000080000007200C00000E1E85__0000008DB277FA49-0000008E42A19FD1", +"000000067F000080000007200C00000DC000-000000067F000080000007200C00000E0000__0000008E3CDF59C0", +"000000067F000080000007200C00000DC000-000000067F000080000007200C00000E0000__0000008F10EA21C8", +"000000067F000080000007200C00000E0000-000000067F000080000007200C00000E4000__0000008E3CDF59C0", +"000000067F000080000007200C00000E0000-000000067F000080000007200C00000E4000__0000008F10EA21C8", +"000000067F000080000007200C00000E1E85-000000067F000080000007200C00000EB5EB__0000008DB277FA49-0000008E42A19FD1", +"000000067F000080000007200C00000E4000-000000067F000080000007200C00000E8000__0000008E3CDF59C0", +"000000067F000080000007200C00000E4000-000000067F000080000007200C00000E8000__0000008F10EA21C8", +"000000067F000080000007200C00000E8000-000000067F000080000007200C00000EC000__0000008E3CDF59C0", +"000000067F000080000007200C00000E8000-000000067F000080000007200C00000EC000__0000008F10EA21C8", +"000000067F000080000007200C00000EB5EB-000000067F000080000007200C00000F4D0C__0000008DB277FA49-0000008E42A19FD1", +"000000067F000080000007200C00000EC000-000000067F000080000007200C00000F0000__0000008E3CDF59C0", +"000000067F000080000007200C00000EC000-000000067F000080000007200C00000F0000__0000008F10EA21C8", +"000000067F000080000007200C00000F0000-000000067F000080000007200C00000F4000__0000008E3CDF59C0", +"000000067F000080000007200C00000F0000-000000067F000080000007200C00000F4000__0000008F10EA21C8", +"000000067F000080000007200C00000F342F-000000067F0000800000072014000000D54C__0000008EBC4827C1-0000008F10E3E189", +"000000067F000080000007200C00000F4000-000000067F000080000007200C00000F8000__0000008E3CDF59C0", +"000000067F000080000007200C00000F4000-000000067F000080000007200C00000F8000__0000008F10EA21C8", +"000000067F000080000007200C00000F4D0C-000000067F000080000007200C00000FE472__0000008DB277FA49-0000008E42A19FD1", +"000000067F000080000007200C00000F8000-000000067F000080000007200C00000FC000__0000008E3CDF59C0", +"000000067F000080000007200C00000F8000-000000067F000080000007200C00000FC000__0000008F10EA21C8", +"000000067F000080000007200C00000FC000-000000067F000080000007200C0000100000__0000008E3CDF59C0", +"000000067F000080000007200C00000FC000-000000067F000080000007200C0000100000__0000008F10EA21C8", +"000000067F000080000007200C00000FE472-000000067F000080000007200C0000107B8E__0000008DB277FA49-0000008E42A19FD1", +"000000067F000080000007200C0000100000-000000067F000080000007200C0000104000__0000008E3CDF59C0", +"000000067F000080000007200C0000100000-000000067F000080000007200C0000104000__0000008F10EA21C8", +"000000067F000080000007200C0000104000-000000067F000080000007200C0000108000__0000008E3CDF59C0", +"000000067F000080000007200C0000104000-000000067F000080000007200C0000108000__0000008F10EA21C8", +"000000067F000080000007200C0000107B8E-000000067F000080000007200C00001112F4__0000008DB277FA49-0000008E42A19FD1", +"000000067F000080000007200C0000108000-000000067F000080000007200C000010C000__0000008E3CDF59C0", +"000000067F000080000007200C0000108000-000000067F000080000007200C000010C000__0000008F10EA21C8", +"000000067F000080000007200C000010C000-000000067F000080000007200C0000110000__0000008F10EA21C8", +"000000067F000080000007200C000010C000-030000000000000000000000000000000002__0000008E3CDF59C0", +"000000067F000080000007200C0000110000-000000067F00008000000720120100000000__0000008F10EA21C8", +"000000067F000080000007200C00001112F4-010000000000000001000000040000000001__0000008DB277FA49-0000008E42A19FD1", +"000000067F00008000000720140000000000-000000067F00008000000720140000004000__0000008F10EA21C8", +"000000067F00008000000720140000001101-000000067F00008000000720140000007E82__0000008E42A19FD1-0000008EBC4827C1", +"000000067F00008000000720140000004000-000000067F00008000000720140000008000__0000008F10EA21C8", +"000000067F00008000000720140000007E82-000000067F0000800000072014000000EB9D__0000008E42A19FD1-0000008EBC4827C1", +"000000067F00008000000720140000008000-000000067F0000800000072014000000C000__0000008F10EA21C8", +"000000067F0000800000072014000000C000-000000067F00008000000720140000010000__0000008F10EA21C8", +"000000067F0000800000072014000000D54D-000000067F00008000000720140000025E6D__0000008EBC4827C1-0000008F10E3E189", +"000000067F0000800000072014000000EB9D-000000067F00008000000720140000015866__0000008E42A19FD1-0000008EBC4827C1", +"000000067F00008000000720140000010000-000000067F00008000000720140000014000__0000008F10EA21C8", +"000000067F00008000000720140000014000-000000067F00008000000720140000018000__0000008F10EA21C8", +"000000067F00008000000720140000015866-000000067F0000800000072014000001C591__0000008E42A19FD1-0000008EBC4827C1", +"000000067F00008000000720140000018000-000000067F0000800000072014000001C000__0000008F10EA21C8", +"000000067F0000800000072014000001C000-000000067F00008000000720140000020000__0000008F10EA21C8", +"000000067F0000800000072014000001C591-000000067F0000800000072014000002326E__0000008E42A19FD1-0000008EBC4827C1", +"000000067F00008000000720140000020000-000000067F00008000000720140000024000__0000008F10EA21C8", +"000000067F0000800000072014000002326E-000000067F00008000000720140000029F59__0000008E42A19FD1-0000008EBC4827C1", +"000000067F00008000000720140000024000-000000067F00008000000720140000028000__0000008F10EA21C8", +"000000067F00008000000720140000025E75-030000000000000000000000000000000002__0000008EBC4827C1-0000008F10E3E189", +"000000067F00008000000720140000028000-000000067F0000800000072014000002C000__0000008F10EA21C8", +"000000067F00008000000720140000029F59-030000000000000000000000000000000002__0000008E42A19FD1-0000008EBC4827C1", +"000000067F0000800000072014000002C000-030000000000000000000000000000000002__0000008F10EA21C8", +"000000067F000080000007400C0000000000-000000067F000080000007400C0000004000__00000091A67E3E18", +"000000067F000080000007400C0000004000-000000067F000080000007400C0000008000__00000091A67E3E18", +"000000067F000080000007400C0000008000-000000067F000080000007400C000000C000__00000091A67E3E18", +"000000067F000080000007400C00000090E9-000000067F000080000007400C000001280C__0000008F10E3E189-0000008F915DE591", +"000000067F000080000007400C000000C000-000000067F000080000007400C0000010000__00000091A67E3E18", +"000000067F000080000007400C0000010000-000000067F000080000007400C0000014000__00000091A67E3E18", +"000000067F000080000007400C000001280C-000000067F000080000007400C000001BF72__0000008F10E3E189-0000008F915DE591", +"000000067F000080000007400C0000014000-000000067F000080000007400C0000018000__00000091A67E3E18", +"000000067F000080000007400C0000018000-000000067F000080000007400C000001C000__00000091A67E3E18", +"000000067F000080000007400C000001BF72-000000067F000080000007400C00000256D8__0000008F10E3E189-0000008F915DE591", +"000000067F000080000007400C000001C000-000000067F000080000007400C0000020000__00000091A67E3E18", +"000000067F000080000007400C0000020000-000000067F000080000007400C0000024000__00000091A67E3E18", +"000000067F000080000007400C0000024000-000000067F000080000007400C0000028000__00000091A67E3E18", +"000000067F000080000007400C00000256D8-000000067F000080000007400C000002EE0B__0000008F10E3E189-0000008F915DE591", +"000000067F000080000007400C0000028000-000000067F000080000007400C000002C000__00000091A67E3E18", +"000000067F000080000007400C000002C000-000000067F000080000007400C0000030000__00000091A67E3E18", +"000000067F000080000007400C000002EE0B-000000067F000080000007400C0000038521__0000008F10E3E189-0000008F915DE591", +"000000067F000080000007400C0000030000-000000067F000080000007400C0000034000__00000091A67E3E18", +"000000067F000080000007400C0000034000-000000067F000080000007400C0000038000__00000091A67E3E18", +"000000067F000080000007400C0000038000-000000067F000080000007400C000003C000__00000091A67E3E18", +"000000067F000080000007400C0000038521-000000067F000080000007400C0000041C87__0000008F10E3E189-0000008F915DE591", +"000000067F000080000007400C000003C000-000000067F000080000007400C0000040000__00000091A67E3E18", +"000000067F000080000007400C0000040000-000000067F000080000007400C0000044000__00000091A67E3E18", +"000000067F000080000007400C0000041C87-000000067F000080000007400C000004B3ED__0000008F10E3E189-0000008F915DE591", +"000000067F000080000007400C0000044000-000000067F000080000007400C0000048000__00000091A67E3E18", +"000000067F000080000007400C0000048000-000000067F000080000007400C000004C000__000000914B20A810", +"000000067F000080000007400C000004B3ED-030000000000000000000000000000000002__0000008F10E3E189-0000008F915DE591", +"000000067F000080000007400C000004BAC9-000000067F000080000007400C00000551FE__0000008F915DE591-000000903121F569", +"000000067F000080000007400C000004C000-000000067F000080000007400C0000050000__000000914B20A810", +"000000067F000080000007400C000004DF0B-000000067F000080000007400C000009B41F__000000914B2393B1-00000091A6DD7A79", +"000000067F000080000007400C0000050000-000000067F000080000007400C0000054000__000000914B20A810", +"000000067F000080000007400C0000054000-000000067F000080000007400C0000058000__000000914B20A810", +"000000067F000080000007400C00000551FE-000000067F000080000007400C000005E90C__0000008F915DE591-000000903121F569", +"000000067F000080000007400C0000058000-000000067F000080000007400C000005C000__000000914B20A810", +"000000067F000080000007400C000005C000-000000067F000080000007400C0000060000__000000914B20A810", +"000000067F000080000007400C000005E90C-000000067F000080000007400C000006802C__0000008F915DE591-000000903121F569", +"000000067F000080000007400C0000060000-000000067F000080000007400C0000064000__000000914B20A810", +"000000067F000080000007400C0000064000-000000067F000080000007400C0000068000__000000914B20A810", +"000000067F000080000007400C0000068000-000000067F000080000007400C000006C000__000000914B20A810", +"000000067F000080000007400C000006802C-000000067F000080000007400C0000071783__0000008F915DE591-000000903121F569", +"000000067F000080000007400C000006C000-000000067F000080000007400C0000070000__000000914B20A810", +"000000067F000080000007400C0000070000-000000067F000080000007400C0000074000__000000914B20A810", +"000000067F000080000007400C0000071783-000000067F000080000007400C000007AEE9__0000008F915DE591-000000903121F569", +"000000067F000080000007400C0000074000-000000067F000080000007400C0000078000__000000914B20A810", +"000000067F000080000007400C0000078000-000000067F000080000007400C000007C000__000000914B20A810", +"000000067F000080000007400C000007AEE9-000000067F000080000007400C000008460B__0000008F915DE591-000000903121F569", +"000000067F000080000007400C000007C000-000000067F000080000007400C0000080000__000000914B20A810", +"000000067F000080000007400C0000080000-000000067F000080000007400C0000084000__000000914B20A810", +"000000067F000080000007400C0000084000-000000067F000080000007400C0000088000__000000914B20A810", +"000000067F000080000007400C000008460B-000000067F000080000007400C000008DD71__0000008F915DE591-000000903121F569", +"000000067F000080000007400C0000088000-000000067F000080000007400C000008C000__000000914B20A810", +"000000067F000080000007400C000008C000-000000067F000080000007400C0000090000__000000914B20A810", +"000000067F000080000007400C000008DD71-000000067F000080000007400C00000974D7__0000008F915DE591-000000903121F569", +"000000067F000080000007400C0000090000-000000067F000080000007400C0000094000__000000914B20A810", +"000000067F000080000007400C0000094000-000000067F000080000007400C0000098000__000000914B20A810", +"000000067F000080000007400C00000974D7-000000067F000080000007400C00000A0C0B__0000008F915DE591-000000903121F569", +"000000067F000080000007400C0000098000-000000067F000080000007400C000009C000__000000914B20A810", +"000000067F000080000007400C000009B420-000000067F000080000007400C00000E830A__000000914B2393B1-00000091A6DD7A79", +"000000067F000080000007400C000009C000-000000067F000080000007400C00000A0000__000000914B20A810", +"000000067F000080000007400C00000A0000-000000067F000080000007400C00000A4000__000000914B20A810", +"000000067F000080000007400C00000A0C0B-000000067F000080000007400C00000AA371__0000008F915DE591-000000903121F569", +"000000067F000080000007400C00000A4000-000000067F000080000007400C00000A8000__000000914B20A810", +"000000067F000080000007400C00000A8000-000000067F000080000007400C00000AC000__00000090DFD64240", +"000000067F000080000007400C00000AA371-000000067F000080000007400C0100000000__0000008F915DE591-000000903121F569", +"000000067F000080000007400C00000AA4EC-000000067F000080000007400C00000B3C0C__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C00000AC000-000000067F000080000007400C00000B0000__00000090DFD64240", +"000000067F000080000007400C00000B0000-000000067F000080000007400C00000B4000__00000090DFD64240", +"000000067F000080000007400C00000B3C0C-000000067F000080000007400C00000BD372__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C00000B4000-000000067F000080000007400C00000B8000__00000090DFD64240", +"000000067F000080000007400C00000B8000-000000067F000080000007400C00000BC000__00000090DFD64240", +"000000067F000080000007400C00000BC000-000000067F000080000007400C00000C0000__00000090DFD64240", +"000000067F000080000007400C00000BD372-000000067F000080000007400C00000C6AD8__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C00000C0000-000000067F000080000007400C00000C4000__00000090DFD64240", +"000000067F000080000007400C00000C4000-000000067F000080000007400C00000C8000__00000090DFD64240", +"000000067F000080000007400C00000C6AD8-000000067F000080000007400C00000D020B__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C00000C8000-000000067F000080000007400C00000CC000__00000090DFD64240", +"000000067F000080000007400C00000CC000-000000067F000080000007400C00000D0000__00000090DFD64240", +"000000067F000080000007400C00000D0000-000000067F000080000007400C00000D4000__00000090DFD64240", +"000000067F000080000007400C00000D020B-000000067F000080000007400C00000D9971__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C00000D4000-000000067F000080000007400C00000D8000__00000090DFD64240", +"000000067F000080000007400C00000D8000-000000067F000080000007400C00000DC000__00000090DFD64240", +"000000067F000080000007400C00000D9971-000000067F000080000007400C00000E30D7__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C00000DC000-000000067F000080000007400C00000E0000__00000090DFD64240", +"000000067F000080000007400C00000E0000-000000067F000080000007400C00000E4000__00000090DFD64240", +"000000067F000080000007400C00000E30D7-000000067F000080000007400C00000EC80B__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C00000E4000-000000067F000080000007400C00000E8000__00000090DFD64240", +"000000067F000080000007400C00000E8000-000000067F000080000007400C00000EC000__00000090DFD64240", +"000000067F000080000007400C00000E8314-000000067F00008000000740140000008178__000000914B2393B1-00000091A6DD7A79", +"000000067F000080000007400C00000EC000-000000067F000080000007400C00000F0000__00000090DFD64240", +"000000067F000080000007400C00000EC80B-000000067F000080000007400C00000F5F38__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C00000F0000-000000067F000080000007400C00000F4000__00000090DFD64240", +"000000067F000080000007400C00000F4000-000000067F000080000007400C00000F8000__00000090DFD64240", +"000000067F000080000007400C00000F5F38-000000067F000080000007400C00000FF69E__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C00000F8000-000000067F000080000007400C00000FC000__00000090DFD64240", +"000000067F000080000007400C00000FC000-000000067F000080000007400C0000100000__00000090DFD64240", +"000000067F000080000007400C00000FCCA8-000000067F000080000007400C00001119BA__00000090D0E5EA29-000000914B2393B1", +"000000067F000080000007400C00000FF69E-000000067F000080000007400C0000108DAF__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C0000100000-000000067F000080000007400C0000104000__00000090DFD64240", +"000000067F000080000007400C0000104000-000000067F000080000007400C0000108000__00000090DFD64240", +"000000067F000080000007400C0000108000-000000067F000080000007400C000010C000__00000090DFD64240", +"000000067F000080000007400C0000108DAF-000000067F000080000007400C0100000000__000000903121F569-00000090D0E5EA29", +"000000067F000080000007400C000010C000-000000067F000080000007400C0000110000__00000090DFD64240", +"000000067F000080000007400C0000110000-030000000000000000000000000000000002__00000090DFD64240", +"000000067F000080000007400C00001119BA-000000067F00008000000740140000004326__00000090D0E5EA29-000000914B2393B1", +"000000067F00008000000740140000004326-000000067F0000800000074014000000B7EE__00000090D0E5EA29-000000914B2393B1", +"000000067F00008000000740140000008179-000000067F0000800000074014000001D4B7__000000914B2393B1-00000091A6DD7A79", +"000000067F0000800000074014000000B7EE-000000067F00008000000740140000012CCD__00000090D0E5EA29-000000914B2393B1", +"000000067F00008000000740140000012CCD-000000067F0000800000074014000001A16B__00000090D0E5EA29-000000914B2393B1", +"000000067F0000800000074014000001A16B-000000067F000080000007401400000215C9__00000090D0E5EA29-000000914B2393B1", +"000000067F0000800000074014000001D4BA-030000000000000000000000000000000002__000000914B2393B1-00000091A6DD7A79", +"000000067F000080000007401400000215C9-000000067F00008000000740140000028A4A__00000090D0E5EA29-000000914B2393B1", +"000000067F00008000000740140000028A4A-030000000000000000000000000000000002__00000090D0E5EA29-000000914B2393B1", +"000000067F000080000007600C0000000000-000000067F000080000007600C0000004000__00000092CA5E4EA8", +"000000067F000080000007600C0000000000-000000067F000080000007600C0000004000__0000009445A06DC8", +"000000067F000080000007600C0000004000-000000067F000080000007600C0000008000__00000092CA5E4EA8", +"000000067F000080000007600C0000004000-000000067F000080000007600C0000008000__0000009445A06DC8", +"000000067F000080000007600C0000008000-000000067F000080000007600C000000C000__00000092CA5E4EA8", +"000000067F000080000007600C0000008000-000000067F000080000007600C000000C000__0000009445A06DC8", +"000000067F000080000007600C0000008180-000000067F000080000007600C00000118E6__00000091A6DD7A79-0000009228F7FA79", +"000000067F000080000007600C000000C000-000000067F000080000007600C0000010000__00000092CA5E4EA8", +"000000067F000080000007600C000000C000-000000067F000080000007600C0000010000__0000009445A06DC8", +"000000067F000080000007600C0000010000-000000067F000080000007600C0000014000__00000092CA5E4EA8", +"000000067F000080000007600C0000010000-000000067F000080000007600C0000014000__0000009445A06DC8", +"000000067F000080000007600C00000118E6-000000067F000080000007600C000001B00A__00000091A6DD7A79-0000009228F7FA79", +"000000067F000080000007600C0000014000-000000067F000080000007600C0000018000__00000092CA5E4EA8", +"000000067F000080000007600C0000014000-000000067F000080000007600C0000018000__0000009445A06DC8", +"000000067F000080000007600C0000018000-000000067F000080000007600C000001C000__00000092CA5E4EA8", +"000000067F000080000007600C0000018000-000000067F000080000007600C000001C000__0000009445A06DC8", +"000000067F000080000007600C000001B00A-000000067F000080000007600C0000024745__00000091A6DD7A79-0000009228F7FA79", +"000000067F000080000007600C000001C000-000000067F000080000007600C0000020000__00000092CA5E4EA8", +"000000067F000080000007600C000001C000-000000067F000080000007600C0000020000__0000009445A06DC8", +"000000067F000080000007600C0000020000-000000067F000080000007600C0000024000__00000092CA5E4EA8", +"000000067F000080000007600C0000020000-000000067F000080000007600C0000024000__0000009445A06DC8", +"000000067F000080000007600C0000024000-000000067F000080000007600C0000028000__00000092CA5E4EA8", +"000000067F000080000007600C0000024000-000000067F000080000007600C0000028000__0000009445A06DC8", +"000000067F000080000007600C0000024745-000000067F000080000007600C000002DEAB__00000091A6DD7A79-0000009228F7FA79", +"000000067F000080000007600C0000028000-000000067F000080000007600C000002C000__00000092CA5E4EA8", +"000000067F000080000007600C0000028000-000000067F000080000007600C000002C000__0000009445A06DC8", +"000000067F000080000007600C000002C000-000000067F000080000007600C0000030000__00000092CA5E4EA8", +"000000067F000080000007600C000002C000-000000067F000080000007600C0000030000__0000009445A06DC8", +"000000067F000080000007600C000002DEAB-000000067F000080000007600C00000375CB__00000091A6DD7A79-0000009228F7FA79", +"000000067F000080000007600C0000030000-000000067F000080000007600C0000034000__00000092CA5E4EA8", +"000000067F000080000007600C0000030000-000000067F000080000007600C0000034000__0000009445A06DC8", +"000000067F000080000007600C0000034000-000000067F000080000007600C0000038000__00000092CA5E4EA8", +"000000067F000080000007600C0000034000-000000067F000080000007600C0000038000__0000009445A06DC8", +"000000067F000080000007600C00000375CB-000000067F000080000007600C0000040D0B__00000091A6DD7A79-0000009228F7FA79", +"000000067F000080000007600C0000038000-000000067F000080000007600C000003C000__00000092CA5E4EA8", +"000000067F000080000007600C0000038000-000000067F000080000007600C000003C000__0000009445A06DC8", +"000000067F000080000007600C000003C000-000000067F000080000007600C0000040000__00000092CA5E4EA8", +"000000067F000080000007600C000003C000-000000067F000080000007600C0000040000__0000009445A06DC8", +"000000067F000080000007600C0000040000-000000067F000080000007600C0000044000__00000092CA5E4EA8", +"000000067F000080000007600C0000040000-000000067F000080000007600C0000044000__0000009445A06DC8", +"000000067F000080000007600C0000040D0B-000000067F000080000007600C000004A471__00000091A6DD7A79-0000009228F7FA79", +"000000067F000080000007600C0000044000-000000067F000080000007600C0000048000__00000092CA5E4EA8", +"000000067F000080000007600C0000044000-000000067F000080000007600C0000048000__0000009445A06DC8", +"000000067F000080000007600C0000048000-000000067F000080000007600C000004C000__00000092CA5E4EA8", +"000000067F000080000007600C0000048000-000000067F000080000007600C000004C000__0000009445A06DC8", +"000000067F000080000007600C000004A471-030000000000000000000000000000000002__00000091A6DD7A79-0000009228F7FA79", +"000000067F000080000007600C000004C000-000000067F000080000007600C0000050000__00000092CA5E4EA8", +"000000067F000080000007600C000004C000-000000067F000080000007600C0000050000__0000009445A06DC8", +"000000067F000080000007600C0000050000-000000067F000080000007600C0000054000__00000092CA5E4EA8", +"000000067F000080000007600C0000050000-000000067F000080000007600C0000054000__0000009445A06DC8", +"000000067F000080000007600C0000054000-000000067F000080000007600C0000058000__00000092CA5E4EA8", +"000000067F000080000007600C0000054000-000000067F000080000007600C0000058000__0000009445A06DC8", +"000000067F000080000007600C00000544BA-000000067F000080000007600C000005DC0A__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C0000058000-000000067F000080000007600C000005C000__00000092CA5E4EA8", +"000000067F000080000007600C0000058000-000000067F000080000007600C000005C000__0000009445A06DC8", +"000000067F000080000007600C000005C000-000000067F000080000007600C0000060000__00000092CA5E4EA8", +"000000067F000080000007600C000005C000-000000067F000080000007600C0000060000__0000009445A06DC8", +"000000067F000080000007600C000005DC0A-000000067F000080000007600C000006732B__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C0000060000-000000067F000080000007600C0000064000__00000092CA5E4EA8", +"000000067F000080000007600C0000060000-000000067F000080000007600C0000064000__0000009445A06DC8", +"000000067F000080000007600C0000061031-000000067F000080000007600C00000C1159__0000009402435A49-0000009446B52FD1", +"000000067F000080000007600C0000064000-000000067F000080000007600C0000068000__00000092CA5E4EA8", +"000000067F000080000007600C0000064000-000000067F000080000007600C0000068000__0000009445A06DC8", +"000000067F000080000007600C000006732B-000000067F000080000007600C0000070A91__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C0000068000-000000067F000080000007600C000006C000__00000092CA5E4EA8", +"000000067F000080000007600C0000068000-000000067F000080000007600C000006C000__0000009445A06DC8", +"000000067F000080000007600C000006C000-000000067F000080000007600C0000070000__00000092CA5E4EA8", +"000000067F000080000007600C000006C000-000000067F000080000007600C0000070000__0000009445A06DC8", +"000000067F000080000007600C0000070000-000000067F000080000007600C0000074000__00000092CA5E4EA8", +"000000067F000080000007600C0000070000-000000067F000080000007600C0000074000__0000009445A06DC8", +"000000067F000080000007600C0000070A91-000000067F000080000007600C000007A1F7__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C0000074000-000000067F000080000007600C0000078000__00000092CA5E4EA8", +"000000067F000080000007600C0000074000-000000067F000080000007600C0000078000__0000009445A06DC8", +"000000067F000080000007600C0000078000-000000067F000080000007600C000007C000__00000092CA5E4EA8", +"000000067F000080000007600C0000078000-000000067F000080000007600C000007C000__0000009445A06DC8", +"000000067F000080000007600C000007A1F7-000000067F000080000007600C000008390C__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C000007C000-000000067F000080000007600C0000080000__00000092CA5E4EA8", +"000000067F000080000007600C000007C000-000000067F000080000007600C0000080000__0000009445A06DC8", +"000000067F000080000007600C0000080000-000000067F000080000007600C0000084000__00000092CA5E4EA8", +"000000067F000080000007600C0000080000-000000067F000080000007600C0000084000__0000009445A06DC8", +"000000067F000080000007600C000008390C-000000067F000080000007600C000008D072__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C0000084000-000000067F000080000007600C0000088000__00000092CA5E4EA8", +"000000067F000080000007600C0000084000-000000067F000080000007600C0000088000__0000009445A06DC8", +"000000067F000080000007600C0000088000-000000067F000080000007600C000008C000__00000092CA5E4EA8", +"000000067F000080000007600C0000088000-000000067F000080000007600C000008C000__0000009445A06DC8", +"000000067F000080000007600C000008C000-000000067F000080000007600C0000090000__00000092CA5E4EA8", +"000000067F000080000007600C000008C000-000000067F000080000007600C0000090000__0000009445A06DC8", +"000000067F000080000007600C000008C52F-000000067F000080000007600C000010B57A__00000093786F8001-0000009402435A49", +"000000067F000080000007600C000008D072-000000067F000080000007600C000009679A__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C0000090000-000000067F000080000007600C0000094000__00000092CA5E4EA8", +"000000067F000080000007600C0000090000-000000067F000080000007600C0000094000__0000009445A06DC8", +"000000067F000080000007600C0000094000-000000067F000080000007600C0000098000__00000092CA5E4EA8", +"000000067F000080000007600C0000094000-000000067F000080000007600C0000098000__0000009445A06DC8", +"000000067F000080000007600C000009679A-000000067F000080000007600C000009FF00__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C0000098000-000000067F000080000007600C000009C000__00000092CA5E4EA8", +"000000067F000080000007600C0000098000-000000067F000080000007600C000009C000__0000009445A06DC8", +"000000067F000080000007600C000009C000-000000067F000080000007600C00000A0000__00000092CA5E4EA8", +"000000067F000080000007600C000009C000-000000067F000080000007600C00000A0000__0000009445A06DC8", +"000000067F000080000007600C000009FF00-000000067F000080000007600C00000A960B__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C00000A0000-000000067F000080000007600C00000A4000__00000092CA5E4EA8", +"000000067F000080000007600C00000A0000-000000067F000080000007600C00000A4000__0000009445A06DC8", +"000000067F000080000007600C00000A4000-000000067F000080000007600C00000A8000__00000092CA5E4EA8", +"000000067F000080000007600C00000A4000-000000067F000080000007600C00000A8000__0000009445A06DC8", +"000000067F000080000007600C00000A8000-000000067F000080000007600C00000AC000__0000009445A06DC8", +"000000067F000080000007600C00000A8000-030000000000000000000000000000000002__00000092CA5E4EA8", +"000000067F000080000007600C00000A960B-000000067F000080000007600C00000B2D55__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C00000AC000-000000067F000080000007600C00000B0000__0000009445A06DC8", +"000000067F000080000007600C00000B0000-000000067F000080000007600C00000B4000__0000009445A06DC8", +"000000067F000080000007600C00000B2D55-000000067F000080000007600C00000BC4BB__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C00000B4000-000000067F000080000007600C00000B8000__0000009445A06DC8", +"000000067F000080000007600C00000B8000-000000067F000080000007600C00000BC000__0000009445A06DC8", +"000000067F000080000007600C00000BC000-000000067F000080000007600C00000C0000__0000009445A06DC8", +"000000067F000080000007600C00000BC4BB-000000067F000080000007600C00000C5BEA__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C00000C0000-000000067F000080000007600C00000C4000__0000009445A06DC8", +"000000067F000080000007600C00000C115D-000000067F0000800000076014000000333A__0000009402435A49-0000009446B52FD1", +"000000067F000080000007600C00000C4000-000000067F000080000007600C00000C8000__0000009445A06DC8", +"000000067F000080000007600C00000C5BEA-000000067F000080000007600C00000CF30B__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C00000C8000-000000067F000080000007600C00000CC000__0000009445A06DC8", +"000000067F000080000007600C00000CC000-000000067F000080000007600C00000D0000__0000009445A06DC8", +"000000067F000080000007600C00000CF30B-000000067F000080000007600C00000D8A2B__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C00000D0000-000000067F000080000007600C00000D4000__0000009445A06DC8", +"000000067F000080000007600C00000D4000-000000067F000080000007600C00000D8000__0000009445A06DC8", +"000000067F000080000007600C00000D8000-000000067F000080000007600C00000DC000__0000009445A06DC8", +"000000067F000080000007600C00000D8A2B-000000067F000080000007600C00000E217C__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C00000DC000-000000067F000080000007600C00000E0000__0000009445A06DC8", +"000000067F000080000007600C00000E0000-000000067F000080000007600C00000E4000__0000009445A06DC8", +"000000067F000080000007600C00000E217C-000000067F000080000007600C00000EB8E2__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C00000E4000-000000067F000080000007600C00000E8000__0000009445A06DC8", +"000000067F000080000007600C00000E8000-000000067F000080000007600C00000EC000__0000009445A06DC8", +"000000067F000080000007600C00000EB8E2-000000067F000080000007600C00000F500B__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C00000EC000-000000067F000080000007600C00000F0000__0000009445A06DC8", +"000000067F000080000007600C00000F0000-000000067F000080000007600C00000F4000__0000009445A06DC8", +"000000067F000080000007600C00000F4000-000000067F000080000007600C00000F8000__0000009445A06DC8", +"000000067F000080000007600C00000F500B-000000067F000080000007600C00000FE771__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C00000F8000-000000067F000080000007600C00000FC000__0000009445A06DC8", +"000000067F000080000007600C00000FC000-000000067F000080000007600C0000100000__0000009445A06DC8", +"000000067F000080000007600C00000FE771-000000067F000080000007600C0000107ED7__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C0000100000-000000067F000080000007600C0000104000__0000009445A06DC8", +"000000067F000080000007600C0000104000-000000067F000080000007600C0000108000__0000009445A06DC8", +"000000067F000080000007600C0000107ED7-000000067F000080000007600C000011160C__0000009228F7FA79-00000093786F8001", +"000000067F000080000007600C0000108000-000000067F000080000007600C000010C000__0000009445A06DC8", +"000000067F000080000007600C000010B57A-000000067F00008000000760140000003D14__00000093786F8001-0000009402435A49", +"000000067F000080000007600C000010C000-000000067F000080000007600C0000110000__0000009445A06DC8", +"000000067F000080000007600C0000110000-000000067F00008000000760120100000000__0000009445A06DC8", +"000000067F000080000007600C000011160C-010000000000000001000000040000000008__0000009228F7FA79-00000093786F8001", +"000000067F00008000000760140000000000-000000067F00008000000760140000004000__0000009445A06DC8", +"000000067F00008000000760140000003354-000000067F00008000000760140000023CAB__0000009402435A49-0000009446B52FD1", +"000000067F00008000000760140000003D14-000000067F0000800000076014000000A251__00000093786F8001-0000009402435A49", +"000000067F00008000000760140000004000-000000067F00008000000760140000008000__0000009445A06DC8", +"000000067F00008000000760140000008000-000000067F0000800000076014000000C000__0000009445A06DC8", +"000000067F0000800000076014000000A251-000000067F000080000007601400000107AC__00000093786F8001-0000009402435A49", +"000000067F0000800000076014000000C000-000000067F00008000000760140000010000__0000009445A06DC8", +"000000067F00008000000760140000010000-000000067F00008000000760140000014000__0000009445A06DC8", +"000000067F000080000007601400000107AC-000000067F00008000000760140000016CC4__00000093786F8001-0000009402435A49", +"000000067F00008000000760140000014000-000000067F00008000000760140000018000__0000009445A06DC8", +"000000067F00008000000760140000016CC4-000000067F0000800000076014000001D272__00000093786F8001-0000009402435A49", +"000000067F00008000000760140000018000-000000067F0000800000076014000001C000__0000009445A06DC8", +"000000067F0000800000076014000001C000-000000067F00008000000760140000020000__0000009445A06DC8", +"000000067F0000800000076014000001D272-000000067F000080000007601400000237C3__00000093786F8001-0000009402435A49", +"000000067F00008000000760140000020000-000000067F00008000000760140000024000__0000009445A06DC8", +"000000067F000080000007601400000237C3-000000067F00008000000760140000029CC5__00000093786F8001-0000009402435A49", +"000000067F00008000000760140000023CB3-030000000000000000000000000000000002__0000009402435A49-0000009446B52FD1", +"000000067F00008000000760140000024000-000000067F00008000000760140000028000__0000009445A06DC8", +"000000067F00008000000760140000028000-000000067F0000800000076014000002C000__0000009445A06DC8", +"000000067F00008000000760140000029CC5-030000000000000000000000000000000002__00000093786F8001-0000009402435A49", +"000000067F0000800000076014000002C000-030000000000000000000000000000000002__0000009445A06DC8", +"000000067F000080000007800C0000000000-000000067F000080000007800C0000004000__00000096187D1FC8", +"000000067F000080000007800C0000000000-000000067F000080000007800C0000004000__00000096E85806C0", +"000000067F000080000007800C0000004000-000000067F000080000007800C0000008000__00000096187D1FC8", +"000000067F000080000007800C0000004000-000000067F000080000007800C0000008000__00000096E85806C0", +"000000067F000080000007800C0000008000-000000067F000080000007800C000000C000__00000096187D1FC8", +"000000067F000080000007800C0000008000-000000067F000080000007800C000000C000__00000096E85806C0", +"000000067F000080000007800C000000974C-000000067F000080000007800C0000012EB2__0000009446B52FD1-00000094D67DF4F9", +"000000067F000080000007800C000000C000-000000067F000080000007800C0000010000__00000096187D1FC8", +"000000067F000080000007800C000000C000-000000067F000080000007800C0000010000__00000096E85806C0", +"000000067F000080000007800C0000010000-000000067F000080000007800C0000014000__00000096187D1FC8", +"000000067F000080000007800C0000010000-000000067F000080000007800C0000014000__00000096E85806C0", +"000000067F000080000007800C0000012EB2-000000067F000080000007800C000001C60B__0000009446B52FD1-00000094D67DF4F9", +"000000067F000080000007800C0000014000-000000067F000080000007800C0000018000__00000096187D1FC8", +"000000067F000080000007800C0000014000-000000067F000080000007800C0000018000__00000096E85806C0", +"000000067F000080000007800C0000018000-000000067F000080000007800C000001C000__00000096187D1FC8", +"000000067F000080000007800C0000018000-000000067F000080000007800C000001C000__00000096E85806C0", +"000000067F000080000007800C000001C000-000000067F000080000007800C0000020000__00000096187D1FC8", +"000000067F000080000007800C000001C000-000000067F000080000007800C0000020000__00000096E85806C0", +"000000067F000080000007800C000001C60B-000000067F000080000007800C0000025D39__0000009446B52FD1-00000094D67DF4F9", +"000000067F000080000007800C0000020000-000000067F000080000007800C0000024000__00000096187D1FC8", +"000000067F000080000007800C0000020000-000000067F000080000007800C0000024000__00000096E85806C0", +"000000067F000080000007800C0000024000-000000067F000080000007800C0000028000__00000096187D1FC8", +"000000067F000080000007800C0000024000-000000067F000080000007800C0000028000__00000096E85806C0", +"000000067F000080000007800C0000025D39-000000067F000080000007800C000002F49F__0000009446B52FD1-00000094D67DF4F9", +"000000067F000080000007800C0000028000-000000067F000080000007800C000002C000__00000096187D1FC8", +"000000067F000080000007800C0000028000-000000067F000080000007800C000002C000__00000096E85806C0", +"000000067F000080000007800C000002C000-000000067F000080000007800C0000030000__00000096187D1FC8", +"000000067F000080000007800C000002C000-000000067F000080000007800C0000030000__00000096E85806C0", +"000000067F000080000007800C000002F49F-000000067F000080000007800C0000038BB2__0000009446B52FD1-00000094D67DF4F9", +"000000067F000080000007800C0000030000-000000067F000080000007800C0000034000__00000096187D1FC8", +"000000067F000080000007800C0000030000-000000067F000080000007800C0000034000__00000096E85806C0", +"000000067F000080000007800C0000034000-000000067F000080000007800C0000038000__00000096187D1FC8", +"000000067F000080000007800C0000034000-000000067F000080000007800C0000038000__00000096E85806C0", +"000000067F000080000007800C0000038000-000000067F000080000007800C000003C000__00000096187D1FC8", +"000000067F000080000007800C0000038000-000000067F000080000007800C000003C000__00000096E85806C0", +"000000067F000080000007800C0000038BB2-000000067F000080000007800C0000042318__0000009446B52FD1-00000094D67DF4F9", +"000000067F000080000007800C000003C000-000000067F000080000007800C0000040000__00000096187D1FC8", +"000000067F000080000007800C000003C000-000000067F000080000007800C0000040000__00000096E85806C0", +"000000067F000080000007800C0000040000-000000067F000080000007800C0000044000__00000096187D1FC8", +"000000067F000080000007800C0000040000-000000067F000080000007800C0000044000__00000096E85806C0", +"000000067F000080000007800C0000042318-000000067F000080000007800C000004BA7E__0000009446B52FD1-00000094D67DF4F9", +"000000067F000080000007800C0000044000-000000067F000080000007800C0000048000__00000096187D1FC8", +"000000067F000080000007800C0000044000-000000067F000080000007800C0000048000__00000096E85806C0", +"000000067F000080000007800C0000048000-000000067F000080000007800C000004C000__00000096187D1FC8", +"000000067F000080000007800C0000048000-000000067F000080000007800C000004C000__00000096E85806C0", +"000000067F000080000007800C000004BA7E-000000067F000080000007800C00000551B3__0000009446B52FD1-00000094D67DF4F9", +"000000067F000080000007800C000004C000-000000067F000080000007800C0000050000__00000096187D1FC8", +"000000067F000080000007800C000004C000-000000067F000080000007800C0000050000__00000096E85806C0", +"000000067F000080000007800C0000050000-000000067F000080000007800C0000054000__00000096187D1FC8", +"000000067F000080000007800C0000050000-000000067F000080000007800C0000054000__00000096E85806C0", +"000000067F000080000007800C0000054000-000000067F000080000007800C0000058000__0000009614F1FFE8", +"000000067F000080000007800C0000054000-000000067F000080000007800C0000058000__00000096E85806C0", +"000000067F000080000007800C00000551B3-030000000000000000000000000000000002__0000009446B52FD1-00000094D67DF4F9", +"000000067F000080000007800C000005523E-000000067F000080000007800C000005E9A4__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C0000058000-000000067F000080000007800C000005C000__0000009614F1FFE8", +"000000067F000080000007800C0000058000-000000067F000080000007800C000005C000__00000096E85806C0", +"000000067F000080000007800C000005C000-000000067F000080000007800C0000060000__0000009614F1FFE8", +"000000067F000080000007800C000005C000-000000067F000080000007800C0000060000__00000096E85806C0", +"000000067F000080000007800C000005E9A4-000000067F000080000007800C000006810A__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C0000060000-000000067F000080000007800C0000064000__0000009614F1FFE8", +"000000067F000080000007800C0000060000-000000067F000080000007800C0000064000__00000096E85806C0", +"000000067F000080000007800C0000064000-000000067F000080000007800C0000068000__0000009614F1FFE8", +"000000067F000080000007800C0000064000-000000067F000080000007800C0000068000__00000096E85806C0", +"000000067F000080000007800C0000068000-000000067F000080000007800C000006C000__0000009614F1FFE8", +"000000067F000080000007800C0000068000-000000067F000080000007800C000006C000__00000096E85806C0", +"000000067F000080000007800C000006810A-000000067F000080000007800C0000071870__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C000006C000-000000067F000080000007800C0000070000__0000009614F1FFE8", +"000000067F000080000007800C000006C000-000000067F000080000007800C0000070000__00000096E85806C0", +"000000067F000080000007800C000006D446-000000067F000080000007800C00000D9B82__00000096AEF27399-00000096E85829C9", +"000000067F000080000007800C0000070000-000000067F000080000007800C0000074000__0000009614F1FFE8", +"000000067F000080000007800C0000070000-000000067F000080000007800C0000074000__00000096E85806C0", +"000000067F000080000007800C0000071870-000000067F000080000007800C000007AFD6__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C0000074000-000000067F000080000007800C0000078000__0000009614F1FFE8", +"000000067F000080000007800C0000074000-000000067F000080000007800C0000078000__00000096E85806C0", +"000000067F000080000007800C0000078000-000000067F000080000007800C000007C000__0000009614F1FFE8", +"000000067F000080000007800C0000078000-000000067F000080000007800C000007C000__00000096E85806C0", +"000000067F000080000007800C000007AFD6-000000067F000080000007800C000008470B__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C000007B8DE-000000067F000080000007800C00000F73DA__00000096193A8001-00000096AEF27399", +"000000067F000080000007800C000007C000-000000067F000080000007800C0000080000__0000009614F1FFE8", +"000000067F000080000007800C000007C000-000000067F000080000007800C0000080000__00000096E85806C0", +"000000067F000080000007800C0000080000-000000067F000080000007800C0000084000__0000009614F1FFE8", +"000000067F000080000007800C0000080000-000000067F000080000007800C0000084000__00000096E85806C0", +"000000067F000080000007800C0000084000-000000067F000080000007800C0000088000__0000009614F1FFE8", +"000000067F000080000007800C0000084000-000000067F000080000007800C0000088000__00000096E85806C0", +"000000067F000080000007800C000008470B-000000067F000080000007800C000008DE71__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C0000088000-000000067F000080000007800C000008C000__0000009614F1FFE8", +"000000067F000080000007800C0000088000-000000067F000080000007800C000008C000__00000096E85806C0", +"000000067F000080000007800C000008C000-000000067F000080000007800C0000090000__0000009614F1FFE8", +"000000067F000080000007800C000008C000-000000067F000080000007800C0000090000__00000096E85806C0", +"000000067F000080000007800C000008DE71-000000067F000080000007800C0000097591__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C0000090000-000000067F000080000007800C0000094000__0000009614F1FFE8", +"000000067F000080000007800C0000090000-000000067F000080000007800C0000094000__00000096E85806C0", +"000000067F000080000007800C0000094000-000000067F000080000007800C0000098000__0000009614F1FFE8", +"000000067F000080000007800C0000094000-000000067F000080000007800C0000098000__00000096E85806C0", +"000000067F000080000007800C0000097591-000000067F000080000007800C00000A0CF7__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C0000098000-000000067F000080000007800C000009C000__0000009614F1FFE8", +"000000067F000080000007800C0000098000-000000067F000080000007800C000009C000__00000096E85806C0", +"000000067F000080000007800C000009C000-000000067F000080000007800C00000A0000__0000009614F1FFE8", +"000000067F000080000007800C000009C000-000000067F000080000007800C00000A0000__00000096E85806C0", +"000000067F000080000007800C00000A0000-000000067F000080000007800C00000A4000__0000009614F1FFE8", +"000000067F000080000007800C00000A0000-000000067F000080000007800C00000A4000__00000096E85806C0", +"000000067F000080000007800C00000A0CF7-000000067F000080000007800C00000AA40B__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C00000A4000-000000067F000080000007800C00000A8000__0000009614F1FFE8", +"000000067F000080000007800C00000A4000-000000067F000080000007800C00000A8000__00000096E85806C0", +"000000067F000080000007800C00000A8000-000000067F000080000007800C00000AC000__0000009614F1FFE8", +"000000067F000080000007800C00000A8000-000000067F000080000007800C00000AC000__00000096E85806C0", +"000000067F000080000007800C00000AA40B-000000067F000080000007800C00000B3B4D__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C00000AC000-000000067F000080000007800C00000B0000__0000009614F1FFE8", +"000000067F000080000007800C00000AC000-000000067F000080000007800C00000B0000__00000096E85806C0", +"000000067F000080000007800C00000B0000-000000067F000080000007800C00000B4000__0000009614F1FFE8", +"000000067F000080000007800C00000B0000-000000067F000080000007800C00000B4000__00000096E85806C0", +"000000067F000080000007800C00000B3B4D-000000067F000080000007800C00000BD2B3__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C00000B4000-000000067F000080000007800C00000B8000__0000009614F1FFE8", +"000000067F000080000007800C00000B4000-000000067F000080000007800C00000B8000__00000096E85806C0", +"000000067F000080000007800C00000B8000-000000067F000080000007800C00000BC000__0000009614F1FFE8", +"000000067F000080000007800C00000B8000-000000067F000080000007800C00000BC000__00000096E85806C0", +"000000067F000080000007800C00000BC000-000000067F000080000007800C00000C0000__0000009614F1FFE8", +"000000067F000080000007800C00000BC000-000000067F000080000007800C00000C0000__00000096E85806C0", +"000000067F000080000007800C00000BD2B3-000000067F000080000007800C00000C69DA__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C00000C0000-000000067F000080000007800C00000C4000__0000009614F1FFE8", +"000000067F000080000007800C00000C0000-000000067F000080000007800C00000C4000__00000096E85806C0", +"000000067F000080000007800C00000C4000-000000067F000080000007800C00000C8000__0000009614F1FFE8", +"000000067F000080000007800C00000C4000-000000067F000080000007800C00000C8000__00000096E85806C0", +"000000067F000080000007800C00000C69DA-000000067F000080000007800C0100000000__00000094D67DF4F9-000000959635F2A9", +"000000067F000080000007800C00000C8000-000000067F000080000007800C00000CC000__0000009614F1FFE8", +"000000067F000080000007800C00000C8000-000000067F000080000007800C00000CC000__00000096E85806C0", +"000000067F000080000007800C00000CC000-000000067F000080000007800C00000D0000__0000009614F1FFE8", +"000000067F000080000007800C00000CC000-000000067F000080000007800C00000D0000__00000096E85806C0", +"000000067F000080000007800C00000CD6B6-000000067F000080000007800C00000D6C18__000000959635F2A9-00000096193A8001", +"000000067F000080000007800C00000D0000-000000067F000080000007800C00000D4000__0000009614F1FFE8", +"000000067F000080000007800C00000D0000-000000067F000080000007800C00000D4000__00000096E85806C0", +"000000067F000080000007800C00000D4000-000000067F000080000007800C00000D8000__0000009614F1FFE8", +"000000067F000080000007800C00000D4000-000000067F000080000007800C00000D8000__00000096E85806C0", +"000000067F000080000007800C00000D6C18-000000067F000080000007800C00000E0179__000000959635F2A9-00000096193A8001", +"000000067F000080000007800C00000D8000-000000067F000080000007800C00000DC000__0000009614F1FFE8", +"000000067F000080000007800C00000D8000-000000067F000080000007800C00000DC000__00000096E85806C0", +"000000067F000080000007800C00000D9BA3-000000067F00008000000780140000013481__00000096AEF27399-00000096E85829C9", +"000000067F000080000007800C00000DC000-000000067F000080000007800C00000E0000__0000009614F1FFE8", +"000000067F000080000007800C00000DC000-000000067F000080000007800C00000E0000__00000096E85806C0", +"000000067F000080000007800C00000E0000-000000067F000080000007800C00000E4000__0000009614F1FFE8", +"000000067F000080000007800C00000E0000-000000067F000080000007800C00000E4000__00000096E85806C0", +"000000067F000080000007800C00000E0179-000000067F000080000007800C00000E96DC__000000959635F2A9-00000096193A8001", +"000000067F000080000007800C00000E4000-000000067F000080000007800C00000E8000__0000009614F1FFE8", +"000000067F000080000007800C00000E4000-000000067F000080000007800C00000E8000__00000096E85806C0", +"000000067F000080000007800C00000E8000-000000067F000080000007800C00000EC000__0000009614F1FFE8", +"000000067F000080000007800C00000E8000-000000067F000080000007800C00000EC000__00000096E85806C0", +"000000067F000080000007800C00000E96DC-000000067F000080000007800C00000F2C3E__000000959635F2A9-00000096193A8001", +"000000067F000080000007800C00000EC000-000000067F000080000007800C00000F0000__0000009614F1FFE8", +"000000067F000080000007800C00000EC000-000000067F000080000007800C00000F0000__00000096E85806C0", +"000000067F000080000007800C00000F0000-000000067F000080000007800C00000F4000__0000009614F1FFE8", +"000000067F000080000007800C00000F0000-000000067F000080000007800C00000F4000__00000096E85806C0", +"000000067F000080000007800C00000F2C3E-000000067F000080000007800C00000FC1A0__000000959635F2A9-00000096193A8001", +"000000067F000080000007800C00000F4000-000000067F000080000007800C00000F8000__0000009614F1FFE8", +"000000067F000080000007800C00000F4000-000000067F000080000007800C00000F8000__00000096E85806C0", +"000000067F000080000007800C00000F73E3-000000067F00008000000780140000003F18__00000096193A8001-00000096AEF27399", +"000000067F000080000007800C00000F8000-000000067F000080000007800C00000FC000__0000009614F1FFE8", +"000000067F000080000007800C00000F8000-000000067F000080000007800C00000FC000__00000096E85806C0", +"000000067F000080000007800C00000FC000-000000067F000080000007800C0000100000__0000009614F1FFE8", +"000000067F000080000007800C00000FC000-000000067F000080000007800C0000100000__00000096E85806C0", +"000000067F000080000007800C00000FC1A0-000000067F000080000007800C00001057C1__000000959635F2A9-00000096193A8001", +"000000067F000080000007800C0000100000-000000067F000080000007800C0000104000__0000009614F1FFE8", +"000000067F000080000007800C0000100000-000000067F000080000007800C0000104000__00000096E85806C0", +"000000067F000080000007800C0000104000-000000067F000080000007800C0000108000__0000009614F1FFE8", +"000000067F000080000007800C0000104000-000000067F000080000007800C0000108000__00000096E85806C0", +"000000067F000080000007800C00001057C1-000000067F000080000007800C000010EF0B__000000959635F2A9-00000096193A8001", +"000000067F000080000007800C0000108000-000000067F000080000007800C000010C000__0000009614F1FFE8", +"000000067F000080000007800C0000108000-000000067F000080000007800C000010C000__00000096E85806C0", +"000000067F000080000007800C000010C000-000000067F000080000007800C0000110000__0000009614F1FFE8", +"000000067F000080000007800C000010C000-000000067F000080000007800C0000110000__00000096E85806C0", +"000000067F000080000007800C000010EF0B-01000000000000000100000004000000000B__000000959635F2A9-00000096193A8001", +"000000067F000080000007800C0000110000-000000067F00008000000780120100000000__00000096E85806C0", +"000000067F000080000007800C0000110000-030000000000000000000000000000000002__0000009614F1FFE8", +"000000067F00008000000780140000000000-000000067F00008000000780140000004000__00000096E85806C0", +"000000067F00008000000780140000003F18-000000067F00008000000780140000009ED4__00000096193A8001-00000096AEF27399", +"000000067F00008000000780140000004000-000000067F00008000000780140000008000__00000096E85806C0", +"000000067F00008000000780140000008000-000000067F0000800000078014000000C000__00000096E85806C0", +"000000067F00008000000780140000009ED4-000000067F0000800000078014000000FE9A__00000096193A8001-00000096AEF27399", +"000000067F0000800000078014000000C000-000000067F00008000000780140000010000__00000096E85806C0", +"000000067F0000800000078014000000FE9A-000000067F00008000000780140000015DD1__00000096193A8001-00000096AEF27399", +"000000067F00008000000780140000010000-000000067F00008000000780140000014000__00000096E85806C0", +"000000067F00008000000780140000013481-030000000000000000000000000000000002__00000096AEF27399-00000096E85829C9", +"000000067F00008000000780140000014000-000000067F00008000000780140000018000__00000096E85806C0", +"000000067F00008000000780140000015DD1-000000067F0000800000078014000001BD7E__00000096193A8001-00000096AEF27399", +"000000067F00008000000780140000018000-000000067F0000800000078014000001C000__00000096E85806C0", +"000000067F0000800000078014000001BD7E-000000067F00008000000780140000021CF0__00000096193A8001-00000096AEF27399", +"000000067F0000800000078014000001C000-000000067F00008000000780140000020000__00000096E85806C0", +"000000067F00008000000780140000020000-000000067F00008000000780140000024000__00000096E85806C0", +"000000067F00008000000780140000021CF0-000000067F00008000000780140000027CF8__00000096193A8001-00000096AEF27399", +"000000067F00008000000780140000024000-000000067F00008000000780140000028000__00000096E85806C0", +"000000067F00008000000780140000027CF8-000000067F0000800000078014000002DC88__00000096193A8001-00000096AEF27399", +"000000067F00008000000780140000028000-000000067F0000800000078014000002C000__00000096E85806C0", +"000000067F0000800000078014000002C000-030000000000000000000000000000000002__00000096E85806C0", +"000000067F0000800000078014000002DC88-030000000000000000000000000000000002__00000096193A8001-00000096AEF27399", +"000000067F000080000007A00C0000000000-000000067F000080000007A00C0000004000__0000009921F3B4A8", +"000000067F000080000007A00C0000004000-000000067F000080000007A00C0000008000__0000009921F3B4A8", +"000000067F000080000007A00C0000008000-000000067F000080000007A00C000000C000__0000009921F3B4A8", +"000000067F000080000007A00C000000974B-000000067F000080000007A00C0000012EB1__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C000000C000-000000067F000080000007A00C0000010000__0000009921F3B4A8", +"000000067F000080000007A00C0000010000-000000067F000080000007A00C0000014000__0000009921F3B4A8", +"000000067F000080000007A00C0000012EB1-000000067F000080000007A00C000001C60B__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000014000-000000067F000080000007A00C0000018000__0000009921F3B4A8", +"000000067F000080000007A00C0000018000-000000067F000080000007A00C000001C000__0000009921F3B4A8", +"000000067F000080000007A00C000001C000-000000067F000080000007A00C0000020000__0000009921F3B4A8", +"000000067F000080000007A00C000001C60B-000000067F000080000007A00C0000025D39__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000020000-000000067F000080000007A00C0000024000__0000009921F3B4A8", +"000000067F000080000007A00C0000024000-000000067F000080000007A00C0000028000__0000009921F3B4A8", +"000000067F000080000007A00C0000025D39-000000067F000080000007A00C000002F49F__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000028000-000000067F000080000007A00C000002C000__0000009921F3B4A8", +"000000067F000080000007A00C000002C000-000000067F000080000007A00C0000030000__0000009921F3B4A8", +"000000067F000080000007A00C000002F49F-000000067F000080000007A00C0000038BB2__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000030000-000000067F000080000007A00C0000034000__0000009921F3B4A8", +"000000067F000080000007A00C0000034000-000000067F000080000007A00C0000038000__0000009921F3B4A8", +"000000067F000080000007A00C0000038000-000000067F000080000007A00C000003C000__0000009921F3B4A8", +"000000067F000080000007A00C0000038BB2-000000067F000080000007A00C0000042318__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C000003C000-000000067F000080000007A00C0000040000__0000009921F3B4A8", +"000000067F000080000007A00C0000040000-000000067F000080000007A00C0000044000__0000009921F3B4A8", +"000000067F000080000007A00C0000042318-000000067F000080000007A00C000004BA7E__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000044000-000000067F000080000007A00C0000048000__0000009921F3B4A8", +"000000067F000080000007A00C0000048000-000000067F000080000007A00C000004C000__0000009921F3B4A8", +"000000067F000080000007A00C000004B9B2-000000067F000080000007A00C0000097B6D__0000009921E47AA1-000000997F5D23C9", +"000000067F000080000007A00C000004BA7E-000000067F000080000007A00C00000551B3__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C000004C000-000000067F000080000007A00C0000050000__0000009921F3B4A8", +"000000067F000080000007A00C0000050000-000000067F000080000007A00C0000054000__0000009921F3B4A8", +"000000067F000080000007A00C0000054000-000000067F000080000007A00C0000058000__0000009921F3B4A8", +"000000067F000080000007A00C00000551B3-000000067F000080000007A00C000005E90A__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000058000-000000067F000080000007A00C000005C000__0000009921F3B4A8", +"000000067F000080000007A00C000005C000-000000067F000080000007A00C0000060000__0000009921F3B4A8", +"000000067F000080000007A00C000005E90A-000000067F000080000007A00C000006802C__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000060000-000000067F000080000007A00C0000064000__0000009921F3B4A8", +"000000067F000080000007A00C0000064000-000000067F000080000007A00C0000068000__0000009921F3B4A8", +"000000067F000080000007A00C0000068000-000000067F000080000007A00C000006C000__0000009921F3B4A8", +"000000067F000080000007A00C000006802C-000000067F000080000007A00C0000071783__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C000006C000-000000067F000080000007A00C0000070000__0000009921F3B4A8", +"000000067F000080000007A00C0000070000-000000067F000080000007A00C0000074000__0000009921F3B4A8", +"000000067F000080000007A00C0000071783-000000067F000080000007A00C000007AEE8__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000074000-000000067F000080000007A00C0000078000__0000009921F3B4A8", +"000000067F000080000007A00C0000078000-000000067F000080000007A00C000007C000__0000009921F3B4A8", +"000000067F000080000007A00C000007AEE8-000000067F000080000007A00C000008460B__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C000007C000-000000067F000080000007A00C0000080000__0000009921F3B4A8", +"000000067F000080000007A00C0000080000-000000067F000080000007A00C0000084000__0000009921F3B4A8", +"000000067F000080000007A00C0000084000-000000067F000080000007A00C0000088000__0000009921F3B4A8", +"000000067F000080000007A00C000008460B-000000067F000080000007A00C000008DD71__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000088000-000000067F000080000007A00C000008C000__0000009921F3B4A8", +"000000067F000080000007A00C000008C000-000000067F000080000007A00C0000090000__0000009921F3B4A8", +"000000067F000080000007A00C000008DD71-000000067F000080000007A00C00000974D7__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000090000-000000067F000080000007A00C0000094000__0000009921F3B4A8", +"000000067F000080000007A00C0000094000-000000067F000080000007A00C0000098000__0000009921F3B4A8", +"000000067F000080000007A00C00000974D7-000000067F000080000007A00C00000A0C0B__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000097B7A-000000067F000080000007A00C00000E3627__0000009921E47AA1-000000997F5D23C9", +"000000067F000080000007A00C0000098000-000000067F000080000007A00C000009C000__0000009921F3B4A8", +"000000067F000080000007A00C000009C000-000000067F000080000007A00C00000A0000__0000009921F3B4A8", +"000000067F000080000007A00C00000A0000-000000067F000080000007A00C00000A4000__0000009921F3B4A8", +"000000067F000080000007A00C00000A0C0B-000000067F000080000007A00C00000AA371__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C00000A4000-000000067F000080000007A00C00000A8000__0000009921F3B4A8", +"000000067F000080000007A00C00000A8000-000000067F000080000007A00C00000AC000__0000009921F3B4A8", +"000000067F000080000007A00C00000AA371-000000067F000080000007A00C00000B3AD7__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C00000AC000-000000067F000080000007A00C00000B0000__0000009921F3B4A8", +"000000067F000080000007A00C00000B0000-000000067F000080000007A00C00000B4000__0000009921F3B4A8", +"000000067F000080000007A00C00000B3AD7-000000067F000080000007A00C00000BD20B__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C00000B4000-000000067F000080000007A00C00000B8000__0000009921F3B4A8", +"000000067F000080000007A00C00000B8000-000000067F000080000007A00C00000BC000__0000009921F3B4A8", +"000000067F000080000007A00C00000BC000-000000067F000080000007A00C00000C0000__0000009921F3B4A8", +"000000067F000080000007A00C00000BD20B-000000067F000080000007A00C00000C6932__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C00000C0000-000000067F000080000007A00C00000C4000__0000009921F3B4A8", +"000000067F000080000007A00C00000C4000-000000067F000080000007A00C00000C8000__0000009921F3B4A8", +"000000067F000080000007A00C00000C6932-000000067F000080000007A00C00000D0098__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C00000C8000-000000067F000080000007A00C00000CC000__0000009921F3B4A8", +"000000067F000080000007A00C00000CC000-000000067F000080000007A00C00000D0000__0000009921F3B4A8", +"000000067F000080000007A00C00000D0000-000000067F000080000007A00C00000D4000__0000009921F3B4A8", +"000000067F000080000007A00C00000D0098-000000067F000080000007A00C00000D97FE__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C00000D4000-000000067F000080000007A00C00000D8000__0000009921F3B4A8", +"000000067F000080000007A00C00000D8000-000000067F000080000007A00C00000DC000__0000009921F3B4A8", +"000000067F000080000007A00C00000D97FE-000000067F000080000007A00C00000E2F0B__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C00000DC000-000000067F000080000007A00C00000E0000__0000009921F3B4A8", +"000000067F000080000007A00C00000E0000-000000067F000080000007A00C00000E4000__0000009921F3B4A8", +"000000067F000080000007A00C00000E2F0B-000000067F000080000007A00C00000EC671__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C00000E364A-000000067F000080000007A01400000065FE__0000009921E47AA1-000000997F5D23C9", +"000000067F000080000007A00C00000E4000-000000067F000080000007A00C00000E8000__0000009921F3B4A8", +"000000067F000080000007A00C00000E8000-000000067F000080000007A00C00000EC000__0000009921F3B4A8", +"000000067F000080000007A00C00000EC000-000000067F000080000007A00C00000F0000__0000009921F3B4A8", +"000000067F000080000007A00C00000EC671-000000067F000080000007A00C00000F5D9F__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C00000F0000-000000067F000080000007A00C00000F4000__0000009921F3B4A8", +"000000067F000080000007A00C00000F4000-000000067F000080000007A00C00000F8000__0000009921F3B4A8", +"000000067F000080000007A00C00000F5D9F-000000067F000080000007A00C00000FF505__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C00000F720F-000000067F000080000007A00C0000111692__00000098A7ADFC91-0000009921E47AA1", +"000000067F000080000007A00C00000F8000-000000067F000080000007A00C00000FC000__0000009921F3B4A8", +"000000067F000080000007A00C00000FC000-000000067F000080000007A00C0000100000__0000009921F3B4A8", +"000000067F000080000007A00C00000FF505-000000067F000080000007A00C0000108C10__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C0000100000-000000067F000080000007A00C0000104000__0000009921F3B4A8", +"000000067F000080000007A00C0000104000-000000067F000080000007A00C0000108000__0000009921F3B4A8", +"000000067F000080000007A00C0000108000-000000067F000080000007A00C000010C000__0000009921F3B4A8", +"000000067F000080000007A00C0000108C10-030000000000000000000000000000000002__00000096E85829C9-00000098A7ADFC91", +"000000067F000080000007A00C000010C000-000000067F000080000007A00C0000110000__0000009921F3B4A8", +"000000067F000080000007A00C0000110000-000000067F000080000007A0120100000000__0000009921F3B4A8", +"000000067F000080000007A00C0000111692-000000067F000080000007A01400000040E7__00000098A7ADFC91-0000009921E47AA1", +"000000067F000080000007A0140000000000-000000067F000080000007A0140000004000__0000009921F3B4A8", +"000000067F000080000007A0140000004000-000000067F000080000007A0140000008000__0000009921F3B4A8", +"000000067F000080000007A01400000040E7-000000067F000080000007A014000000B5F6__00000098A7ADFC91-0000009921E47AA1", +"000000067F000080000007A0140000006601-000000067F000080000007A014000001B4CB__0000009921E47AA1-000000997F5D23C9", +"000000067F000080000007A0140000008000-000000067F000080000007A014000000C000__0000009921F3B4A8", +"000000067F000080000007A014000000B5F6-000000067F000080000007A0140000012AFC__00000098A7ADFC91-0000009921E47AA1", +"000000067F000080000007A014000000C000-000000067F000080000007A0140000010000__0000009921F3B4A8", +"000000067F000080000007A0140000010000-000000067F000080000007A0140000014000__0000009921F3B4A8", +"000000067F000080000007A0140000012AFC-000000067F000080000007A0140000019F9B__00000098A7ADFC91-0000009921E47AA1", +"000000067F000080000007A0140000014000-000000067F000080000007A0140000018000__0000009921F3B4A8", +"000000067F000080000007A0140000018000-000000067F000080000007A014000001C000__0000009921F3B4A8", +"000000067F000080000007A0140000019F9B-000000067F000080000007A01400000214BE__00000098A7ADFC91-0000009921E47AA1", +"000000067F000080000007A014000001B4CB-030000000000000000000000000000000002__0000009921E47AA1-000000997F5D23C9", +"000000067F000080000007A014000001C000-000000067F000080000007A0140000020000__0000009921F3B4A8", +"000000067F000080000007A0140000020000-000000067F000080000007A0140000024000__0000009921F3B4A8", +"000000067F000080000007A01400000214BE-000000067F000080000007A01400000289C9__00000098A7ADFC91-0000009921E47AA1", +"000000067F000080000007A0140000024000-000000067F000080000007A0140000028000__0000009921F3B4A8", +"000000067F000080000007A0140000028000-000000067F000080000007A014000002C000__0000009921F3B4A8", +"000000067F000080000007A01400000289C9-030000000000000000000000000000000002__00000098A7ADFC91-0000009921E47AA1", +"000000067F000080000007A014000002C000-030000000000000000000000000000000002__0000009921F3B4A8", +"000000067F000080000007C00C0000000000-000000067F000080000007C00C0000004000__0000009B5229DFE8", +"000000067F000080000007C00C0000004000-000000067F000080000007C00C0000008000__0000009B5229DFE8", +"000000067F000080000007C00C0000007EA5-000000067F000080000007C00C00000115FE__000000997F5D23C9-00000099F1C9FC71", +"000000067F000080000007C00C0000008000-000000067F000080000007C00C000000C000__0000009B5229DFE8", +"000000067F000080000007C00C000000C000-000000067F000080000007C00C0000010000__0000009B5229DFE8", +"000000067F000080000007C00C0000010000-000000067F000080000007C00C0000014000__0000009B5229DFE8", +"000000067F000080000007C00C00000115FE-000000067F000080000007C00C000001AD0C__000000997F5D23C9-00000099F1C9FC71", +"000000067F000080000007C00C0000014000-000000067F000080000007C00C0000018000__0000009B5229DFE8", +"000000067F000080000007C00C0000018000-000000067F000080000007C00C000001C000__0000009B5229DFE8", +"000000067F000080000007C00C000001AD0C-000000067F000080000007C00C0000024472__000000997F5D23C9-00000099F1C9FC71", +"000000067F000080000007C00C000001C000-000000067F000080000007C00C0000020000__0000009B5229DFE8", +"000000067F000080000007C00C0000020000-000000067F000080000007C00C0000024000__0000009B5229DFE8", +"000000067F000080000007C00C0000024000-000000067F000080000007C00C0000028000__0000009B5229DFE8", +"000000067F000080000007C00C0000024472-000000067F000080000007C00C000002DBD8__000000997F5D23C9-00000099F1C9FC71", +"000000067F000080000007C00C0000028000-000000067F000080000007C00C000002C000__0000009B5229DFE8", +"000000067F000080000007C00C000002C000-000000067F000080000007C00C0000030000__0000009B5229DFE8", +"000000067F000080000007C00C000002DBD8-000000067F000080000007C00C000003732B__000000997F5D23C9-00000099F1C9FC71", +"000000067F000080000007C00C0000030000-000000067F000080000007C00C0000034000__0000009B5229DFE8", +"000000067F000080000007C00C0000034000-000000067F000080000007C00C0000038000__0000009B5229DFE8", +"000000067F000080000007C00C000003732B-000000067F000080000007C00C0000040A91__000000997F5D23C9-00000099F1C9FC71", +"000000067F000080000007C00C0000038000-000000067F000080000007C00C000003C000__0000009B5229DFE8", +"000000067F000080000007C00C000003C000-000000067F000080000007C00C0000040000__0000009B5229DFE8", +"000000067F000080000007C00C0000040000-000000067F000080000007C00C0000044000__0000009B40525F80", +"000000067F000080000007C00C0000040000-000000067F000080000007C00C0000044000__0000009C1E3799F0", +"000000067F000080000007C00C0000040A91-030000000000000000000000000000000002__000000997F5D23C9-00000099F1C9FC71", +"000000067F000080000007C00C0000042360-000000067F000080000007C00C000004BAC6__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C0000044000-000000067F000080000007C00C0000048000__0000009B40525F80", +"000000067F000080000007C00C0000044000-000000067F000080000007C00C0000048000__0000009C1E3799F0", +"000000067F000080000007C00C0000048000-000000067F000080000007C00C000004C000__0000009B40525F80", +"000000067F000080000007C00C0000048000-000000067F000080000007C00C000004C000__0000009C1E3799F0", +"000000067F000080000007C00C000004BAC6-000000067F000080000007C00C00000551FB__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C000004C000-000000067F000080000007C00C0000050000__0000009B40525F80", +"000000067F000080000007C00C000004C000-000000067F000080000007C00C0000050000__0000009C1E3799F0", +"000000067F000080000007C00C0000050000-000000067F000080000007C00C0000054000__0000009B40525F80", +"000000067F000080000007C00C0000050000-000000067F000080000007C00C0000054000__0000009C1E3799F0", +"000000067F000080000007C00C0000052AA4-000000067F000080000007C00C00000A4244__0000009BCB4E4461-0000009C1E8CC879", +"000000067F000080000007C00C0000054000-000000067F000080000007C00C0000058000__0000009B40525F80", +"000000067F000080000007C00C0000054000-000000067F000080000007C00C0000058000__0000009C1E3799F0", +"000000067F000080000007C00C00000551FB-000000067F000080000007C00C000005E90B__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C0000058000-000000067F000080000007C00C000005C000__0000009B40525F80", +"000000067F000080000007C00C0000058000-000000067F000080000007C00C000005C000__0000009C1E3799F0", +"000000067F000080000007C00C000005C000-000000067F000080000007C00C0000060000__0000009B40525F80", +"000000067F000080000007C00C000005C000-000000067F000080000007C00C0000060000__0000009C1E3799F0", +"000000067F000080000007C00C000005E90B-000000067F000080000007C00C000006802B__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C0000060000-000000067F000080000007C00C0000064000__0000009B40525F80", +"000000067F000080000007C00C0000060000-000000067F000080000007C00C0000064000__0000009C1E3799F0", +"000000067F000080000007C00C0000064000-000000067F000080000007C00C0000068000__0000009B40525F80", +"000000067F000080000007C00C0000064000-000000067F000080000007C00C0000068000__0000009C1E3799F0", +"000000067F000080000007C00C0000068000-000000067F000080000007C00C000006C000__0000009B40525F80", +"000000067F000080000007C00C0000068000-000000067F000080000007C00C000006C000__0000009C1E3799F0", +"000000067F000080000007C00C000006802B-000000067F000080000007C00C0000071782__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C000006C000-000000067F000080000007C00C0000070000__0000009B40525F80", +"000000067F000080000007C00C000006C000-000000067F000080000007C00C0000070000__0000009C1E3799F0", +"000000067F000080000007C00C0000070000-000000067F000080000007C00C0000074000__0000009B40525F80", +"000000067F000080000007C00C0000070000-000000067F000080000007C00C0000074000__0000009C1E3799F0", +"000000067F000080000007C00C0000071782-000000067F000080000007C00C000007AEE8__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C0000074000-000000067F000080000007C00C0000078000__0000009B40525F80", +"000000067F000080000007C00C0000074000-000000067F000080000007C00C0000078000__0000009C1E3799F0", +"000000067F000080000007C00C0000078000-000000067F000080000007C00C000007C000__0000009B40525F80", +"000000067F000080000007C00C0000078000-000000067F000080000007C00C000007C000__0000009C1E3799F0", +"000000067F000080000007C00C000007AEE8-000000067F000080000007C00C000008460B__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C000007C000-000000067F000080000007C00C0000080000__0000009B40525F80", +"000000067F000080000007C00C000007C000-000000067F000080000007C00C0000080000__0000009C1E3799F0", +"000000067F000080000007C00C0000080000-000000067F000080000007C00C0000084000__0000009B40525F80", +"000000067F000080000007C00C0000080000-000000067F000080000007C00C0000084000__0000009C1E3799F0", +"000000067F000080000007C00C0000084000-000000067F000080000007C00C0000088000__0000009B40525F80", +"000000067F000080000007C00C0000084000-000000067F000080000007C00C0000088000__0000009C1E3799F0", +"000000067F000080000007C00C000008460B-000000067F000080000007C00C000008DD71__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C0000088000-000000067F000080000007C00C000008C000__0000009B40525F80", +"000000067F000080000007C00C0000088000-000000067F000080000007C00C000008C000__0000009C1E3799F0", +"000000067F000080000007C00C000008C000-000000067F000080000007C00C0000090000__0000009B40525F80", +"000000067F000080000007C00C000008C000-000000067F000080000007C00C0000090000__0000009C1E3799F0", +"000000067F000080000007C00C000008DD71-000000067F000080000007C00C00000974D7__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C0000090000-000000067F000080000007C00C0000094000__0000009B40525F80", +"000000067F000080000007C00C0000090000-000000067F000080000007C00C0000094000__0000009C1E3799F0", +"000000067F000080000007C00C0000094000-000000067F000080000007C00C0000098000__0000009B40525F80", +"000000067F000080000007C00C0000094000-000000067F000080000007C00C0000098000__0000009C1E3799F0", +"000000067F000080000007C00C00000974D7-000000067F000080000007C00C00000A0C0B__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C0000098000-000000067F000080000007C00C000009C000__0000009B40525F80", +"000000067F000080000007C00C0000098000-000000067F000080000007C00C000009C000__0000009C1E3799F0", +"000000067F000080000007C00C000009C000-000000067F000080000007C00C00000A0000__0000009B40525F80", +"000000067F000080000007C00C000009C000-000000067F000080000007C00C00000A0000__0000009C1E3799F0", +"000000067F000080000007C00C00000A0000-000000067F000080000007C00C00000A4000__0000009B40525F80", +"000000067F000080000007C00C00000A0000-000000067F000080000007C00C00000A4000__0000009C1E3799F0", +"000000067F000080000007C00C00000A0C0B-000000067F000080000007C00C0100000000__00000099F1C9FC71-0000009A918DF181", +"000000067F000080000007C00C00000A4000-000000067F000080000007C00C00000A8000__0000009B40525F80", +"000000067F000080000007C00C00000A4000-000000067F000080000007C00C00000A8000__0000009C1E3799F0", +"000000067F000080000007C00C00000A424C-000000067F000080000007C00C00000F5B43__0000009BCB4E4461-0000009C1E8CC879", +"000000067F000080000007C00C00000A8000-000000067F000080000007C00C00000AC000__0000009B40525F80", +"000000067F000080000007C00C00000A8000-000000067F000080000007C00C00000AC000__0000009C1E3799F0", +"000000067F000080000007C00C00000A9244-000000067F000080000007C00C00000B2991__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C00000AC000-000000067F000080000007C00C00000B0000__0000009B40525F80", +"000000067F000080000007C00C00000AC000-000000067F000080000007C00C00000B0000__0000009C1E3799F0", +"000000067F000080000007C00C00000B0000-000000067F000080000007C00C00000B4000__0000009B40525F80", +"000000067F000080000007C00C00000B0000-000000067F000080000007C00C00000B4000__0000009C1E3799F0", +"000000067F000080000007C00C00000B2991-000000067F000080000007C00C00000BC0F7__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C00000B4000-000000067F000080000007C00C00000B8000__0000009B40525F80", +"000000067F000080000007C00C00000B4000-000000067F000080000007C00C00000B8000__0000009C1E3799F0", +"000000067F000080000007C00C00000B8000-000000067F000080000007C00C00000BC000__0000009B40525F80", +"000000067F000080000007C00C00000B8000-000000067F000080000007C00C00000BC000__0000009C1E3799F0", +"000000067F000080000007C00C00000BA258-000000067F000080000007C01400000011E2__0000009B51A8BBB9-0000009BCB4E4461", +"000000067F000080000007C00C00000BC000-000000067F000080000007C00C00000C0000__0000009B40525F80", +"000000067F000080000007C00C00000BC000-000000067F000080000007C00C00000C0000__0000009C1E3799F0", +"000000067F000080000007C00C00000BC0F7-000000067F000080000007C00C00000C580C__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C00000C0000-000000067F000080000007C00C00000C4000__0000009B40525F80", +"000000067F000080000007C00C00000C0000-000000067F000080000007C00C00000C4000__0000009C1E3799F0", +"000000067F000080000007C00C00000C4000-000000067F000080000007C00C00000C8000__0000009B40525F80", +"000000067F000080000007C00C00000C4000-000000067F000080000007C00C00000C8000__0000009C1E3799F0", +"000000067F000080000007C00C00000C580C-000000067F000080000007C00C00000CEF72__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C00000C8000-000000067F000080000007C00C00000CC000__0000009B40525F80", +"000000067F000080000007C00C00000C8000-000000067F000080000007C00C00000CC000__0000009C1E3799F0", +"000000067F000080000007C00C00000CC000-000000067F000080000007C00C00000D0000__0000009B40525F80", +"000000067F000080000007C00C00000CC000-000000067F000080000007C00C00000D0000__0000009C1E3799F0", +"000000067F000080000007C00C00000CEF72-000000067F000080000007C00C00000D86D8__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C00000D0000-000000067F000080000007C00C00000D4000__0000009B40525F80", +"000000067F000080000007C00C00000D0000-000000067F000080000007C00C00000D4000__0000009C1E3799F0", +"000000067F000080000007C00C00000D4000-000000067F000080000007C00C00000D8000__0000009B40525F80", +"000000067F000080000007C00C00000D4000-000000067F000080000007C00C00000D8000__0000009C1E3799F0", +"000000067F000080000007C00C00000D8000-000000067F000080000007C00C00000DC000__0000009B40525F80", +"000000067F000080000007C00C00000D8000-000000067F000080000007C00C00000DC000__0000009C1E3799F0", +"000000067F000080000007C00C00000D86D8-000000067F000080000007C00C00000E1E0B__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C00000DC000-000000067F000080000007C00C00000E0000__0000009B40525F80", +"000000067F000080000007C00C00000DC000-000000067F000080000007C00C00000E0000__0000009C1E3799F0", +"000000067F000080000007C00C00000E0000-000000067F000080000007C00C00000E4000__0000009B40525F80", +"000000067F000080000007C00C00000E0000-000000067F000080000007C00C00000E4000__0000009C1E3799F0", +"000000067F000080000007C00C00000E1E0B-000000067F000080000007C00C00000EB571__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C00000E4000-000000067F000080000007C00C00000E8000__0000009B40525F80", +"000000067F000080000007C00C00000E4000-000000067F000080000007C00C00000E8000__0000009C1E3799F0", +"000000067F000080000007C00C00000E8000-000000067F000080000007C00C00000EC000__0000009B40525F80", +"000000067F000080000007C00C00000E8000-000000067F000080000007C00C00000EC000__0000009C1E3799F0", +"000000067F000080000007C00C00000EB571-000000067F000080000007C00C00000F4CD7__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C00000EC000-000000067F000080000007C00C00000F0000__0000009B40525F80", +"000000067F000080000007C00C00000EC000-000000067F000080000007C00C00000F0000__0000009C1E3799F0", +"000000067F000080000007C00C00000F0000-000000067F000080000007C00C00000F4000__0000009B40525F80", +"000000067F000080000007C00C00000F0000-000000067F000080000007C00C00000F4000__0000009C1E3799F0", +"000000067F000080000007C00C00000F4000-000000067F000080000007C00C00000F8000__0000009B40525F80", +"000000067F000080000007C00C00000F4000-000000067F000080000007C00C00000F8000__0000009C1E3799F0", +"000000067F000080000007C00C00000F4CD7-000000067F000080000007C00C00000FE40B__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C00000F5B56-000000067F000080000007C014000000EB5A__0000009BCB4E4461-0000009C1E8CC879", +"000000067F000080000007C00C00000F8000-000000067F000080000007C00C00000FC000__0000009B40525F80", +"000000067F000080000007C00C00000F8000-000000067F000080000007C00C00000FC000__0000009C1E3799F0", +"000000067F000080000007C00C00000FC000-000000067F000080000007C00C0000100000__0000009B40525F80", +"000000067F000080000007C00C00000FC000-000000067F000080000007C00C0000100000__0000009C1E3799F0", +"000000067F000080000007C00C00000FE40B-000000067F000080000007C00C0000107B27__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C0000100000-000000067F000080000007C00C0000104000__0000009B40525F80", +"000000067F000080000007C00C0000100000-000000067F000080000007C00C0000104000__0000009C1E3799F0", +"000000067F000080000007C00C0000104000-000000067F000080000007C00C0000108000__0000009B40525F80", +"000000067F000080000007C00C0000104000-000000067F000080000007C00C0000108000__0000009C1E3799F0", +"000000067F000080000007C00C0000107B27-000000067F000080000007C00C000011128D__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C00C0000108000-000000067F000080000007C00C000010C000__0000009C1E3799F0", +"000000067F000080000007C00C0000108000-030000000000000000000000000000000002__0000009B40525F80", +"000000067F000080000007C00C000010C000-000000067F000080000007C00C0000110000__0000009C1E3799F0", +"000000067F000080000007C00C0000110000-000000067F000080000007C0120100000000__0000009C1E3799F0", +"000000067F000080000007C00C000011128D-010000000000000001000000040000000012__0000009A918DF181-0000009B51A8BBB9", +"000000067F000080000007C0140000000000-000000067F000080000007C0140000004000__0000009C1E3799F0", +"000000067F000080000007C01400000011E2-000000067F000080000007C0140000007F04__0000009B51A8BBB9-0000009BCB4E4461", +"000000067F000080000007C0140000004000-000000067F000080000007C0140000008000__0000009C1E3799F0", +"000000067F000080000007C0140000007F04-000000067F000080000007C014000000EC12__0000009B51A8BBB9-0000009BCB4E4461", +"000000067F000080000007C0140000008000-000000067F000080000007C014000000C000__0000009C1E3799F0", +"000000067F000080000007C014000000C000-000000067F000080000007C0140000010000__0000009C1E3799F0", +"000000067F000080000007C014000000EB5A-000000067F000080000007C0140000027B5C__0000009BCB4E4461-0000009C1E8CC879", +"000000067F000080000007C014000000EC12-000000067F000080000007C0140000015910__0000009B51A8BBB9-0000009BCB4E4461", +"000000067F000080000007C0140000010000-000000067F000080000007C0140000014000__0000009C1E3799F0", +"000000067F000080000007C0140000014000-000000067F000080000007C0140000018000__0000009C1E3799F0", +"000000067F000080000007C0140000015910-000000067F000080000007C014000001C5BB__0000009B51A8BBB9-0000009BCB4E4461", +"000000067F000080000007C0140000018000-000000067F000080000007C014000001C000__0000009C1E3799F0", +"000000067F000080000007C014000001C000-000000067F000080000007C0140000020000__0000009C1E3799F0", +"000000067F000080000007C014000001C5BB-000000067F000080000007C0140000023298__0000009B51A8BBB9-0000009BCB4E4461", +"000000067F000080000007C0140000020000-000000067F000080000007C0140000024000__0000009C1E3799F0", +"000000067F000080000007C0140000023298-000000067F000080000007C0140000029F9A__0000009B51A8BBB9-0000009BCB4E4461", +"000000067F000080000007C0140000024000-000000067F000080000007C0140000028000__0000009C1E3799F0", +"000000067F000080000007C0140000027B5E-030000000000000000000000000000000002__0000009BCB4E4461-0000009C1E8CC879", +"000000067F000080000007C0140000028000-000000067F000080000007C014000002C000__0000009C1E3799F0", +"000000067F000080000007C0140000029F9A-030000000000000000000000000000000002__0000009B51A8BBB9-0000009BCB4E4461", +"000000067F000080000007C014000002C000-030000000000000000000000000000000002__0000009C1E3799F0", +"000000067F000080000007E00C0000000000-000000067F000080000007E00C0000004000__0000009DEF760000", +"000000067F000080000007E00C0000004000-000000067F000080000007E00C0000008000__0000009DEF760000", +"000000067F000080000007E00C0000008000-000000067F000080000007E00C000000C000__0000009DEF760000", +"000000067F000080000007E00C00000092CD-000000067F000080000007E00C0000012A0A__0000009C1E8CC879-0000009C9ED3F059", +"000000067F000080000007E00C000000C000-000000067F000080000007E00C0000010000__0000009DEF760000", +"000000067F000080000007E00C0000010000-000000067F000080000007E00C0000014000__0000009DEF760000", +"000000067F000080000007E00C0000012A0A-000000067F000080000007E00C000001C170__0000009C1E8CC879-0000009C9ED3F059", +"000000067F000080000007E00C0000014000-000000067F000080000007E00C0000018000__0000009DEF760000", +"000000067F000080000007E00C0000018000-000000067F000080000007E00C000001C000__0000009DEF760000", +"000000067F000080000007E00C000001C000-000000067F000080000007E00C0000020000__0000009DEF760000", +"000000067F000080000007E00C000001C170-000000067F000080000007E00C00000258D6__0000009C1E8CC879-0000009C9ED3F059", +"000000067F000080000007E00C0000020000-000000067F000080000007E00C0000024000__0000009DEF760000", +"000000067F000080000007E00C0000024000-000000067F000080000007E00C0000028000__0000009DEF760000", +"000000067F000080000007E00C00000258D6-000000067F000080000007E00C000002F00B__0000009C1E8CC879-0000009C9ED3F059", +"000000067F000080000007E00C0000028000-000000067F000080000007E00C000002C000__0000009DEF760000", +"000000067F000080000007E00C000002C000-000000067F000080000007E00C0000030000__0000009DEF760000", +"000000067F000080000007E00C000002F00B-000000067F000080000007E00C0000038720__0000009C1E8CC879-0000009C9ED3F059", +"000000067F000080000007E00C0000030000-000000067F000080000007E00C0000034000__0000009DEF760000", +"000000067F000080000007E00C0000034000-000000067F000080000007E00C0000038000__0000009DEF760000", +"000000067F000080000007E00C0000038000-000000067F000080000007E00C000003C000__0000009DEF760000", +"000000067F000080000007E00C0000038720-000000067F000080000007E00C0000041E86__0000009C1E8CC879-0000009C9ED3F059", +"000000067F000080000007E00C000003C000-000000067F000080000007E00C0000040000__0000009DEF760000", +"000000067F000080000007E00C0000040000-000000067F000080000007E00C0000044000__0000009DEF760000", +"000000067F000080000007E00C0000041E86-000000067F000080000007E00C000004B5EC__0000009C1E8CC879-0000009C9ED3F059", +"000000067F000080000007E00C0000044000-000000067F000080000007E00C0000048000__0000009DEF760000", +"000000067F000080000007E00C0000048000-000000067F000080000007E00C000004C000__0000009DDBE10620", +"000000067F000080000007E00C0000048000-000000067F000080000007E00C000004C000__0000009EBB11FFC0", +"000000067F000080000007E00C000004B5EC-030000000000000000000000000000000002__0000009C1E8CC879-0000009C9ED3F059", +"000000067F000080000007E00C000004BACA-000000067F000080000007E00C00000551FF__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C000004C000-000000067F000080000007E00C0000050000__0000009DDBE10620", +"000000067F000080000007E00C000004C000-000000067F000080000007E00C0000050000__0000009EBB11FFC0", +"000000067F000080000007E00C0000050000-000000067F000080000007E00C0000054000__0000009DDBE10620", +"000000067F000080000007E00C0000050000-000000067F000080000007E00C0000054000__0000009EBB11FFC0", +"000000067F000080000007E00C0000054000-000000067F000080000007E00C0000058000__0000009DDBE10620", +"000000067F000080000007E00C0000054000-000000067F000080000007E00C0000058000__0000009EBB11FFC0", +"000000067F000080000007E00C00000551FF-000000067F000080000007E00C000005E90C__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C0000058000-000000067F000080000007E00C000005C000__0000009DDBE10620", +"000000067F000080000007E00C0000058000-000000067F000080000007E00C000005C000__0000009EBB11FFC0", +"000000067F000080000007E00C000005C000-000000067F000080000007E00C0000060000__0000009DDBE10620", +"000000067F000080000007E00C000005C000-000000067F000080000007E00C0000060000__0000009EBB11FFC0", +"000000067F000080000007E00C000005E90C-000000067F000080000007E00C000006802C__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C0000060000-000000067F000080000007E00C0000064000__0000009DDBE10620", +"000000067F000080000007E00C0000060000-000000067F000080000007E00C0000064000__0000009EBB11FFC0", +"000000067F000080000007E00C0000061AE1-000000067F000080000007E00C00000C2A6C__0000009E781A9731-0000009EBBC72771", +"000000067F000080000007E00C0000064000-000000067F000080000007E00C0000068000__0000009DDBE10620", +"000000067F000080000007E00C0000064000-000000067F000080000007E00C0000068000__0000009EBB11FFC0", +"000000067F000080000007E00C0000068000-000000067F000080000007E00C000006C000__0000009DDBE10620", +"000000067F000080000007E00C0000068000-000000067F000080000007E00C000006C000__0000009EBB11FFC0", +"000000067F000080000007E00C000006802C-000000067F000080000007E00C0000071783__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C000006C000-000000067F000080000007E00C0000070000__0000009DDBE10620", +"000000067F000080000007E00C000006C000-000000067F000080000007E00C0000070000__0000009EBB11FFC0", +"000000067F000080000007E00C0000070000-000000067F000080000007E00C0000074000__0000009DDBE10620", +"000000067F000080000007E00C0000070000-000000067F000080000007E00C0000074000__0000009EBB11FFC0", +"000000067F000080000007E00C0000071783-000000067F000080000007E00C000007AEE9__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C0000074000-000000067F000080000007E00C0000078000__0000009DDBE10620", +"000000067F000080000007E00C0000074000-000000067F000080000007E00C0000078000__0000009EBB11FFC0", +"000000067F000080000007E00C0000078000-000000067F000080000007E00C000007C000__0000009DDBE10620", +"000000067F000080000007E00C0000078000-000000067F000080000007E00C000007C000__0000009EBB11FFC0", +"000000067F000080000007E00C000007AEE9-000000067F000080000007E00C000008460B__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C000007C000-000000067F000080000007E00C0000080000__0000009DDBE10620", +"000000067F000080000007E00C000007C000-000000067F000080000007E00C0000080000__0000009EBB11FFC0", +"000000067F000080000007E00C0000080000-000000067F000080000007E00C0000084000__0000009DDBE10620", +"000000067F000080000007E00C0000080000-000000067F000080000007E00C0000084000__0000009EBB11FFC0", +"000000067F000080000007E00C0000084000-000000067F000080000007E00C0000088000__0000009DDBE10620", +"000000067F000080000007E00C0000084000-000000067F000080000007E00C0000088000__0000009EBB11FFC0", +"000000067F000080000007E00C000008460B-000000067F000080000007E00C000008DD71__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C0000088000-000000067F000080000007E00C000008C000__0000009DDBE10620", +"000000067F000080000007E00C0000088000-000000067F000080000007E00C000008C000__0000009EBB11FFC0", +"000000067F000080000007E00C000008C000-000000067F000080000007E00C0000090000__0000009DDBE10620", +"000000067F000080000007E00C000008C000-000000067F000080000007E00C0000090000__0000009EBB11FFC0", +"000000067F000080000007E00C000008DD71-000000067F000080000007E00C00000974D7__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C0000090000-000000067F000080000007E00C0000094000__0000009DDBE10620", +"000000067F000080000007E00C0000090000-000000067F000080000007E00C0000094000__0000009EBB11FFC0", +"000000067F000080000007E00C0000093E3A-000000067F000080000007E00C0000111CED__0000009DEEE6BFF9-0000009E781A9731", +"000000067F000080000007E00C0000094000-000000067F000080000007E00C0000098000__0000009DDBE10620", +"000000067F000080000007E00C0000094000-000000067F000080000007E00C0000098000__0000009EBB11FFC0", +"000000067F000080000007E00C00000974D7-000000067F000080000007E00C00000A0C0B__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C0000098000-000000067F000080000007E00C000009C000__0000009DDBE10620", +"000000067F000080000007E00C0000098000-000000067F000080000007E00C000009C000__0000009EBB11FFC0", +"000000067F000080000007E00C000009C000-000000067F000080000007E00C00000A0000__0000009DDBE10620", +"000000067F000080000007E00C000009C000-000000067F000080000007E00C00000A0000__0000009EBB11FFC0", +"000000067F000080000007E00C00000A0000-000000067F000080000007E00C00000A4000__0000009DDBE10620", +"000000067F000080000007E00C00000A0000-000000067F000080000007E00C00000A4000__0000009EBB11FFC0", +"000000067F000080000007E00C00000A0C0B-000000067F000080000007E00C00000AA371__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C00000A4000-000000067F000080000007E00C00000A8000__0000009DDBE10620", +"000000067F000080000007E00C00000A4000-000000067F000080000007E00C00000A8000__0000009EBB11FFC0", +"000000067F000080000007E00C00000A8000-000000067F000080000007E00C00000AC000__0000009DDBE10620", +"000000067F000080000007E00C00000A8000-000000067F000080000007E00C00000AC000__0000009EBB11FFC0", +"000000067F000080000007E00C00000AA371-000000067F000080000007E00C0100000000__0000009C9ED3F059-0000009D3E97E549", +"000000067F000080000007E00C00000AC000-000000067F000080000007E00C00000B0000__0000009DDBE10620", +"000000067F000080000007E00C00000AC000-000000067F000080000007E00C00000B0000__0000009EBB11FFC0", +"000000067F000080000007E00C00000B0000-000000067F000080000007E00C00000B4000__0000009DDBE10620", +"000000067F000080000007E00C00000B0000-000000067F000080000007E00C00000B4000__0000009EBB11FFC0", +"000000067F000080000007E00C00000B2704-000000067F000080000007E00C00000BBE0F__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C00000B4000-000000067F000080000007E00C00000B8000__0000009DDBE10620", +"000000067F000080000007E00C00000B4000-000000067F000080000007E00C00000B8000__0000009EBB11FFC0", +"000000067F000080000007E00C00000B8000-000000067F000080000007E00C00000BC000__0000009DDBE10620", +"000000067F000080000007E00C00000B8000-000000067F000080000007E00C00000BC000__0000009EBB11FFC0", +"000000067F000080000007E00C00000BBE0F-000000067F000080000007E00C00000C5542__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C00000BC000-000000067F000080000007E00C00000C0000__0000009DDBE10620", +"000000067F000080000007E00C00000BC000-000000067F000080000007E00C00000C0000__0000009EBB11FFC0", +"000000067F000080000007E00C00000C0000-000000067F000080000007E00C00000C4000__0000009DDBE10620", +"000000067F000080000007E00C00000C0000-000000067F000080000007E00C00000C4000__0000009EBB11FFC0", +"000000067F000080000007E00C00000C2A75-000000067F000080000007E0140000004415__0000009E781A9731-0000009EBBC72771", +"000000067F000080000007E00C00000C4000-000000067F000080000007E00C00000C8000__0000009DDBE10620", +"000000067F000080000007E00C00000C4000-000000067F000080000007E00C00000C8000__0000009EBB11FFC0", +"000000067F000080000007E00C00000C5542-000000067F000080000007E00C00000CECA8__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C00000C8000-000000067F000080000007E00C00000CC000__0000009DDBE10620", +"000000067F000080000007E00C00000C8000-000000067F000080000007E00C00000CC000__0000009EBB11FFC0", +"000000067F000080000007E00C00000CC000-000000067F000080000007E00C00000D0000__0000009DDBE10620", +"000000067F000080000007E00C00000CC000-000000067F000080000007E00C00000D0000__0000009EBB11FFC0", +"000000067F000080000007E00C00000CECA8-000000067F000080000007E00C00000D83BF__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C00000D0000-000000067F000080000007E00C00000D4000__0000009DDBE10620", +"000000067F000080000007E00C00000D0000-000000067F000080000007E00C00000D4000__0000009EBB11FFC0", +"000000067F000080000007E00C00000D4000-000000067F000080000007E00C00000D8000__0000009DDBE10620", +"000000067F000080000007E00C00000D4000-000000067F000080000007E00C00000D8000__0000009EBB11FFC0", +"000000067F000080000007E00C00000D8000-000000067F000080000007E00C00000DC000__0000009DDBE10620", +"000000067F000080000007E00C00000D8000-000000067F000080000007E00C00000DC000__0000009EBB11FFC0", +"000000067F000080000007E00C00000D83BF-000000067F000080000007E00C00000E1B0A__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C00000DC000-000000067F000080000007E00C00000E0000__0000009DDBE10620", +"000000067F000080000007E00C00000DC000-000000067F000080000007E00C00000E0000__0000009EBB11FFC0", +"000000067F000080000007E00C00000E0000-000000067F000080000007E00C00000E4000__0000009DDBE10620", +"000000067F000080000007E00C00000E0000-000000067F000080000007E00C00000E4000__0000009EBB11FFC0", +"000000067F000080000007E00C00000E1B0A-000000067F000080000007E00C00000EB270__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C00000E4000-000000067F000080000007E00C00000E8000__0000009DDBE10620", +"000000067F000080000007E00C00000E4000-000000067F000080000007E00C00000E8000__0000009EBB11FFC0", +"000000067F000080000007E00C00000E8000-000000067F000080000007E00C00000EC000__0000009DDBE10620", +"000000067F000080000007E00C00000E8000-000000067F000080000007E00C00000EC000__0000009EBB11FFC0", +"000000067F000080000007E00C00000EB270-000000067F000080000007E00C00000F49AA__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C00000EC000-000000067F000080000007E00C00000F0000__0000009DDBE10620", +"000000067F000080000007E00C00000EC000-000000067F000080000007E00C00000F0000__0000009EBB11FFC0", +"000000067F000080000007E00C00000F0000-000000067F000080000007E00C00000F4000__0000009DDBE10620", +"000000067F000080000007E00C00000F0000-000000067F000080000007E00C00000F4000__0000009EBB11FFC0", +"000000067F000080000007E00C00000F4000-000000067F000080000007E00C00000F8000__0000009DDBE10620", +"000000067F000080000007E00C00000F4000-000000067F000080000007E00C00000F8000__0000009EBB11FFC0", +"000000067F000080000007E00C00000F49AA-000000067F000080000007E00C00000FE10A__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C00000F8000-000000067F000080000007E00C00000FC000__0000009DDBE10620", +"000000067F000080000007E00C00000F8000-000000067F000080000007E00C00000FC000__0000009EBB11FFC0", +"000000067F000080000007E00C00000FC000-000000067F000080000007E00C0000100000__0000009DDBE10620", +"000000067F000080000007E00C00000FC000-000000067F000080000007E00C0000100000__0000009EBB11FFC0", +"000000067F000080000007E00C00000FE10A-000000067F000080000007E00C000010782C__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C0000100000-000000067F000080000007E00C0000104000__0000009DDBE10620", +"000000067F000080000007E00C0000100000-000000067F000080000007E00C0000104000__0000009EBB11FFC0", +"000000067F000080000007E00C0000104000-000000067F000080000007E00C0000108000__0000009EBB11FFC0", +"000000067F000080000007E00C0000104000-030000000000000000000000000000000002__0000009DDBE10620", +"000000067F000080000007E00C000010782C-000000067F000080000007E00C0000110F88__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C0000108000-000000067F000080000007E00C000010C000__0000009EBB11FFC0", +"000000067F000080000007E00C000010C000-000000067F000080000007E00C0000110000__0000009EBB11FFC0", +"000000067F000080000007E00C0000110000-000000067F000080000007E0120100000000__0000009EBB11FFC0", +"000000067F000080000007E00C0000110F88-010000000000000001000000040000000015__0000009D3E97E549-0000009DEEE6BFF9", +"000000067F000080000007E00C0000111CED-000000067F000080000007E0140000004818__0000009DEEE6BFF9-0000009E781A9731", +"000000067F000080000007E0140000000000-000000067F000080000007E0140000004000__0000009EBB11FFC0", +"000000067F000080000007E0140000004000-000000067F000080000007E0140000008000__0000009EBB11FFC0", +"000000067F000080000007E0140000004418-000000067F000080000007E0140000025351__0000009E781A9731-0000009EBBC72771", +"000000067F000080000007E0140000004818-000000067F000080000007E014000000AD57__0000009DEEE6BFF9-0000009E781A9731", +"000000067F000080000007E0140000008000-000000067F000080000007E014000000C000__0000009EBB11FFC0", +"000000067F000080000007E014000000AD57-000000067F000080000007E0140000011291__0000009DEEE6BFF9-0000009E781A9731", +"000000067F000080000007E014000000C000-000000067F000080000007E0140000010000__0000009EBB11FFC0", +"000000067F000080000007E0140000010000-000000067F000080000007E0140000014000__0000009EBB11FFC0", +"000000067F000080000007E0140000011291-000000067F000080000007E0140000017809__0000009DEEE6BFF9-0000009E781A9731", +"000000067F000080000007E0140000014000-000000067F000080000007E0140000018000__0000009EBB11FFC0", +"000000067F000080000007E0140000017809-000000067F000080000007E014000001DD22__0000009DEEE6BFF9-0000009E781A9731", +"000000067F000080000007E0140000018000-000000067F000080000007E014000001C000__0000009EBB11FFC0", +"000000067F000080000007E014000001C000-000000067F000080000007E0140000020000__0000009EBB11FFC0", +"000000067F000080000007E014000001DD22-000000067F000080000007E0140000024244__0000009DEEE6BFF9-0000009E781A9731", +"000000067F000080000007E0140000020000-000000067F000080000007E0140000024000__0000009EBB11FFC0", +"000000067F000080000007E0140000024000-000000067F000080000007E0140000028000__0000009EBB11FFC0", +"000000067F000080000007E0140000024244-000000067F000080000007E014000002A798__0000009DEEE6BFF9-0000009E781A9731", +"000000067F000080000007E0140000025355-030000000000000000000000000000000002__0000009E781A9731-0000009EBBC72771", +"000000067F000080000007E0140000028000-000000067F000080000007E014000002C000__0000009EBB11FFC0", +"000000067F000080000007E014000002A798-030000000000000000000000000000000002__0000009DEEE6BFF9-0000009E781A9731", +"000000067F000080000007E014000002C000-030000000000000000000000000000000002__0000009EBB11FFC0", +"000000067F000080000008000C00000081F6-000000067F000080000008000C0000010448__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C0000010448-000000067F000080000008000C000001870A__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C000001870A-000000067F000080000008000C0000020905__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C0000020905-000000067F000080000008000C0000028AF3__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C0000028AF3-000000067F000080000008000C0000030CEA__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C0000030CEA-000000067F000080000008000C0000038EB6__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C0000038EB6-000000067F000080000008000C00000410B5__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000410B5-000000067F000080000008000C00000492CB__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000492CB-000000067F000080000008000C00000514F8__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000514F8-000000067F000080000008000C000005977B__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C000005977B-000000067F000080000008000C00000619C6__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000619C6-000000067F000080000008000C0000069B6B__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C0000069B6B-000000067F000080000008000C0000071DBE__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C0000071DBE-000000067F000080000008000C0000079F8E__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C0000079F8E-000000067F000080000008000C00000821D7__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000821D7-000000067F000080000008000C000008A3AB__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C000008A3AB-000000067F000080000008000C0000092556__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C0000092556-000000067F000080000008000C000009A744__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C000009A744-000000067F000080000008000C00000A29B0__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000A29B0-000000067F000080000008000C00000AAC4B__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000AAC4B-000000067F000080000008000C00000B2E21__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000B2E21-000000067F000080000008000C00000BB0DB__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000BB0DB-000000067F000080000008000C00000C331B__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000C331B-000000067F000080000008000C00000CB4D2__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000CB4D2-000000067F000080000008000C00000D3754__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000D3754-000000067F000080000008000C00000DB9C6__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000DB9C6-000000067F000080000008000C00000E3BC1__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000E3BC1-000000067F000080000008000C00000EBE00__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000EBE00-000000067F000080000008000C00000F3F63__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000F3F63-000000067F000080000008000C00000FC160__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C00000FC160-000000067F000080000008000C0000104448__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C0000104448-000000067F000080000008000C000010C675__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C000010C675-000000067F000080000008000C020000000B__0000009EBBC72771-000000A154401909", +"000000067F000080000008000C020000000B-000000067F00008000000800140000003ED1__0000009EBBC72771-000000A154401909", +"000000067F00008000000800140000003ED1-000000067F00008000000800140000009486__0000009EBBC72771-000000A154401909", +"000000067F00008000000800140000009486-000000067F0000800000080014000000EA73__0000009EBBC72771-000000A154401909", +"000000067F0000800000080014000000EA73-000000067F0000800000080014000001404D__0000009EBBC72771-000000A154401909", +"000000067F0000800000080014000001404D-000000067F000080000008001400000195A4__0000009EBBC72771-000000A154401909", +"000000067F000080000008001400000195A4-000000067F0000800000080014000001EBB4__0000009EBBC72771-000000A154401909", +"000000067F0000800000080014000001EBB4-000000067F000080000008001400000241E2__0000009EBBC72771-000000A154401909", +"000000067F000080000008001400000241E2-000000067F00008000000800140000029762__0000009EBBC72771-000000A154401909", +"000000067F00008000000800140000029762-030000000000000000000000000000000002__0000009EBBC72771-000000A154401909", +"000000067F000080000008200C0000000000-000000067F000080000008200C0000004000__000000A29F1D8950", +"000000067F000080000008200C0000004000-000000067F000080000008200C0000008000__000000A29F1D8950", +"000000067F000080000008200C0000008000-000000067F000080000008200C000000C000__000000A29F1D8950", +"000000067F000080000008200C000000974D-000000067F000080000008200C0000012EB3__000000A154401909-000000A1E407F839", +"000000067F000080000008200C000000C000-000000067F000080000008200C0000010000__000000A29F1D8950", +"000000067F000080000008200C0000010000-000000067F000080000008200C0000014000__000000A29F1D8950", +"000000067F000080000008200C0000012EB3-000000067F000080000008200C000001C60A__000000A154401909-000000A1E407F839", +"000000067F000080000008200C0000014000-000000067F000080000008200C0000018000__000000A29F1D8950", +"000000067F000080000008200C0000018000-000000067F000080000008200C000001C000__000000A29F1D8950", +"000000067F000080000008200C000001C000-000000067F000080000008200C0000020000__000000A29F1D8950", +"000000067F000080000008200C000001C60A-000000067F000080000008200C0000025D38__000000A154401909-000000A1E407F839", +"000000067F000080000008200C0000020000-000000067F000080000008200C0000024000__000000A29F1D8950", +"000000067F000080000008200C0000024000-000000067F000080000008200C0000028000__000000A29F1D8950", +"000000067F000080000008200C0000025D38-000000067F000080000008200C000002F49E__000000A154401909-000000A1E407F839", +"000000067F000080000008200C0000028000-000000067F000080000008200C000002C000__000000A29F1D8950", +"000000067F000080000008200C000002C000-000000067F000080000008200C0000030000__000000A29F1D8950", +"000000067F000080000008200C000002F49E-000000067F000080000008200C0000038BB1__000000A154401909-000000A1E407F839", +"000000067F000080000008200C0000030000-000000067F000080000008200C0000034000__000000A29F1D8950", +"000000067F000080000008200C0000034000-000000067F000080000008200C0000038000__000000A29F1D8950", +"000000067F000080000008200C0000038000-000000067F000080000008200C000003C000__000000A29F1D8950", +"000000067F000080000008200C0000038BB1-000000067F000080000008200C0000042317__000000A154401909-000000A1E407F839", +"000000067F000080000008200C000003C000-000000067F000080000008200C0000040000__000000A29F1D8950", +"000000067F000080000008200C0000040000-000000067F000080000008200C0000044000__000000A29F1D8950", +"000000067F000080000008200C0000042317-000000067F000080000008200C000004BA7D__000000A154401909-000000A1E407F839", +"000000067F000080000008200C0000044000-000000067F000080000008200C0000048000__000000A29F1D8950", +"000000067F000080000008200C0000048000-000000067F000080000008200C000004C000__000000A29F1D8950", +"000000067F000080000008200C000004BA7D-000000067F000080000008200C00000551B2__000000A154401909-000000A1E407F839", +"000000067F000080000008200C000004C000-000000067F000080000008200C0000050000__000000A29F1D8950", +"000000067F000080000008200C0000050000-000000067F000080000008200C0000054000__000000A29F1D8950", +"000000067F000080000008200C0000054000-000000067F000080000008200C0000058000__000000A29F1D8950", +"000000067F000080000008200C00000551B2-030000000000000000000000000000000002__000000A154401909-000000A1E407F839", +"000000067F000080000008200C0000058000-000000067F000080000008200C000005C000__000000A29F1D8950", +"000000067F000080000008200C000005C000-000000067F000080000008200C0000060000__000000A29F1D8950", +"000000067F000080000008200C000005D8FE-000000067F000080000008200C000006700C__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C0000060000-000000067F000080000008200C0000064000__000000A29F1D8950", +"000000067F000080000008200C0000064000-000000067F000080000008200C0000068000__000000A29F1D8950", +"000000067F000080000008200C000006700C-000000067F000080000008200C000007076D__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C0000068000-000000067F000080000008200C000006C000__000000A29F1D8950", +"000000067F000080000008200C000006C000-000000067F000080000008200C0000070000__000000A29F1D8950", +"000000067F000080000008200C0000070000-000000067F000080000008200C0000074000__000000A29F1D8950", +"000000067F000080000008200C000007076D-000000067F000080000008200C0000079ED3__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C0000074000-000000067F000080000008200C0000078000__000000A29F1D8950", +"000000067F000080000008200C0000078000-000000067F000080000008200C000007C000__000000A29F1D8950", +"000000067F000080000008200C0000079ED3-000000067F000080000008200C000008360A__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C000007C000-000000067F000080000008200C0000080000__000000A29F1D8950", +"000000067F000080000008200C0000080000-000000067F000080000008200C0000084000__000000A29F1D8950", +"000000067F000080000008200C000008360A-000000067F000080000008200C000008CD70__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C0000084000-000000067F000080000008200C0000088000__000000A29F1D8950", +"000000067F000080000008200C0000088000-000000067F000080000008200C000008C000__000000A29F1D8950", +"000000067F000080000008200C000008C000-000000067F000080000008200C0000090000__000000A29F1D8950", +"000000067F000080000008200C000008CD70-000000067F000080000008200C00000964D6__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C0000090000-000000067F000080000008200C0000094000__000000A29F1D8950", +"000000067F000080000008200C0000094000-000000067F000080000008200C0000098000__000000A29F1D8950", +"000000067F000080000008200C00000964D6-000000067F000080000008200C000009FC0B__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C0000098000-000000067F000080000008200C000009C000__000000A29F1D8950", +"000000067F000080000008200C000009C000-000000067F000080000008200C00000A0000__000000A29F1D8950", +"000000067F000080000008200C000009FC0B-000000067F000080000008200C00000A9319__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C00000A0000-000000067F000080000008200C00000A4000__000000A29F1D8950", +"000000067F000080000008200C00000A4000-000000067F000080000008200C00000A8000__000000A29F1D8950", +"000000067F000080000008200C00000A8000-000000067F000080000008200C00000AC000__000000A29F1D8950", +"000000067F000080000008200C00000A9319-000000067F000080000008200C00000B2A7F__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C00000AC000-000000067F000080000008200C00000B0000__000000A29F1D8950", +"000000067F000080000008200C00000B0000-000000067F000080000008200C00000B4000__000000A29F1D8950", +"000000067F000080000008200C00000B2A7F-000000067F000080000008200C00000BC1E5__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C00000B4000-000000067F000080000008200C00000B8000__000000A29F1D8950", +"000000067F000080000008200C00000B8000-000000067F000080000008200C00000BC000__000000A29F1D8950", +"000000067F000080000008200C00000BC000-000000067F000080000008200C00000C0000__000000A29F1D8950", +"000000067F000080000008200C00000BC1E5-000000067F000080000008200C00000C590C__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C00000C0000-010000000000000000000000000000000001__000000A29F1D8950", +"000000067F000080000008200C00000C590C-000000067F000080000008200C00000CF071__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C00000CF071-000000067F000080000008200C00000D8786__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C00000D8786-000000067F000080000008200C00000E1EEC__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C00000E1EEC-000000067F000080000008200C00000EB60C__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C00000EB60C-000000067F000080000008200C00000F4D43__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C00000F4D43-000000067F000080000008200C00000FE4A9__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C00000FE4A9-000000067F000080000008200C0000107BC5__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C0000107BC5-000000067F000080000008200C000011130B__000000A1E407F839-000000A323C9E001", +"000000067F000080000008200C000011130B-01000000000000000100000004000000001C__000000A1E407F839-000000A323C9E001", +"000000067F0000800000082014000000393C-000000067F0000800000082014000000B84D__000000A323C9E001-000000A37A60B1A9", +"000000067F0000800000082014000000B84D-000000067F0000800000082014000001375E__000000A323C9E001-000000A37A60B1A9", +"000000067F0000800000082014000001375E-000000067F0000800000082014000001B66D__000000A323C9E001-000000A37A60B1A9", +"000000067F0000800000082014000001B66D-000000067F0000800000082014000002357E__000000A323C9E001-000000A37A60B1A9", +"000000067F0000800000082014000002357E-000000067F0000800000082014000002B48D__000000A323C9E001-000000A37A60B1A9", +"000000067F0000800000082014000002B48D-030000000000000000000000000000000002__000000A323C9E001-000000A37A60B1A9", +"000000067F000080000008600C0000000000-000000067F000080000008600C0000004000__000000A434813A68", +"000000067F000080000008600C0000004000-000000067F000080000008600C0000008000__000000A434813A68", +"000000067F000080000008600C0000008000-000000067F000080000008600C000000C000__000000A434813A68", +"000000067F000080000008600C0000009747-000000067F000080000008600C0000012EAD__000000A37A60B1A9-000000A3CA47ECA9", +"000000067F000080000008600C000000C000-000000067F000080000008600C0000010000__000000A434813A68", +"000000067F000080000008600C0000010000-000000067F000080000008600C0000014000__000000A434813A68", +"000000067F000080000008600C0000012EAD-000000067F000080000008600C000001C60A__000000A37A60B1A9-000000A3CA47ECA9", +"000000067F000080000008600C0000014000-000000067F000080000008600C0000018000__000000A434813A68", +"000000067F000080000008600C0000018000-000000067F000080000008600C000001C000__000000A434813A68", +"000000067F000080000008600C000001C000-000000067F000080000008600C0000020000__000000A434813A68", +"000000067F000080000008600C000001C60A-000000067F000080000008600C0000025D38__000000A37A60B1A9-000000A3CA47ECA9", +"000000067F000080000008600C0000020000-000000067F000080000008600C0000024000__000000A434813A68", +"000000067F000080000008600C0000024000-000000067F000080000008600C0000028000__000000A434813A68", +"000000067F000080000008600C0000025D38-000000067F000080000008600C000002F49E__000000A37A60B1A9-000000A3CA47ECA9", +"000000067F000080000008600C0000028000-000000067F000080000008600C000002C000__000000A434813A68", +"000000067F000080000008600C000002C000-000000067F000080000008600C0000030000__000000A434813A68", +"000000067F000080000008600C000002F49E-030000000000000000000000000000000002__000000A37A60B1A9-000000A3CA47ECA9", +"000000067F000080000008600C000002F4CA-000000067F000080000008600C0000038BDD__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C0000030000-000000067F000080000008600C0000034000__000000A434813A68", +"000000067F000080000008600C0000034000-000000067F000080000008600C0000038000__000000A434813A68", +"000000067F000080000008600C0000038000-000000067F000080000008600C000003C000__000000A434813A68", +"000000067F000080000008600C0000038BDD-000000067F000080000008600C000004230B__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C000003C000-000000067F000080000008600C0000040000__000000A434813A68", +"000000067F000080000008600C0000040000-000000067F000080000008600C0000044000__000000A434813A68", +"000000067F000080000008600C000004230B-000000067F000080000008600C000004BA71__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C0000044000-000000067F000080000008600C0000048000__000000A434813A68", +"000000067F000080000008600C0000048000-000000067F000080000008600C000004C000__000000A434813A68", +"000000067F000080000008600C000004BA71-000000067F000080000008600C00000551A6__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C000004C000-000000067F000080000008600C0000050000__000000A434813A68", +"000000067F000080000008600C0000050000-000000067F000080000008600C0000054000__000000A434813A68", +"000000067F000080000008600C0000054000-000000067F000080000008600C0000058000__000000A434813A68", +"000000067F000080000008600C00000551A6-000000067F000080000008600C000005E90A__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C0000058000-000000067F000080000008600C000005C000__000000A434813A68", +"000000067F000080000008600C000005C000-000000067F000080000008600C0000060000__000000A434813A68", +"000000067F000080000008600C000005E90A-000000067F000080000008600C000006802C__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C0000060000-000000067F000080000008600C0000064000__000000A434813A68", +"000000067F000080000008600C0000064000-000000067F000080000008600C0000068000__000000A434813A68", +"000000067F000080000008600C0000068000-000000067F000080000008600C000006C000__000000A434813A68", +"000000067F000080000008600C000006802C-000000067F000080000008600C0000071783__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C000006C000-030000000000000000000000000000000002__000000A434813A68", +"000000067F000080000008600C0000071783-000000067F000080000008600C000007AEE9__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C000007AEE9-000000067F000080000008600C000008460B__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C000008460B-000000067F000080000008600C000008DD71__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C000008DD71-000000067F000080000008600C00000974D7__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000974D7-000000067F000080000008600C00000A0C0B__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000A0C0B-000000067F000080000008600C00000AA371__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000AA371-000000067F000080000008600C00000B3AD7__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000B3AD7-000000067F000080000008600C00000BD20B__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000BD20B-000000067F000080000008600C00000C6932__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000C6932-000000067F000080000008600C00000D0098__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000D0098-000000067F000080000008600C00000D97FE__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000D97FE-000000067F000080000008600C00000E2F0B__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000E2F0B-000000067F000080000008600C00000EC671__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000EC671-000000067F000080000008600C00000F5D9F__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000F5D9F-000000067F000080000008600C00000FF505__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C00000FF505-000000067F000080000008600C0000108C10__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C0000108C10-000000067F000080000008600C0100000000__000000A3CA47ECA9-000000A539BDE561", +"000000067F000080000008600C000010ECC4-000000067F00008000000860140000002607__000000A539BDE561-000000A5A081B661", +"000000067F00008000000860140000002607-000000067F0000800000086014000000A518__000000A539BDE561-000000A5A081B661", +"000000067F0000800000086014000000A518-000000067F00008000000860140000012429__000000A539BDE561-000000A5A081B661", +"000000067F00008000000860140000012429-000000067F0000800000086014000001A338__000000A539BDE561-000000A5A081B661", +"000000067F0000800000086014000001A338-000000067F00008000000860140000022249__000000A539BDE561-000000A5A081B661", +"000000067F00008000000860140000022249-000000067F0000800000086014000002A159__000000A539BDE561-000000A5A081B661", +"000000067F0000800000086014000002A159-030000000000000000000000000000000002__000000A539BDE561-000000A5A081B661", +"000000067F000080000008801C0000009703-000000067F000080000008801C0000012E0E__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C0000012E0E-000000067F000080000008801C000001C574__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C000001C574-000000067F000080000008801C0000025CDA__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C0000025CDA-000000067F000080000008801C000002F40A__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C000002F40A-000000067F000080000008801C0000038B1D__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C0000038B1D-000000067F000080000008801C0000042283__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C0000042283-000000067F000080000008801C000004B9E9__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C000004B9E9-000000067F000080000008801C000005510B__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C000005510B-000000067F000080000008801C000005E871__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C000005E871-000000067F000080000008801C0000067F8B__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C0000067F8B-030000000000000000000000000000000002__000000A5A081B661-000000A6503DE919", +"000000067F000080000008801C0000068000-000000067F000080000008801C000006C000__000000A76EC5DFE8", +"000000067F000080000008801C00000680F7-000000067F000080000008801C000007180C__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C000006C000-000000067F000080000008801C0000070000__000000A76EC5DFE8", +"000000067F000080000008801C0000070000-000000067F000080000008801C0000074000__000000A76EC5DFE8", +"000000067F000080000008801C000007180C-000000067F000080000008801C000007AF72__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C0000074000-000000067F000080000008801C0000078000__000000A76EC5DFE8", +"000000067F000080000008801C0000078000-000000067F000080000008801C000007C000__000000A76F097A80", +"000000067F000080000008801C000007AF72-000000067F000080000008801C00000846D8__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C000007C000-000000067F000080000008801C0000080000__000000A76F097A80", +"000000067F000080000008801C0000080000-000000067F000080000008801C0000084000__000000A76F097A80", +"000000067F000080000008801C0000084000-000000067F000080000008801C0000088000__000000A76F097A80", +"000000067F000080000008801C00000846D8-000000067F000080000008801C000008DE0B__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C0000088000-000000067F000080000008801C000008C000__000000A76F097A80", +"000000067F000080000008801C000008C000-000000067F000080000008801C0000090000__000000A76F097A80", +"000000067F000080000008801C000008DE0B-000000067F000080000008801C000009752B__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C0000090000-000000067F000080000008801C0000094000__000000A76F097A80", +"000000067F000080000008801C0000094000-000000067F000080000008801C0000098000__000000A76F097A80", +"000000067F000080000008801C000009752B-000000067F000080000008801C00000A0C91__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C0000098000-000000067F000080000008801C000009C000__000000A76F097A80", +"000000067F000080000008801C000009C000-000000067F000080000008801C00000A0000__000000A76F097A80", +"000000067F000080000008801C00000A0000-000000067F000080000008801C00000A4000__000000A76F097A80", +"000000067F000080000008801C00000A0C91-000000067F000080000008801C00000AA3F7__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C00000A4000-000000067F000080000008801C00000A8000__000000A76F097A80", +"000000067F000080000008801C00000A8000-000000067F000080000008801C00000AC000__000000A76F097A80", +"000000067F000080000008801C00000AA3F7-000000067F000080000008801C00000B3B0C__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C00000AC000-000000067F000080000008801C00000B0000__000000A76F097A80", +"000000067F000080000008801C00000B0000-000000067F000080000008801C00000B4000__000000A76F097A80", +"000000067F000080000008801C00000B3B0C-000000067F000080000008801C00000BD272__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C00000B4000-000000067F000080000008801C00000B8000__000000A76F097A80", +"000000067F000080000008801C00000B8000-000000067F000080000008801C00000BC000__000000A76F097A80", +"000000067F000080000008801C00000BC000-000000067F000080000008801C00000C0000__000000A76F097A80", +"000000067F000080000008801C00000BD272-000000067F000080000008801C00000C6999__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C00000C0000-000000067F000080000008801C00000C4000__000000A76F097A80", +"000000067F000080000008801C00000C4000-000000067F000080000008801C00000C8000__000000A76F097A80", +"000000067F000080000008801C00000C6999-000000067F000080000008801C0100000000__000000A6503DE919-000000A6F001F909", +"000000067F000080000008801C00000C8000-000000067F000080000008801C00000CC000__000000A76F097A80", +"000000067F000080000008801C00000CC000-000000067F000080000008801C00000D0000__000000A76F097A80", +"000000067F000080000008801C00000CF6B0-000000067F000080000008801C00000D8DC1__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008801C00000D0000-000000067F000080000008801C00000D4000__000000A76F097A80", +"000000067F000080000008801C00000D4000-000000067F000080000008801C00000D8000__000000A76F097A80", +"000000067F000080000008801C00000D8000-000000067F000080000008801C00000DC000__000000A76F097A80", +"000000067F000080000008801C00000D8DC1-000000067F000080000008801C00000E250B__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008801C00000DC000-000000067F000080000008801C00000E0000__000000A76F097A80", +"000000067F000080000008801C00000E0000-000000067F000080000008801C00000E4000__000000A76F097A80", +"000000067F000080000008801C00000E250B-000000067F000080000008801C00000EBC71__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008801C00000E4000-000000067F000080000008801C00000E8000__000000A76F097A80", +"000000067F000080000008801C00000E8000-000000067F000080000008801C00000EC000__000000A76F097A80", +"000000067F000080000008801C00000EBC71-000000067F000080000008801C00000F53A5__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008801C00000EC000-000000067F000080000008801C00000F0000__000000A76F097A80", +"000000067F000080000008801C00000F0000-000000067F000080000008801C00000F4000__000000A76F097A80", +"000000067F000080000008801C00000F4000-000000067F000080000008801C00000F8000__000000A76F097A80", +"000000067F000080000008801C00000F53A5-000000067F000080000008801C00000FEB0B__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008801C00000F8000-000000067F000080000008801C00000FC000__000000A76F097A80", +"000000067F000080000008801C00000FC000-000000067F000080000008801C0000100000__000000A76F097A80", +"000000067F000080000008801C00000FEB0B-000000067F000080000008801C000010822C__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008801C0000100000-000000067F000080000008801C0000104000__000000A76F097A80", +"000000067F000080000008801C0000104000-000000067F000080000008801C0000108000__000000A76F097A80", +"000000067F000080000008801C0000108000-000000067F000080000008801C000010C000__000000A76F097A80", +"000000067F000080000008801C000010822C-000000067F000080000008801C0000111982__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008801C000010C000-000000067F000080000008801C0000110000__000000A76F097A80", +"000000067F000080000008801C0000110000-030000000000000000000000000000000002__000000A76F097A80", +"000000067F000080000008801C0000111982-000000067F000080000008A00C00000084EA__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000084EA-000000067F000080000008A00C0000011C0C__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C0000011C0C-000000067F000080000008A00C000001B372__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C000001B372-000000067F000080000008A00C0000024AD8__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C0000024AD8-000000067F000080000008A00C000002E20B__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C000002E20B-000000067F000080000008A00C0000037928__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C0000037928-000000067F000080000008A00C000004108E__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C000004108E-000000067F000080000008A00C000004A7F4__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C000004A7F4-000000067F000080000008A00C0000053F0B__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C0000053F0B-000000067F000080000008A00C000005D671__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C000005D671-000000067F000080000008A00C0000066D95__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C0000066D95-000000067F000080000008A00C00000704FB__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000704FB-000000067F000080000008A00C0000079C0B__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C0000079C0B-000000067F000080000008A00C0000083351__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C0000083351-000000067F000080000008A00C000008CAB7__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C000008CAB7-000000067F000080000008A00C00000961E2__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000961E2-000000067F000080000008A00C000009F90B__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C000009F90B-000000067F000080000008A00C00000A902B__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000A902B-000000067F000080000008A00C00000B2779__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000B2779-000000067F000080000008A00C00000BBEDF__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000BBEDF-000000067F000080000008A00C00000C560A__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000C560A-000000067F000080000008A00C00000CED70__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000CED70-000000067F000080000008A00C00000D84D6__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000D84D6-000000067F000080000008A00C00000E1C0A__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000E1C0A-000000067F000080000008A00C00000EB370__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000EB370-000000067F000080000008A00C00000F4AD6__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000F4AD6-000000067F000080000008A00C00000FE20B__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C00000FE20B-030000000000000000000000000000000002__000000A6F001F909-000000A91D97FD49", +"000000067F000080000008A00C0000104A0C-000000067F000080000008A00C000010DF6E__000000A91D97FD49-000000A98AB7EE49", +"000000067F000080000008A00C000010DF6E-000000067F000080000008A0140000001A21__000000A91D97FD49-000000A98AB7EE49", +"000000067F000080000008A0140000001A21-000000067F000080000008A0140000009932__000000A91D97FD49-000000A98AB7EE49", +"000000067F000080000008A0140000009932-000000067F000080000008A0140000011843__000000A91D97FD49-000000A98AB7EE49", +"000000067F000080000008A0140000011843-000000067F000080000008A0140000019753__000000A91D97FD49-000000A98AB7EE49", +"000000067F000080000008A0140000019753-000000067F000080000008A0140000021664__000000A91D97FD49-000000A98AB7EE49", +"000000067F000080000008A0140000021664-01000000000000000100000004000000001C__000000A91D97FD49-000000A98AB7EE49", +"000000067F000080000008C00C0000000000-000000067F000080000008C00C0000004000__000000AAEBE534F8", +"000000067F000080000008C00C0000002330-000000067F000080000008C00C000000BA96__000000A98AB7EE49-000000AA2597E9A1", +"000000067F000080000008C00C0000004000-000000067F000080000008C00C0000008000__000000AAEBE534F8", +"000000067F000080000008C00C0000008000-000000067F000080000008C00C000000C000__000000AAEBE534F8", +"000000067F000080000008C00C000000BA96-000000067F000080000008C00C00000151CB__000000A98AB7EE49-000000AA2597E9A1", +"000000067F000080000008C00C000000C000-000000067F000080000008C00C0000010000__000000AAEBE534F8", +"000000067F000080000008C00C0000010000-000000067F000080000008C00C0000014000__000000AAEBE534F8", +"000000067F000080000008C00C0000014000-000000067F000080000008C00C0000018000__000000AAEBE534F8", +"000000067F000080000008C00C00000151CB-000000067F000080000008C00C000001E90B__000000A98AB7EE49-000000AA2597E9A1", +"000000067F000080000008C00C0000018000-000000067F000080000008C00C000001C000__000000AAEBE534F8", +"000000067F000080000008C00C000001C000-000000067F000080000008C00C0000020000__000000AAEBE534F8", +"000000067F000080000008C00C000001E90B-000000067F000080000008C00C000002802C__000000A98AB7EE49-000000AA2597E9A1", +"000000067F000080000008C00C0000020000-000000067F000080000008C00C0000024000__000000AAEBE534F8", +"000000067F000080000008C00C0000024000-000000067F000080000008C00C0000028000__000000AAEBE534F8", +"000000067F000080000008C00C0000028000-000000067F000080000008C00C000002C000__000000AAEBE534F8", +"000000067F000080000008C00C000002802C-000000067F000080000008C00C0000031783__000000A98AB7EE49-000000AA2597E9A1", +"000000067F000080000008C00C000002C000-000000067F000080000008C00C0000030000__000000AAEBE534F8", +"000000067F000080000008C00C0000030000-000000067F000080000008C00C0000034000__000000AAEBE534F8", +"000000067F000080000008C00C0000031783-000000067F000080000008C00C000003AEE9__000000A98AB7EE49-000000AA2597E9A1", +"000000067F000080000008C00C0000034000-000000067F000080000008C00C0000038000__000000AAEBE534F8", +"000000067F000080000008C00C0000038000-000000067F000080000008C00C000003C000__000000AAEBE534F8", +"000000067F000080000008C00C000003AEE9-000000067F000080000008C00C000004460B__000000A98AB7EE49-000000AA2597E9A1", +"000000067F000080000008C00C000003C000-000000067F000080000008C00C0000040000__000000AAEBE534F8", +"000000067F000080000008C00C0000040000-000000067F000080000008C00C0000044000__000000AAEBE534F8", +"000000067F000080000008C00C0000044000-000000067F000080000008C00C0000048000__000000AAEBE534F8", +"000000067F000080000008C00C000004460B-000000067F000080000008C00C000004DD71__000000A98AB7EE49-000000AA2597E9A1", +"000000067F000080000008C00C0000048000-000000067F000080000008C00C000004C000__000000AAEBE534F8", +"000000067F000080000008C00C000004C000-000000067F000080000008C00C0000050000__000000AAEBE534F8", +"000000067F000080000008C00C000004DD71-030000000000000000000000000000000002__000000A98AB7EE49-000000AA2597E9A1", +"000000067F000080000008C00C0000050000-000000067F000080000008C00C0000054000__000000AAEBE534F8", +"000000067F000080000008C00C0000054000-000000067F000080000008C00C0000058000__000000AAEBE534F8", +"000000067F000080000008C00C0000058000-000000067F000080000008C00C000005C000__000000AAEBE534F8", +"000000067F000080000008C00C000005C000-000000067F000080000008C00C0000060000__000000AAEBE534F8", +"000000067F000080000008C00C000005DA8C-000000067F000080000008C00C00000671AE__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C0000060000-000000067F000080000008C00C0000064000__000000AAEBE534F8", +"000000067F000080000008C00C0000064000-000000067F000080000008C00C0000068000__000000AAEBE534F8", +"000000067F000080000008C00C00000671AE-000000067F000080000008C00C000007090A__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C0000068000-000000067F000080000008C00C000006C000__000000AAEBE534F8", +"000000067F000080000008C00C000006C000-000000067F000080000008C00C0000070000__000000AAEBE534F8", +"000000067F000080000008C00C0000070000-000000067F000080000008C00C0000074000__000000AAEBE534F8", +"000000067F000080000008C00C000007090A-000000067F000080000008C00C000007A070__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C0000074000-000000067F000080000008C00C0000078000__000000AAEBE534F8", +"000000067F000080000008C00C0000078000-000000067F000080000008C00C000007C000__000000AAEBE534F8", +"000000067F000080000008C00C000007A070-000000067F000080000008C00C00000837B4__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C000007C000-000000067F000080000008C00C0000080000__000000AAEBE534F8", +"000000067F000080000008C00C0000080000-000000067F000080000008C00C0000084000__000000AAEBE534F8", +"000000067F000080000008C00C00000837B4-000000067F000080000008C00C000008CF0A__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C0000084000-000000067F000080000008C00C0000088000__000000AAEBE534F8", +"000000067F000080000008C00C0000088000-000000067F000080000008C00C000008C000__000000AAEBE534F8", +"000000067F000080000008C00C000008C000-000000067F000080000008C00C0000090000__000000AAEBE534F8", +"000000067F000080000008C00C000008CF0A-000000067F000080000008C00C0000096670__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C0000090000-000000067F000080000008C00C0000094000__000000AAEBE534F8", +"000000067F000080000008C00C0000094000-000000067F000080000008C00C0000098000__000000AAEBE534F8", +"000000067F000080000008C00C0000096670-000000067F000080000008C00C000009FDD6__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C0000098000-000000067F000080000008C00C000009C000__000000AAEBE534F8", +"000000067F000080000008C00C000009C000-000000067F000080000008C00C00000A0000__000000AAEBE534F8", +"000000067F000080000008C00C000009FDD6-000000067F000080000008C00C00000A952A__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C00000A0000-000000067F000080000008C00C00000A4000__000000AAEBE534F8", +"000000067F000080000008C00C00000A4000-000000067F000080000008C00C00000A8000__000000AAEBE534F8", +"000000067F000080000008C00C00000A8000-000000067F000080000008C00C00000AC000__000000AAEBE534F8", +"000000067F000080000008C00C00000A952A-000000067F000080000008C00C00000B2C90__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C00000AC000-000000067F000080000008C00C00000B0000__000000AAEBE534F8", +"000000067F000080000008C00C00000B0000-000000067F000080000008C00C00000B4000__000000AAEBE534F8", +"000000067F000080000008C00C00000B2C90-000000067F000080000008C00C00000BC3F6__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C00000B4000-000000067F000080000008C00C00000B8000__000000AAEBE534F8", +"000000067F000080000008C00C00000B8000-000000067F000080000008C00C00000BC000__000000AAEBE534F8", +"000000067F000080000008C00C00000BC000-000000067F000080000008C00C00000C0000__000000AAEBE534F8", +"000000067F000080000008C00C00000BC3F6-000000067F000080000008C00C00000C5B0C__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C00000C0000-000000067F000080000008C00C00000C4000__000000AAEBE534F8", +"000000067F000080000008C00C00000C4000-000000067F000080000008C00C00000C8000__000000AAEBE534F8", +"000000067F000080000008C00C00000C5B0C-000000067F000080000008C00C00000CF272__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C00000C8000-030000000000000000000000000000000002__000000AAEBE534F8", +"000000067F000080000008C00C00000CF272-000000067F000080000008C00C00000D8986__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C00000D8986-000000067F000080000008C00C00000E20EC__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C00000E20EC-000000067F000080000008C00C00000EB80A__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C00000EB80A-000000067F000080000008C00C00000F4F40__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C00000F4F40-000000067F000080000008C00C00000FE6A6__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C00000FE6A6-000000067F000080000008C00C0000107DC1__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C0000107DC1-000000067F000080000008C00C000011150A__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008C00C000011150A-01000000000000000100000004000000001C__000000AA2597E9A1-000000AB6533BFD9", +"000000067F000080000008E00C0000000000-000000067F000080000008E00C0000004000__000000AD3698E000", +"000000067F000080000008E00C0000004000-000000067F000080000008E00C0000008000__000000AD3698E000", +"000000067F000080000008E00C00000077B3-000000067F000080000008E00C0000010F0A__000000AB6533BFD9-000000ABF63DF511", +"000000067F000080000008E00C0000008000-000000067F000080000008E00C000000C000__000000AD3698E000", +"000000067F000080000008E00C000000C000-000000067F000080000008E00C0000010000__000000AD3698E000", +"000000067F000080000008E00C0000010000-000000067F000080000008E00C0000014000__000000AD3698E000", +"000000067F000080000008E00C0000010F0A-000000067F000080000008E00C000001A670__000000AB6533BFD9-000000ABF63DF511", +"000000067F000080000008E00C0000014000-000000067F000080000008E00C0000018000__000000AD3698E000", +"000000067F000080000008E00C0000018000-000000067F000080000008E00C000001C000__000000AD3698E000", +"000000067F000080000008E00C000001A670-000000067F000080000008E00C0000023DB1__000000AB6533BFD9-000000ABF63DF511", +"000000067F000080000008E00C000001C000-000000067F000080000008E00C0000020000__000000AD3698E000", +"000000067F000080000008E00C0000020000-000000067F000080000008E00C0000024000__000000AD3698E000", +"000000067F000080000008E00C0000023DB1-000000067F000080000008E00C000002D50A__000000AB6533BFD9-000000ABF63DF511", +"000000067F000080000008E00C0000024000-000000067F000080000008E00C0000028000__000000AD3698E000", +"000000067F000080000008E00C0000028000-000000067F000080000008E00C000002C000__000000AD3698E000", +"000000067F000080000008E00C000002C000-000000067F000080000008E00C0000030000__000000AD3698E000", +"000000067F000080000008E00C000002D50A-000000067F000080000008E00C0000036C30__000000AB6533BFD9-000000ABF63DF511", +"000000067F000080000008E00C0000030000-000000067F000080000008E00C0000034000__000000AD3698E000", +"000000067F000080000008E00C0000034000-000000067F000080000008E00C0000038000__000000AD3698E000", +"000000067F000080000008E00C0000036C30-000000067F000080000008E00C0000040393__000000AB6533BFD9-000000ABF63DF511", +"000000067F000080000008E00C0000038000-000000067F000080000008E00C000003C000__000000AD3698E000", +"000000067F000080000008E00C000003C000-000000067F000080000008E00C0000040000__000000AD3698E000", +"000000067F000080000008E00C0000040000-000000067F000080000008E00C0000044000__000000AD3698E000", +"000000067F000080000008E00C0000040393-000000067F000080000008E00C0000049AF9__000000AB6533BFD9-000000ABF63DF511", +"000000067F000080000008E00C0000044000-000000067F000080000008E00C0000048000__000000AD3698E000", +"000000067F000080000008E00C0000048000-000000067F000080000008E00C000004C000__000000AD3698E000", +"000000067F000080000008E00C0000049AF9-000000067F000080000008E00C000005320C__000000AB6533BFD9-000000ABF63DF511", +"000000067F000080000008E00C000004C000-000000067F000080000008E00C0000050000__000000AD3698E000", +"000000067F000080000008E00C0000050000-000000067F000080000008E00C0000054000__000000AD3698E000", +"000000067F000080000008E00C000005320C-030000000000000000000000000000000002__000000AB6533BFD9-000000ABF63DF511", +"000000067F000080000008E00C0000054000-000000067F000080000008E00C0000058000__000000AD34AF7FD8", +"000000067F000080000008E00C000005523E-000000067F000080000008E00C000005E9A4__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C0000058000-000000067F000080000008E00C000005C000__000000AD34AF7FD8", +"000000067F000080000008E00C000005C000-000000067F000080000008E00C0000060000__000000AD34AF7FD8", +"000000067F000080000008E00C000005E9A4-000000067F000080000008E00C000006810A__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C0000060000-000000067F000080000008E00C0000064000__000000AD34AF7FD8", +"000000067F000080000008E00C0000064000-000000067F000080000008E00C0000068000__000000AD34AF7FD8", +"000000067F000080000008E00C0000068000-000000067F000080000008E00C000006C000__000000AD34AF7FD8", +"000000067F000080000008E00C000006810A-000000067F000080000008E00C0000071870__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C000006C000-000000067F000080000008E00C0000070000__000000AD34AF7FD8", +"000000067F000080000008E00C0000070000-000000067F000080000008E00C0000074000__000000AD34AF7FD8", +"000000067F000080000008E00C0000071870-000000067F000080000008E00C000007AFD6__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C0000074000-000000067F000080000008E00C0000078000__000000AD34AF7FD8", +"000000067F000080000008E00C0000078000-000000067F000080000008E00C000007C000__000000AD34AF7FD8", +"000000067F000080000008E00C000007AFD6-000000067F000080000008E00C000008470B__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C000007C000-000000067F000080000008E00C0000080000__000000AD34AF7FD8", +"000000067F000080000008E00C0000080000-000000067F000080000008E00C0000084000__000000AD34AF7FD8", +"000000067F000080000008E00C0000084000-000000067F000080000008E00C0000088000__000000AD34AF7FD8", +"000000067F000080000008E00C000008470B-000000067F000080000008E00C000008DE71__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C0000088000-000000067F000080000008E00C000008C000__000000AD34AF7FD8", +"000000067F000080000008E00C000008C000-000000067F000080000008E00C0000090000__000000AD34AF7FD8", +"000000067F000080000008E00C000008DE71-000000067F000080000008E00C0000097591__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C0000090000-000000067F000080000008E00C0000094000__000000AD34AF7FD8", +"000000067F000080000008E00C0000094000-000000067F000080000008E00C0000098000__000000AD34AF7FD8", +"000000067F000080000008E00C0000097591-000000067F000080000008E00C00000A0CF7__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C0000098000-000000067F000080000008E00C000009C000__000000AD34AF7FD8", +"000000067F000080000008E00C000009C000-000000067F000080000008E00C00000A0000__000000AD34AF7FD8", +"000000067F000080000008E00C00000A0000-000000067F000080000008E00C00000A4000__000000AD34AF7FD8", +"000000067F000080000008E00C00000A0CF7-000000067F000080000008E00C00000AA40B__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C00000A4000-000000067F000080000008E00C00000A8000__000000AD34AF7FD8", +"000000067F000080000008E00C00000A8000-000000067F000080000008E00C00000AC000__000000AD34AF7FD8", +"000000067F000080000008E00C00000AA40B-000000067F000080000008E00C00000B3B4D__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C00000AC000-000000067F000080000008E00C00000B0000__000000AD34AF7FD8", +"000000067F000080000008E00C00000B0000-000000067F000080000008E00C00000B4000__000000AD34AF7FD8", +"000000067F000080000008E00C00000B3B4D-000000067F000080000008E00C0100000000__000000ABF63DF511-000000AC9601EA19", +"000000067F000080000008E00C00000B4000-000000067F000080000008E00C00000B8000__000000AD34AF7FD8", +"000000067F000080000008E00C00000B8000-000000067F000080000008E00C00000BC000__000000AD34AF7FD8", +"000000067F000080000008E00C00000BC000-000000067F000080000008E00C00000C0000__000000AD34AF7FD8", +"000000067F000080000008E00C00000BC018-000000067F000080000008E00C00000C5749__000000AC9601EA19-000000AD36393FE9", +"000000067F000080000008E00C00000C0000-000000067F000080000008E00C00000C4000__000000AD34AF7FD8", +"000000067F000080000008E00C00000C4000-000000067F000080000008E00C00000C8000__000000AD34AF7FD8", +"000000067F000080000008E00C00000C5749-000000067F000080000008E00C00000CEEAF__000000AC9601EA19-000000AD36393FE9", +"000000067F000080000008E00C00000C8000-000000067F000080000008E00C00000CC000__000000AD34AF7FD8", +"000000067F000080000008E00C00000CC000-000000067F000080000008E00C00000D0000__000000AD34AF7FD8", +"000000067F000080000008E00C00000CEEAF-000000067F000080000008E00C00000D85C5__000000AC9601EA19-000000AD36393FE9", +"000000067F000080000008E00C00000D0000-000000067F000080000008E00C00000D4000__000000AD34AF7FD8", +"000000067F000080000008E00C00000D4000-000000067F000080000008E00C00000D8000__000000AD34AF7FD8", +"000000067F000080000008E00C00000D8000-000000067F000080000008E00C00000DC000__000000AD34AF7FD8", +"000000067F000080000008E00C00000D85C5-000000067F000080000008E00C00000E1D0B__000000AC9601EA19-000000AD36393FE9", +"000000067F000080000008E00C00000DC000-000000067F000080000008E00C00000E0000__000000AD34AF7FD8", +"000000067F000080000008E00C00000E0000-000000067F000080000008E00C00000E4000__000000AD34AF7FD8", +"000000067F000080000008E00C00000E1D0B-000000067F000080000008E00C00000EB471__000000AC9601EA19-000000AD36393FE9", +"000000067F000080000008E00C00000E4000-000000067F000080000008E00C00000E8000__000000AD34AF7FD8", +"000000067F000080000008E00C00000E8000-000000067F000080000008E00C00000EC000__000000AD34AF7FD8", +"000000067F000080000008E00C00000EB471-000000067F000080000008E00C00000F4BAA__000000AC9601EA19-000000AD36393FE9", +"000000067F000080000008E00C00000EC000-000000067F000080000008E00C00000F0000__000000AD34AF7FD8", +"000000067F000080000008E00C00000F0000-000000067F000080000008E00C00000F4000__000000AD34AF7FD8", +"000000067F000080000008E00C00000F4000-000000067F000080000008E00C00000F8000__000000AD34AF7FD8", +"000000067F000080000008E00C00000F4BAA-000000067F000080000008E00C00000FE30A__000000AC9601EA19-000000AD36393FE9", +"000000067F000080000008E00C00000F8000-000000067F000080000008E00C00000FC000__000000AD34AF7FD8", +"000000067F000080000008E00C00000FC000-000000067F000080000008E00C0000100000__000000AD34AF7FD8", +"000000067F000080000008E00C00000FE30A-000000067F000080000008E00C0000107A2C__000000AC9601EA19-000000AD36393FE9", +"000000067F000080000008E00C0000100000-000000067F000080000008E00C0000104000__000000AD34AF7FD8", +"000000067F000080000008E00C0000104000-000000067F000080000008E00C0000108000__000000AD34AF7FD8", +"000000067F000080000008E00C0000107A2C-000000067F000080000008E00C0000111187__000000AC9601EA19-000000AD36393FE9", +"000000067F000080000008E00C0000108000-000000067F000080000008E00C000010C000__000000AD34AF7FD8", +"000000067F000080000008E00C000010C000-000000067F000080000008E00C0000110000__000000AD34AF7FD8", +"000000067F000080000008E00C0000110000-030000000000000000000000000000000002__000000AD34AF7FD8", +"000000067F000080000008E00C0000111187-01000000000000000100000004000000001C__000000AC9601EA19-000000AD36393FE9", +"000000067F000080000008E0140000003E33-000000067F000080000008E014000000BD44__000000AD36393FE9-000000ADB047EAB9", +"000000067F000080000008E014000000BD44-000000067F000080000008E0140000013C54__000000AD36393FE9-000000ADB047EAB9", +"000000067F000080000008E0140000013C54-000000067F000080000008E014000001BB63__000000AD36393FE9-000000ADB047EAB9", +"000000067F000080000008E014000001BB63-000000067F000080000008E0140000023A74__000000AD36393FE9-000000ADB047EAB9", +"000000067F000080000008E0140000023A74-000000067F000080000008E014000002B984__000000AD36393FE9-000000ADB047EAB9", +"000000067F000080000008E014000002B984-000000067F000080000008E0220000006AD0__000000AD36393FE9-000000ADB047EAB9", +"000000067F000080000008E0220000000000-000000067F000080000008E0220000004000__000000AF5D7D4000", +"000000067F000080000008E0220000004000-000000067F000080000008E0220000008000__000000AF5D7D4000", +"000000067F000080000008E0220000006AD0-000000067F000080000008E022000001020C__000000AD36393FE9-000000ADB047EAB9", +"000000067F000080000008E0220000008000-000000067F000080000008E022000000C000__000000AF5D7D4000", +"000000067F000080000008E022000000C000-000000067F000080000008E0220000010000__000000AF5D7D4000", +"000000067F000080000008E0220000010000-000000067F000080000008E0220000014000__000000AF5D7D4000", +"000000067F000080000008E022000001020C-01000000000000000100000004000000001C__000000AD36393FE9-000000ADB047EAB9", +"000000067F000080000008E0220000014000-000000067F000080000008E0220000018000__000000AF56604248", +"000000067F000080000008E02200000151DD-000000067F000080000008E022000001E90B__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E0220000018000-000000067F000080000008E022000001C000__000000AF56604248", +"000000067F000080000008E022000001C000-000000067F000080000008E0220000020000__000000AF56604248", +"000000067F000080000008E022000001E90B-000000067F000080000008E022000002802C__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E0220000020000-000000067F000080000008E0220000024000__000000AF56604248", +"000000067F000080000008E0220000024000-000000067F000080000008E0220000028000__000000AF56604248", +"000000067F000080000008E0220000028000-000000067F000080000008E022000002C000__000000AF56604248", +"000000067F000080000008E022000002802C-000000067F000080000008E0220000031783__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E022000002C000-000000067F000080000008E0220000030000__000000AF56604248", +"000000067F000080000008E0220000030000-000000067F000080000008E0220000034000__000000AF56604248", +"000000067F000080000008E0220000031783-000000067F000080000008E022000003AEE9__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E0220000034000-000000067F000080000008E0220000038000__000000AF56604248", +"000000067F000080000008E0220000038000-000000067F000080000008E022000003C000__000000AF56604248", +"000000067F000080000008E022000003AEE9-000000067F000080000008E022000004460B__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E022000003C000-000000067F000080000008E0220000040000__000000AF56604248", +"000000067F000080000008E0220000040000-000000067F000080000008E0220000044000__000000AF56604248", +"000000067F000080000008E0220000044000-000000067F000080000008E0220000048000__000000AF56604248", +"000000067F000080000008E022000004460B-000000067F000080000008E022000004DD71__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E0220000048000-000000067F000080000008E022000004C000__000000AF56604248", +"000000067F000080000008E022000004C000-000000067F000080000008E0220000050000__000000AF56604248", +"000000067F000080000008E022000004DD71-000000067F000080000008E02200000574D7__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E0220000050000-000000067F000080000008E0220000054000__000000AF56604248", +"000000067F000080000008E0220000054000-000000067F000080000008E0220000058000__000000AF56604248", +"000000067F000080000008E02200000574D7-000000067F000080000008E0220000060C0B__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E0220000058000-000000067F000080000008E022000005C000__000000AF56604248", +"000000067F000080000008E022000005C000-000000067F000080000008E0220000060000__000000AF56604248", +"000000067F000080000008E0220000060000-000000067F000080000008E0220000064000__000000AF56604248", +"000000067F000080000008E0220000060C0B-000000067F000080000008E022000006A371__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E0220000064000-000000067F000080000008E0220000068000__000000AF56604248", +"000000067F000080000008E0220000068000-000000067F000080000008E022000006C000__000000AF56604248", +"000000067F000080000008E022000006A371-000000067F000080000008E0220000073AD7__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E022000006C000-000000067F000080000008E0220000070000__000000AF56604248", +"000000067F000080000008E0220000070000-000000067F000080000008E0220000074000__000000AF56604248", +"000000067F000080000008E0220000073AD7-000000067F000080000008E022000007D20B__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E0220000074000-000000067F000080000008E0220000078000__000000AF56604248", +"000000067F000080000008E0220000078000-000000067F000080000008E022000007C000__000000AF56604248", +"000000067F000080000008E022000007C000-000000067F000080000008E0220000080000__000000AF56604248", +"000000067F000080000008E022000007D20B-000000067F000080000008E0220000086932__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E0220000080000-000000067F000080000008E0220000084000__000000AF56604248", +"000000067F000080000008E0220000084000-000000067F000080000008E0220000088000__000000AF56604248", +"000000067F000080000008E0220000086932-000000067F000080000008E0220100000000__000000ADB047EAB9-000000AE6FFFE799", +"000000067F000080000008E0220000088000-000000067F000080000008E022000008C000__000000AF56604248", +"000000067F000080000008E022000008C000-000000067F000080000008E0220000090000__000000AF56604248", +"000000067F000080000008E022000008E3D1-000000067F000080000008E022000009797E__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E0220000090000-000000067F000080000008E0220000094000__000000AF56604248", +"000000067F000080000008E0220000094000-000000067F000080000008E0220000098000__000000AF56604248", +"000000067F000080000008E022000009797E-000000067F000080000008E02200000A10E4__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E0220000098000-000000067F000080000008E022000009C000__000000AF56604248", +"000000067F000080000008E022000009C000-000000067F000080000008E02200000A0000__000000AF56604248", +"000000067F000080000008E02200000A0000-000000067F000080000008E02200000A4000__000000AF56604248", +"000000067F000080000008E02200000A10E4-000000067F000080000008E02200000AA80B__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02200000A4000-000000067F000080000008E02200000A8000__000000AF56604248", +"000000067F000080000008E02200000A8000-000000067F000080000008E02200000AC000__000000AF56604248", +"000000067F000080000008E02200000AA80B-000000067F000080000008E02200000B3F4B__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02200000AC000-000000067F000080000008E02200000B0000__000000AF56604248", +"000000067F000080000008E02200000B0000-000000067F000080000008E02200000B4000__000000AF56604248", +"000000067F000080000008E02200000B3F4B-000000067F000080000008E02200000BD6B1__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02200000B4000-000000067F000080000008E02200000B8000__000000AF56604248", +"000000067F000080000008E02200000B8000-000000067F000080000008E02200000BC000__000000AF56604248", +"000000067F000080000008E02200000BC000-000000067F000080000008E02200000C0000__000000AF56604248", +"000000067F000080000008E02200000BD6B1-000000067F000080000008E02200000C6DD5__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02200000C0000-000000067F000080000008E02200000C4000__000000AF56604248", +"000000067F000080000008E02200000C4000-000000067F000080000008E02200000C8000__000000AF56604248", +"000000067F000080000008E02200000C6DD5-000000067F000080000008E02200000D050B__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02200000C8000-000000067F000080000008E02200000CC000__000000AF56604248", +"000000067F000080000008E02200000CC000-000000067F000080000008E02200000D0000__000000AF56604248", +"000000067F000080000008E02200000D0000-000000067F000080000008E02200000D4000__000000AF56604248", +"000000067F000080000008E02200000D050B-000000067F000080000008E02200000D9C71__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02200000D4000-000000067F000080000008E02200000D8000__000000AF56604248", +"000000067F000080000008E02200000D8000-000000067F000080000008E02200000DC000__000000AF56604248", +"000000067F000080000008E02200000D9C71-000000067F000080000008E02200000E33B8__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02200000DC000-000000067F000080000008E02200000E0000__000000AF56604248", +"000000067F000080000008E02200000E0000-000000067F000080000008E02200000E4000__000000AF56604248", +"000000067F000080000008E02200000E33B8-000000067F000080000008E02200000ECB09__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02200000E4000-000000067F000080000008E02200000E8000__000000AF56604248", +"000000067F000080000008E02200000E8000-000000067F000080000008E02200000EC000__000000AF56604248", +"000000067F000080000008E02200000EC000-000000067F000080000008E02200000F0000__000000AF56604248", +"000000067F000080000008E02200000ECB09-000000067F000080000008E02200000F626F__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02200000F0000-000000067F000080000008E02200000F4000__000000AF56604248", +"000000067F000080000008E02200000F4000-000000067F000080000008E02200000F8000__000000AF56604248", +"000000067F000080000008E02200000F626F-000000067F000080000008E02200000FF9D5__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02200000F8000-000000067F000080000008E02200000FC000__000000AF56604248", +"000000067F000080000008E02200000FC000-000000067F000080000008E0220000100000__000000AF56604248", +"000000067F000080000008E02200000FF9D5-000000067F000080000008E022000010912A__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E0220000100000-000000067F000080000008E0220000104000__000000AF56604248", +"000000067F000080000008E0220000104000-000000067F000080000008E0220000108000__000000AF56604248", +"000000067F000080000008E0220000108000-000000067F000080000008E022000010C000__000000AF56604248", +"000000067F000080000008E022000010912A-000000067F000080000008E0220000111C20__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E022000010C000-030000000000000000000000000000000002__000000AF56604248", +"000000067F000080000008E02200FFFFFFFF-01000000000000000100000004000000001C__000000AE6FFFE799-000000AF5D587FE1", +"000000067F000080000008E02A000000529F-000000067F000080000008E02A000000D1B0__000000AF5D587FE1-000000AFB4666001", +"000000067F000080000008E02A000000D1B0-000000067F000080000008E02A00000150BF__000000AF5D587FE1-000000AFB4666001", +"000000067F000080000008E02A00000150BF-000000067F000080000008E02A000001CFD0__000000AF5D587FE1-000000AFB4666001", +"000000067F000080000008E02A000001CFD0-000000067F000080000008E02A0000024EE1__000000AF5D587FE1-000000AFB4666001", +"000000067F000080000008E02A0000024EE1-000000067F000080000008E02A000002CDF1__000000AF5D587FE1-000000AFB4666001", +"000000067F000080000008E02A000002CDF1-030000000000000000000000000000000002__000000AF5D587FE1-000000AFB4666001", +"000000067F00008000000900380000000000-000000067F0000800000090038000000970B__000000AFB4666001-000000B05429F579", +"000000067F0000800000090038000000970B-000000067F00008000000900380000012E71__000000AFB4666001-000000B05429F579", +"000000067F00008000000900380000012E71-000000067F0000800000090038000001C5D7__000000AFB4666001-000000B05429F579", +"000000067F0000800000090038000001C5D7-000000067F00008000000900380000025D2B__000000AFB4666001-000000B05429F579", +"000000067F00008000000900380000025D2B-000000067F0000800000090038000002F491__000000AFB4666001-000000B05429F579", +"000000067F0000800000090038000002F491-000000067F00008000000900380000038BA4__000000AFB4666001-000000B05429F579", +"000000067F00008000000900380000038BA4-000000067F0000800000090038000004230A__000000AFB4666001-000000B05429F579", +"000000067F0000800000090038000004230A-000000067F0000800000090038000004BA70__000000AFB4666001-000000B05429F579", +"000000067F0000800000090038000004BA70-000000067F000080000009003800000551A5__000000AFB4666001-000000B05429F579", +"000000067F000080000009003800000551A5-000000067F0000800000090038000005E909__000000AFB4666001-000000B05429F579", +"000000067F0000800000090038000005C000-000000067F00008000000900380000060000__000000B18434BFD0", +"000000067F0000800000090038000005E909-000000067F000080000009003B0100000000__000000AFB4666001-000000B05429F579", +"000000067F0000800000090038000005EA0C-000000067F00008000000900380000068125__000000B05429F579-000000B0F3EDEAC9", +"000000067F00008000000900380000060000-000000067F00008000000900380000064000__000000B18434BFD0", +"000000067F00008000000900380000064000-000000067F00008000000900380000068000__000000B18434BFD0", +"000000067F00008000000900380000068000-000000067F0000800000090038000006C000__000000B18434BFD0", +"000000067F00008000000900380000068125-000000067F0000800000090038000007188B__000000B05429F579-000000B0F3EDEAC9", +"000000067F0000800000090038000006C000-000000067F00008000000900380000070000__000000B18434BFD0", +"000000067F00008000000900380000070000-000000067F00008000000900380000074000__000000B18434BFD0", +"000000067F0000800000090038000007188B-000000067F0000800000090038000007AFF1__000000B05429F579-000000B0F3EDEAC9", +"000000067F00008000000900380000074000-000000067F00008000000900380000078000__000000B18434BFD0", +"000000067F00008000000900380000078000-000000067F0000800000090038000007C000__000000B18434BFD0", +"000000067F0000800000090038000007AFF1-000000067F0000800000090038000008470C__000000B05429F579-000000B0F3EDEAC9", +"000000067F0000800000090038000007C000-000000067F00008000000900380000080000__000000B18434BFD0", +"000000067F00008000000900380000080000-000000067F00008000000900380000084000__000000B18434BFD0", +"000000067F00008000000900380000084000-000000067F00008000000900380000088000__000000B18434BFD0", +"000000067F0000800000090038000008470C-000000067F0000800000090038000008DE72__000000B05429F579-000000B0F3EDEAC9", +"000000067F00008000000900380000088000-000000067F0000800000090038000008C000__000000B18434BFD0", +"000000067F0000800000090038000008C000-000000067F00008000000900380000090000__000000B18434BFD0", +"000000067F0000800000090038000008DE72-000000067F00008000000900380000097592__000000B05429F579-000000B0F3EDEAC9", +"000000067F00008000000900380000090000-000000067F00008000000900380000094000__000000B18434BFD0", +"000000067F00008000000900380000094000-000000067F00008000000900380000098000__000000B18434BFD0", +"000000067F00008000000900380000097592-000000067F000080000009003800000A0CF8__000000B05429F579-000000B0F3EDEAC9", +"000000067F00008000000900380000098000-000000067F0000800000090038000009C000__000000B18434BFD0", +"000000067F0000800000090038000009C000-000000067F000080000009003800000A0000__000000B18434BFD0", +"000000067F000080000009003800000A0000-000000067F000080000009003800000A4000__000000B18434BFD0", +"000000067F000080000009003800000A0CF8-000000067F000080000009003800000AA40C__000000B05429F579-000000B0F3EDEAC9", +"000000067F000080000009003800000A4000-000000067F000080000009003800000A8000__000000B18434BFD0", +"000000067F000080000009003800000A8000-000000067F000080000009003800000AC000__000000B18434BFD0", +"000000067F000080000009003800000AA40C-000000067F000080000009003800000B3B4E__000000B05429F579-000000B0F3EDEAC9", +"000000067F000080000009003800000AC000-000000067F000080000009003800000B0000__000000B18434BFD0", +"000000067F000080000009003800000B0000-000000067F000080000009003800000B4000__000000B18434BFD0", +"000000067F000080000009003800000B3B4E-000000067F000080000009003800000BD2B4__000000B05429F579-000000B0F3EDEAC9", +"000000067F000080000009003800000B4000-000000067F000080000009003800000B8000__000000B18434BFD0", +"000000067F000080000009003800000B8000-000000067F000080000009003800000BC000__000000B18434BFD0", +"000000067F000080000009003800000BC000-000000067F000080000009003800000C0000__000000B18434BFD0", +"000000067F000080000009003800000BD2B4-000000067F00008000000900380100000000__000000B05429F579-000000B0F3EDEAC9", +"000000067F000080000009003800000C0000-000000067F000080000009003800000C4000__000000B18434BFD0", +"000000067F000080000009003800000C4000-000000067F000080000009003800000C8000__000000B18434BFD0", +"000000067F000080000009003800000C5213-000000067F000080000009003800000CE979__000000B0F3EDEAC9-000000B18495C001", +"000000067F000080000009003800000C8000-000000067F000080000009003800000CC000__000000B18434BFD0", +"000000067F000080000009003800000CC000-000000067F000080000009003800000D0000__000000B18434BFD0", +"000000067F000080000009003800000CE979-000000067F000080000009003800000D80DF__000000B0F3EDEAC9-000000B18495C001", +"000000067F000080000009003800000D0000-000000067F000080000009003800000D4000__000000B18434BFD0", +"000000067F000080000009003800000D4000-000000067F000080000009003800000D8000__000000B18434BFD0", +"000000067F000080000009003800000D8000-000000067F000080000009003800000DC000__000000B18434BFD0", +"000000067F000080000009003800000D80DF-000000067F000080000009003800000E180A__000000B0F3EDEAC9-000000B18495C001", +"000000067F000080000009003800000DC000-000000067F000080000009003800000E0000__000000B18434BFD0", +"000000067F000080000009003800000E0000-000000067F000080000009003800000E4000__000000B18434BFD0", +"000000067F000080000009003800000E180A-000000067F000080000009003800000EAF70__000000B0F3EDEAC9-000000B18495C001", +"000000067F000080000009003800000E4000-000000067F000080000009003800000E8000__000000B18434BFD0", +"000000067F000080000009003800000E8000-000000067F000080000009003800000EC000__000000B18434BFD0", +"000000067F000080000009003800000EAF70-000000067F000080000009003800000F46D6__000000B0F3EDEAC9-000000B18495C001", +"000000067F000080000009003800000EC000-000000067F000080000009003800000F0000__000000B18434BFD0", +"000000067F000080000009003800000F0000-000000067F000080000009003800000F4000__000000B18434BFD0", +"000000067F000080000009003800000F4000-000000067F000080000009003800000F8000__000000B18434BFD0", +"000000067F000080000009003800000F46D6-000000067F000080000009003800000FDE0B__000000B0F3EDEAC9-000000B18495C001", +"000000067F000080000009003800000F8000-000000067F000080000009003800000FC000__000000B18434BFD0", +"000000067F000080000009003800000FC000-000000067F00008000000900380000100000__000000B18434BFD0", +"000000067F000080000009003800000FDE0B-000000067F0000800000090038000010752B__000000B0F3EDEAC9-000000B18495C001", +"000000067F00008000000900380000100000-000000067F00008000000900380000104000__000000B18434BFD0", +"000000067F00008000000900380000104000-000000067F00008000000900380000108000__000000B18434BFD0", +"000000067F0000800000090038000010752B-000000067F00008000000900380000110C91__000000B0F3EDEAC9-000000B18495C001", +"000000067F00008000000900380000108000-000000067F0000800000090038000010C000__000000B18434BFD0", +"000000067F0000800000090038000010C000-000000067F00008000000900380000110000__000000B18434BFD0", +"000000067F00008000000900380000110000-030000000000000000000000000000000002__000000B18434BFD0", +"000000067F00008000000900380000110C91-01000000000000000100000004000000001C__000000B0F3EDEAC9-000000B18495C001", +"000000067F000080000009004000000047E0-000000067F0000800000090040000000C6F1__000000B18495C001-000000B1FA75F501", +"000000067F0000800000090040000000C6F1-000000067F00008000000900400000014600__000000B18495C001-000000B1FA75F501", +"000000067F00008000000900400000014600-000000067F0000800000090040000001C511__000000B18495C001-000000B1FA75F501", +"000000067F0000800000090040000001C511-000000067F00008000000900400000024421__000000B18495C001-000000B1FA75F501", +"000000067F00008000000900400000024421-000000067F0000800000090040000002C331__000000B18495C001-000000B1FA75F501", +"000000067F0000800000090040000002C331-000000067F000080000009200C0000007658__000000B18495C001-000000B1FA75F501", +"000000067F000080000009200C0000000000-000000067F000080000009200C0000004000__000000B3AC039FE8", +"000000067F000080000009200C0000004000-000000067F000080000009200C0000008000__000000B3AC039FE8", +"000000067F000080000009200C0000007658-000000067F000080000009200C0000010DB5__000000B18495C001-000000B1FA75F501", +"000000067F000080000009200C0000008000-000000067F000080000009200C000000C000__000000B3AC039FE8", +"000000067F000080000009200C000000C000-000000067F000080000009200C0000010000__000000B3AC039FE8", +"000000067F000080000009200C0000010000-000000067F000080000009200C0000014000__000000B3A3EC82C8", +"000000067F000080000009200C0000010DB5-030000000000000000000000000000000002__000000B18495C001-000000B1FA75F501", +"000000067F000080000009200C0000012E97-000000067F000080000009200C000001C5FD__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000014000-000000067F000080000009200C0000018000__000000B3A3EC82C8", +"000000067F000080000009200C0000018000-000000067F000080000009200C000001C000__000000B3A3EC82C8", +"000000067F000080000009200C000001C000-000000067F000080000009200C0000020000__000000B3A3EC82C8", +"000000067F000080000009200C000001C5FD-000000067F000080000009200C0000025D0C__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000020000-000000067F000080000009200C0000024000__000000B3A3EC82C8", +"000000067F000080000009200C0000024000-000000067F000080000009200C0000028000__000000B3A3EC82C8", +"000000067F000080000009200C0000025D0C-000000067F000080000009200C000002F472__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000028000-000000067F000080000009200C000002C000__000000B3A3EC82C8", +"000000067F000080000009200C000002C000-000000067F000080000009200C0000030000__000000B3A3EC82C8", +"000000067F000080000009200C000002F472-000000067F000080000009200C0000038B85__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000030000-000000067F000080000009200C0000034000__000000B3A3EC82C8", +"000000067F000080000009200C0000034000-000000067F000080000009200C0000038000__000000B3A3EC82C8", +"000000067F000080000009200C0000038000-000000067F000080000009200C000003C000__000000B3A3EC82C8", +"000000067F000080000009200C0000038B85-000000067F000080000009200C00000422EB__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C000003C000-000000067F000080000009200C0000040000__000000B3A3EC82C8", +"000000067F000080000009200C0000040000-000000067F000080000009200C0000044000__000000B3A3EC82C8", +"000000067F000080000009200C00000422EB-000000067F000080000009200C000004BA0C__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000044000-000000067F000080000009200C0000048000__000000B3A3EC82C8", +"000000067F000080000009200C0000048000-000000067F000080000009200C000004C000__000000B3A3EC82C8", +"000000067F000080000009200C000004BA0C-000000067F000080000009200C0000055141__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C000004C000-000000067F000080000009200C0000050000__000000B3A3EC82C8", +"000000067F000080000009200C0000050000-000000067F000080000009200C0000054000__000000B3A3EC82C8", +"000000067F000080000009200C0000054000-000000067F000080000009200C0000058000__000000B3A3EC82C8", +"000000067F000080000009200C0000055141-000000067F000080000009200C000005E8A7__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000058000-000000067F000080000009200C000005C000__000000B3A3EC82C8", +"000000067F000080000009200C000005C000-000000067F000080000009200C0000060000__000000B3A3EC82C8", +"000000067F000080000009200C000005E8A7-000000067F000080000009200C0000067FC1__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000060000-000000067F000080000009200C0000064000__000000B3A3EC82C8", +"000000067F000080000009200C0000064000-000000067F000080000009200C0000068000__000000B3A3EC82C8", +"000000067F000080000009200C0000067FC1-000000067F000080000009200C0000071709__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000068000-000000067F000080000009200C000006C000__000000B3A3EC82C8", +"000000067F000080000009200C000006C000-000000067F000080000009200C0000070000__000000B3A3EC82C8", +"000000067F000080000009200C0000070000-000000067F000080000009200C0000074000__000000B3A3EC82C8", +"000000067F000080000009200C0000071709-000000067F000080000009200C000007AE6F__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000074000-000000067F000080000009200C0000078000__000000B3A3EC82C8", +"000000067F000080000009200C0000078000-000000067F000080000009200C000007C000__000000B3A3EC82C8", +"000000067F000080000009200C000007AE6F-000000067F000080000009200C00000845AB__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C000007C000-000000067F000080000009200C0000080000__000000B3A3EC82C8", +"000000067F000080000009200C0000080000-000000067F000080000009200C0000084000__000000B3A3EC82C8", +"000000067F000080000009200C0000084000-000000067F000080000009200C0000088000__000000B3A3EC82C8", +"000000067F000080000009200C00000845AB-000000067F000080000009200C000008DD09__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000088000-000000067F000080000009200C000008C000__000000B3A3EC82C8", +"000000067F000080000009200C000008C000-000000067F000080000009200C0000090000__000000B3A3EC82C8", +"000000067F000080000009200C000008DD09-000000067F000080000009200C0100000000__000000B1FA75F501-000000B2CA27F641", +"000000067F000080000009200C0000090000-000000067F000080000009200C0000094000__000000B3A3EC82C8", +"000000067F000080000009200C0000094000-000000067F000080000009200C0000098000__000000B3A3EC82C8", +"000000067F000080000009200C000009567A-000000067F000080000009200C000009EDE0__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C0000098000-000000067F000080000009200C000009C000__000000B3A3EC82C8", +"000000067F000080000009200C000009C000-000000067F000080000009200C00000A0000__000000B3A3EC82C8", +"000000067F000080000009200C000009EDE0-000000067F000080000009200C00000A852B__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C00000A0000-000000067F000080000009200C00000A4000__000000B3A3EC82C8", +"000000067F000080000009200C00000A4000-000000067F000080000009200C00000A8000__000000B3A3EC82C8", +"000000067F000080000009200C00000A8000-000000067F000080000009200C00000AC000__000000B3A3EC82C8", +"000000067F000080000009200C00000A852B-000000067F000080000009200C00000B1C91__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C00000AC000-000000067F000080000009200C00000B0000__000000B3A3EC82C8", +"000000067F000080000009200C00000B0000-000000067F000080000009200C00000B4000__000000B3A3EC82C8", +"000000067F000080000009200C00000B1C91-000000067F000080000009200C00000BB3F7__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C00000B4000-000000067F000080000009200C00000B8000__000000B3A3EC82C8", +"000000067F000080000009200C00000B8000-000000067F000080000009200C00000BC000__000000B3A3EC82C8", +"000000067F000080000009200C00000BB3F7-000000067F000080000009200C00000C4B0C__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C00000BC000-000000067F000080000009200C00000C0000__000000B3A3EC82C8", +"000000067F000080000009200C00000C0000-000000067F000080000009200C00000C4000__000000B3A3EC82C8", +"000000067F000080000009200C00000C4000-000000067F000080000009200C00000C8000__000000B3A3EC82C8", +"000000067F000080000009200C00000C4B0C-000000067F000080000009200C00000CE272__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C00000C8000-000000067F000080000009200C00000CC000__000000B3A3EC82C8", +"000000067F000080000009200C00000CC000-000000067F000080000009200C00000D0000__000000B3A3EC82C8", +"000000067F000080000009200C00000CE272-000000067F000080000009200C00000D798F__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C00000D0000-000000067F000080000009200C00000D4000__000000B3A3EC82C8", +"000000067F000080000009200C00000D4000-000000067F000080000009200C00000D8000__000000B3A3EC82C8", +"000000067F000080000009200C00000D798F-000000067F000080000009200C00000E10F5__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C00000D8000-000000067F000080000009200C00000DC000__000000B3A3EC82C8", +"000000067F000080000009200C00000DC000-000000067F000080000009200C00000E0000__000000B3A3EC82C8", +"000000067F000080000009200C00000E0000-000000067F000080000009200C00000E4000__000000B3A3EC82C8", +"000000067F000080000009200C00000E10F5-000000067F000080000009200C00000EA80B__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C00000E4000-000000067F000080000009200C00000E8000__000000B3A3EC82C8", +"000000067F000080000009200C00000E8000-000000067F000080000009200C00000EC000__000000B3A3EC82C8", +"000000067F000080000009200C00000EA80B-000000067F000080000009200C00000F3F4B__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C00000EC000-000000067F000080000009200C00000F0000__000000B3A3EC82C8", +"000000067F000080000009200C00000F0000-000000067F000080000009200C00000F4000__000000B3A3EC82C8", +"000000067F000080000009200C00000F3F4B-000000067F000080000009200C00000FD6B1__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C00000F4000-000000067F000080000009200C00000F8000__000000B3A3EC82C8", +"000000067F000080000009200C00000F8000-000000067F000080000009200C00000FC000__000000B3A3EC82C8", +"000000067F000080000009200C00000FC000-000000067F000080000009200C0000100000__000000B3A3EC82C8", +"000000067F000080000009200C00000FD6B1-000000067F000080000009200C0000106DD5__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C0000100000-000000067F000080000009200C0000104000__000000B3A3EC82C8", +"000000067F000080000009200C0000104000-000000067F000080000009200C0000108000__000000B3A3EC82C8", +"000000067F000080000009200C0000106DD5-000000067F000080000009200C000011050B__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F000080000009200C0000108000-000000067F000080000009200C000010C000__000000B3A3EC82C8", +"000000067F000080000009200C000010C000-030000000000000000000000000000000002__000000B3A3EC82C8", +"000000067F000080000009200C000011050B-01000000000000000100000004000000001C__000000B2CA27F641-000000B3AB3B7FC9", +"000000067F00008000000920140000005289-000000067F0000800000092014000000D19A__000000B3AB3B7FC9-000000B4208FF3D1", +"000000067F0000800000092014000000D19A-000000067F000080000009201400000150A9__000000B3AB3B7FC9-000000B4208FF3D1", +"000000067F000080000009201400000150A9-000000067F0000800000092014000001CFBA__000000B3AB3B7FC9-000000B4208FF3D1", +"000000067F0000800000092014000001CFBA-000000067F00008000000920140000024ECB__000000B3AB3B7FC9-000000B4208FF3D1", +"000000067F00008000000920140000024ECB-000000067F0000800000092014000002CDDB__000000B3AB3B7FC9-000000B4208FF3D1", +"000000067F0000800000092014000002CDDB-000000067F000080000009400C000000830C__000000B3AB3B7FC9-000000B4208FF3D1", +"000000067F000080000009400C0000000000-000000067F000080000009400C0000004000__000000B5CED8CF78", +"000000067F000080000009400C0000004000-000000067F000080000009400C0000008000__000000B5CED8CF78", +"000000067F000080000009400C0000008000-000000067F000080000009400C000000C000__000000B5CED8CF78", +"000000067F000080000009400C000000830C-000000067F000080000009400C0000011A72__000000B3AB3B7FC9-000000B4208FF3D1", +"000000067F000080000009400C000000C000-000000067F000080000009400C0000010000__000000B5CED8CF78", +"000000067F000080000009400C0000010000-000000067F000080000009400C0000014000__000000B568835548", +"000000067F000080000009400C0000011A72-030000000000000000000000000000000002__000000B3AB3B7FC9-000000B4208FF3D1", +"000000067F000080000009400C0000012E51-000000067F000080000009400C000001C5B7__000000B4208FF3D1-000000B43089EC11", +"000000067F000080000009400C0000012E51-000000067F000080000009400C000001C5B7__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C0000014000-000000067F000080000009400C0000018000__000000B568835548", +"000000067F000080000009400C0000018000-000000067F000080000009400C000001C000__000000B568835548", +"000000067F000080000009400C000001C000-000000067F000080000009400C0000020000__000000B568835548", +"000000067F000080000009400C000001C5B7-000000067F000080000009400C0000025D1D__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C000001C5B7-000000067F000080000009400C0100000000__000000B4208FF3D1-000000B43089EC11", +"000000067F000080000009400C0000020000-000000067F000080000009400C0000024000__000000B568835548", +"000000067F000080000009400C0000024000-000000067F000080000009400C0000028000__000000B568835548", +"000000067F000080000009400C0000025D1D-000000067F000080000009400C000002F483__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C0000028000-000000067F000080000009400C000002C000__000000B568835548", +"000000067F000080000009400C000002C000-000000067F000080000009400C0000030000__000000B568835548", +"000000067F000080000009400C000002F483-000000067F000080000009400C0000038B96__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C0000030000-000000067F000080000009400C0000034000__000000B568835548", +"000000067F000080000009400C0000034000-000000067F000080000009400C0000038000__000000B568835548", +"000000067F000080000009400C0000038000-000000067F000080000009400C000003C000__000000B568835548", +"000000067F000080000009400C0000038B96-000000067F000080000009400C00000422FC__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C000003C000-000000067F000080000009400C0000040000__000000B568835548", +"000000067F000080000009400C0000040000-000000067F000080000009400C0000044000__000000B568835548", +"000000067F000080000009400C00000422FC-000000067F000080000009400C000004BA0C__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C0000044000-000000067F000080000009400C0000048000__000000B568835548", +"000000067F000080000009400C0000048000-000000067F000080000009400C000004C000__000000B568835548", +"000000067F000080000009400C000004BA0C-000000067F000080000009400C0000055141__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C000004C000-000000067F000080000009400C0000050000__000000B568835548", +"000000067F000080000009400C0000050000-000000067F000080000009400C0000054000__000000B568835548", +"000000067F000080000009400C0000054000-000000067F000080000009400C0000058000__000000B568835548", +"000000067F000080000009400C0000055141-000000067F000080000009400C000005E8A7__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C0000058000-000000067F000080000009400C000005C000__000000B568835548", +"000000067F000080000009400C000005C000-000000067F000080000009400C0000060000__000000B568835548", +"000000067F000080000009400C000005E8A7-000000067F000080000009400C0000067FC1__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C0000060000-000000067F000080000009400C0000064000__000000B568835548", +"000000067F000080000009400C0000064000-000000067F000080000009400C0000068000__000000B568835548", +"000000067F000080000009400C0000067FC1-000000067F000080000009400C0000071709__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C0000068000-000000067F000080000009400C000006C000__000000B568835548", +"000000067F000080000009400C000006C000-000000067F000080000009400C0000070000__000000B568835548", +"000000067F000080000009400C0000070000-000000067F000080000009400C0000074000__000000B568835548", +"000000067F000080000009400C0000071709-000000067F000080000009400C000007AE6F__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C0000074000-000000067F000080000009400C0000078000__000000B568835548", +"000000067F000080000009400C0000078000-000000067F000080000009400C000007C000__000000B568835548", +"000000067F000080000009400C000007AE6F-000000067F000080000009400C00000845AB__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C000007C000-000000067F000080000009400C0000080000__000000B568835548", +"000000067F000080000009400C0000080000-000000067F000080000009400C0000084000__000000B568835548", +"000000067F000080000009400C0000084000-000000067F000080000009400C0000088000__000000B568835548", +"000000067F000080000009400C00000845AB-000000067F000080000009400C0100000000__000000B4208FF3D1-000000B4E047E5A9", +"000000067F000080000009400C0000088000-000000067F000080000009400C000008C000__000000B568835548", +"000000067F000080000009400C000008C000-000000067F000080000009400C0000090000__000000B568835548", +"000000067F000080000009400C000008DEA4-000000067F000080000009400C00000975C4__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C0000090000-000000067F000080000009400C0000094000__000000B568835548", +"000000067F000080000009400C0000094000-000000067F000080000009400C0000098000__000000B568835548", +"000000067F000080000009400C00000975C4-000000067F000080000009400C00000A0D0A__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C0000098000-000000067F000080000009400C000009C000__000000B568835548", +"000000067F000080000009400C000009C000-000000067F000080000009400C00000A0000__000000B568835548", +"000000067F000080000009400C00000A0000-000000067F000080000009400C00000A4000__000000B568835548", +"000000067F000080000009400C00000A0D0A-000000067F000080000009400C00000AA470__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00000A4000-000000067F000080000009400C00000A8000__000000B568835548", +"000000067F000080000009400C00000A8000-000000067F000080000009400C00000AC000__000000B568835548", +"000000067F000080000009400C00000AA470-000000067F000080000009400C00000B3BB2__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00000AC000-000000067F000080000009400C00000B0000__000000B568835548", +"000000067F000080000009400C00000B0000-000000067F000080000009400C00000B4000__000000B568835548", +"000000067F000080000009400C00000B3BB2-000000067F000080000009400C00000BD30A__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00000B4000-000000067F000080000009400C00000B8000__000000B568835548", +"000000067F000080000009400C00000B8000-000000067F000080000009400C00000BC000__000000B568835548", +"000000067F000080000009400C00000BC000-000000067F000080000009400C00000C0000__000000B568835548", +"000000067F000080000009400C00000BD30A-000000067F000080000009400C00000C6A30__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00000C0000-000000067F000080000009400C00000C4000__000000B568835548", +"000000067F000080000009400C00000C4000-000000067F000080000009400C00000C8000__000000B568835548", +"000000067F000080000009400C00000C6A30-000000067F000080000009400C00000D0194__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00000C8000-000000067F000080000009400C00000CC000__000000B568835548", +"000000067F000080000009400C00000CC000-000000067F000080000009400C00000D0000__000000B568835548", +"000000067F000080000009400C00000D0000-000000067F000080000009400C00000D4000__000000B568835548", +"000000067F000080000009400C00000D0194-000000067F000080000009400C00000D98FA__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00000D4000-030000000000000000000000000000000002__000000B568835548", +"000000067F000080000009400C00000D98FA-000000067F000080000009400C00000E300D__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00000E300D-000000067F000080000009400C00000EC773__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00000EC773-000000067F000080000009400C00000F5ED9__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00000F5ED9-000000067F000080000009400C00000FF60C__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00000FF60C-000000067F000080000009400C0000108D1D__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C0000108D1D-000000067F000080000009400C0000111C20__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009400C00FFFFFFFF-030000000000000000000000000000000002__000000B4E047E5A9-000000B5CED8CF79", +"000000067F000080000009600C0000000000-000000067F000080000009600C0000004000__000000B79F439FE0", +"000000067F000080000009600C0000004000-000000067F000080000009600C0000008000__000000B79F439FE0", +"000000067F000080000009600C0000008000-000000067F000080000009600C000000C000__000000B79F439FE0", +"000000067F000080000009600C000000974F-000000067F000080000009600C0000012EB5__000000B5CED8CF79-000000B63EADE5B9", +"000000067F000080000009600C000000C000-000000067F000080000009600C0000010000__000000B79F439FE0", +"000000067F000080000009600C0000010000-000000067F000080000009600C0000014000__000000B79F439FE0", +"000000067F000080000009600C0000012EB5-000000067F000080000009600C000001C60A__000000B5CED8CF79-000000B63EADE5B9", +"000000067F000080000009600C0000014000-000000067F000080000009600C0000018000__000000B79F439FE0", +"000000067F000080000009600C0000018000-000000067F000080000009600C000001C000__000000B79F439FE0", +"000000067F000080000009600C000001C000-000000067F000080000009600C0000020000__000000B79F439FE0", +"000000067F000080000009600C000001C60A-000000067F000080000009600C0000025D38__000000B5CED8CF79-000000B63EADE5B9", +"000000067F000080000009600C0000020000-000000067F000080000009600C0000024000__000000B79F439FE0", +"000000067F000080000009600C0000024000-000000067F000080000009600C0000028000__000000B79F439FE0", +"000000067F000080000009600C0000025D38-000000067F000080000009600C000002F49E__000000B5CED8CF79-000000B63EADE5B9", +"000000067F000080000009600C0000028000-000000067F000080000009600C000002C000__000000B79F439FE0", +"000000067F000080000009600C000002C000-000000067F000080000009600C0000030000__000000B79F439FE0", +"000000067F000080000009600C000002F49E-000000067F000080000009600C0000038BB1__000000B5CED8CF79-000000B63EADE5B9", +"000000067F000080000009600C0000030000-000000067F000080000009600C0000034000__000000B79F439FE0", +"000000067F000080000009600C0000034000-000000067F000080000009600C0000038000__000000B79F439FE0", +"000000067F000080000009600C0000038000-000000067F000080000009600C000003C000__000000B79F439FE0", +"000000067F000080000009600C0000038BB1-000000067F000080000009600C0000042317__000000B5CED8CF79-000000B63EADE5B9", +"000000067F000080000009600C000003C000-000000067F000080000009600C0000040000__000000B79F439FE0", +"000000067F000080000009600C0000040000-000000067F000080000009600C0000044000__000000B79D17BFD0", +"000000067F000080000009600C0000040000-000000067F000080000009600C0000044000__000000B8606C92A0", +"000000067F000080000009600C0000042317-030000000000000000000000000000000002__000000B5CED8CF79-000000B63EADE5B9", +"000000067F000080000009600C000004236E-000000067F000080000009600C000004BAD4__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C0000044000-000000067F000080000009600C0000048000__000000B79D17BFD0", +"000000067F000080000009600C0000044000-000000067F000080000009600C0000048000__000000B8606C92A0", +"000000067F000080000009600C0000048000-000000067F000080000009600C000004C000__000000B79D17BFD0", +"000000067F000080000009600C0000048000-000000067F000080000009600C000004C000__000000B8606C92A0", +"000000067F000080000009600C000004BAD4-000000067F000080000009600C0000055208__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C000004C000-000000067F000080000009600C0000050000__000000B79D17BFD0", +"000000067F000080000009600C000004C000-000000067F000080000009600C0000050000__000000B8606C92A0", +"000000067F000080000009600C0000050000-000000067F000080000009600C0000054000__000000B79D17BFD0", +"000000067F000080000009600C0000050000-000000067F000080000009600C0000054000__000000B8606C92A0", +"000000067F000080000009600C0000054000-000000067F000080000009600C0000058000__000000B79D17BFD0", +"000000067F000080000009600C0000054000-000000067F000080000009600C0000058000__000000B8606C92A0", +"000000067F000080000009600C0000055208-000000067F000080000009600C000005E96E__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C0000055A77-000000067F000080000009600C00000AAEA5__000000B808718889-000000B8606C92A1", +"000000067F000080000009600C0000058000-000000067F000080000009600C000005C000__000000B79D17BFD0", +"000000067F000080000009600C0000058000-000000067F000080000009600C000005C000__000000B8606C92A0", +"000000067F000080000009600C000005C000-000000067F000080000009600C0000060000__000000B79D17BFD0", +"000000067F000080000009600C000005C000-000000067F000080000009600C0000060000__000000B8606C92A0", +"000000067F000080000009600C000005E96E-000000067F000080000009600C00000680D4__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C0000060000-000000067F000080000009600C0000064000__000000B79D17BFD0", +"000000067F000080000009600C0000060000-000000067F000080000009600C0000064000__000000B8606C92A0", +"000000067F000080000009600C0000064000-000000067F000080000009600C0000068000__000000B79D17BFD0", +"000000067F000080000009600C0000064000-000000067F000080000009600C0000068000__000000B8606C92A0", +"000000067F000080000009600C0000068000-000000067F000080000009600C000006C000__000000B79D17BFD0", +"000000067F000080000009600C0000068000-000000067F000080000009600C000006C000__000000B8606C92A0", +"000000067F000080000009600C00000680D4-000000067F000080000009600C000007180B__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C000006C000-000000067F000080000009600C0000070000__000000B79D17BFD0", +"000000067F000080000009600C000006C000-000000067F000080000009600C0000070000__000000B8606C92A0", +"000000067F000080000009600C0000070000-000000067F000080000009600C0000074000__000000B79D17BFD0", +"000000067F000080000009600C0000070000-000000067F000080000009600C0000074000__000000B8606C92A0", +"000000067F000080000009600C000007180B-000000067F000080000009600C000007AF71__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C0000074000-000000067F000080000009600C0000078000__000000B79D17BFD0", +"000000067F000080000009600C0000074000-000000067F000080000009600C0000078000__000000B8606C92A0", +"000000067F000080000009600C0000078000-000000067F000080000009600C000007C000__000000B79D17BFD0", +"000000067F000080000009600C0000078000-000000067F000080000009600C000007C000__000000B8606C92A0", +"000000067F000080000009600C000007AF71-000000067F000080000009600C00000846D7__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C000007C000-000000067F000080000009600C0000080000__000000B79D17BFD0", +"000000067F000080000009600C000007C000-000000067F000080000009600C0000080000__000000B8606C92A0", +"000000067F000080000009600C0000080000-000000067F000080000009600C0000084000__000000B79D17BFD0", +"000000067F000080000009600C0000080000-000000067F000080000009600C0000084000__000000B8606C92A0", +"000000067F000080000009600C0000084000-000000067F000080000009600C0000088000__000000B79D17BFD0", +"000000067F000080000009600C0000084000-000000067F000080000009600C0000088000__000000B8606C92A0", +"000000067F000080000009600C00000846D7-000000067F000080000009600C000008DE0C__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C0000088000-000000067F000080000009600C000008C000__000000B79D17BFD0", +"000000067F000080000009600C0000088000-000000067F000080000009600C000008C000__000000B8606C92A0", +"000000067F000080000009600C000008C000-000000067F000080000009600C0000090000__000000B79D17BFD0", +"000000067F000080000009600C000008C000-000000067F000080000009600C0000090000__000000B8606C92A0", +"000000067F000080000009600C000008DE0C-000000067F000080000009600C000009752C__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C0000090000-000000067F000080000009600C0000094000__000000B79D17BFD0", +"000000067F000080000009600C0000090000-000000067F000080000009600C0000094000__000000B8606C92A0", +"000000067F000080000009600C0000094000-000000067F000080000009600C0000098000__000000B79D17BFD0", +"000000067F000080000009600C0000094000-000000067F000080000009600C0000098000__000000B8606C92A0", +"000000067F000080000009600C000009752C-000000067F000080000009600C00000A0C92__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C0000098000-000000067F000080000009600C000009C000__000000B79D17BFD0", +"000000067F000080000009600C0000098000-000000067F000080000009600C000009C000__000000B8606C92A0", +"000000067F000080000009600C000009C000-000000067F000080000009600C00000A0000__000000B79D17BFD0", +"000000067F000080000009600C000009C000-000000067F000080000009600C00000A0000__000000B8606C92A0", +"000000067F000080000009600C00000A0000-000000067F000080000009600C00000A4000__000000B79D17BFD0", +"000000067F000080000009600C00000A0000-000000067F000080000009600C00000A4000__000000B8606C92A0", +"000000067F000080000009600C00000A0C92-000000067F000080000009600C0100000000__000000B63EADE5B9-000000B6DE71F5F9", +"000000067F000080000009600C00000A4000-000000067F000080000009600C00000A8000__000000B79D17BFD0", +"000000067F000080000009600C00000A4000-000000067F000080000009600C00000A8000__000000B8606C92A0", +"000000067F000080000009600C00000A8000-000000067F000080000009600C00000AC000__000000B79D17BFD0", +"000000067F000080000009600C00000A8000-000000067F000080000009600C00000AC000__000000B8606C92A0", +"000000067F000080000009600C00000A93FD-000000067F000080000009600C00000B2B0C__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C00000AAEA5-000000067F000080000009600C0000101445__000000B808718889-000000B8606C92A1", +"000000067F000080000009600C00000AC000-000000067F000080000009600C00000B0000__000000B79D17BFD0", +"000000067F000080000009600C00000AC000-000000067F000080000009600C00000B0000__000000B8606C92A0", +"000000067F000080000009600C00000B0000-000000067F000080000009600C00000B4000__000000B79D17BFD0", +"000000067F000080000009600C00000B0000-000000067F000080000009600C00000B4000__000000B8606C92A0", +"000000067F000080000009600C00000B2B0C-000000067F000080000009600C00000BC272__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C00000B4000-000000067F000080000009600C00000B8000__000000B79D17BFD0", +"000000067F000080000009600C00000B4000-000000067F000080000009600C00000B8000__000000B8606C92A0", +"000000067F000080000009600C00000B8000-000000067F000080000009600C00000BC000__000000B79D17BFD0", +"000000067F000080000009600C00000B8000-000000067F000080000009600C00000BC000__000000B8606C92A0", +"000000067F000080000009600C00000BC000-000000067F000080000009600C00000C0000__000000B79D17BFD0", +"000000067F000080000009600C00000BC000-000000067F000080000009600C00000C0000__000000B8606C92A0", +"000000067F000080000009600C00000BC272-000000067F000080000009600C00000C59A2__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C00000C0000-000000067F000080000009600C00000C4000__000000B79D17BFD0", +"000000067F000080000009600C00000C0000-000000067F000080000009600C00000C4000__000000B8606C92A0", +"000000067F000080000009600C00000C4000-000000067F000080000009600C00000C8000__000000B79D17BFD0", +"000000067F000080000009600C00000C4000-000000067F000080000009600C00000C8000__000000B8606C92A0", +"000000067F000080000009600C00000C59A2-000000067F000080000009600C00000CF108__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C00000C8000-000000067F000080000009600C00000CC000__000000B79D17BFD0", +"000000067F000080000009600C00000C8000-000000067F000080000009600C00000CC000__000000B8606C92A0", +"000000067F000080000009600C00000CC000-000000067F000080000009600C00000D0000__000000B79D17BFD0", +"000000067F000080000009600C00000CC000-000000067F000080000009600C00000D0000__000000B8606C92A0", +"000000067F000080000009600C00000CF108-000000067F000080000009600C00000D882B__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C00000D0000-000000067F000080000009600C00000D4000__000000B79D17BFD0", +"000000067F000080000009600C00000D0000-000000067F000080000009600C00000D4000__000000B8606C92A0", +"000000067F000080000009600C00000D4000-000000067F000080000009600C00000D8000__000000B79D17BFD0", +"000000067F000080000009600C00000D4000-000000067F000080000009600C00000D8000__000000B8606C92A0", +"000000067F000080000009600C00000D8000-000000067F000080000009600C00000DC000__000000B79D17BFD0", +"000000067F000080000009600C00000D8000-000000067F000080000009600C00000DC000__000000B8606C92A0", +"000000067F000080000009600C00000D882B-000000067F000080000009600C00000E1F7E__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C00000DC000-000000067F000080000009600C00000E0000__000000B79D17BFD0", +"000000067F000080000009600C00000DC000-000000067F000080000009600C00000E0000__000000B8606C92A0", +"000000067F000080000009600C00000E0000-000000067F000080000009600C00000E4000__000000B79D17BFD0", +"000000067F000080000009600C00000E0000-000000067F000080000009600C00000E4000__000000B8606C92A0", +"000000067F000080000009600C00000E1F7E-000000067F000080000009600C00000EB6E4__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C00000E4000-000000067F000080000009600C00000E8000__000000B79D17BFD0", +"000000067F000080000009600C00000E4000-000000067F000080000009600C00000E8000__000000B8606C92A0", +"000000067F000080000009600C00000E8000-000000067F000080000009600C00000EC000__000000B79D17BFD0", +"000000067F000080000009600C00000E8000-000000067F000080000009600C00000EC000__000000B8606C92A0", +"000000067F000080000009600C00000EB6E4-000000067F000080000009600C00000F4E0B__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C00000EC000-000000067F000080000009600C00000F0000__000000B79D17BFD0", +"000000067F000080000009600C00000EC000-000000067F000080000009600C00000F0000__000000B8606C92A0", +"000000067F000080000009600C00000F0000-000000067F000080000009600C00000F4000__000000B79D17BFD0", +"000000067F000080000009600C00000F0000-000000067F000080000009600C00000F4000__000000B8606C92A0", +"000000067F000080000009600C00000F4000-000000067F000080000009600C00000F8000__000000B79D17BFD0", +"000000067F000080000009600C00000F4000-000000067F000080000009600C00000F8000__000000B8606C92A0", +"000000067F000080000009600C00000F4E0B-000000067F000080000009600C00000FE571__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C00000F8000-000000067F000080000009600C00000FC000__000000B79D17BFD0", +"000000067F000080000009600C00000F8000-000000067F000080000009600C00000FC000__000000B8606C92A0", +"000000067F000080000009600C00000FC000-000000067F000080000009600C0000100000__000000B79D17BFD0", +"000000067F000080000009600C00000FC000-000000067F000080000009600C0000100000__000000B8606C92A0", +"000000067F000080000009600C00000FE571-000000067F000080000009600C0000107CD7__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C0000100000-000000067F000080000009600C0000104000__000000B79D17BFD0", +"000000067F000080000009600C0000100000-000000067F000080000009600C0000104000__000000B8606C92A0", +"000000067F000080000009600C000010144D-000000067F0000800000096014000000E7D9__000000B808718889-000000B8606C92A1", +"000000067F000080000009600C0000104000-000000067F000080000009600C0000108000__000000B79D17BFD0", +"000000067F000080000009600C0000104000-000000067F000080000009600C0000108000__000000B8606C92A0", +"000000067F000080000009600C0000107CD7-000000067F000080000009600C000011140C__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C0000108000-000000067F000080000009600C000010C000__000000B79D17BFD0", +"000000067F000080000009600C0000108000-000000067F000080000009600C000010C000__000000B8606C92A0", +"000000067F000080000009600C000010C000-000000067F000080000009600C0000110000__000000B79D17BFD0", +"000000067F000080000009600C000010C000-000000067F000080000009600C0000110000__000000B8606C92A0", +"000000067F000080000009600C0000110000-000000067F00008000000960120100000000__000000B8606C92A0", +"000000067F000080000009600C0000110000-030000000000000000000000000000000002__000000B79D17BFD0", +"000000067F000080000009600C000011140C-01000000000000000100000004000000001C__000000B6DE71F5F9-000000B79E68FFF9", +"000000067F000080000009600C020000000B-000000067F0000800000096014000000571F__000000B79E68FFF9-000000B808718889", +"000000067F00008000000960140000000000-000000067F00008000000960140000004000__000000B8606C92A0", +"000000067F00008000000960140000004000-000000067F00008000000960140000008000__000000B8606C92A0", +"000000067F0000800000096014000000571F-000000067F0000800000096014000000CB61__000000B79E68FFF9-000000B808718889", +"000000067F00008000000960140000008000-000000067F0000800000096014000000C000__000000B8606C92A0", +"000000067F0000800000096014000000C000-000000067F00008000000960140000010000__000000B8606C92A0", +"000000067F0000800000096014000000CB61-000000067F00008000000960140000013F98__000000B79E68FFF9-000000B808718889", +"000000067F0000800000096014000000E7DB-000000067F00008000000960140000022A8D__000000B808718889-000000B8606C92A1", +"000000067F00008000000960140000010000-000000067F00008000000960140000014000__000000B8606C92A0", +"000000067F00008000000960140000013F98-000000067F0000800000096014000001B3C2__000000B79E68FFF9-000000B808718889", +"000000067F00008000000960140000014000-000000067F00008000000960140000018000__000000B8606C92A0", +"000000067F00008000000960140000018000-000000067F0000800000096014000001C000__000000B8606C92A0", +"000000067F0000800000096014000001B3C2-000000067F000080000009601400000227FC__000000B79E68FFF9-000000B808718889", +"000000067F0000800000096014000001C000-000000067F00008000000960140000020000__000000B8606C92A0", +"000000067F00008000000960140000020000-000000067F00008000000960140000024000__000000B8606C92A0", +"000000067F000080000009601400000227FC-000000067F00008000000960140000029BD8__000000B79E68FFF9-000000B808718889", +"000000067F00008000000960140000022A8D-030000000000000000000000000000000002__000000B808718889-000000B8606C92A1", +"000000067F00008000000960140000024000-000000067F00008000000960140000028000__000000B8606C92A0", +"000000067F00008000000960140000028000-000000067F0000800000096014000002C000__000000B8606C92A0", +"000000067F00008000000960140000029BD8-030000000000000000000000000000000002__000000B79E68FFF9-000000B808718889", +"000000067F0000800000096014000002C000-030000000000000000000000000000000002__000000B8606C92A0", +"000000067F000080000009800C0000009748-000000067F000080000009800C0000012EAE__000000B8606C92A1-000000B8E03BF0B9", +"000000067F000080000009800C0000012EAE-000000067F000080000009800C000001C60A__000000B8606C92A1-000000B8E03BF0B9", +"000000067F000080000009800C000001C60A-000000067F000080000009800C0000025D38__000000B8606C92A1-000000B8E03BF0B9", +"000000067F000080000009800C0000025D38-000000067F000080000009800C000002F49E__000000B8606C92A1-000000B8E03BF0B9", +"000000067F000080000009800C000002F49E-000000067F000080000009800C0000038BB1__000000B8606C92A1-000000B8E03BF0B9", +"000000067F000080000009800C0000038BB1-000000067F000080000009800C0000042317__000000B8606C92A1-000000B8E03BF0B9", +"000000067F000080000009800C0000042317-000000067F000080000009800C000004BA7D__000000B8606C92A1-000000B8E03BF0B9", +"000000067F000080000009800C000004BA7D-030000000000000000000000000000000002__000000B8606C92A1-000000B8E03BF0B9", +"000000067F000080000009800C000004BAD2-000000067F000080000009800C0000055206__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C0000055206-000000067F000080000009800C000005E911__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C000005E911-000000067F000080000009800C000006802B__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C000006802B-000000067F000080000009800C0000071782__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C0000071782-000000067F000080000009800C000007AEE8__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C000007AEE8-000000067F000080000009800C000008460B__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C000008460B-000000067F000080000009800C000008DD71__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C000008DD71-000000067F000080000009800C00000974D7__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C00000974D7-000000067F000080000009800C00000A0C0B__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C00000A0C0B-000000067F000080000009800C00000AA371__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C00000A8000-000000067F000080000009800C00000AC000__000000BA2E67EA20", +"000000067F000080000009800C00000AA371-000000067F000080000009800C0100000000__000000B8E03BF0B9-000000B97FFFFFE9", +"000000067F000080000009800C00000AA4F5-000000067F000080000009800C00000B3C0B__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C00000AC000-000000067F000080000009800C00000B0000__000000BA2E67EA20", +"000000067F000080000009800C00000B0000-000000067F000080000009800C00000B4000__000000BA2E67EA20", +"000000067F000080000009800C00000B3C0B-000000067F000080000009800C00000BD371__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C00000B4000-000000067F000080000009800C00000B8000__000000BA2E67EA20", +"000000067F000080000009800C00000B8000-000000067F000080000009800C00000BC000__000000BA2E67EA20", +"000000067F000080000009800C00000BC000-000000067F000080000009800C00000C0000__000000BA2E67EA20", +"000000067F000080000009800C00000BD371-000000067F000080000009800C00000C6AD7__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C00000C0000-000000067F000080000009800C00000C4000__000000BA2E67EA20", +"000000067F000080000009800C00000C4000-000000067F000080000009800C00000C8000__000000BA2E67EA20", +"000000067F000080000009800C00000C6AD7-000000067F000080000009800C00000D020B__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C00000C8000-000000067F000080000009800C00000CC000__000000BA2E67EA20", +"000000067F000080000009800C00000CC000-000000067F000080000009800C00000D0000__000000BA2E67EA20", +"000000067F000080000009800C00000D0000-000000067F000080000009800C00000D4000__000000BA2E67EA20", +"000000067F000080000009800C00000D020B-000000067F000080000009800C00000D9971__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C00000D4000-000000067F000080000009800C00000D8000__000000BA2E67EA20", +"000000067F000080000009800C00000D8000-000000067F000080000009800C00000DC000__000000BA2E67EA20", +"000000067F000080000009800C00000D9971-000000067F000080000009800C00000E30D7__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C00000DC000-000000067F000080000009800C00000E0000__000000BA2E67EA20", +"000000067F000080000009800C00000E0000-000000067F000080000009800C00000E4000__000000BA2E67EA20", +"000000067F000080000009800C00000E30D7-000000067F000080000009800C00000EC80B__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C00000E4000-000000067F000080000009800C00000E8000__000000BA2E67EA20", +"000000067F000080000009800C00000E8000-000000067F000080000009800C00000EC000__000000BA2E67EA20", +"000000067F000080000009800C00000EC000-000000067F000080000009800C00000F0000__000000BA2E67EA20", +"000000067F000080000009800C00000EC80B-000000067F000080000009800C00000F5F38__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C00000F0000-000000067F000080000009800C00000F4000__000000BA2E67EA20", +"000000067F000080000009800C00000F4000-000000067F000080000009800C00000F8000__000000BA2E67EA20", +"000000067F000080000009800C00000F5F38-000000067F000080000009800C00000FF69E__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C00000F8000-000000067F000080000009800C00000FC000__000000BA2E67EA20", +"000000067F000080000009800C00000FC000-000000067F000080000009800C0000100000__000000BA2E67EA20", +"000000067F000080000009800C00000FF69E-000000067F000080000009800C0000108DAF__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C0000100000-000000067F000080000009800C0000104000__000000BA2E67EA20", +"000000067F000080000009800C0000104000-000000067F000080000009800C0000108000__000000BA2E67EA20", +"000000067F000080000009800C0000108000-000000067F000080000009800C000010C000__000000BA2E67EA20", +"000000067F000080000009800C0000108DAF-000000067F000080000009800F0100000003__000000B97FFFFFE9-000000BA1FC3FB39", +"000000067F000080000009800C000010C000-000000067F000080000009800C0000110000__000000BA2E67EA20", +"000000067F000080000009800C000010EC71-000000067F000080000009801400000025C3__000000BA1FC3FB39-000000BA9685E7C1", +"000000067F000080000009800C0000110000-030000000000000000000000000000000002__000000BA2E67EA20", +"000000067F000080000009801400000025C3-000000067F0000800000098014000000A4D3__000000BA1FC3FB39-000000BA9685E7C1", +"000000067F0000800000098014000000A4D3-000000067F000080000009801400000123E4__000000BA1FC3FB39-000000BA9685E7C1", +"000000067F000080000009801400000123E4-000000067F0000800000098014000001A2F3__000000BA1FC3FB39-000000BA9685E7C1", +"000000067F0000800000098014000001A2F3-000000067F00008000000980140000022204__000000BA1FC3FB39-000000BA9685E7C1", +"000000067F00008000000980140000022204-000000067F0000800000098014000002A114__000000BA1FC3FB39-000000BA9685E7C1", +"000000067F0000800000098014000002A114-000000067F000080000009A00C0000004DB3__000000BA1FC3FB39-000000BA9685E7C1", +"000000067F000080000009A00C0000000000-000000067F000080000009A00C0000004000__000000BCEF79BE90", +"000000067F000080000009A00C0000004000-000000067F000080000009A00C0000008000__000000BCEF79BE90", +"000000067F000080000009A00C0000004DB3-030000000000000000000000000000000002__000000BA1FC3FB39-000000BA9685E7C1", +"000000067F000080000009A00C0000008000-000000067F000080000009A00C000000C000__000000BC59629F98", +"000000067F000080000009A00C0000008000-000000067F000080000009A00C000000C000__000000BD25E66810", +"000000067F000080000009A00C00000096E8-000000067F000080000009A00C0000012E0B__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C000000C000-000000067F000080000009A00C0000010000__000000BC59629F98", +"000000067F000080000009A00C000000C000-000000067F000080000009A00C0000010000__000000BD25E66810", +"000000067F000080000009A00C0000010000-000000067F000080000009A00C0000014000__000000BC59629F98", +"000000067F000080000009A00C0000010000-000000067F000080000009A00C0000014000__000000BD25E66810", +"000000067F000080000009A00C0000012E0B-000000067F000080000009A00C000001C571__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C0000014000-000000067F000080000009A00C0000018000__000000BC59629F98", +"000000067F000080000009A00C0000014000-000000067F000080000009A00C0000018000__000000BD25E66810", +"000000067F000080000009A00C0000018000-000000067F000080000009A00C000001C000__000000BC59629F98", +"000000067F000080000009A00C0000018000-000000067F000080000009A00C000001C000__000000BD25E66810", +"000000067F000080000009A00C000001C000-000000067F000080000009A00C0000020000__000000BC59629F98", +"000000067F000080000009A00C000001C000-000000067F000080000009A00C0000020000__000000BD25E66810", +"000000067F000080000009A00C000001C571-000000067F000080000009A00C0000025CD7__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C0000020000-000000067F000080000009A00C0000024000__000000BC59629F98", +"000000067F000080000009A00C0000020000-000000067F000080000009A00C0000024000__000000BD25E66810", +"000000067F000080000009A00C0000024000-000000067F000080000009A00C0000028000__000000BC59629F98", +"000000067F000080000009A00C0000024000-000000067F000080000009A00C0000028000__000000BD25E66810", +"000000067F000080000009A00C0000025CD7-000000067F000080000009A00C000002F40B__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C0000028000-000000067F000080000009A00C000002C000__000000BC59629F98", +"000000067F000080000009A00C0000028000-000000067F000080000009A00C000002C000__000000BD25E66810", +"000000067F000080000009A00C000002C000-000000067F000080000009A00C0000030000__000000BC59629F98", +"000000067F000080000009A00C000002C000-000000067F000080000009A00C0000030000__000000BD25E66810", +"000000067F000080000009A00C000002F40B-000000067F000080000009A00C0000038B1E__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C0000030000-000000067F000080000009A00C0000034000__000000BC59629F98", +"000000067F000080000009A00C0000030000-000000067F000080000009A00C0000034000__000000BD25E66810", +"000000067F000080000009A00C0000034000-000000067F000080000009A00C0000038000__000000BC59629F98", +"000000067F000080000009A00C0000034000-000000067F000080000009A00C0000038000__000000BD25E66810", +"000000067F000080000009A00C0000038000-000000067F000080000009A00C000003C000__000000BC59629F98", +"000000067F000080000009A00C0000038000-000000067F000080000009A00C000003C000__000000BD25E66810", +"000000067F000080000009A00C0000038B1E-000000067F000080000009A00C0000042284__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C000003C000-000000067F000080000009A00C0000040000__000000BC59629F98", +"000000067F000080000009A00C000003C000-000000067F000080000009A00C0000040000__000000BD25E66810", +"000000067F000080000009A00C0000040000-000000067F000080000009A00C0000044000__000000BC59629F98", +"000000067F000080000009A00C0000040000-000000067F000080000009A00C0000044000__000000BD25E66810", +"000000067F000080000009A00C0000042284-000000067F000080000009A00C000004B9EA__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C0000044000-000000067F000080000009A00C0000048000__000000BC59629F98", +"000000067F000080000009A00C0000044000-000000067F000080000009A00C0000048000__000000BD25E66810", +"000000067F000080000009A00C0000048000-000000067F000080000009A00C000004C000__000000BC59629F98", +"000000067F000080000009A00C0000048000-000000067F000080000009A00C000004C000__000000BD25E66810", +"000000067F000080000009A00C000004B9EA-000000067F000080000009A00C000005510B__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C000004C000-000000067F000080000009A00C0000050000__000000BC59629F98", +"000000067F000080000009A00C000004C000-000000067F000080000009A00C0000050000__000000BD25E66810", +"000000067F000080000009A00C0000050000-000000067F000080000009A00C0000054000__000000BC59629F98", +"000000067F000080000009A00C0000050000-000000067F000080000009A00C0000054000__000000BD25E66810", +"000000067F000080000009A00C0000054000-000000067F000080000009A00C0000058000__000000BC59629F98", +"000000067F000080000009A00C0000054000-000000067F000080000009A00C0000058000__000000BD25E66810", +"000000067F000080000009A00C000005510B-000000067F000080000009A00C000005E871__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C0000058000-000000067F000080000009A00C000005C000__000000BC59629F98", +"000000067F000080000009A00C0000058000-000000067F000080000009A00C000005C000__000000BD25E66810", +"000000067F000080000009A00C000005C000-000000067F000080000009A00C0000060000__000000BC59629F98", +"000000067F000080000009A00C000005C000-000000067F000080000009A00C0000060000__000000BD25E66810", +"000000067F000080000009A00C000005E871-000000067F000080000009A00C0000067F8B__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C0000060000-000000067F000080000009A00C0000064000__000000BC59629F98", +"000000067F000080000009A00C0000060000-000000067F000080000009A00C0000064000__000000BD25E66810", +"000000067F000080000009A00C0000064000-000000067F000080000009A00C0000068000__000000BC59629F98", +"000000067F000080000009A00C0000064000-000000067F000080000009A00C0000068000__000000BD25E66810", +"000000067F000080000009A00C0000067F8B-000000067F000080000009A00C00000716F1__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C0000068000-000000067F000080000009A00C000006C000__000000BC59629F98", +"000000067F000080000009A00C0000068000-000000067F000080000009A00C000006C000__000000BD25E66810", +"000000067F000080000009A00C000006C000-000000067F000080000009A00C0000070000__000000BC59629F98", +"000000067F000080000009A00C000006C000-000000067F000080000009A00C0000070000__000000BD25E66810", +"000000067F000080000009A00C0000070000-000000067F000080000009A00C0000074000__000000BC53F74828", +"000000067F000080000009A00C0000070000-000000067F000080000009A00C0000074000__000000BD25E66810", +"000000067F000080000009A00C00000716F1-000000067F000080000009A00C0100000000__000000BA9685E7C1-000000BB4643FBD1", +"000000067F000080000009A00C0000071875-000000067F000080000009A00C000007AFDB__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C0000071F8D-000000067F000080000009A00C00000E4F8F__000000BCEF79BE91-000000BD263A5849", +"000000067F000080000009A00C0000074000-000000067F000080000009A00C0000078000__000000BC53F74828", +"000000067F000080000009A00C0000074000-000000067F000080000009A00C0000078000__000000BD25E66810", +"000000067F000080000009A00C0000078000-000000067F000080000009A00C000007C000__000000BC53F74828", +"000000067F000080000009A00C0000078000-000000067F000080000009A00C000007C000__000000BD25E66810", +"000000067F000080000009A00C00000794E0-000000067F000080000009A00C00000F2480__000000BC596B5D59-000000BCEF79BE91", +"000000067F000080000009A00C000007AFDB-000000067F000080000009A00C000008470A__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C000007C000-000000067F000080000009A00C0000080000__000000BC53F74828", +"000000067F000080000009A00C000007C000-000000067F000080000009A00C0000080000__000000BD25E66810", +"000000067F000080000009A00C0000080000-000000067F000080000009A00C0000084000__000000BC53F74828", +"000000067F000080000009A00C0000080000-000000067F000080000009A00C0000084000__000000BD25E66810", +"000000067F000080000009A00C0000084000-000000067F000080000009A00C0000088000__000000BC53F74828", +"000000067F000080000009A00C0000084000-000000067F000080000009A00C0000088000__000000BD25E66810", +"000000067F000080000009A00C000008470A-000000067F000080000009A00C000008DE70__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C0000088000-000000067F000080000009A00C000008C000__000000BC53F74828", +"000000067F000080000009A00C0000088000-000000067F000080000009A00C000008C000__000000BD25E66810", +"000000067F000080000009A00C000008C000-000000067F000080000009A00C0000090000__000000BC53F74828", +"000000067F000080000009A00C000008C000-000000067F000080000009A00C0000090000__000000BD25E66810", +"000000067F000080000009A00C000008DE70-000000067F000080000009A00C0000097590__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C0000090000-000000067F000080000009A00C0000094000__000000BC53F74828", +"000000067F000080000009A00C0000090000-000000067F000080000009A00C0000094000__000000BD25E66810", +"000000067F000080000009A00C0000094000-000000067F000080000009A00C0000098000__000000BC53F74828", +"000000067F000080000009A00C0000094000-000000067F000080000009A00C0000098000__000000BD25E66810", +"000000067F000080000009A00C0000097590-000000067F000080000009A00C00000A0CF6__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C0000098000-000000067F000080000009A00C000009C000__000000BC53F74828", +"000000067F000080000009A00C0000098000-000000067F000080000009A00C000009C000__000000BD25E66810", +"000000067F000080000009A00C000009C000-000000067F000080000009A00C00000A0000__000000BC53F74828", +"000000067F000080000009A00C000009C000-000000067F000080000009A00C00000A0000__000000BD25E66810", +"000000067F000080000009A00C00000A0000-000000067F000080000009A00C00000A4000__000000BC53F74828", +"000000067F000080000009A00C00000A0000-000000067F000080000009A00C00000A4000__000000BD25E66810", +"000000067F000080000009A00C00000A0CF6-000000067F000080000009A00C00000AA40B__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C00000A4000-000000067F000080000009A00C00000A8000__000000BC53F74828", +"000000067F000080000009A00C00000A4000-000000067F000080000009A00C00000A8000__000000BD25E66810", +"000000067F000080000009A00C00000A8000-000000067F000080000009A00C00000AC000__000000BC53F74828", +"000000067F000080000009A00C00000A8000-000000067F000080000009A00C00000AC000__000000BD25E66810", +"000000067F000080000009A00C00000AA40B-000000067F000080000009A00C00000B3B4D__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C00000AC000-000000067F000080000009A00C00000B0000__000000BC53F74828", +"000000067F000080000009A00C00000AC000-000000067F000080000009A00C00000B0000__000000BD25E66810", +"000000067F000080000009A00C00000B0000-000000067F000080000009A00C00000B4000__000000BC53F74828", +"000000067F000080000009A00C00000B0000-000000067F000080000009A00C00000B4000__000000BD25E66810", +"000000067F000080000009A00C00000B3B4D-000000067F000080000009A00C00000BD2B3__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C00000B4000-000000067F000080000009A00C00000B8000__000000BC53F74828", +"000000067F000080000009A00C00000B4000-000000067F000080000009A00C00000B8000__000000BD25E66810", +"000000067F000080000009A00C00000B8000-000000067F000080000009A00C00000BC000__000000BC53F74828", +"000000067F000080000009A00C00000B8000-000000067F000080000009A00C00000BC000__000000BD25E66810", +"000000067F000080000009A00C00000BC000-000000067F000080000009A00C00000C0000__000000BC53F74828", +"000000067F000080000009A00C00000BC000-000000067F000080000009A00C00000C0000__000000BD25E66810", +"000000067F000080000009A00C00000BD2B3-000000067F000080000009A00C00000C69D9__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C00000C0000-000000067F000080000009A00C00000C4000__000000BC53F74828", +"000000067F000080000009A00C00000C0000-000000067F000080000009A00C00000C4000__000000BD25E66810", +"000000067F000080000009A00C00000C4000-000000067F000080000009A00C00000C8000__000000BC53F74828", +"000000067F000080000009A00C00000C4000-000000067F000080000009A00C00000C8000__000000BD25E66810", +"000000067F000080000009A00C00000C69D9-000000067F000080000009A00C00000D010C__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C00000C8000-000000067F000080000009A00C00000CC000__000000BC53F74828", +"000000067F000080000009A00C00000C8000-000000067F000080000009A00C00000CC000__000000BD25E66810", +"000000067F000080000009A00C00000CC000-000000067F000080000009A00C00000D0000__000000BC53F74828", +"000000067F000080000009A00C00000CC000-000000067F000080000009A00C00000D0000__000000BD25E66810", +"000000067F000080000009A00C00000D0000-000000067F000080000009A00C00000D4000__000000BC53F74828", +"000000067F000080000009A00C00000D0000-000000067F000080000009A00C00000D4000__000000BD25E66810", +"000000067F000080000009A00C00000D010C-000000067F000080000009A00C0100000000__000000BB4643FBD1-000000BBE607E8F1", +"000000067F000080000009A00C00000D4000-000000067F000080000009A00C00000D8000__000000BC53F74828", +"000000067F000080000009A00C00000D4000-000000067F000080000009A00C00000D8000__000000BD25E66810", +"000000067F000080000009A00C00000D6C06-000000067F000080000009A00C00000E0166__000000BBE607E8F1-000000BC596B5D59", +"000000067F000080000009A00C00000D8000-000000067F000080000009A00C00000DC000__000000BC53F74828", +"000000067F000080000009A00C00000D8000-000000067F000080000009A00C00000DC000__000000BD25E66810", +"000000067F000080000009A00C00000DC000-000000067F000080000009A00C00000E0000__000000BC53F74828", +"000000067F000080000009A00C00000DC000-000000067F000080000009A00C00000E0000__000000BD25E66810", +"000000067F000080000009A00C00000E0000-000000067F000080000009A00C00000E4000__000000BC53F74828", +"000000067F000080000009A00C00000E0000-000000067F000080000009A00C00000E4000__000000BD25E66810", +"000000067F000080000009A00C00000E0166-000000067F000080000009A00C00000E96C9__000000BBE607E8F1-000000BC596B5D59", +"000000067F000080000009A00C00000E4000-000000067F000080000009A00C00000E8000__000000BC53F74828", +"000000067F000080000009A00C00000E4000-000000067F000080000009A00C00000E8000__000000BD25E66810", +"000000067F000080000009A00C00000E4F97-000000067F000080000009A0140000019842__000000BCEF79BE91-000000BD263A5849", +"000000067F000080000009A00C00000E8000-000000067F000080000009A00C00000EC000__000000BC53F74828", +"000000067F000080000009A00C00000E8000-000000067F000080000009A00C00000EC000__000000BD25E66810", +"000000067F000080000009A00C00000E96C9-000000067F000080000009A00C00000F2C2B__000000BBE607E8F1-000000BC596B5D59", +"000000067F000080000009A00C00000EC000-000000067F000080000009A00C00000F0000__000000BC53F74828", +"000000067F000080000009A00C00000EC000-000000067F000080000009A00C00000F0000__000000BD25E66810", +"000000067F000080000009A00C00000F0000-000000067F000080000009A00C00000F4000__000000BC53F74828", +"000000067F000080000009A00C00000F0000-000000067F000080000009A00C00000F4000__000000BD25E66810", +"000000067F000080000009A00C00000F248B-000000067F000080000009A0140000004031__000000BC596B5D59-000000BCEF79BE91", +"000000067F000080000009A00C00000F2C2B-000000067F000080000009A00C00000FC18E__000000BBE607E8F1-000000BC596B5D59", +"000000067F000080000009A00C00000F4000-000000067F000080000009A00C00000F8000__000000BC53F74828", +"000000067F000080000009A00C00000F4000-000000067F000080000009A00C00000F8000__000000BD25E66810", +"000000067F000080000009A00C00000F8000-000000067F000080000009A00C00000FC000__000000BC53F74828", +"000000067F000080000009A00C00000F8000-000000067F000080000009A00C00000FC000__000000BD25E66810", +"000000067F000080000009A00C00000FC000-000000067F000080000009A00C0000100000__000000BC53F74828", +"000000067F000080000009A00C00000FC000-000000067F000080000009A00C0000100000__000000BD25E66810", +"000000067F000080000009A00C00000FC18E-000000067F000080000009A00C00001056F2__000000BBE607E8F1-000000BC596B5D59", +"000000067F000080000009A00C0000100000-000000067F000080000009A00C0000104000__000000BC53F74828", +"000000067F000080000009A00C0000100000-000000067F000080000009A00C0000104000__000000BD25E66810", +"000000067F000080000009A00C0000104000-000000067F000080000009A00C0000108000__000000BC53F74828", +"000000067F000080000009A00C0000104000-000000067F000080000009A00C0000108000__000000BD25E66810", +"000000067F000080000009A00C00001056F2-000000067F000080000009A00C000010EC54__000000BBE607E8F1-000000BC596B5D59", +"000000067F000080000009A00C0000108000-000000067F000080000009A00C000010C000__000000BC53F74828", +"000000067F000080000009A00C0000108000-000000067F000080000009A00C000010C000__000000BD25E66810", +"000000067F000080000009A00C000010C000-000000067F000080000009A00C0000110000__000000BC53F74828", +"000000067F000080000009A00C000010C000-000000067F000080000009A00C0000110000__000000BD25E66810", +"000000067F000080000009A00C000010EC54-010000000000000001000000040000000020__000000BBE607E8F1-000000BC596B5D59", +"000000067F000080000009A00C0000110000-000000067F000080000009A0120100000000__000000BD25E66810", +"000000067F000080000009A00C0000110000-030000000000000000000000000000000002__000000BC53F74828", +"000000067F000080000009A0140000000000-000000067F000080000009A0140000004000__000000BD25E66810", +"000000067F000080000009A0140000004000-000000067F000080000009A0140000008000__000000BD25E66810", +"000000067F000080000009A0140000004031-000000067F000080000009A0140000009FC7__000000BC596B5D59-000000BCEF79BE91", +"000000067F000080000009A0140000008000-000000067F000080000009A014000000C000__000000BD25E66810", +"000000067F000080000009A0140000009FC7-000000067F000080000009A014000000FF53__000000BC596B5D59-000000BCEF79BE91", +"000000067F000080000009A014000000C000-000000067F000080000009A0140000010000__000000BD25E66810", +"000000067F000080000009A014000000FF53-000000067F000080000009A0140000015F1C__000000BC596B5D59-000000BCEF79BE91", +"000000067F000080000009A0140000010000-000000067F000080000009A0140000014000__000000BD25E66810", +"000000067F000080000009A0140000014000-000000067F000080000009A0140000018000__000000BD25E66810", +"000000067F000080000009A0140000015F1C-000000067F000080000009A014000001BED0__000000BC596B5D59-000000BCEF79BE91", +"000000067F000080000009A0140000018000-000000067F000080000009A014000001C000__000000BD25E66810", +"000000067F000080000009A0140000019844-030000000000000000000000000000000002__000000BCEF79BE91-000000BD263A5849", +"000000067F000080000009A014000001BED0-000000067F000080000009A0140000021E6C__000000BC596B5D59-000000BCEF79BE91", +"000000067F000080000009A014000001C000-000000067F000080000009A0140000020000__000000BD25E66810", +"000000067F000080000009A0140000020000-000000067F000080000009A0140000024000__000000BD25E66810", +"000000067F000080000009A0140000021E6C-000000067F000080000009A0140000027DB1__000000BC596B5D59-000000BCEF79BE91", +"000000067F000080000009A0140000024000-000000067F000080000009A0140000028000__000000BD25E66810", +"000000067F000080000009A0140000027DB1-000000067F000080000009A014000002DC9E__000000BC596B5D59-000000BCEF79BE91", +"000000067F000080000009A0140000028000-000000067F000080000009A014000002C000__000000BD25E66810", +"000000067F000080000009A014000002C000-030000000000000000000000000000000002__000000BD25E66810", +"000000067F000080000009A01400FFFFFFFF-030000000000000000000000000000000002__000000BC596B5D59-000000BCEF79BE91", +"000000067F000080000009C00C0000000000-000000067F000080000009C00C0000004000__000000BEF683BFD0", +"000000067F000080000009C00C0000004000-000000067F000080000009C00C0000008000__000000BEF683BFD0", +"000000067F000080000009C00C0000008000-000000067F000080000009C00C000000C000__000000BEF683BFD0", +"000000067F000080000009C00C0000009749-000000067F000080000009C00C0000012EAF__000000BD263A5849-000000BDA607F261", +"000000067F000080000009C00C000000C000-000000067F000080000009C00C0000010000__000000BEF683BFD0", +"000000067F000080000009C00C0000010000-000000067F000080000009C00C0000014000__000000BEF683BFD0", +"000000067F000080000009C00C0000012EAF-000000067F000080000009C00C000001C60B__000000BD263A5849-000000BDA607F261", +"000000067F000080000009C00C0000014000-000000067F000080000009C00C0000018000__000000BEF683BFD0", +"000000067F000080000009C00C0000018000-000000067F000080000009C00C000001C000__000000BEF683BFD0", +"000000067F000080000009C00C000001C000-000000067F000080000009C00C0000020000__000000BEF683BFD0", +"000000067F000080000009C00C000001C60B-000000067F000080000009C00C0000025D39__000000BD263A5849-000000BDA607F261", +"000000067F000080000009C00C0000020000-000000067F000080000009C00C0000024000__000000BEF683BFD0", +"000000067F000080000009C00C0000024000-000000067F000080000009C00C0000028000__000000BEF683BFD0", +"000000067F000080000009C00C0000025D39-000000067F000080000009C00C000002F49F__000000BD263A5849-000000BDA607F261", +"000000067F000080000009C00C0000028000-000000067F000080000009C00C000002C000__000000BEF683BFD0", +"000000067F000080000009C00C000002C000-000000067F000080000009C00C0000030000__000000BEF683BFD0", +"000000067F000080000009C00C000002F49F-000000067F000080000009C00C0000038BB2__000000BD263A5849-000000BDA607F261", +"000000067F000080000009C00C0000030000-000000067F000080000009C00C0000034000__000000BEF683BFD0", +"000000067F000080000009C00C0000034000-000000067F000080000009C00C0000038000__000000BEF683BFD0", +"000000067F000080000009C00C0000038000-000000067F000080000009C00C000003C000__000000BEF683BFD0", +"000000067F000080000009C00C0000038BB2-000000067F000080000009C00C0000042318__000000BD263A5849-000000BDA607F261", +"000000067F000080000009C00C000003C000-000000067F000080000009C00C0000040000__000000BEF683BFD0", +"000000067F000080000009C00C0000040000-000000067F000080000009C00C0000044000__000000BEF683BFD0", +"000000067F000080000009C00C0000042318-000000067F000080000009C00C000004BA7E__000000BD263A5849-000000BDA607F261", +"000000067F000080000009C00C0000044000-000000067F000080000009C00C0000048000__000000BEF683BFD0", +"000000067F000080000009C00C0000048000-000000067F000080000009C00C000004C000__000000BEF06884C8", +"000000067F000080000009C00C000004BA7E-030000000000000000000000000000000002__000000BD263A5849-000000BDA607F261", +"000000067F000080000009C00C000004BAC3-000000067F000080000009C00C00000551F8__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C000004C000-000000067F000080000009C00C0000050000__000000BEF06884C8", +"000000067F000080000009C00C0000050000-000000067F000080000009C00C0000054000__000000BEF06884C8", +"000000067F000080000009C00C0000054000-000000067F000080000009C00C0000058000__000000BEF06884C8", +"000000067F000080000009C00C00000551F8-000000067F000080000009C00C000005E90C__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C0000058000-000000067F000080000009C00C000005C000__000000BEF06884C8", +"000000067F000080000009C00C000005C000-000000067F000080000009C00C0000060000__000000BEF06884C8", +"000000067F000080000009C00C000005E90C-000000067F000080000009C00C000006802C__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C0000060000-000000067F000080000009C00C0000064000__000000BEF06884C8", +"000000067F000080000009C00C0000064000-000000067F000080000009C00C0000068000__000000BEF06884C8", +"000000067F000080000009C00C0000068000-000000067F000080000009C00C000006C000__000000BEF06884C8", +"000000067F000080000009C00C000006802C-000000067F000080000009C00C0000071783__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C000006C000-000000067F000080000009C00C0000070000__000000BEF06884C8", +"000000067F000080000009C00C0000070000-000000067F000080000009C00C0000074000__000000BEF06884C8", +"000000067F000080000009C00C0000071783-000000067F000080000009C00C000007AEE9__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C0000074000-000000067F000080000009C00C0000078000__000000BEF06884C8", +"000000067F000080000009C00C0000078000-000000067F000080000009C00C000007C000__000000BEF06884C8", +"000000067F000080000009C00C000007AEE9-000000067F000080000009C00C000008460B__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C000007C000-000000067F000080000009C00C0000080000__000000BEF06884C8", +"000000067F000080000009C00C0000080000-000000067F000080000009C00C0000084000__000000BEF06884C8", +"000000067F000080000009C00C0000084000-000000067F000080000009C00C0000088000__000000BEF06884C8", +"000000067F000080000009C00C000008460B-000000067F000080000009C00C000008DD71__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C0000088000-000000067F000080000009C00C000008C000__000000BEF06884C8", +"000000067F000080000009C00C000008C000-000000067F000080000009C00C0000090000__000000BEF06884C8", +"000000067F000080000009C00C000008DD71-000000067F000080000009C00C00000974D7__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C0000090000-000000067F000080000009C00C0000094000__000000BEF06884C8", +"000000067F000080000009C00C0000094000-000000067F000080000009C00C0000098000__000000BEF06884C8", +"000000067F000080000009C00C00000974D7-000000067F000080000009C00C00000A0C0B__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C0000098000-000000067F000080000009C00C000009C000__000000BEF06884C8", +"000000067F000080000009C00C000009C000-000000067F000080000009C00C00000A0000__000000BEF06884C8", +"000000067F000080000009C00C00000A0000-000000067F000080000009C00C00000A4000__000000BEF06884C8", +"000000067F000080000009C00C00000A0C0B-000000067F000080000009C00C00000AA371__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C00000A4000-000000067F000080000009C00C00000A8000__000000BEF06884C8", +"000000067F000080000009C00C00000A8000-000000067F000080000009C00C00000AC000__000000BEF06884C8", +"000000067F000080000009C00C00000AA371-000000067F000080000009C00C0100000000__000000BDA607F261-000000BE45CBFBB9", +"000000067F000080000009C00C00000AC000-000000067F000080000009C00C00000B0000__000000BEF06884C8", +"000000067F000080000009C00C00000B0000-000000067F000080000009C00C00000B4000__000000BEF06884C8", +"000000067F000080000009C00C00000B2921-000000067F000080000009C00C00000BC087__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009C00C00000B4000-000000067F000080000009C00C00000B8000__000000BEF06884C8", +"000000067F000080000009C00C00000B8000-000000067F000080000009C00C00000BC000__000000BEF06884C8", +"000000067F000080000009C00C00000BC000-000000067F000080000009C00C00000C0000__000000BEF06884C8", +"000000067F000080000009C00C00000BC087-000000067F000080000009C00C00000C57B8__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009C00C00000C0000-000000067F000080000009C00C00000C4000__000000BEF06884C8", +"000000067F000080000009C00C00000C4000-000000067F000080000009C00C00000C8000__000000BEF06884C8", +"000000067F000080000009C00C00000C57B8-000000067F000080000009C00C00000CEF09__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009C00C00000C8000-000000067F000080000009C00C00000CC000__000000BEF06884C8", +"000000067F000080000009C00C00000CC000-000000067F000080000009C00C00000D0000__000000BEF06884C8", +"000000067F000080000009C00C00000CEF09-000000067F000080000009C00C00000D862B__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009C00C00000D0000-000000067F000080000009C00C00000D4000__000000BEF06884C8", +"000000067F000080000009C00C00000D4000-000000067F000080000009C00C00000D8000__000000BEF06884C8", +"000000067F000080000009C00C00000D8000-000000067F000080000009C00C00000DC000__000000BEF06884C8", +"000000067F000080000009C00C00000D862B-000000067F000080000009C00C00000E1D7F__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009C00C00000DC000-000000067F000080000009C00C00000E0000__000000BEF06884C8", +"000000067F000080000009C00C00000E0000-000000067F000080000009C00C00000E4000__000000BEF06884C8", +"000000067F000080000009C00C00000E1D7F-000000067F000080000009C00C00000EB4E5__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009C00C00000E4000-000000067F000080000009C00C00000E8000__000000BEF06884C8", +"000000067F000080000009C00C00000E8000-000000067F000080000009C00C00000EC000__000000BEF06884C8", +"000000067F000080000009C00C00000EB4E5-000000067F000080000009C00C00000F4C0B__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009C00C00000EC000-000000067F000080000009C00C00000F0000__000000BEF06884C8", +"000000067F000080000009C00C00000F0000-000000067F000080000009C00C00000F4000__000000BEF06884C8", +"000000067F000080000009C00C00000F4000-000000067F000080000009C00C00000F8000__000000BEF06884C8", +"000000067F000080000009C00C00000F4C0B-000000067F000080000009C00C00000FE371__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009C00C00000F8000-000000067F000080000009C00C00000FC000__000000BEF06884C8", +"000000067F000080000009C00C00000FC000-000000067F000080000009C00C0000100000__000000BEF06884C8", +"000000067F000080000009C00C00000FE371-000000067F000080000009C00C0000107AD7__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009C00C0000100000-000000067F000080000009C00C0000104000__000000BEF06884C8", +"000000067F000080000009C00C0000104000-000000067F000080000009C00C0000108000__000000BEF06884C8", +"000000067F000080000009C00C0000107AD7-000000067F000080000009C00C000011120B__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009C00C0000108000-000000067F000080000009C00C000010C000__000000BEF06884C8", +"000000067F000080000009C00C000010C000-030000000000000000000000000000000002__000000BEF06884C8", +"000000067F000080000009C00C000011120B-010000000000000001000000050000000003__000000BE45CBFBB9-000000BEF5F47FD1", +"000000067F000080000009E00C0000000000-000000067F000080000009E00C0000004000__000000C0C9769FD8", +"000000067F000080000009E00C0000004000-000000067F000080000009E00C0000008000__000000C0C9769FD8", +"000000067F000080000009E00C0000004916-000000067F000080000009E00C000000E07C__000000BEF5F47FD1-000000BF48FFEB11", +"000000067F000080000009E00C0000008000-000000067F000080000009E00C000000C000__000000C0C9769FD8", +"000000067F000080000009E00C000000C000-000000067F000080000009E00C0000010000__000000C0C9769FD8", +"000000067F000080000009E00C000000E07C-000000067F000080000009E00C000001779A__000000BEF5F47FD1-000000BF48FFEB11", +"000000067F000080000009E00C0000010000-000000067F000080000009E00C0000014000__000000C0C9769FD8", +"000000067F000080000009E00C0000014000-000000067F000080000009E00C0000018000__000000C0C9769FD8", +"000000067F000080000009E00C000001779A-000000067F000080000009E00C0000020F00__000000BEF5F47FD1-000000BF48FFEB11", +"000000067F000080000009E00C0000018000-000000067F000080000009E00C000001C000__000000C0C9769FD8", +"000000067F000080000009E00C000001C000-000000067F000080000009E00C0000020000__000000C0C9769FD8", +"000000067F000080000009E00C0000020000-000000067F000080000009E00C0000024000__000000C0C9769FD8", +"000000067F000080000009E00C0000020F00-000000067F000080000009E00C000002A60B__000000BEF5F47FD1-000000BF48FFEB11", +"000000067F000080000009E00C0000024000-000000067F000080000009E00C0000028000__000000C0C9769FD8", +"000000067F000080000009E00C0000028000-000000067F000080000009E00C000002C000__000000C0C9769FD8", +"000000067F000080000009E00C000002A60B-030000000000000000000000000000000002__000000BEF5F47FD1-000000BF48FFEB11", +"000000067F000080000009E00C000002C000-000000067F000080000009E00C0000030000__000000C0B597E900", +"000000067F000080000009E00C000002C000-000000067F000080000009E00C0000030000__000000C1972392A8", +"000000067F000080000009E00C000002F506-000000067F000080000009E00C0000038C11__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C0000030000-000000067F000080000009E00C0000034000__000000C0B597E900", +"000000067F000080000009E00C0000030000-000000067F000080000009E00C0000034000__000000C1972392A8", +"000000067F000080000009E00C0000034000-000000067F000080000009E00C0000038000__000000C0B597E900", +"000000067F000080000009E00C0000034000-000000067F000080000009E00C0000038000__000000C1972392A8", +"000000067F000080000009E00C0000038000-000000067F000080000009E00C000003C000__000000C0B597E900", +"000000067F000080000009E00C0000038000-000000067F000080000009E00C000003C000__000000C1972392A8", +"000000067F000080000009E00C0000038C11-000000067F000080000009E00C0000042361__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C000003C000-000000067F000080000009E00C0000040000__000000C0B597E900", +"000000067F000080000009E00C000003C000-000000067F000080000009E00C0000040000__000000C1972392A8", +"000000067F000080000009E00C0000040000-000000067F000080000009E00C0000044000__000000C0B597E900", +"000000067F000080000009E00C0000040000-000000067F000080000009E00C0000044000__000000C1972392A8", +"000000067F000080000009E00C0000042361-000000067F000080000009E00C000004BAC7__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C0000044000-000000067F000080000009E00C0000048000__000000C0B597E900", +"000000067F000080000009E00C0000044000-000000067F000080000009E00C0000048000__000000C1972392A8", +"000000067F000080000009E00C0000048000-000000067F000080000009E00C000004C000__000000C0B597E900", +"000000067F000080000009E00C0000048000-000000067F000080000009E00C000004C000__000000C1972392A8", +"000000067F000080000009E00C000004BAC7-000000067F000080000009E00C00000551FC__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C000004C000-000000067F000080000009E00C0000050000__000000C0B597E900", +"000000067F000080000009E00C000004C000-000000067F000080000009E00C0000050000__000000C1972392A8", +"000000067F000080000009E00C0000050000-000000067F000080000009E00C0000054000__000000C0B597E900", +"000000067F000080000009E00C0000050000-000000067F000080000009E00C0000054000__000000C1972392A8", +"000000067F000080000009E00C0000050E89-000000067F000080000009E00C00000A18A0__000000C1426D92E1-000000C19744E959", +"000000067F000080000009E00C0000054000-000000067F000080000009E00C0000058000__000000C0B597E900", +"000000067F000080000009E00C0000054000-000000067F000080000009E00C0000058000__000000C1972392A8", +"000000067F000080000009E00C00000551FC-000000067F000080000009E00C000005E90B__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C0000058000-000000067F000080000009E00C000005C000__000000C0B597E900", +"000000067F000080000009E00C0000058000-000000067F000080000009E00C000005C000__000000C1972392A8", +"000000067F000080000009E00C000005C000-000000067F000080000009E00C0000060000__000000C0B597E900", +"000000067F000080000009E00C000005C000-000000067F000080000009E00C0000060000__000000C1972392A8", +"000000067F000080000009E00C000005E90B-000000067F000080000009E00C000006802B__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C0000060000-000000067F000080000009E00C0000064000__000000C0B597E900", +"000000067F000080000009E00C0000060000-000000067F000080000009E00C0000064000__000000C1972392A8", +"000000067F000080000009E00C0000064000-000000067F000080000009E00C0000068000__000000C0B597E900", +"000000067F000080000009E00C0000064000-000000067F000080000009E00C0000068000__000000C1972392A8", +"000000067F000080000009E00C0000068000-000000067F000080000009E00C000006C000__000000C0B597E900", +"000000067F000080000009E00C0000068000-000000067F000080000009E00C000006C000__000000C1972392A8", +"000000067F000080000009E00C000006802B-000000067F000080000009E00C0000071782__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C000006C000-000000067F000080000009E00C0000070000__000000C0B597E900", +"000000067F000080000009E00C000006C000-000000067F000080000009E00C0000070000__000000C1972392A8", +"000000067F000080000009E00C0000070000-000000067F000080000009E00C0000074000__000000C0B597E900", +"000000067F000080000009E00C0000070000-000000067F000080000009E00C0000074000__000000C1972392A8", +"000000067F000080000009E00C0000071782-000000067F000080000009E00C000007AEE8__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C0000074000-000000067F000080000009E00C0000078000__000000C0B597E900", +"000000067F000080000009E00C0000074000-000000067F000080000009E00C0000078000__000000C1972392A8", +"000000067F000080000009E00C0000078000-000000067F000080000009E00C000007C000__000000C0B597E900", +"000000067F000080000009E00C0000078000-000000067F000080000009E00C000007C000__000000C1972392A8", +"000000067F000080000009E00C000007AEE8-000000067F000080000009E00C000008460B__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C000007C000-000000067F000080000009E00C0000080000__000000C0B597E900", +"000000067F000080000009E00C000007C000-000000067F000080000009E00C0000080000__000000C1972392A8", +"000000067F000080000009E00C0000080000-000000067F000080000009E00C0000084000__000000C0B597E900", +"000000067F000080000009E00C0000080000-000000067F000080000009E00C0000084000__000000C1972392A8", +"000000067F000080000009E00C0000084000-000000067F000080000009E00C0000088000__000000C0B597E900", +"000000067F000080000009E00C0000084000-000000067F000080000009E00C0000088000__000000C1972392A8", +"000000067F000080000009E00C000008460B-000000067F000080000009E00C000008DD71__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C0000088000-000000067F000080000009E00C000008C000__000000C0B597E900", +"000000067F000080000009E00C0000088000-000000067F000080000009E00C000008C000__000000C1972392A8", +"000000067F000080000009E00C000008C000-000000067F000080000009E00C0000090000__000000C0B597E900", +"000000067F000080000009E00C000008C000-000000067F000080000009E00C0000090000__000000C1972392A8", +"000000067F000080000009E00C000008DD71-000000067F000080000009E00C00000974D7__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C0000090000-000000067F000080000009E00C0000094000__000000C0B597E900", +"000000067F000080000009E00C0000090000-000000067F000080000009E00C0000094000__000000C1972392A8", +"000000067F000080000009E00C0000094000-000000067F000080000009E00C0000098000__000000C0B597E900", +"000000067F000080000009E00C0000094000-000000067F000080000009E00C0000098000__000000C1972392A8", +"000000067F000080000009E00C00000974D7-000000067F000080000009E00C0100000000__000000BF48FFEB11-000000BFF8BDFEE9", +"000000067F000080000009E00C0000098000-000000067F000080000009E00C000009C000__000000C0B597E900", +"000000067F000080000009E00C0000098000-000000067F000080000009E00C000009C000__000000C1972392A8", +"000000067F000080000009E00C000009C000-000000067F000080000009E00C00000A0000__000000C0B597E900", +"000000067F000080000009E00C000009C000-000000067F000080000009E00C00000A0000__000000C1972392A8", +"000000067F000080000009E00C000009FB21-000000067F000080000009E00C00000A9230__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C00000A0000-000000067F000080000009E00C00000A4000__000000C0B597E900", +"000000067F000080000009E00C00000A0000-000000067F000080000009E00C00000A4000__000000C1972392A8", +"000000067F000080000009E00C00000A18A4-000000067F000080000009E00C00000F2B76__000000C1426D92E1-000000C19744E959", +"000000067F000080000009E00C00000A4000-000000067F000080000009E00C00000A8000__000000C0B597E900", +"000000067F000080000009E00C00000A4000-000000067F000080000009E00C00000A8000__000000C1972392A8", +"000000067F000080000009E00C00000A8000-000000067F000080000009E00C00000AC000__000000C0B597E900", +"000000067F000080000009E00C00000A8000-000000067F000080000009E00C00000AC000__000000C1972392A8", +"000000067F000080000009E00C00000A9230-000000067F000080000009E00C00000B297D__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C00000AC000-000000067F000080000009E00C00000B0000__000000C0B597E900", +"000000067F000080000009E00C00000AC000-000000067F000080000009E00C00000B0000__000000C1972392A8", +"000000067F000080000009E00C00000B0000-000000067F000080000009E00C00000B4000__000000C0B597E900", +"000000067F000080000009E00C00000B0000-000000067F000080000009E00C00000B4000__000000C1972392A8", +"000000067F000080000009E00C00000B297D-000000067F000080000009E00C00000BC0E3__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C00000B4000-000000067F000080000009E00C00000B8000__000000C0B597E900", +"000000067F000080000009E00C00000B4000-000000067F000080000009E00C00000B8000__000000C1972392A8", +"000000067F000080000009E00C00000B8000-000000067F000080000009E00C00000BC000__000000C0B597E900", +"000000067F000080000009E00C00000B8000-000000067F000080000009E00C00000BC000__000000C1972392A8", +"000000067F000080000009E00C00000BC000-000000067F000080000009E00C00000C0000__000000C0B597E900", +"000000067F000080000009E00C00000BC000-000000067F000080000009E00C00000C0000__000000C1972392A8", +"000000067F000080000009E00C00000BC0E3-000000067F000080000009E00C00000C580C__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C00000C0000-000000067F000080000009E00C00000C4000__000000C0B597E900", +"000000067F000080000009E00C00000C0000-000000067F000080000009E00C00000C4000__000000C1972392A8", +"000000067F000080000009E00C00000C0C74-000000067F000080000009E0140000001880__000000C0C8CA5FF1-000000C1426D92E1", +"000000067F000080000009E00C00000C4000-000000067F000080000009E00C00000C8000__000000C0B597E900", +"000000067F000080000009E00C00000C4000-000000067F000080000009E00C00000C8000__000000C1972392A8", +"000000067F000080000009E00C00000C580C-000000067F000080000009E00C00000CEF71__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C00000C8000-000000067F000080000009E00C00000CC000__000000C0B597E900", +"000000067F000080000009E00C00000C8000-000000067F000080000009E00C00000CC000__000000C1972392A8", +"000000067F000080000009E00C00000CC000-000000067F000080000009E00C00000D0000__000000C0B597E900", +"000000067F000080000009E00C00000CC000-000000067F000080000009E00C00000D0000__000000C1972392A8", +"000000067F000080000009E00C00000CEF71-000000067F000080000009E00C00000D86D7__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C00000D0000-000000067F000080000009E00C00000D4000__000000C0B597E900", +"000000067F000080000009E00C00000D0000-000000067F000080000009E00C00000D4000__000000C1972392A8", +"000000067F000080000009E00C00000D4000-000000067F000080000009E00C00000D8000__000000C0B597E900", +"000000067F000080000009E00C00000D4000-000000067F000080000009E00C00000D8000__000000C1972392A8", +"000000067F000080000009E00C00000D8000-000000067F000080000009E00C00000DC000__000000C0B597E900", +"000000067F000080000009E00C00000D8000-000000067F000080000009E00C00000DC000__000000C1972392A8", +"000000067F000080000009E00C00000D86D7-000000067F000080000009E00C00000E1E0C__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C00000DC000-000000067F000080000009E00C00000E0000__000000C0B597E900", +"000000067F000080000009E00C00000DC000-000000067F000080000009E00C00000E0000__000000C1972392A8", +"000000067F000080000009E00C00000E0000-000000067F000080000009E00C00000E4000__000000C0B597E900", +"000000067F000080000009E00C00000E0000-000000067F000080000009E00C00000E4000__000000C1972392A8", +"000000067F000080000009E00C00000E1E0C-000000067F000080000009E00C00000EB572__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C00000E4000-000000067F000080000009E00C00000E8000__000000C0B597E900", +"000000067F000080000009E00C00000E4000-000000067F000080000009E00C00000E8000__000000C1972392A8", +"000000067F000080000009E00C00000E8000-000000067F000080000009E00C00000EC000__000000C0B597E900", +"000000067F000080000009E00C00000E8000-000000067F000080000009E00C00000EC000__000000C1972392A8", +"000000067F000080000009E00C00000EB572-000000067F000080000009E00C00000F4CD8__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C00000EC000-000000067F000080000009E00C00000F0000__000000C0B597E900", +"000000067F000080000009E00C00000EC000-000000067F000080000009E00C00000F0000__000000C1972392A8", +"000000067F000080000009E00C00000F0000-000000067F000080000009E00C00000F4000__000000C0B597E900", +"000000067F000080000009E00C00000F0000-000000067F000080000009E00C00000F4000__000000C1972392A8", +"000000067F000080000009E00C00000F2B77-000000067F000080000009E014000000D3EB__000000C1426D92E1-000000C19744E959", +"000000067F000080000009E00C00000F4000-000000067F000080000009E00C00000F8000__000000C0B597E900", +"000000067F000080000009E00C00000F4000-000000067F000080000009E00C00000F8000__000000C1972392A8", +"000000067F000080000009E00C00000F4CD8-000000067F000080000009E00C00000FE40B__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C00000F8000-000000067F000080000009E00C00000FC000__000000C0B597E900", +"000000067F000080000009E00C00000F8000-000000067F000080000009E00C00000FC000__000000C1972392A8", +"000000067F000080000009E00C00000FC000-000000067F000080000009E00C0000100000__000000C0B597E900", +"000000067F000080000009E00C00000FC000-000000067F000080000009E00C0000100000__000000C1972392A8", +"000000067F000080000009E00C00000FE40B-000000067F000080000009E00C0000107B27__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C0000100000-000000067F000080000009E00C0000104000__000000C0B597E900", +"000000067F000080000009E00C0000100000-000000067F000080000009E00C0000104000__000000C1972392A8", +"000000067F000080000009E00C0000104000-000000067F000080000009E00C0000108000__000000C1972392A8", +"000000067F000080000009E00C0000104000-030000000000000000000000000000000002__000000C0B597E900", +"000000067F000080000009E00C0000107B27-000000067F000080000009E00C000011128D__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E00C0000108000-000000067F000080000009E00C000010C000__000000C1972392A8", +"000000067F000080000009E00C000010C000-000000067F000080000009E00C0000110000__000000C1972392A8", +"000000067F000080000009E00C0000110000-000000067F000080000009E0120100000000__000000C1972392A8", +"000000067F000080000009E00C000011128D-010000000000000001000000050000000003__000000BFF8BDFEE9-000000C0C8CA5FF1", +"000000067F000080000009E0140000000000-000000067F000080000009E0140000004000__000000C1972392A8", +"000000067F000080000009E0140000001880-000000067F000080000009E014000000842E__000000C0C8CA5FF1-000000C1426D92E1", +"000000067F000080000009E0140000004000-000000067F000080000009E0140000008000__000000C1972392A8", +"000000067F000080000009E0140000008000-000000067F000080000009E014000000C000__000000C1972392A8", +"000000067F000080000009E014000000842E-000000067F000080000009E014000000F011__000000C0C8CA5FF1-000000C1426D92E1", +"000000067F000080000009E014000000C000-000000067F000080000009E0140000010000__000000C1972392A8", +"000000067F000080000009E014000000D3EB-000000067F000080000009E014000002578F__000000C1426D92E1-000000C19744E959", +"000000067F000080000009E014000000F011-000000067F000080000009E0140000015BD8__000000C0C8CA5FF1-000000C1426D92E1", +"000000067F000080000009E0140000010000-000000067F000080000009E0140000014000__000000C1972392A8", +"000000067F000080000009E0140000014000-000000067F000080000009E0140000018000__000000C1972392A8", +"000000067F000080000009E0140000015BD8-000000067F000080000009E014000001C7C5__000000C0C8CA5FF1-000000C1426D92E1", +"000000067F000080000009E0140000018000-000000067F000080000009E014000001C000__000000C1972392A8", +"000000067F000080000009E014000001C000-000000067F000080000009E0140000020000__000000C1972392A8", +"000000067F000080000009E014000001C7C5-000000067F000080000009E014000002337F__000000C0C8CA5FF1-000000C1426D92E1", +"000000067F000080000009E0140000020000-000000067F000080000009E0140000024000__000000C1972392A8", +"000000067F000080000009E014000002337F-000000067F000080000009E0140000029F4A__000000C0C8CA5FF1-000000C1426D92E1", +"000000067F000080000009E0140000024000-000000067F000080000009E0140000028000__000000C1972392A8", +"000000067F000080000009E0140000025790-030000000000000000000000000000000002__000000C1426D92E1-000000C19744E959", +"000000067F000080000009E0140000028000-000000067F000080000009E014000002C000__000000C1972392A8", +"000000067F000080000009E0140000029F4A-030000000000000000000000000000000002__000000C0C8CA5FF1-000000C1426D92E1", +"000000067F000080000009E014000002C000-030000000000000000000000000000000002__000000C1972392A8", +"000000067F00008000000A000C0000000000-000000067F00008000000A000C0000004000__000000C3687EDFE8", +"000000067F00008000000A000C0000004000-000000067F00008000000A000C0000008000__000000C3687EDFE8", +"000000067F00008000000A000C0000008000-000000067F00008000000A000C000000C000__000000C3687EDFE8", +"000000067F00008000000A000C0000008EF9-000000067F00008000000A000C000001260C__000000C19744E959-000000C217F3F379", +"000000067F00008000000A000C000000C000-000000067F00008000000A000C0000010000__000000C3687EDFE8", +"000000067F00008000000A000C0000010000-000000067F00008000000A000C0000014000__000000C3687EDFE8", +"000000067F00008000000A000C000001260C-000000067F00008000000A000C000001BD72__000000C19744E959-000000C217F3F379", +"000000067F00008000000A000C0000014000-000000067F00008000000A000C0000018000__000000C3687EDFE8", +"000000067F00008000000A000C0000018000-000000067F00008000000A000C000001C000__000000C3687EDFE8", +"000000067F00008000000A000C000001BD72-000000067F00008000000A000C00000254D8__000000C19744E959-000000C217F3F379", +"000000067F00008000000A000C000001C000-000000067F00008000000A000C0000020000__000000C3687EDFE8", +"000000067F00008000000A000C0000020000-000000067F00008000000A000C0000024000__000000C3687EDFE8", +"000000067F00008000000A000C0000024000-000000067F00008000000A000C0000028000__000000C3687EDFE8", +"000000067F00008000000A000C00000254D8-000000067F00008000000A000C000002EC0B__000000C19744E959-000000C217F3F379", +"000000067F00008000000A000C0000028000-000000067F00008000000A000C000002C000__000000C3687EDFE8", +"000000067F00008000000A000C000002C000-000000067F00008000000A000C0000030000__000000C3687EDFE8", +"000000067F00008000000A000C000002EC0B-000000067F00008000000A000C0000038322__000000C19744E959-000000C217F3F379", +"000000067F00008000000A000C0000030000-000000067F00008000000A000C0000034000__000000C3687EDFE8", +"000000067F00008000000A000C0000034000-000000067F00008000000A000C0000038000__000000C3687EDFE8", +"000000067F00008000000A000C0000038000-000000067F00008000000A000C000003C000__000000C3687EDFE8", +"000000067F00008000000A000C0000038322-000000067F00008000000A000C0000041A88__000000C19744E959-000000C217F3F379", +"000000067F00008000000A000C000003C000-000000067F00008000000A000C0000040000__000000C3687EDFE8", +"000000067F00008000000A000C0000040000-000000067F00008000000A000C0000044000__000000C3687EDFE8", +"000000067F00008000000A000C0000041A88-000000067F00008000000A000C000004B1EE__000000C19744E959-000000C217F3F379", +"000000067F00008000000A000C0000044000-000000067F00008000000A000C0000048000__000000C3687EDFE8", +"000000067F00008000000A000C0000048000-000000067F00008000000A000C000004C000__000000C366619FD8", +"000000067F00008000000A000C0000048000-000000067F00008000000A000C000004C000__000000C42FE73810", +"000000067F00008000000A000C000004B1EE-030000000000000000000000000000000002__000000C19744E959-000000C217F3F379", +"000000067F00008000000A000C000004BACE-000000067F00008000000A000C0000055202__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C000004C000-000000067F00008000000A000C0000050000__000000C366619FD8", +"000000067F00008000000A000C000004C000-000000067F00008000000A000C0000050000__000000C42FE73810", +"000000067F00008000000A000C0000050000-000000067F00008000000A000C0000054000__000000C366619FD8", +"000000067F00008000000A000C0000050000-000000067F00008000000A000C0000054000__000000C42FE73810", +"000000067F00008000000A000C0000054000-000000067F00008000000A000C0000058000__000000C366619FD8", +"000000067F00008000000A000C0000054000-000000067F00008000000A000C0000058000__000000C42FE73810", +"000000067F00008000000A000C0000055202-000000067F00008000000A000C000005E90D__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C0000056365-000000067F00008000000A000C00000ACA1A__000000C3E17E01A1-000000C430961E71", +"000000067F00008000000A000C0000058000-000000067F00008000000A000C000005C000__000000C366619FD8", +"000000067F00008000000A000C0000058000-000000067F00008000000A000C000005C000__000000C42FE73810", +"000000067F00008000000A000C000005C000-000000067F00008000000A000C0000060000__000000C366619FD8", +"000000067F00008000000A000C000005C000-000000067F00008000000A000C0000060000__000000C42FE73810", +"000000067F00008000000A000C000005E90D-000000067F00008000000A000C000006802B__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C0000060000-000000067F00008000000A000C0000064000__000000C366619FD8", +"000000067F00008000000A000C0000060000-000000067F00008000000A000C0000064000__000000C42FE73810", +"000000067F00008000000A000C0000064000-000000067F00008000000A000C0000068000__000000C366619FD8", +"000000067F00008000000A000C0000064000-000000067F00008000000A000C0000068000__000000C42FE73810", +"000000067F00008000000A000C0000068000-000000067F00008000000A000C000006C000__000000C366619FD8", +"000000067F00008000000A000C0000068000-000000067F00008000000A000C000006C000__000000C42FE73810", +"000000067F00008000000A000C000006802B-000000067F00008000000A000C0000071782__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C000006C000-000000067F00008000000A000C0000070000__000000C366619FD8", +"000000067F00008000000A000C000006C000-000000067F00008000000A000C0000070000__000000C42FE73810", +"000000067F00008000000A000C0000070000-000000067F00008000000A000C0000074000__000000C366619FD8", +"000000067F00008000000A000C0000070000-000000067F00008000000A000C0000074000__000000C42FE73810", +"000000067F00008000000A000C0000071782-000000067F00008000000A000C000007AEE8__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C0000074000-000000067F00008000000A000C0000078000__000000C366619FD8", +"000000067F00008000000A000C0000074000-000000067F00008000000A000C0000078000__000000C42FE73810", +"000000067F00008000000A000C0000078000-000000067F00008000000A000C000007C000__000000C366619FD8", +"000000067F00008000000A000C0000078000-000000067F00008000000A000C000007C000__000000C42FE73810", +"000000067F00008000000A000C000007AEE8-000000067F00008000000A000C000008460B__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C000007C000-000000067F00008000000A000C0000080000__000000C366619FD8", +"000000067F00008000000A000C000007C000-000000067F00008000000A000C0000080000__000000C42FE73810", +"000000067F00008000000A000C0000080000-000000067F00008000000A000C0000084000__000000C366619FD8", +"000000067F00008000000A000C0000080000-000000067F00008000000A000C0000084000__000000C42FE73810", +"000000067F00008000000A000C0000084000-000000067F00008000000A000C0000088000__000000C366619FD8", +"000000067F00008000000A000C0000084000-000000067F00008000000A000C0000088000__000000C42FE73810", +"000000067F00008000000A000C000008460B-000000067F00008000000A000C000008DD71__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C0000088000-000000067F00008000000A000C000008C000__000000C366619FD8", +"000000067F00008000000A000C0000088000-000000067F00008000000A000C000008C000__000000C42FE73810", +"000000067F00008000000A000C000008C000-000000067F00008000000A000C0000090000__000000C366619FD8", +"000000067F00008000000A000C000008C000-000000067F00008000000A000C0000090000__000000C42FE73810", +"000000067F00008000000A000C000008DD71-000000067F00008000000A000C00000974D7__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C0000090000-000000067F00008000000A000C0000094000__000000C366619FD8", +"000000067F00008000000A000C0000090000-000000067F00008000000A000C0000094000__000000C42FE73810", +"000000067F00008000000A000C0000094000-000000067F00008000000A000C0000098000__000000C366619FD8", +"000000067F00008000000A000C0000094000-000000067F00008000000A000C0000098000__000000C42FE73810", +"000000067F00008000000A000C00000974D7-000000067F00008000000A000C00000A0C0B__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C0000098000-000000067F00008000000A000C000009C000__000000C366619FD8", +"000000067F00008000000A000C0000098000-000000067F00008000000A000C000009C000__000000C42FE73810", +"000000067F00008000000A000C000009C000-000000067F00008000000A000C00000A0000__000000C366619FD8", +"000000067F00008000000A000C000009C000-000000067F00008000000A000C00000A0000__000000C42FE73810", +"000000067F00008000000A000C00000A0000-000000067F00008000000A000C00000A4000__000000C366619FD8", +"000000067F00008000000A000C00000A0000-000000067F00008000000A000C00000A4000__000000C42FE73810", +"000000067F00008000000A000C00000A0C0B-000000067F00008000000A000C00000AA371__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C00000A4000-000000067F00008000000A000C00000A8000__000000C366619FD8", +"000000067F00008000000A000C00000A4000-000000067F00008000000A000C00000A8000__000000C42FE73810", +"000000067F00008000000A000C00000A8000-000000067F00008000000A000C00000AC000__000000C366619FD8", +"000000067F00008000000A000C00000A8000-000000067F00008000000A000C00000AC000__000000C42FE73810", +"000000067F00008000000A000C00000AA371-000000067F00008000000A000C00000B3AD7__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C00000AC000-000000067F00008000000A000C00000B0000__000000C366619FD8", +"000000067F00008000000A000C00000AC000-000000067F00008000000A000C00000B0000__000000C42FE73810", +"000000067F00008000000A000C00000ACA25-000000067F00008000000A000C0000102D7C__000000C3E17E01A1-000000C430961E71", +"000000067F00008000000A000C00000B0000-000000067F00008000000A000C00000B4000__000000C366619FD8", +"000000067F00008000000A000C00000B0000-000000067F00008000000A000C00000B4000__000000C42FE73810", +"000000067F00008000000A000C00000B3AD7-000000067F00008000000A000C0100000000__000000C217F3F379-000000C2C7B1ECC1", +"000000067F00008000000A000C00000B4000-000000067F00008000000A000C00000B8000__000000C366619FD8", +"000000067F00008000000A000C00000B4000-000000067F00008000000A000C00000B8000__000000C42FE73810", +"000000067F00008000000A000C00000B8000-000000067F00008000000A000C00000BC000__000000C366619FD8", +"000000067F00008000000A000C00000B8000-000000067F00008000000A000C00000BC000__000000C42FE73810", +"000000067F00008000000A000C00000B8B52-000000067F00008000000A00140000001132__000000C367E48001-000000C3E17E01A1", +"000000067F00008000000A000C00000BC000-000000067F00008000000A000C00000C0000__000000C366619FD8", +"000000067F00008000000A000C00000BC000-000000067F00008000000A000C00000C0000__000000C42FE73810", +"000000067F00008000000A000C00000BC072-000000067F00008000000A000C00000C57A3__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000A000C00000C0000-000000067F00008000000A000C00000C4000__000000C366619FD8", +"000000067F00008000000A000C00000C0000-000000067F00008000000A000C00000C4000__000000C42FE73810", +"000000067F00008000000A000C00000C4000-000000067F00008000000A000C00000C8000__000000C366619FD8", +"000000067F00008000000A000C00000C4000-000000067F00008000000A000C00000C8000__000000C42FE73810", +"000000067F00008000000A000C00000C57A3-000000067F00008000000A000C00000CEF09__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000A000C00000C8000-000000067F00008000000A000C00000CC000__000000C366619FD8", +"000000067F00008000000A000C00000C8000-000000067F00008000000A000C00000CC000__000000C42FE73810", +"000000067F00008000000A000C00000CC000-000000067F00008000000A000C00000D0000__000000C366619FD8", +"000000067F00008000000A000C00000CC000-000000067F00008000000A000C00000D0000__000000C42FE73810", +"000000067F00008000000A000C00000CEF09-000000067F00008000000A000C00000D862B__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000A000C00000D0000-000000067F00008000000A000C00000D4000__000000C366619FD8", +"000000067F00008000000A000C00000D0000-000000067F00008000000A000C00000D4000__000000C42FE73810", +"000000067F00008000000A000C00000D4000-000000067F00008000000A000C00000D8000__000000C366619FD8", +"000000067F00008000000A000C00000D4000-000000067F00008000000A000C00000D8000__000000C42FE73810", +"000000067F00008000000A000C00000D8000-000000067F00008000000A000C00000DC000__000000C366619FD8", +"000000067F00008000000A000C00000D8000-000000067F00008000000A000C00000DC000__000000C42FE73810", +"000000067F00008000000A000C00000D862B-000000067F00008000000A000C00000E1D7F__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000A000C00000DC000-000000067F00008000000A000C00000E0000__000000C366619FD8", +"000000067F00008000000A000C00000DC000-000000067F00008000000A000C00000E0000__000000C42FE73810", +"000000067F00008000000A000C00000E0000-000000067F00008000000A000C00000E4000__000000C366619FD8", +"000000067F00008000000A000C00000E0000-000000067F00008000000A000C00000E4000__000000C42FE73810", +"000000067F00008000000A000C00000E1D7F-000000067F00008000000A000C00000EB4E5__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000A000C00000E4000-000000067F00008000000A000C00000E8000__000000C366619FD8", +"000000067F00008000000A000C00000E4000-000000067F00008000000A000C00000E8000__000000C42FE73810", +"000000067F00008000000A000C00000E8000-000000067F00008000000A000C00000EC000__000000C366619FD8", +"000000067F00008000000A000C00000E8000-000000067F00008000000A000C00000EC000__000000C42FE73810", +"000000067F00008000000A000C00000EB4E5-000000067F00008000000A000C00000F4C0B__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000A000C00000EC000-000000067F00008000000A000C00000F0000__000000C366619FD8", +"000000067F00008000000A000C00000EC000-000000067F00008000000A000C00000F0000__000000C42FE73810", +"000000067F00008000000A000C00000F0000-000000067F00008000000A000C00000F4000__000000C366619FD8", +"000000067F00008000000A000C00000F0000-000000067F00008000000A000C00000F4000__000000C42FE73810", +"000000067F00008000000A000C00000F4000-000000067F00008000000A000C00000F8000__000000C366619FD8", +"000000067F00008000000A000C00000F4000-000000067F00008000000A000C00000F8000__000000C42FE73810", +"000000067F00008000000A000C00000F4C0B-000000067F00008000000A000C00000FE371__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000A000C00000F8000-000000067F00008000000A000C00000FC000__000000C366619FD8", +"000000067F00008000000A000C00000F8000-000000067F00008000000A000C00000FC000__000000C42FE73810", +"000000067F00008000000A000C00000FC000-000000067F00008000000A000C0000100000__000000C366619FD8", +"000000067F00008000000A000C00000FC000-000000067F00008000000A000C0000100000__000000C42FE73810", +"000000067F00008000000A000C00000FE371-000000067F00008000000A000C0000107AD7__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000A000C0000100000-000000067F00008000000A000C0000104000__000000C366619FD8", +"000000067F00008000000A000C0000100000-000000067F00008000000A000C0000104000__000000C42FE73810", +"000000067F00008000000A000C0000102D7F-000000067F00008000000A0014000001409C__000000C3E17E01A1-000000C430961E71", +"000000067F00008000000A000C0000104000-000000067F00008000000A000C0000108000__000000C366619FD8", +"000000067F00008000000A000C0000104000-000000067F00008000000A000C0000108000__000000C42FE73810", +"000000067F00008000000A000C0000107AD7-000000067F00008000000A000C000011120B__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000A000C0000108000-000000067F00008000000A000C000010C000__000000C366619FD8", +"000000067F00008000000A000C0000108000-000000067F00008000000A000C000010C000__000000C42FE73810", +"000000067F00008000000A000C000010C000-000000067F00008000000A000C0000110000__000000C366619FD8", +"000000067F00008000000A000C000010C000-000000067F00008000000A000C0000110000__000000C42FE73810", +"000000067F00008000000A000C0000110000-000000067F00008000000A00120100000000__000000C42FE73810", +"000000067F00008000000A000C0000110000-030000000000000000000000000000000002__000000C366619FD8", +"000000067F00008000000A000C000011120B-010000000000000001000000050000000007__000000C2C7B1ECC1-000000C367E48001", +"000000067F00008000000A00140000000000-000000067F00008000000A00140000004000__000000C42FE73810", +"000000067F00008000000A00140000001132-000000067F00008000000A00140000007E49__000000C367E48001-000000C3E17E01A1", +"000000067F00008000000A00140000004000-000000067F00008000000A00140000008000__000000C42FE73810", +"000000067F00008000000A00140000007E49-000000067F00008000000A0014000000EBBC__000000C367E48001-000000C3E17E01A1", +"000000067F00008000000A00140000008000-000000067F00008000000A0014000000C000__000000C42FE73810", +"000000067F00008000000A0014000000C000-000000067F00008000000A00140000010000__000000C42FE73810", +"000000067F00008000000A0014000000EBBC-000000067F00008000000A00140000015925__000000C367E48001-000000C3E17E01A1", +"000000067F00008000000A00140000010000-000000067F00008000000A00140000014000__000000C42FE73810", +"000000067F00008000000A00140000014000-000000067F00008000000A00140000018000__000000C42FE73810", +"000000067F00008000000A0014000001409F-000000067F00008000000A0016000000020E__000000C3E17E01A1-000000C430961E71", +"000000067F00008000000A00140000015925-000000067F00008000000A0014000001C612__000000C367E48001-000000C3E17E01A1", +"000000067F00008000000A00140000018000-000000067F00008000000A0014000001C000__000000C42FE73810", +"000000067F00008000000A0014000001C000-000000067F00008000000A00140000020000__000000C42FE73810", +"000000067F00008000000A0014000001C612-000000067F00008000000A00140000023364__000000C367E48001-000000C3E17E01A1", +"000000067F00008000000A00140000020000-000000067F00008000000A00140000024000__000000C42FE73810", +"000000067F00008000000A00140000023364-000000067F00008000000A0014000002A070__000000C367E48001-000000C3E17E01A1", +"000000067F00008000000A00140000024000-000000067F00008000000A00140000028000__000000C42FE73810", +"000000067F00008000000A00140000028000-000000067F00008000000A0014000002C000__000000C42FE73810", +"000000067F00008000000A0014000002A070-030000000000000000000000000000000002__000000C367E48001-000000C3E17E01A1", +"000000067F00008000000A0014000002C000-030000000000000000000000000000000002__000000C42FE73810", +"000000067F00008000000A0016000000020E-030000000000000000000000000000000002__000000C3E17E01A1-000000C430961E71", +"000000067F00008000000A200C0000000000-000000067F00008000000A200C0000004000__000000C601294000", +"000000067F00008000000A200C0000004000-000000067F00008000000A200C0000008000__000000C601294000", +"000000067F00008000000A200C0000008000-000000067F00008000000A200C000000C000__000000C601294000", +"000000067F00008000000A200C0000009748-000000067F00008000000A200C0000012EAE__000000C430961E71-000000C4C05DDB29", +"000000067F00008000000A200C000000C000-000000067F00008000000A200C0000010000__000000C601294000", +"000000067F00008000000A200C0000010000-000000067F00008000000A200C0000014000__000000C601294000", +"000000067F00008000000A200C0000012EAE-000000067F00008000000A200C000001C60A__000000C430961E71-000000C4C05DDB29", +"000000067F00008000000A200C0000014000-000000067F00008000000A200C0000018000__000000C601294000", +"000000067F00008000000A200C0000018000-000000067F00008000000A200C000001C000__000000C601294000", +"000000067F00008000000A200C000001C000-000000067F00008000000A200C0000020000__000000C601294000", +"000000067F00008000000A200C000001C60A-000000067F00008000000A200C0000025D38__000000C430961E71-000000C4C05DDB29", +"000000067F00008000000A200C0000020000-000000067F00008000000A200C0000024000__000000C601294000", +"000000067F00008000000A200C0000024000-000000067F00008000000A200C0000028000__000000C601294000", +"000000067F00008000000A200C0000025D38-000000067F00008000000A200C000002F49E__000000C430961E71-000000C4C05DDB29", +"000000067F00008000000A200C0000028000-000000067F00008000000A200C000002C000__000000C601294000", +"000000067F00008000000A200C000002C000-000000067F00008000000A200C0000030000__000000C601294000", +"000000067F00008000000A200C000002F49E-000000067F00008000000A200C0000038BB1__000000C430961E71-000000C4C05DDB29", +"000000067F00008000000A200C0000030000-000000067F00008000000A200C0000034000__000000C601294000", +"000000067F00008000000A200C0000034000-000000067F00008000000A200C0000038000__000000C601294000", +"000000067F00008000000A200C0000038000-000000067F00008000000A200C000003C000__000000C601294000", +"000000067F00008000000A200C0000038BB1-000000067F00008000000A200C0000042317__000000C430961E71-000000C4C05DDB29", +"000000067F00008000000A200C000003C000-000000067F00008000000A200C0000040000__000000C601294000", +"000000067F00008000000A200C0000040000-000000067F00008000000A200C0000044000__000000C601294000", +"000000067F00008000000A200C0000042317-000000067F00008000000A200C000004BA7D__000000C430961E71-000000C4C05DDB29", +"000000067F00008000000A200C0000044000-000000067F00008000000A200C0000048000__000000C601294000", +"000000067F00008000000A200C0000048000-000000067F00008000000A200C000004C000__000000C601294000", +"000000067F00008000000A200C000004BA7D-000000067F00008000000A200C00000551B2__000000C430961E71-000000C4C05DDB29", +"000000067F00008000000A200C000004C000-000000067F00008000000A200C0000050000__000000C601294000", +"000000067F00008000000A200C0000050000-000000067F00008000000A200C0000054000__000000C601294000", +"000000067F00008000000A200C0000054000-000000067F00008000000A200C0000058000__000000C5FED35FC8", +"000000067F00008000000A200C0000054000-000000067F00008000000A200C0000058000__000000C6C7BD8140", +"000000067F00008000000A200C00000551B2-030000000000000000000000000000000002__000000C430961E71-000000C4C05DDB29", +"000000067F00008000000A200C0000055230-000000067F00008000000A200C000005E996__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C0000058000-000000067F00008000000A200C000005C000__000000C5FED35FC8", +"000000067F00008000000A200C0000058000-000000067F00008000000A200C000005C000__000000C6C7BD8140", +"000000067F00008000000A200C000005C000-000000067F00008000000A200C0000060000__000000C5FED35FC8", +"000000067F00008000000A200C000005C000-000000067F00008000000A200C0000060000__000000C6C7BD8140", +"000000067F00008000000A200C000005E996-000000067F00008000000A200C00000680FC__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C0000060000-000000067F00008000000A200C0000064000__000000C5FED35FC8", +"000000067F00008000000A200C0000060000-000000067F00008000000A200C0000064000__000000C6C7BD8140", +"000000067F00008000000A200C0000064000-000000067F00008000000A200C0000068000__000000C5FED35FC8", +"000000067F00008000000A200C0000064000-000000067F00008000000A200C0000068000__000000C6C7BD8140", +"000000067F00008000000A200C00000677DB-000000067F00008000000A200C00000CF739__000000C689AF4AC1-000000C6C87B6329", +"000000067F00008000000A200C0000068000-000000067F00008000000A200C000006C000__000000C5FED35FC8", +"000000067F00008000000A200C0000068000-000000067F00008000000A200C000006C000__000000C6C7BD8140", +"000000067F00008000000A200C00000680FC-000000067F00008000000A200C000007180C__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C000006C000-000000067F00008000000A200C0000070000__000000C5FED35FC8", +"000000067F00008000000A200C000006C000-000000067F00008000000A200C0000070000__000000C6C7BD8140", +"000000067F00008000000A200C0000070000-000000067F00008000000A200C0000074000__000000C5FED35FC8", +"000000067F00008000000A200C0000070000-000000067F00008000000A200C0000074000__000000C6C7BD8140", +"000000067F00008000000A200C000007180C-000000067F00008000000A200C000007AF72__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C0000074000-000000067F00008000000A200C0000078000__000000C5FED35FC8", +"000000067F00008000000A200C0000074000-000000067F00008000000A200C0000078000__000000C6C7BD8140", +"000000067F00008000000A200C0000078000-000000067F00008000000A200C000007C000__000000C5FED35FC8", +"000000067F00008000000A200C0000078000-000000067F00008000000A200C000007C000__000000C6C7BD8140", +"000000067F00008000000A200C000007AF72-000000067F00008000000A200C00000846D8__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C000007C000-000000067F00008000000A200C0000080000__000000C5FED35FC8", +"000000067F00008000000A200C000007C000-000000067F00008000000A200C0000080000__000000C6C7BD8140", +"000000067F00008000000A200C0000080000-000000067F00008000000A200C0000084000__000000C5FED35FC8", +"000000067F00008000000A200C0000080000-000000067F00008000000A200C0000084000__000000C6C7BD8140", +"000000067F00008000000A200C0000084000-000000067F00008000000A200C0000088000__000000C5FED35FC8", +"000000067F00008000000A200C0000084000-000000067F00008000000A200C0000088000__000000C6C7BD8140", +"000000067F00008000000A200C00000846D8-000000067F00008000000A200C000008DE0B__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C0000088000-000000067F00008000000A200C000008C000__000000C5FED35FC8", +"000000067F00008000000A200C0000088000-000000067F00008000000A200C000008C000__000000C6C7BD8140", +"000000067F00008000000A200C000008C000-000000067F00008000000A200C0000090000__000000C5FED35FC8", +"000000067F00008000000A200C000008C000-000000067F00008000000A200C0000090000__000000C6C7BD8140", +"000000067F00008000000A200C000008DE0B-000000067F00008000000A200C000009752B__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C0000090000-000000067F00008000000A200C0000094000__000000C5FED35FC8", +"000000067F00008000000A200C0000090000-000000067F00008000000A200C0000094000__000000C6C7BD8140", +"000000067F00008000000A200C00000933F0-000000067F00008000000A200C0000110901__000000C600A8FFF9-000000C689AF4AC1", +"000000067F00008000000A200C0000094000-000000067F00008000000A200C0000098000__000000C5FED35FC8", +"000000067F00008000000A200C0000094000-000000067F00008000000A200C0000098000__000000C6C7BD8140", +"000000067F00008000000A200C000009752B-000000067F00008000000A200C00000A0C91__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C0000098000-000000067F00008000000A200C000009C000__000000C5FED35FC8", +"000000067F00008000000A200C0000098000-000000067F00008000000A200C000009C000__000000C6C7BD8140", +"000000067F00008000000A200C000009C000-000000067F00008000000A200C00000A0000__000000C5FED35FC8", +"000000067F00008000000A200C000009C000-000000067F00008000000A200C00000A0000__000000C6C7BD8140", +"000000067F00008000000A200C00000A0000-000000067F00008000000A200C00000A4000__000000C5FED35FC8", +"000000067F00008000000A200C00000A0000-000000067F00008000000A200C00000A4000__000000C6C7BD8140", +"000000067F00008000000A200C00000A0C91-000000067F00008000000A200C00000AA3F7__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C00000A4000-000000067F00008000000A200C00000A8000__000000C5FED35FC8", +"000000067F00008000000A200C00000A4000-000000067F00008000000A200C00000A8000__000000C6C7BD8140", +"000000067F00008000000A200C00000A8000-000000067F00008000000A200C00000AC000__000000C5FED35FC8", +"000000067F00008000000A200C00000A8000-000000067F00008000000A200C00000AC000__000000C6C7BD8140", +"000000067F00008000000A200C00000AA3F7-000000067F00008000000A200C00000B3B0C__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C00000AC000-000000067F00008000000A200C00000B0000__000000C5FED35FC8", +"000000067F00008000000A200C00000AC000-000000067F00008000000A200C00000B0000__000000C6C7BD8140", +"000000067F00008000000A200C00000B0000-000000067F00008000000A200C00000B4000__000000C5FED35FC8", +"000000067F00008000000A200C00000B0000-000000067F00008000000A200C00000B4000__000000C6C7BD8140", +"000000067F00008000000A200C00000B3B0C-000000067F00008000000A200C0100000000__000000C4C05DDB29-000000C56021EB29", +"000000067F00008000000A200C00000B4000-000000067F00008000000A200C00000B8000__000000C5FED35FC8", +"000000067F00008000000A200C00000B4000-000000067F00008000000A200C00000B8000__000000C6C7BD8140", +"000000067F00008000000A200C00000B8000-000000067F00008000000A200C00000BC000__000000C5FED35FC8", +"000000067F00008000000A200C00000B8000-000000067F00008000000A200C00000BC000__000000C6C7BD8140", +"000000067F00008000000A200C00000BBC1F-000000067F00008000000A200C00000C5353__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000A200C00000BC000-000000067F00008000000A200C00000C0000__000000C5FED35FC8", +"000000067F00008000000A200C00000BC000-000000067F00008000000A200C00000C0000__000000C6C7BD8140", +"000000067F00008000000A200C00000C0000-000000067F00008000000A200C00000C4000__000000C5FED35FC8", +"000000067F00008000000A200C00000C0000-000000067F00008000000A200C00000C4000__000000C6C7BD8140", +"000000067F00008000000A200C00000C4000-000000067F00008000000A200C00000C8000__000000C5FED35FC8", +"000000067F00008000000A200C00000C4000-000000067F00008000000A200C00000C8000__000000C6C7BD8140", +"000000067F00008000000A200C00000C5353-000000067F00008000000A200C00000CEAB9__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000A200C00000C8000-000000067F00008000000A200C00000CC000__000000C5FED35FC8", +"000000067F00008000000A200C00000C8000-000000067F00008000000A200C00000CC000__000000C6C7BD8140", +"000000067F00008000000A200C00000CC000-000000067F00008000000A200C00000D0000__000000C5FED35FC8", +"000000067F00008000000A200C00000CC000-000000067F00008000000A200C00000D0000__000000C6C7BD8140", +"000000067F00008000000A200C00000CEAB9-000000067F00008000000A200C00000D81D2__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000A200C00000CF742-000000067F00008000000A2014000000B47B__000000C689AF4AC1-000000C6C87B6329", +"000000067F00008000000A200C00000D0000-000000067F00008000000A200C00000D4000__000000C5FED35FC8", +"000000067F00008000000A200C00000D0000-000000067F00008000000A200C00000D4000__000000C6C7BD8140", +"000000067F00008000000A200C00000D4000-000000067F00008000000A200C00000D8000__000000C5FED35FC8", +"000000067F00008000000A200C00000D4000-000000067F00008000000A200C00000D8000__000000C6C7BD8140", +"000000067F00008000000A200C00000D8000-000000067F00008000000A200C00000DC000__000000C5FED35FC8", +"000000067F00008000000A200C00000D8000-000000067F00008000000A200C00000DC000__000000C6C7BD8140", +"000000067F00008000000A200C00000D81D2-000000067F00008000000A200C00000E190B__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000A200C00000DC000-000000067F00008000000A200C00000E0000__000000C5FED35FC8", +"000000067F00008000000A200C00000DC000-000000067F00008000000A200C00000E0000__000000C6C7BD8140", +"000000067F00008000000A200C00000E0000-000000067F00008000000A200C00000E4000__000000C5FED35FC8", +"000000067F00008000000A200C00000E0000-000000067F00008000000A200C00000E4000__000000C6C7BD8140", +"000000067F00008000000A200C00000E190B-000000067F00008000000A200C00000EB071__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000A200C00000E4000-000000067F00008000000A200C00000E8000__000000C5FED35FC8", +"000000067F00008000000A200C00000E4000-000000067F00008000000A200C00000E8000__000000C6C7BD8140", +"000000067F00008000000A200C00000E8000-000000067F00008000000A200C00000EC000__000000C5FED35FC8", +"000000067F00008000000A200C00000E8000-000000067F00008000000A200C00000EC000__000000C6C7BD8140", +"000000067F00008000000A200C00000EB071-000000067F00008000000A200C00000F47AC__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000A200C00000EC000-000000067F00008000000A200C00000F0000__000000C5FED35FC8", +"000000067F00008000000A200C00000EC000-000000067F00008000000A200C00000F0000__000000C6C7BD8140", +"000000067F00008000000A200C00000F0000-000000067F00008000000A200C00000F4000__000000C5FED35FC8", +"000000067F00008000000A200C00000F0000-000000067F00008000000A200C00000F4000__000000C6C7BD8140", +"000000067F00008000000A200C00000F4000-000000067F00008000000A200C00000F8000__000000C5FED35FC8", +"000000067F00008000000A200C00000F4000-000000067F00008000000A200C00000F8000__000000C6C7BD8140", +"000000067F00008000000A200C00000F47AC-000000067F00008000000A200C00000FDF0A__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000A200C00000F8000-000000067F00008000000A200C00000FC000__000000C5FED35FC8", +"000000067F00008000000A200C00000F8000-000000067F00008000000A200C00000FC000__000000C6C7BD8140", +"000000067F00008000000A200C00000FC000-000000067F00008000000A200C0000100000__000000C5FED35FC8", +"000000067F00008000000A200C00000FC000-000000067F00008000000A200C0000100000__000000C6C7BD8140", +"000000067F00008000000A200C00000FDF0A-000000067F00008000000A200C000010762B__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000A200C0000100000-000000067F00008000000A200C0000104000__000000C5FED35FC8", +"000000067F00008000000A200C0000100000-000000067F00008000000A200C0000104000__000000C6C7BD8140", +"000000067F00008000000A200C0000104000-000000067F00008000000A200C0000108000__000000C5FED35FC8", +"000000067F00008000000A200C0000104000-000000067F00008000000A200C0000108000__000000C6C7BD8140", +"000000067F00008000000A200C000010762B-000000067F00008000000A200C0000110D88__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000A200C0000108000-000000067F00008000000A200C000010C000__000000C5FED35FC8", +"000000067F00008000000A200C0000108000-000000067F00008000000A200C000010C000__000000C6C7BD8140", +"000000067F00008000000A200C000010C000-000000067F00008000000A200C0000110000__000000C5FED35FC8", +"000000067F00008000000A200C000010C000-000000067F00008000000A200C0000110000__000000C6C7BD8140", +"000000067F00008000000A200C0000110000-000000067F00008000000A20120100000000__000000C6C7BD8140", +"000000067F00008000000A200C0000110000-030000000000000000000000000000000002__000000C5FED35FC8", +"000000067F00008000000A200C0000110901-000000067F00008000000A201400000047CD__000000C600A8FFF9-000000C689AF4AC1", +"000000067F00008000000A200C0000110D88-01000000000000000100000005000000000A__000000C56021EB29-000000C600A8FFF9", +"000000067F00008000000A20140000000000-000000067F00008000000A20140000004000__000000C6C7BD8140", +"000000067F00008000000A20140000004000-000000067F00008000000A20140000008000__000000C6C7BD8140", +"000000067F00008000000A201400000047CD-000000067F00008000000A2014000000ADA8__000000C600A8FFF9-000000C689AF4AC1", +"000000067F00008000000A20140000008000-000000067F00008000000A2014000000C000__000000C6C7BD8140", +"000000067F00008000000A2014000000ADA8-000000067F00008000000A201400000113B8__000000C600A8FFF9-000000C689AF4AC1", +"000000067F00008000000A2014000000B47C-010000000000000001000000050100000000__000000C689AF4AC1-000000C6C87B6329", +"000000067F00008000000A2014000000C000-000000067F00008000000A20140000010000__000000C6C7BD8140", +"000000067F00008000000A20140000010000-000000067F00008000000A20140000014000__000000C6C7BD8140", +"000000067F00008000000A201400000113B8-000000067F00008000000A20140000017969__000000C600A8FFF9-000000C689AF4AC1", +"000000067F00008000000A20140000014000-000000067F00008000000A20140000018000__000000C6C7BD8140", +"000000067F00008000000A20140000017969-000000067F00008000000A2014000001DF7E__000000C600A8FFF9-000000C689AF4AC1", +"000000067F00008000000A20140000018000-000000067F00008000000A2014000001C000__000000C6C7BD8140", +"000000067F00008000000A2014000001C000-000000067F00008000000A20140000020000__000000C6C7BD8140", +"000000067F00008000000A2014000001DF7E-000000067F00008000000A2014000002457D__000000C600A8FFF9-000000C689AF4AC1", +"000000067F00008000000A20140000020000-000000067F00008000000A20140000024000__000000C6C7BD8140", +"000000067F00008000000A20140000024000-000000067F00008000000A20140000028000__000000C6C7BD8140", +"000000067F00008000000A2014000002457D-000000067F00008000000A2014000002AB1D__000000C600A8FFF9-000000C689AF4AC1", +"000000067F00008000000A20140000028000-000000067F00008000000A2014000002C000__000000C6C7BD8140", +"000000067F00008000000A2014000002AB1D-030000000000000000000000000000000002__000000C600A8FFF9-000000C689AF4AC1", +"000000067F00008000000A2014000002C000-030000000000000000000000000000000002__000000C6C7BD8140", +"000000067F00008000000A400C0000000000-000000067F00008000000A400C0000004000__000000C896B8DFD8", +"000000067F00008000000A400C0000004000-000000067F00008000000A400C0000008000__000000C896B8DFD8", +"000000067F00008000000A400C0000008000-000000067F00008000000A400C000000C000__000000C896B8DFD8", +"000000067F00008000000A400C0000009743-000000067F00008000000A400C0000012EA9__000000C6C87B6329-000000C74849FAE1", +"000000067F00008000000A400C000000C000-000000067F00008000000A400C0000010000__000000C896B8DFD8", +"000000067F00008000000A400C0000010000-000000067F00008000000A400C0000014000__000000C896B8DFD8", +"000000067F00008000000A400C0000012EA9-000000067F00008000000A400C000001C60A__000000C6C87B6329-000000C74849FAE1", +"000000067F00008000000A400C0000014000-000000067F00008000000A400C0000018000__000000C896B8DFD8", +"000000067F00008000000A400C0000018000-000000067F00008000000A400C000001C000__000000C896B8DFD8", +"000000067F00008000000A400C000001C000-000000067F00008000000A400C0000020000__000000C896B8DFD8", +"000000067F00008000000A400C000001C60A-000000067F00008000000A400C0000025D38__000000C6C87B6329-000000C74849FAE1", +"000000067F00008000000A400C0000020000-000000067F00008000000A400C0000024000__000000C896B8DFD8", +"000000067F00008000000A400C0000024000-000000067F00008000000A400C0000028000__000000C896B8DFD8", +"000000067F00008000000A400C0000025D38-000000067F00008000000A400C000002F49E__000000C6C87B6329-000000C74849FAE1", +"000000067F00008000000A400C0000028000-000000067F00008000000A400C000002C000__000000C896B8DFD8", +"000000067F00008000000A400C000002C000-000000067F00008000000A400C0000030000__000000C896B8DFD8", +"000000067F00008000000A400C000002F49E-000000067F00008000000A400C0000038BB1__000000C6C87B6329-000000C74849FAE1", +"000000067F00008000000A400C0000030000-000000067F00008000000A400C0000034000__000000C896B8DFD8", +"000000067F00008000000A400C0000034000-000000067F00008000000A400C0000038000__000000C896B8DFD8", +"000000067F00008000000A400C0000038000-000000067F00008000000A400C000003C000__000000C896B8DFD8", +"000000067F00008000000A400C0000038BB1-000000067F00008000000A400C0000042317__000000C6C87B6329-000000C74849FAE1", +"000000067F00008000000A400C000003C000-000000067F00008000000A400C0000040000__000000C896B8DFD8", +"000000067F00008000000A400C0000040000-000000067F00008000000A400C0000044000__000000C896B8DFD8", +"000000067F00008000000A400C0000042317-000000067F00008000000A400C000004BA7D__000000C6C87B6329-000000C74849FAE1", +"000000067F00008000000A400C0000044000-000000067F00008000000A400C0000048000__000000C896B8DFD8", +"000000067F00008000000A400C0000048000-000000067F00008000000A400C000004C000__000000C896B8DFD8", +"000000067F00008000000A400C000004BA7D-030000000000000000000000000000000002__000000C6C87B6329-000000C74849FAE1", +"000000067F00008000000A400C000004C000-000000067F00008000000A400C0000050000__000000C896B8DFD8", +"000000067F00008000000A400C0000050000-000000067F00008000000A400C0000054000__000000C896B8DFD8", +"000000067F00008000000A400C0000054000-000000067F00008000000A400C0000058000__000000C896B8DFD8", +"000000067F00008000000A400C00000551FC-000000067F00008000000A400C000005E90B__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C0000058000-000000067F00008000000A400C000005C000__000000C896B8DFD8", +"000000067F00008000000A400C000005C000-000000067F00008000000A400C0000060000__000000C896B8DFD8", +"000000067F00008000000A400C000005E90B-000000067F00008000000A400C000006802B__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C0000060000-000000067F00008000000A400C0000064000__000000C896B8DFD8", +"000000067F00008000000A400C0000064000-000000067F00008000000A400C0000068000__000000C896B8DFD8", +"000000067F00008000000A400C0000068000-000000067F00008000000A400C000006C000__000000C896B8DFD8", +"000000067F00008000000A400C000006802B-000000067F00008000000A400C0000071782__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C000006C000-000000067F00008000000A400C0000070000__000000C896B8DFD8", +"000000067F00008000000A400C0000070000-000000067F00008000000A400C0000074000__000000C896B8DFD8", +"000000067F00008000000A400C0000071782-000000067F00008000000A400C000007AEE8__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C0000074000-000000067F00008000000A400C0000078000__000000C896B8DFD8", +"000000067F00008000000A400C0000078000-000000067F00008000000A400C000007C000__000000C896B8DFD8", +"000000067F00008000000A400C000007AEE8-000000067F00008000000A400C000008460B__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C000007C000-000000067F00008000000A400C0000080000__000000C896B8DFD8", +"000000067F00008000000A400C0000080000-000000067F00008000000A400C0000084000__000000C896B8DFD8", +"000000067F00008000000A400C0000084000-000000067F00008000000A400C0000088000__000000C896B8DFD8", +"000000067F00008000000A400C000008460B-000000067F00008000000A400C000008DD71__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C0000088000-000000067F00008000000A400C000008C000__000000C896B8DFD8", +"000000067F00008000000A400C000008C000-000000067F00008000000A400C0000090000__000000C896B8DFD8", +"000000067F00008000000A400C000008DD71-000000067F00008000000A400C00000974D7__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C0000090000-000000067F00008000000A400C0000094000__000000C896B8DFD8", +"000000067F00008000000A400C0000094000-000000067F00008000000A400C0000098000__000000C896B8DFD8", +"000000067F00008000000A400C00000974D7-000000067F00008000000A400C00000A0C0B__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C0000098000-000000067F00008000000A400C000009C000__000000C896B8DFD8", +"000000067F00008000000A400C000009C000-000000067F00008000000A400C00000A0000__000000C896B8DFD8", +"000000067F00008000000A400C00000A0000-000000067F00008000000A400C00000A4000__000000C896B8DFD8", +"000000067F00008000000A400C00000A0C0B-000000067F00008000000A400C00000AA371__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C00000A4000-000000067F00008000000A400C00000A8000__000000C896B8DFD8", +"000000067F00008000000A400C00000A8000-000000067F00008000000A400C00000AC000__000000C896B8DFD8", +"000000067F00008000000A400C00000AA371-000000067F00008000000A400C00000B3AD7__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C00000AC000-000000067F00008000000A400C00000B0000__000000C896B8DFD8", +"000000067F00008000000A400C00000B0000-000000067F00008000000A400C00000B4000__000000C896B8DFD8", +"000000067F00008000000A400C00000B3AD7-000000067F00008000000A400C00000BD20B__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C00000B4000-000000067F00008000000A400C00000B8000__000000C896B8DFD8", +"000000067F00008000000A400C00000B8000-000000067F00008000000A400C00000BC000__000000C896B8DFD8", +"000000067F00008000000A400C00000BC000-000000067F00008000000A400C00000C0000__000000C896B8DFD8", +"000000067F00008000000A400C00000BD20B-000000067F00008000000A400C0100000000__000000C74849FAE1-000000C80801E859", +"000000067F00008000000A400C00000C0000-000000067F00008000000A400C00000C4000__000000C896B8DFD8", +"000000067F00008000000A400C00000C4000-000000067F00008000000A400C00000C8000__000000C896B8DFD8", +"000000067F00008000000A400C00000C4AE6-000000067F00008000000A400C00000CE20C__000000C80801E859-000000C8993EBFF9", +"000000067F00008000000A400C00000C8000-000000067F00008000000A400C00000CC000__000000C896B8DFD8", +"000000067F00008000000A400C00000CC000-000000067F00008000000A400C00000D0000__000000C896B8DFD8", +"000000067F00008000000A400C00000CE20C-000000067F00008000000A400C00000D7929__000000C80801E859-000000C8993EBFF9", +"000000067F00008000000A400C00000D0000-000000067F00008000000A400C00000D4000__000000C896B8DFD8", +"000000067F00008000000A400C00000D4000-000000067F00008000000A400C00000D8000__000000C896B8DFD8", +"000000067F00008000000A400C00000D7929-000000067F00008000000A400C00000E108F__000000C80801E859-000000C8993EBFF9", +"000000067F00008000000A400C00000D8000-000000067F00008000000A400C00000DC000__000000C896B8DFD8", +"000000067F00008000000A400C00000DC000-000000067F00008000000A400C00000E0000__000000C896B8DFD8", +"000000067F00008000000A400C00000E0000-000000067F00008000000A400C00000E4000__000000C896B8DFD8", +"000000067F00008000000A400C00000E108F-000000067F00008000000A400C00000EA7F5__000000C80801E859-000000C8993EBFF9", +"000000067F00008000000A400C00000E4000-000000067F00008000000A400C00000E8000__000000C896B8DFD8", +"000000067F00008000000A400C00000E8000-000000067F00008000000A400C00000EC000__000000C896B8DFD8", +"000000067F00008000000A400C00000EA7F5-000000067F00008000000A400C00000F3F0B__000000C80801E859-000000C8993EBFF9", +"000000067F00008000000A400C00000EC000-000000067F00008000000A400C00000F0000__000000C896B8DFD8", +"000000067F00008000000A400C00000F0000-000000067F00008000000A400C00000F4000__000000C896B8DFD8", +"000000067F00008000000A400C00000F3F0B-000000067F00008000000A400C00000FD671__000000C80801E859-000000C8993EBFF9", +"000000067F00008000000A400C00000F4000-000000067F00008000000A400C00000F8000__000000C896B8DFD8", +"000000067F00008000000A400C00000F8000-000000067F00008000000A400C00000FC000__000000C896B8DFD8", +"000000067F00008000000A400C00000FC000-000000067F00008000000A400C0000100000__000000C896B8DFD8", +"000000067F00008000000A400C00000FD671-000000067F00008000000A400C0000106D95__000000C80801E859-000000C8993EBFF9", +"000000067F00008000000A400C0000100000-000000067F00008000000A400C0000104000__000000C896B8DFD8", +"000000067F00008000000A400C0000104000-000000067F00008000000A400C0000108000__000000C896B8DFD8", +"000000067F00008000000A400C0000106D95-000000067F00008000000A400C00001104FB__000000C80801E859-000000C8993EBFF9", +"000000067F00008000000A400C0000107F8F-000000067F00008000000A40140000005626__000000C8993EBFF9-000000C90726D0D9", +"000000067F00008000000A400C0000108000-000000067F00008000000A400C000010C000__000000C896B8DFD8", +"000000067F00008000000A400C000010C000-000000067F00008000000A400C0000110000__000000C896B8DFD8", +"000000067F00008000000A400C0000110000-030000000000000000000000000000000002__000000C896B8DFD8", +"000000067F00008000000A400C00001104FB-01000000000000000100000005000000000D__000000C80801E859-000000C8993EBFF9", +"000000067F00008000000A40140000005626-000000067F00008000000A4014000000C7F9__000000C8993EBFF9-000000C90726D0D9", +"000000067F00008000000A4014000000C7F9-000000067F00008000000A401400000139F8__000000C8993EBFF9-000000C90726D0D9", +"000000067F00008000000A401400000139F8-000000067F00008000000A4014000001ABE9__000000C8993EBFF9-000000C90726D0D9", +"000000067F00008000000A4014000001ABE9-000000067F00008000000A40140000021DF4__000000C8993EBFF9-000000C90726D0D9", +"000000067F00008000000A40140000021DF4-000000067F00008000000A40140000028FA9__000000C8993EBFF9-000000C90726D0D9", +"000000067F00008000000A40140000028FA9-030000000000000000000000000000000002__000000C8993EBFF9-000000C90726D0D9", +"000000067F00008000000A600C0000000000-000000067F00008000000A600C0000004000__000000CA2C877DC8", +"000000067F00008000000A600C0000000000-000000067F00008000000A600C0000004000__000000CB82C2FF68", +"000000067F00008000000A600C0000004000-000000067F00008000000A600C0000008000__000000CA2C877DC8", +"000000067F00008000000A600C0000004000-000000067F00008000000A600C0000008000__000000CB82C2FF68", +"000000067F00008000000A600C0000008000-000000067F00008000000A600C000000C000__000000CA2C877DC8", +"000000067F00008000000A600C0000008000-000000067F00008000000A600C000000C000__000000CB82C2FF68", +"000000067F00008000000A600C0000009746-000000067F00008000000A600C0000012EAC__000000C90726D0D9-000000C986F5F0D9", +"000000067F00008000000A600C000000C000-000000067F00008000000A600C0000010000__000000CA2C877DC8", +"000000067F00008000000A600C000000C000-000000067F00008000000A600C0000010000__000000CB82C2FF68", +"000000067F00008000000A600C0000010000-000000067F00008000000A600C0000014000__000000CA2C877DC8", +"000000067F00008000000A600C0000010000-000000067F00008000000A600C0000014000__000000CB82C2FF68", +"000000067F00008000000A600C0000012EAC-000000067F00008000000A600C000001C60A__000000C90726D0D9-000000C986F5F0D9", +"000000067F00008000000A600C0000014000-000000067F00008000000A600C0000018000__000000CA2C877DC8", +"000000067F00008000000A600C0000014000-000000067F00008000000A600C0000018000__000000CB82C2FF68", +"000000067F00008000000A600C0000018000-000000067F00008000000A600C000001C000__000000CA2C877DC8", +"000000067F00008000000A600C0000018000-000000067F00008000000A600C000001C000__000000CB82C2FF68", +"000000067F00008000000A600C000001C000-000000067F00008000000A600C0000020000__000000CA2C877DC8", +"000000067F00008000000A600C000001C000-000000067F00008000000A600C0000020000__000000CB82C2FF68", +"000000067F00008000000A600C000001C60A-000000067F00008000000A600C0000025D38__000000C90726D0D9-000000C986F5F0D9", +"000000067F00008000000A600C0000020000-000000067F00008000000A600C0000024000__000000CA2C877DC8", +"000000067F00008000000A600C0000020000-000000067F00008000000A600C0000024000__000000CB82C2FF68", +"000000067F00008000000A600C0000024000-000000067F00008000000A600C0000028000__000000CA2C877DC8", +"000000067F00008000000A600C0000024000-000000067F00008000000A600C0000028000__000000CB82C2FF68", +"000000067F00008000000A600C0000025D38-000000067F00008000000A600C000002F49E__000000C90726D0D9-000000C986F5F0D9", +"000000067F00008000000A600C0000028000-000000067F00008000000A600C000002C000__000000CA2C877DC8", +"000000067F00008000000A600C0000028000-000000067F00008000000A600C000002C000__000000CB82C2FF68", +"000000067F00008000000A600C000002C000-000000067F00008000000A600C0000030000__000000CA2C877DC8", +"000000067F00008000000A600C000002C000-000000067F00008000000A600C0000030000__000000CB82C2FF68", +"000000067F00008000000A600C000002F49E-000000067F00008000000A600C0000038BB1__000000C90726D0D9-000000C986F5F0D9", +"000000067F00008000000A600C0000030000-000000067F00008000000A600C0000034000__000000CA2C877DC8", +"000000067F00008000000A600C0000030000-000000067F00008000000A600C0000034000__000000CB82C2FF68", +"000000067F00008000000A600C0000034000-000000067F00008000000A600C0000038000__000000CA2C877DC8", +"000000067F00008000000A600C0000034000-000000067F00008000000A600C0000038000__000000CB82C2FF68", +"000000067F00008000000A600C0000038000-000000067F00008000000A600C000003C000__000000CA2C877DC8", +"000000067F00008000000A600C0000038000-000000067F00008000000A600C000003C000__000000CB82C2FF68", +"000000067F00008000000A600C0000038BB1-000000067F00008000000A600C0000042317__000000C90726D0D9-000000C986F5F0D9", +"000000067F00008000000A600C000003C000-000000067F00008000000A600C0000040000__000000CA2C877DC8", +"000000067F00008000000A600C000003C000-000000067F00008000000A600C0000040000__000000CB82C2FF68", +"000000067F00008000000A600C0000040000-000000067F00008000000A600C0000044000__000000CA2C877DC8", +"000000067F00008000000A600C0000040000-000000067F00008000000A600C0000044000__000000CB82C2FF68", +"000000067F00008000000A600C0000042317-000000067F00008000000A600C000004BA7D__000000C90726D0D9-000000C986F5F0D9", +"000000067F00008000000A600C0000044000-000000067F00008000000A600C0000048000__000000CA2C877DC8", +"000000067F00008000000A600C0000044000-000000067F00008000000A600C0000048000__000000CB82C2FF68", +"000000067F00008000000A600C0000048000-000000067F00008000000A600C000004C000__000000CA2C877DC8", +"000000067F00008000000A600C0000048000-000000067F00008000000A600C000004C000__000000CB82C2FF68", +"000000067F00008000000A600C000004BA7D-030000000000000000000000000000000002__000000C90726D0D9-000000C986F5F0D9", +"000000067F00008000000A600C000004C000-000000067F00008000000A600C0000050000__000000CA2C877DC8", +"000000067F00008000000A600C000004C000-000000067F00008000000A600C0000050000__000000CB82C2FF68", +"000000067F00008000000A600C0000050000-000000067F00008000000A600C0000054000__000000CA2C877DC8", +"000000067F00008000000A600C0000050000-000000067F00008000000A600C0000054000__000000CB82C2FF68", +"000000067F00008000000A600C0000054000-000000067F00008000000A600C0000058000__000000CA2C877DC8", +"000000067F00008000000A600C0000054000-000000067F00008000000A600C0000058000__000000CB82C2FF68", +"000000067F00008000000A600C0000054BFB-000000067F00008000000A600C000005E30C__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C0000058000-000000067F00008000000A600C000005C000__000000CA2C877DC8", +"000000067F00008000000A600C0000058000-000000067F00008000000A600C000005C000__000000CB82C2FF68", +"000000067F00008000000A600C000005C000-000000067F00008000000A600C0000060000__000000CA2C877DC8", +"000000067F00008000000A600C000005C000-000000067F00008000000A600C0000060000__000000CB82C2FF68", +"000000067F00008000000A600C000005E30C-000000067F00008000000A600C0000067A2B__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C0000060000-000000067F00008000000A600C0000064000__000000CA2C877DC8", +"000000067F00008000000A600C0000060000-000000067F00008000000A600C0000064000__000000CB82C2FF68", +"000000067F00008000000A600C0000064000-000000067F00008000000A600C0000068000__000000CA2C877DC8", +"000000067F00008000000A600C0000064000-000000067F00008000000A600C0000068000__000000CB82C2FF68", +"000000067F00008000000A600C0000067A2B-000000067F00008000000A600C0000071186__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C0000068000-000000067F00008000000A600C000006C000__000000CA2C877DC8", +"000000067F00008000000A600C0000068000-000000067F00008000000A600C000006C000__000000CB82C2FF68", +"000000067F00008000000A600C000006C000-000000067F00008000000A600C0000070000__000000CA2C877DC8", +"000000067F00008000000A600C000006C000-000000067F00008000000A600C0000070000__000000CB82C2FF68", +"000000067F00008000000A600C0000070000-000000067F00008000000A600C0000074000__000000CA2C877DC8", +"000000067F00008000000A600C0000070000-000000067F00008000000A600C0000074000__000000CB82C2FF68", +"000000067F00008000000A600C0000071186-000000067F00008000000A600C000007A8EC__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C0000074000-000000067F00008000000A600C0000078000__000000CA2C877DC8", +"000000067F00008000000A600C0000074000-000000067F00008000000A600C0000078000__000000CB82C2FF68", +"000000067F00008000000A600C0000078000-000000067F00008000000A600C000007C000__000000CA2C877DC8", +"000000067F00008000000A600C0000078000-000000067F00008000000A600C000007C000__000000CB82C2FF68", +"000000067F00008000000A600C000007A149-000000067F00008000000A600C00000F5F42__000000CB40C16489-000000CB82C37859", +"000000067F00008000000A600C000007A8EC-000000067F00008000000A600C000008400A__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C000007C000-000000067F00008000000A600C0000080000__000000CA2C877DC8", +"000000067F00008000000A600C000007C000-000000067F00008000000A600C0000080000__000000CB82C2FF68", +"000000067F00008000000A600C0000080000-000000067F00008000000A600C0000084000__000000CA2C877DC8", +"000000067F00008000000A600C0000080000-000000067F00008000000A600C0000084000__000000CB82C2FF68", +"000000067F00008000000A600C0000084000-000000067F00008000000A600C0000088000__000000CA2C877DC8", +"000000067F00008000000A600C0000084000-000000067F00008000000A600C0000088000__000000CB82C2FF68", +"000000067F00008000000A600C000008400A-000000067F00008000000A600C000008D770__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C0000088000-000000067F00008000000A600C000008C000__000000CA2C877DC8", +"000000067F00008000000A600C0000088000-000000067F00008000000A600C000008C000__000000CB82C2FF68", +"000000067F00008000000A600C000008C000-000000067F00008000000A600C0000090000__000000CA2C877DC8", +"000000067F00008000000A600C000008C000-000000067F00008000000A600C0000090000__000000CB82C2FF68", +"000000067F00008000000A600C000008D770-000000067F00008000000A600C0000096ED6__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C0000090000-000000067F00008000000A600C0000094000__000000CA2C877DC8", +"000000067F00008000000A600C0000090000-000000067F00008000000A600C0000094000__000000CB82C2FF68", +"000000067F00008000000A600C0000094000-000000067F00008000000A600C0000098000__000000CA2C877DC8", +"000000067F00008000000A600C0000094000-000000067F00008000000A600C0000098000__000000CB82C2FF68", +"000000067F00008000000A600C0000096ED6-000000067F00008000000A600C00000A060B__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C0000098000-000000067F00008000000A600C000009C000__000000CA2C877DC8", +"000000067F00008000000A600C0000098000-000000067F00008000000A600C000009C000__000000CB82C2FF68", +"000000067F00008000000A600C000009C000-000000067F00008000000A600C00000A0000__000000CA2C877DC8", +"000000067F00008000000A600C000009C000-000000067F00008000000A600C00000A0000__000000CB82C2FF68", +"000000067F00008000000A600C00000A0000-000000067F00008000000A600C00000A4000__000000CA2C877DC8", +"000000067F00008000000A600C00000A0000-000000067F00008000000A600C00000A4000__000000CB82C2FF68", +"000000067F00008000000A600C00000A060B-000000067F00008000000A600C00000A9D71__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C00000A4000-000000067F00008000000A600C00000A8000__000000CA2C877DC8", +"000000067F00008000000A600C00000A4000-000000067F00008000000A600C00000A8000__000000CB82C2FF68", +"000000067F00008000000A600C00000A8000-000000067F00008000000A600C00000AC000__000000CA2C877DC8", +"000000067F00008000000A600C00000A8000-000000067F00008000000A600C00000AC000__000000CB82C2FF68", +"000000067F00008000000A600C00000A9D71-000000067F00008000000A600C00000B34D7__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C00000AC000-000000067F00008000000A600C00000B0000__000000CB82C2FF68", +"000000067F00008000000A600C00000AC000-030000000000000000000000000000000002__000000CA2C877DC8", +"000000067F00008000000A600C00000B0000-000000067F00008000000A600C00000B4000__000000CB82C2FF68", +"000000067F00008000000A600C00000B34D7-000000067F00008000000A600C00000BCC0C__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C00000B4000-000000067F00008000000A600C00000B8000__000000CB82C2FF68", +"000000067F00008000000A600C00000B8000-000000067F00008000000A600C00000BC000__000000CB82C2FF68", +"000000067F00008000000A600C00000BC000-000000067F00008000000A600C00000C0000__000000CB82C2FF68", +"000000067F00008000000A600C00000BCC0C-000000067F00008000000A600C00000C6336__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C00000C0000-000000067F00008000000A600C00000C4000__000000CB82C2FF68", +"000000067F00008000000A600C00000C4000-000000067F00008000000A600C00000C8000__000000CB82C2FF68", +"000000067F00008000000A600C00000C6336-000000067F00008000000A600C00000CFA9C__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C00000C8000-000000067F00008000000A600C00000CC000__000000CB82C2FF68", +"000000067F00008000000A600C00000CC000-000000067F00008000000A600C00000D0000__000000CB82C2FF68", +"000000067F00008000000A600C00000CFA9C-000000067F00008000000A600C00000D91AB__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C00000D0000-000000067F00008000000A600C00000D4000__000000CB82C2FF68", +"000000067F00008000000A600C00000D4000-000000067F00008000000A600C00000D8000__000000CB82C2FF68", +"000000067F00008000000A600C00000D8000-000000067F00008000000A600C00000DC000__000000CB82C2FF68", +"000000067F00008000000A600C00000D91AB-000000067F00008000000A600C00000E2911__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C00000DC000-000000067F00008000000A600C00000E0000__000000CB82C2FF68", +"000000067F00008000000A600C00000E0000-000000067F00008000000A600C00000E4000__000000CB82C2FF68", +"000000067F00008000000A600C00000E2911-000000067F00008000000A600C00000EC077__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C00000E4000-000000067F00008000000A600C00000E8000__000000CB82C2FF68", +"000000067F00008000000A600C00000E8000-000000067F00008000000A600C00000EC000__000000CB82C2FF68", +"000000067F00008000000A600C00000EC000-000000067F00008000000A600C00000F0000__000000CB82C2FF68", +"000000067F00008000000A600C00000EC077-000000067F00008000000A600C00000F57A8__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C00000F0000-000000067F00008000000A600C00000F4000__000000CB82C2FF68", +"000000067F00008000000A600C00000F4000-000000067F00008000000A600C00000F8000__000000CB82C2FF68", +"000000067F00008000000A600C00000F57A8-000000067F00008000000A600C00000FEF0A__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C00000F5F4F-000000067F00008000000A60140000011158__000000CB40C16489-000000CB82C37859", +"000000067F00008000000A600C00000F8000-000000067F00008000000A600C00000FC000__000000CB82C2FF68", +"000000067F00008000000A600C00000FC000-000000067F00008000000A600C0000100000__000000CB82C2FF68", +"000000067F00008000000A600C00000FEF0A-000000067F00008000000A600C000010862B__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C0000100000-000000067F00008000000A600C0000104000__000000CB82C2FF68", +"000000067F00008000000A600C0000104000-000000067F00008000000A600C0000108000__000000CB82C2FF68", +"000000067F00008000000A600C0000108000-000000067F00008000000A600C000010C000__000000CB82C2FF68", +"000000067F00008000000A600C000010862B-000000067F00008000000A600C0000111C20__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A600C000010C000-000000067F00008000000A600C0000110000__000000CB82C2FF68", +"000000067F00008000000A600C0000110000-000000067F00008000000A60120100000000__000000CB82C2FF68", +"000000067F00008000000A600C00001117CB-000000067F00008000000A6014000000499B__000000CAD5D7FFF1-000000CB40C16489", +"000000067F00008000000A600C00FFFFFFFF-01000000000000000100000005000000000E__000000C986F5F0D9-000000CAD5D7FFF1", +"000000067F00008000000A60140000000000-000000067F00008000000A60140000004000__000000CB82C2FF68", +"000000067F00008000000A60140000004000-000000067F00008000000A60140000008000__000000CB82C2FF68", +"000000067F00008000000A6014000000499B-000000067F00008000000A6014000000BD4E__000000CAD5D7FFF1-000000CB40C16489", +"000000067F00008000000A60140000008000-000000067F00008000000A6014000000C000__000000CB82C2FF68", +"000000067F00008000000A6014000000BD4E-000000067F00008000000A601400000130ED__000000CAD5D7FFF1-000000CB40C16489", +"000000067F00008000000A6014000000C000-000000067F00008000000A60140000010000__000000CB82C2FF68", +"000000067F00008000000A60140000010000-000000067F00008000000A60140000014000__000000CB82C2FF68", +"000000067F00008000000A60140000011159-000000067F00008000000A60140000029BB2__000000CB40C16489-000000CB82C37859", +"000000067F00008000000A601400000130ED-000000067F00008000000A6014000001A4BD__000000CAD5D7FFF1-000000CB40C16489", +"000000067F00008000000A60140000014000-000000067F00008000000A60140000018000__000000CB82C2FF68", +"000000067F00008000000A60140000018000-000000067F00008000000A6014000001C000__000000CB82C2FF68", +"000000067F00008000000A6014000001A4BD-000000067F00008000000A60140000021886__000000CAD5D7FFF1-000000CB40C16489", +"000000067F00008000000A6014000001C000-000000067F00008000000A60140000020000__000000CB82C2FF68", +"000000067F00008000000A60140000020000-000000067F00008000000A60140000024000__000000CB82C2FF68", +"000000067F00008000000A60140000021886-000000067F00008000000A60140000028C0A__000000CAD5D7FFF1-000000CB40C16489", +"000000067F00008000000A60140000024000-000000067F00008000000A60140000028000__000000CB82C2FF68", +"000000067F00008000000A60140000028000-000000067F00008000000A6014000002C000__000000CB82C2FF68", +"000000067F00008000000A60140000028C0A-030000000000000000000000000000000002__000000CAD5D7FFF1-000000CB40C16489", +"000000067F00008000000A60140000029BB2-030000000000000000000000000000000002__000000CB40C16489-000000CB82C37859", +"000000067F00008000000A6014000002C000-030000000000000000000000000000000002__000000CB82C2FF68", +"000000067F00008000000A800C0000000000-000000067F00008000000A800C0000004000__000000CD51009FE8", +"000000067F00008000000A800C0000004000-000000067F00008000000A800C0000008000__000000CD51009FE8", +"000000067F00008000000A800C0000008000-000000067F00008000000A800C000000C000__000000CD51009FE8", +"000000067F00008000000A800C0000009748-000000067F00008000000A800C0000012EAE__000000CB82C37859-000000CC11F5EDC9", +"000000067F00008000000A800C000000C000-000000067F00008000000A800C0000010000__000000CD51009FE8", +"000000067F00008000000A800C0000010000-000000067F00008000000A800C0000014000__000000CD51009FE8", +"000000067F00008000000A800C0000012EAE-000000067F00008000000A800C000001C60A__000000CB82C37859-000000CC11F5EDC9", +"000000067F00008000000A800C0000014000-000000067F00008000000A800C0000018000__000000CD51009FE8", +"000000067F00008000000A800C0000018000-000000067F00008000000A800C000001C000__000000CD51009FE8", +"000000067F00008000000A800C000001C000-000000067F00008000000A800C0000020000__000000CD51009FE8", +"000000067F00008000000A800C000001C60A-000000067F00008000000A800C0000025D38__000000CB82C37859-000000CC11F5EDC9", +"000000067F00008000000A800C0000020000-000000067F00008000000A800C0000024000__000000CD51009FE8", +"000000067F00008000000A800C0000024000-000000067F00008000000A800C0000028000__000000CD51009FE8", +"000000067F00008000000A800C0000025D38-000000067F00008000000A800C000002F49E__000000CB82C37859-000000CC11F5EDC9", +"000000067F00008000000A800C0000028000-000000067F00008000000A800C000002C000__000000CD51009FE8", +"000000067F00008000000A800C000002C000-000000067F00008000000A800C0000030000__000000CD51009FE8", +"000000067F00008000000A800C000002F49E-000000067F00008000000A800C0000038BB1__000000CB82C37859-000000CC11F5EDC9", +"000000067F00008000000A800C0000030000-000000067F00008000000A800C0000034000__000000CD51009FE8", +"000000067F00008000000A800C0000034000-000000067F00008000000A800C0000038000__000000CD51009FE8", +"000000067F00008000000A800C0000038000-000000067F00008000000A800C000003C000__000000CD51009FE8", +"000000067F00008000000A800C0000038BB1-000000067F00008000000A800C0000042317__000000CB82C37859-000000CC11F5EDC9", +"000000067F00008000000A800C000003C000-000000067F00008000000A800C0000040000__000000CD51009FE8", +"000000067F00008000000A800C0000040000-000000067F00008000000A800C0000044000__000000CD51009FE8", +"000000067F00008000000A800C0000042317-000000067F00008000000A800C000004BA7D__000000CB82C37859-000000CC11F5EDC9", +"000000067F00008000000A800C0000044000-000000067F00008000000A800C0000048000__000000CD51009FE8", +"000000067F00008000000A800C0000048000-000000067F00008000000A800C000004C000__000000CD51009FE8", +"000000067F00008000000A800C000004BA7D-000000067F00008000000A800C0000054CA0__000000CB82C37859-000000CC11F5EDC9", +"000000067F00008000000A800C000004C000-000000067F00008000000A800C0000050000__000000CD51009FE8", +"000000067F00008000000A800C0000050000-000000067F00008000000A800C0000054000__000000CD51009FE8", +"000000067F00008000000A800C0000054000-000000067F00008000000A800C0000058000__000000CD51009FE8", +"000000067F00008000000A800C0000054C9F-000000067F00008000000A800C000005E405__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C0000058000-000000067F00008000000A800C000005C000__000000CD51009FE8", +"000000067F00008000000A800C000005C000-000000067F00008000000A800C0000060000__000000CD51009FE8", +"000000067F00008000000A800C000005E405-000000067F00008000000A800C0000067B10__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C0000060000-000000067F00008000000A800C0000064000__000000CD51009FE8", +"000000067F00008000000A800C0000064000-000000067F00008000000A800C0000068000__000000CD51009FE8", +"000000067F00008000000A800C0000067B10-000000067F00008000000A800C0000071276__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C0000068000-000000067F00008000000A800C000006C000__000000CD51009FE8", +"000000067F00008000000A800C000006C000-000000067F00008000000A800C0000070000__000000CD51009FE8", +"000000067F00008000000A800C0000070000-000000067F00008000000A800C0000074000__000000CD51009FE8", +"000000067F00008000000A800C0000071276-000000067F00008000000A800C000007A9DC__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C0000074000-000000067F00008000000A800C0000078000__000000CD51009FE8", +"000000067F00008000000A800C0000078000-000000067F00008000000A800C000007C000__000000CD51009FE8", +"000000067F00008000000A800C000007A9DC-000000067F00008000000A800C000008410B__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C000007C000-000000067F00008000000A800C0000080000__000000CD51009FE8", +"000000067F00008000000A800C0000080000-000000067F00008000000A800C0000084000__000000CD51009FE8", +"000000067F00008000000A800C0000084000-000000067F00008000000A800C0000088000__000000CD51009FE8", +"000000067F00008000000A800C000008410B-000000067F00008000000A800C000008D871__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C0000088000-000000067F00008000000A800C000008C000__000000CD51009FE8", +"000000067F00008000000A800C000008C000-000000067F00008000000A800C0000090000__000000CD51009FE8", +"000000067F00008000000A800C000008D871-000000067F00008000000A800C0000096F94__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C0000090000-000000067F00008000000A800C0000094000__000000CD51009FE8", +"000000067F00008000000A800C0000094000-000000067F00008000000A800C0000098000__000000CD51009FE8", +"000000067F00008000000A800C0000096F94-000000067F00008000000A800C00000A06FA__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C0000098000-000000067F00008000000A800C000009C000__000000CD51009FE8", +"000000067F00008000000A800C000009C000-000000067F00008000000A800C00000A0000__000000CD51009FE8", +"000000067F00008000000A800C00000A0000-000000067F00008000000A800C00000A4000__000000CD51009FE8", +"000000067F00008000000A800C00000A06FA-000000067F00008000000A800C00000A9E0D__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C00000A4000-000000067F00008000000A800C00000A8000__000000CD51009FE8", +"000000067F00008000000A800C00000A8000-000000067F00008000000A800C00000AC000__000000CD51009FE8", +"000000067F00008000000A800C00000A9E0D-000000067F00008000000A800C00000B3553__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C00000AC000-000000067F00008000000A800C00000B0000__000000CD51009FE8", +"000000067F00008000000A800C00000B0000-000000067F00008000000A800C00000B4000__000000CD51009FE8", +"000000067F00008000000A800C00000B3553-000000067F00008000000A800C0100000000__000000CC11F5EDC9-000000CCB1B9E181", +"000000067F00008000000A800C00000B4000-000000067F00008000000A800C00000B8000__000000CD51009FE8", +"000000067F00008000000A800C00000B8000-000000067F00008000000A800C00000BC000__000000CD51009FE8", +"000000067F00008000000A800C00000BC000-000000067F00008000000A800C00000C0000__000000CD51009FE8", +"000000067F00008000000A800C00000BCB46-000000067F00008000000A800C00000C62AC__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000A800C00000C0000-000000067F00008000000A800C00000C4000__000000CD51009FE8", +"000000067F00008000000A800C00000C4000-000000067F00008000000A800C00000C8000__000000CD51009FE8", +"000000067F00008000000A800C00000C62AC-000000067F00008000000A800C00000CFA09__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000A800C00000C8000-000000067F00008000000A800C00000CC000__000000CD51009FE8", +"000000067F00008000000A800C00000CC000-000000067F00008000000A800C00000D0000__000000CD51009FE8", +"000000067F00008000000A800C00000CFA09-000000067F00008000000A800C00000D9118__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000A800C00000D0000-000000067F00008000000A800C00000D4000__000000CD51009FE8", +"000000067F00008000000A800C00000D4000-000000067F00008000000A800C00000D8000__000000CD51009FE8", +"000000067F00008000000A800C00000D8000-000000067F00008000000A800C00000DC000__000000CD51009FE8", +"000000067F00008000000A800C00000D9118-000000067F00008000000A800C00000E287E__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000A800C00000DC000-000000067F00008000000A800C00000E0000__000000CD51009FE8", +"000000067F00008000000A800C00000E0000-000000067F00008000000A800C00000E4000__000000CD51009FE8", +"000000067F00008000000A800C00000E287E-000000067F00008000000A800C00000EBFE4__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000A800C00000E4000-000000067F00008000000A800C00000E8000__000000CD51009FE8", +"000000067F00008000000A800C00000E8000-000000067F00008000000A800C00000EC000__000000CD51009FE8", +"000000067F00008000000A800C00000EBFE4-000000067F00008000000A800C00000F570B__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000A800C00000EC000-000000067F00008000000A800C00000F0000__000000CD51009FE8", +"000000067F00008000000A800C00000F0000-000000067F00008000000A800C00000F4000__000000CD51009FE8", +"000000067F00008000000A800C00000F4000-000000067F00008000000A800C00000F8000__000000CD51009FE8", +"000000067F00008000000A800C00000F570B-000000067F00008000000A800C00000FEE71__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000A800C00000F8000-000000067F00008000000A800C00000FC000__000000CD51009FE8", +"000000067F00008000000A800C00000FC000-000000067F00008000000A800C0000100000__000000CD51009FE8", +"000000067F00008000000A800C00000FEE71-000000067F00008000000A800C0000108587__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000A800C0000100000-000000067F00008000000A800C0000104000__000000CD51009FE8", +"000000067F00008000000A800C0000104000-000000067F00008000000A800C0000108000__000000CD51009FE8", +"000000067F00008000000A800C0000108000-000000067F00008000000A800C000010C000__000000CD51009FE8", +"000000067F00008000000A800C0000108587-000000067F00008000000A800C0000111C20__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000A800C000010C000-000000067F00008000000A800C0000110000__000000CD51009FE8", +"000000067F00008000000A800C0000110000-030000000000000000000000000000000002__000000CD51009FE8", +"000000067F00008000000A800C00FFFFFFFF-010000000000000001000000050000000011__000000CCB1B9E181-000000CD51344F89", +"000000067F00008000000A800C00FFFFFFFF-030000000000000000000000000000000002__000000CB82C37859-000000CC11F5EDC9", +"000000067F00008000000A800F0200000000-000000067F00008000000A80140000007ADF__000000CD51344F89-000000CDCC7BF889", +"000000067F00008000000A80140000007ADF-000000067F00008000000A8014000000F7D0__000000CD51344F89-000000CDCC7BF889", +"000000067F00008000000A8014000000F7D0-000000067F00008000000A801400000176D0__000000CD51344F89-000000CDCC7BF889", +"000000067F00008000000A801400000176D0-000000067F00008000000A8014000001F5D2__000000CD51344F89-000000CDCC7BF889", +"000000067F00008000000A8014000001F5D2-000000067F00008000000A801400000274D5__000000CD51344F89-000000CDCC7BF889", +"000000067F00008000000A801400000274D5-000000067F00008000000AA00C0000001863__000000CD51344F89-000000CDCC7BF889", +"000000067F00008000000AA00C0000000000-000000067F00008000000AA00C0000004000__000000CF7E08BFD0", +"000000067F00008000000AA00C0000001863-000000067F00008000000AA00C000000AFC9__000000CD51344F89-000000CDCC7BF889", +"000000067F00008000000AA00C0000004000-000000067F00008000000AA00C0000008000__000000CF7E08BFD0", +"000000067F00008000000AA00C0000008000-000000067F00008000000AA00C000000C000__000000CF7E08BFD0", +"000000067F00008000000AA00C000000AFC9-030000000000000000000000000000000002__000000CD51344F89-000000CDCC7BF889", +"000000067F00008000000AA00C000000C000-000000067F00008000000AA00C0000010000__000000CF7E08BFD0", +"000000067F00008000000AA00C0000010000-000000067F00008000000AA00C0000014000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000126EC-000000067F00008000000AA00C000001BE0C__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C0000014000-000000067F00008000000AA00C0000018000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000018000-000000067F00008000000AA00C000001C000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000001BE0C-000000067F00008000000AA00C000002553F__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C000001C000-000000067F00008000000AA00C0000020000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000020000-000000067F00008000000AA00C0000024000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000024000-000000067F00008000000AA00C0000028000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000002553F-000000067F00008000000AA00C000002ECA5__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C0000028000-000000067F00008000000AA00C000002C000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000002C000-000000067F00008000000AA00C0000030000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000002ECA5-000000067F00008000000AA00C00000383BC__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C0000030000-000000067F00008000000AA00C0000034000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000034000-000000067F00008000000AA00C0000038000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000038000-000000067F00008000000AA00C000003C000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000383BC-000000067F00008000000AA00C0000041B0A__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C000003C000-000000067F00008000000AA00C0000040000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000040000-000000067F00008000000AA00C0000044000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000041B0A-000000067F00008000000AA00C000004B270__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C0000044000-000000067F00008000000AA00C0000048000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000048000-000000067F00008000000AA00C000004C000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000004B270-000000067F00008000000AA00C00000549AA__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C000004C000-000000067F00008000000AA00C0000050000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000050000-000000067F00008000000AA00C0000054000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000054000-000000067F00008000000AA00C0000058000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000549AA-000000067F00008000000AA00C000005E10B__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C0000058000-000000067F00008000000AA00C000005C000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000005C000-000000067F00008000000AA00C0000060000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000005E10B-000000067F00008000000AA00C000006782C__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C0000060000-000000067F00008000000AA00C0000064000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000064000-000000067F00008000000AA00C0000068000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000006782C-000000067F00008000000AA00C0000070F88__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C0000068000-000000067F00008000000AA00C000006C000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000006C000-000000067F00008000000AA00C0000070000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000070000-000000067F00008000000AA00C0000074000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000070F88-000000067F00008000000AA00C0100000000__000000CDCC7BF889-000000CE6C3FED31", +"000000067F00008000000AA00C0000074000-000000067F00008000000AA00C0000078000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000078000-000000067F00008000000AA00C000007C000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000078E97-000000067F00008000000AA00C00000823F9__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C000007C000-000000067F00008000000AA00C0000080000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000080000-000000067F00008000000AA00C0000084000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000823F9-000000067F00008000000AA00C000008BA8A__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C0000084000-000000067F00008000000AA00C0000088000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000088000-000000067F00008000000AA00C000008C000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000008BA8A-000000067F00008000000AA00C00000951BF__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C000008C000-000000067F00008000000AA00C0000090000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000090000-000000067F00008000000AA00C0000094000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000094000-000000067F00008000000AA00C0000098000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000951BF-000000067F00008000000AA00C000009E90A__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C0000098000-000000067F00008000000AA00C000009C000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000009C000-000000067F00008000000AA00C00000A0000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000009E90A-000000067F00008000000AA00C00000A802B__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C00000A0000-000000067F00008000000AA00C00000A4000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000A4000-000000067F00008000000AA00C00000A8000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000A8000-000000067F00008000000AA00C00000AC000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000A802B-000000067F00008000000AA00C00000B1782__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C00000AC000-000000067F00008000000AA00C00000B0000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000B0000-000000067F00008000000AA00C00000B4000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000B1782-000000067F00008000000AA00C00000BAEE8__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C00000B4000-000000067F00008000000AA00C00000B8000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000B8000-000000067F00008000000AA00C00000BC000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000BAEE8-000000067F00008000000AA00C00000C460C__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C00000BC000-000000067F00008000000AA00C00000C0000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000C0000-000000067F00008000000AA00C00000C4000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000C4000-000000067F00008000000AA00C00000C8000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000C460C-000000067F00008000000AA00C00000CDD72__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C00000C8000-000000067F00008000000AA00C00000CC000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000CC000-000000067F00008000000AA00C00000D0000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000CDD72-000000067F00008000000AA00C00000D74D8__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C00000D0000-000000067F00008000000AA00C00000D4000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000D4000-000000067F00008000000AA00C00000D8000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000D74D8-000000067F00008000000AA00C00000E0C0B__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C00000D8000-000000067F00008000000AA00C00000DC000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000DC000-000000067F00008000000AA00C00000E0000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000E0000-000000067F00008000000AA00C00000E4000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000E0C0B-000000067F00008000000AA00C00000EA371__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C00000E4000-000000067F00008000000AA00C00000E8000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000E8000-000000067F00008000000AA00C00000EC000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000EA371-000000067F00008000000AA00C00000F3AD7__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C00000EC000-000000067F00008000000AA00C00000F0000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000F0000-000000067F00008000000AA00C00000F4000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000F3AD7-000000067F00008000000AA00C00000FD20B__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C00000F4000-000000067F00008000000AA00C00000F8000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000F8000-000000067F00008000000AA00C00000FC000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000FC000-000000067F00008000000AA00C0000100000__000000CF7B8D3FD0", +"000000067F00008000000AA00C00000FD20B-000000067F00008000000AA00C0000106932__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C0000100000-000000067F00008000000AA00C0000104000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000104000-000000067F00008000000AA00C0000108000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000106932-000000067F00008000000AA00C0000110098__000000CE6C3FED31-000000CF7DC97FD1", +"000000067F00008000000AA00C0000108000-000000067F00008000000AA00C000010C000__000000CF7B8D3FD0", +"000000067F00008000000AA00C000010C000-000000067F00008000000AA00C0000110000__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000110000-030000000000000000000000000000000002__000000CF7B8D3FD0", +"000000067F00008000000AA00C0000110098-010000000000000001000000050000000012__000000CE6C3FED31-000000CF7DC97FD1", +"010000000000000001000000000000000000-030000000000000000000000000000000002__000000A29F1D8950", +"030000000000000000000000000000000001-030000000000000000000000000000000002__000000C689AF4AC1-000000C6C87B6329", +]; diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index 3dd2f92b5e..47ef9284b8 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -59,13 +59,14 @@ pub mod block_io; mod delta_layer; mod disk_btree; pub(crate) mod ephemeral_file; -mod filename; +pub mod filename; mod image_layer; mod inmemory_layer; -mod layer_map; +pub mod layer_map; + pub mod metadata; mod par_fsync; -mod storage_layer; +pub mod storage_layer; mod timeline; From 2418e726491991370f0fbefabad237109e7cc500 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Mon, 17 Oct 2022 16:51:01 +0300 Subject: [PATCH 35/64] Speed up layer_map::search, by remembering the "envelope" for each layer. Lookups in the R-tree call the "envelope" function for every comparison, and our envelope function isn't very cheap, so that overhead adds up. Create the envelope once, when the layer is inserted into the tree, and store it along with the layer. That uses some more memory per layer, but that's not very significant. Speeds up the search operation 2x --- pageserver/src/tenant/layer_map.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/pageserver/src/tenant/layer_map.rs b/pageserver/src/tenant/layer_map.rs index 495833e3ae..9d914c1839 100644 --- a/pageserver/src/tenant/layer_map.rs +++ b/pageserver/src/tenant/layer_map.rs @@ -62,6 +62,8 @@ pub struct LayerMap { struct LayerRTreeObject { layer: Arc, + + envelope: AABB<[IntKey; 2]>, } // Representation of Key as numeric type. @@ -197,9 +199,16 @@ impl PartialEq for LayerRTreeObject { impl RTreeObject for LayerRTreeObject { type Envelope = AABB<[IntKey; 2]>; fn envelope(&self) -> Self::Envelope { - let key_range = self.layer.get_key_range(); - let lsn_range = self.layer.get_lsn_range(); - AABB::from_corners( + self.envelope + } +} + +impl LayerRTreeObject { + fn new(layer: Arc) -> Self { + let key_range = layer.get_key_range(); + let lsn_range = layer.get_lsn_range(); + + let envelope = AABB::from_corners( [ IntKey::from(key_range.start.to_i128()), IntKey::from(lsn_range.start.0 as i128), @@ -208,7 +217,8 @@ impl RTreeObject for LayerRTreeObject { IntKey::from(key_range.end.to_i128() - 1), IntKey::from(lsn_range.end.0 as i128 - 1), ], // AABB::upper is inclusive, while `key_range.end` and `lsn_range.end` are exclusive - ) + ); + LayerRTreeObject { layer, envelope } } } @@ -338,7 +348,7 @@ impl LayerMap { if layer.get_key_range() == (Key::MIN..Key::MAX) { self.l0_delta_layers.push(layer.clone()); } - self.historic_layers.insert(LayerRTreeObject { layer }); + self.historic_layers.insert(LayerRTreeObject::new(layer)); NUM_ONDISK_LAYERS.inc(); } @@ -362,7 +372,7 @@ impl LayerMap { } assert!(self .historic_layers - .remove(&LayerRTreeObject { layer }) + .remove(&LayerRTreeObject::new(layer)) .is_some()); NUM_ONDISK_LAYERS.dec(); } From 59bc7e67e0e406576c0d1e670815253892a891bc Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Mon, 17 Oct 2022 16:54:04 +0300 Subject: [PATCH 36/64] Use an optimized version of amplify_num. Speeds up layer_map::search somewhat. I also opened a PR in the upstream rust-amplify repository with these changes, see https://github.com/rust-amplify/rust-amplify/pull/148. We can switch back to upstream version when that's merged. --- Cargo.lock | 3 +-- pageserver/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d02ec1f5a1..657baf5d80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,8 +40,7 @@ dependencies = [ [[package]] name = "amplify_num" version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27d3d00d3d115395a7a8a4dc045feb7aa82b641e485f7e15f4e67ac16f4f56d" +source = "git+https://github.com/hlinnaka/rust-amplify.git?branch=unsigned-int-perf#bd49b737c2e6e623ab8e9ba5ceaed5712d3a3940" [[package]] name = "android_system_properties" diff --git a/pageserver/Cargo.toml b/pageserver/Cargo.toml index 75aa6e93eb..2139e24ee2 100644 --- a/pageserver/Cargo.toml +++ b/pageserver/Cargo.toml @@ -56,7 +56,7 @@ fail = "0.5.0" git-version = "0.3.5" rstar = "0.9.3" num-traits = "0.2.15" -amplify_num = "0.4.1" +amplify_num = { git = "https://github.com/hlinnaka/rust-amplify.git", branch = "unsigned-int-perf" } pageserver_api = { path = "../libs/pageserver_api" } postgres_ffi = { path = "../libs/postgres_ffi" } From 546e9bdbec4ebdabdf39ea5e70c625fb5a53ca4b Mon Sep 17 00:00:00 2001 From: Sergey Melnikov Date: Tue, 18 Oct 2022 15:52:15 +0300 Subject: [PATCH 37/64] Deploy storage into new account and migrate to management API v2 (#2619) Deploy storage into new account Migrate safekeeper and pageserver initialisation to management api v2 --- .github/ansible/deploy.yaml | 6 +-- .github/ansible/neon-stress.hosts.yaml | 13 +++--- .github/ansible/production.hosts.yaml | 12 ++--- .github/ansible/scripts/init_pageserver.sh | 9 ++-- .github/ansible/scripts/init_safekeeper.sh | 10 ++--- .github/ansible/ssm_config | 3 ++ .github/ansible/staging.hosts.yaml | 22 ++++----- .github/ansible/staging.us-east-2.hosts.yaml | 32 +++++++++++++ .github/ansible/systemd/pageserver.service | 2 +- .github/ansible/systemd/safekeeper.service | 4 +- .github/workflows/build_and_test.yml | 47 ++++++++++++++++++-- 11 files changed, 116 insertions(+), 44 deletions(-) create mode 100644 .github/ansible/ssm_config create mode 100644 .github/ansible/staging.us-east-2.hosts.yaml diff --git a/.github/ansible/deploy.yaml b/.github/ansible/deploy.yaml index bfd3fd123d..4adc685684 100644 --- a/.github/ansible/deploy.yaml +++ b/.github/ansible/deploy.yaml @@ -1,7 +1,7 @@ - name: Upload Neon binaries hosts: storage gather_facts: False - remote_user: admin + remote_user: "{{ remote_user }}" tasks: @@ -36,7 +36,7 @@ - name: Deploy pageserver hosts: pageservers gather_facts: False - remote_user: admin + remote_user: "{{ remote_user }}" tasks: @@ -124,7 +124,7 @@ - name: Deploy safekeeper hosts: safekeepers gather_facts: False - remote_user: admin + remote_user: "{{ remote_user }}" tasks: diff --git a/.github/ansible/neon-stress.hosts.yaml b/.github/ansible/neon-stress.hosts.yaml index d4c77e7ada..8afc9a5be8 100644 --- a/.github/ansible/neon-stress.hosts.yaml +++ b/.github/ansible/neon-stress.hosts.yaml @@ -12,19 +12,20 @@ storage: bucket_name: "{{ bucket_name }}" bucket_region: "{{ bucket_region }}" prefix_in_bucket: "{{ inventory_hostname }}" - + hostname_suffix: ".local" + remote_user: admin children: pageservers: hosts: neon-stress-ps-1: - console_region_id: 1 + console_region_id: aws-eu-west-1 neon-stress-ps-2: - console_region_id: 1 + console_region_id: aws-eu-west-1 safekeepers: hosts: neon-stress-sk-1: - console_region_id: 1 + console_region_id: aws-eu-west-1 neon-stress-sk-2: - console_region_id: 1 + console_region_id: aws-eu-west-1 neon-stress-sk-3: - console_region_id: 1 + console_region_id: aws-eu-west-1 diff --git a/.github/ansible/production.hosts.yaml b/.github/ansible/production.hosts.yaml index c276ca3805..9f9b12d25d 100644 --- a/.github/ansible/production.hosts.yaml +++ b/.github/ansible/production.hosts.yaml @@ -12,20 +12,22 @@ storage: bucket_name: "{{ bucket_name }}" bucket_region: "{{ bucket_region }}" prefix_in_bucket: "{{ inventory_hostname }}" + hostname_suffix: ".local" + remote_user: admin children: pageservers: hosts: zenith-1-ps-2: - console_region_id: 1 + console_region_id: aws-us-west-2 zenith-1-ps-3: - console_region_id: 1 + console_region_id: aws-us-west-2 safekeepers: hosts: zenith-1-sk-1: - console_region_id: 1 + console_region_id: aws-us-west-2 zenith-1-sk-2: - console_region_id: 1 + console_region_id: aws-us-west-2 zenith-1-sk-3: - console_region_id: 1 + console_region_id: aws-us-west-2 diff --git a/.github/ansible/scripts/init_pageserver.sh b/.github/ansible/scripts/init_pageserver.sh index 1cbdd0db94..426925a837 100644 --- a/.github/ansible/scripts/init_pageserver.sh +++ b/.github/ansible/scripts/init_pageserver.sh @@ -12,18 +12,19 @@ cat <> $GITHUB_OUTPUT elif [[ "$GITHUB_REF_NAME" == "release" ]]; then - PRODUCTION='{"env_name": "production", "proxy_job": "neon-proxy", "proxy_config": "production.proxy", "kubeconfig_secret": "PRODUCTION_KUBECONFIG_DATA"}' + PRODUCTION='{"env_name": "production", "proxy_job": "neon-proxy", "proxy_config": "production.proxy", "kubeconfig_secret": "PRODUCTION_KUBECONFIG_DATA", "console_api_key_secret": "NEON_PRODUCTION_API_KEY"}' echo "include=[$PRODUCTION]" >> $GITHUB_OUTPUT else echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main' or 'release'" @@ -735,7 +735,46 @@ jobs: ssh-add ssh-key rm -f ssh-key ssh-key-cert.pub ansible-galaxy collection install sivel.toiletwater - ansible-playbook deploy.yaml -i ${{ matrix.env_name }}.hosts.yaml + ansible-playbook deploy.yaml -i ${{ matrix.env_name }}.hosts.yaml -e CONSOLE_API_TOKEN=${{ secrets[matrix.console_api_key_secret] }} + rm -f neon_install.tar.gz .neon_current_version + + deploy-new: + runs-on: dev + container: 369495373322.dkr.ecr.eu-central-1.amazonaws.com/ansible:pinned + # We need both storage **and** compute images for deploy, because control plane picks the compute version based on the storage version. + # If it notices a fresh storage it may bump the compute version. And if compute image failed to build it may break things badly + needs: [ push-docker-hub, calculate-deploy-targets, tag, regress-tests ] + if: | + (github.ref_name == 'main') && + github.event_name != 'workflow_dispatch' + defaults: + run: + shell: bash + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_DEV }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_KEY_DEV }} + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: true + fetch-depth: 0 + + - name: Redeploy + run: | + export DOCKER_TAG=${{needs.tag.outputs.build-tag}} + cd "$(pwd)/.github/ansible" + + if [[ "$GITHUB_REF_NAME" == "main" ]]; then + ./get_binaries.sh + elif [[ "$GITHUB_REF_NAME" == "release" ]]; then + RELEASE=true ./get_binaries.sh + else + echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main' or 'release'" + exit 1 + fi + + ansible-playbook deploy.yaml -i staging.us-east-2.hosts.yaml -e @ssm_config -e CONSOLE_API_TOKEN=${{secrets.NEON_STAGING_API_KEY}} rm -f neon_install.tar.gz .neon_current_version deploy-proxy: From 0cd2d91b9d114010b41a41baf736182160d3be04 Mon Sep 17 00:00:00 2001 From: Sergey Melnikov Date: Tue, 18 Oct 2022 17:44:19 +0300 Subject: [PATCH 38/64] Fix deploy-new job by installing sivel.toiletwater (#2641) --- .github/workflows/build_and_test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index ad68b09832..d90455ccca 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -774,6 +774,7 @@ jobs: exit 1 fi + ansible-galaxy collection install sivel.toiletwater ansible-playbook deploy.yaml -i staging.us-east-2.hosts.yaml -e @ssm_config -e CONSOLE_API_TOKEN=${{secrets.NEON_STAGING_API_KEY}} rm -f neon_install.tar.gz .neon_current_version From 41550ec8bfcb0fa558662012a4c0e7e44dfbc919 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Tue, 18 Oct 2022 17:00:06 +0300 Subject: [PATCH 39/64] Remove unnecessary indirections of libpqwalproposer functions In the Postgres backend, we cannot link directly with libpq (check the pgsql-hackers arhive for all kinds of fun that ensued when we tried to do that). Therefore, the libpq functions are used through the thin wrapper functions in libpqwalreceiver.so, and libpqwalreceiver.so is loaded dynamically. To hide the dynamic loading and make the calls look like regular functions, we use macros to hide the function pointers. We had inherited the same indirections in libpqwalproposer, but it's not needed since the neon extension is already a shared library that's loaded dynamically. There's no problem calling the functions directly there. Remove the indirections. --- pgxn/neon/libpqwalproposer.c | 99 +++++++++++------------------------- pgxn/neon/neon.c | 1 - pgxn/neon/neon.h | 1 - pgxn/neon/walproposer.c | 7 --- pgxn/neon/walproposer.h | 81 +++++------------------------ 5 files changed, 42 insertions(+), 147 deletions(-) diff --git a/pgxn/neon/libpqwalproposer.c b/pgxn/neon/libpqwalproposer.c index 1f739f3722..6b1e6a8bcc 100644 --- a/pgxn/neon/libpqwalproposer.c +++ b/pgxn/neon/libpqwalproposer.c @@ -10,51 +10,12 @@ struct WalProposerConn PGconn *pg_conn; bool is_nonblocking; /* whether the connection is non-blocking */ char *recvbuf; /* last received data from - * libpqprop_async_read */ + * walprop_async_read */ }; -/* Prototypes for exported functions */ -static char *libpqprop_error_message(WalProposerConn * conn); -static WalProposerConnStatusType libpqprop_status(WalProposerConn * conn); -static WalProposerConn * libpqprop_connect_start(char *conninfo); -static WalProposerConnectPollStatusType libpqprop_connect_poll(WalProposerConn * conn); -static bool libpqprop_send_query(WalProposerConn * conn, char *query); -static WalProposerExecStatusType libpqprop_get_query_result(WalProposerConn * conn); -static pgsocket libpqprop_socket(WalProposerConn * conn); -static int libpqprop_flush(WalProposerConn * conn); -static void libpqprop_finish(WalProposerConn * conn); -static PGAsyncReadResult libpqprop_async_read(WalProposerConn * conn, char **buf, int *amount); -static PGAsyncWriteResult libpqprop_async_write(WalProposerConn * conn, void const *buf, size_t size); -static bool libpqprop_blocking_write(WalProposerConn * conn, void const *buf, size_t size); - -static WalProposerFunctionsType PQWalProposerFunctions = -{ - libpqprop_error_message, - libpqprop_status, - libpqprop_connect_start, - libpqprop_connect_poll, - libpqprop_send_query, - libpqprop_get_query_result, - libpqprop_socket, - libpqprop_flush, - libpqprop_finish, - libpqprop_async_read, - libpqprop_async_write, - libpqprop_blocking_write, -}; - -/* Module initialization */ -void -pg_init_libpqwalproposer(void) -{ - if (WalProposerFunctions != NULL) - elog(ERROR, "libpqwalproposer already loaded"); - WalProposerFunctions = &PQWalProposerFunctions; -} - /* Helper function */ static bool -ensure_nonblocking_status(WalProposerConn * conn, bool is_nonblocking) +ensure_nonblocking_status(WalProposerConn *conn, bool is_nonblocking) { /* If we're already correctly blocking or nonblocking, all good */ if (is_nonblocking == conn->is_nonblocking) @@ -69,14 +30,14 @@ ensure_nonblocking_status(WalProposerConn * conn, bool is_nonblocking) } /* Exported function definitions */ -static char * -libpqprop_error_message(WalProposerConn * conn) +char * +walprop_error_message(WalProposerConn *conn) { return PQerrorMessage(conn->pg_conn); } -static WalProposerConnStatusType -libpqprop_status(WalProposerConn * conn) +WalProposerConnStatusType +walprop_status(WalProposerConn *conn) { switch (PQstatus(conn->pg_conn)) { @@ -89,8 +50,8 @@ libpqprop_status(WalProposerConn * conn) } } -static WalProposerConn * -libpqprop_connect_start(char *conninfo) +WalProposerConn * +walprop_connect_start(char *conninfo) { WalProposerConn *conn; PGconn *pg_conn; @@ -119,8 +80,8 @@ libpqprop_connect_start(char *conninfo) return conn; } -static WalProposerConnectPollStatusType -libpqprop_connect_poll(WalProposerConn * conn) +WalProposerConnectPollStatusType +walprop_connect_poll(WalProposerConn *conn) { WalProposerConnectPollStatusType return_val; @@ -160,8 +121,8 @@ libpqprop_connect_poll(WalProposerConn * conn) return return_val; } -static bool -libpqprop_send_query(WalProposerConn * conn, char *query) +bool +walprop_send_query(WalProposerConn *conn, char *query) { /* * We need to be in blocking mode for sending the query to run without @@ -177,8 +138,8 @@ libpqprop_send_query(WalProposerConn * conn, char *query) return true; } -static WalProposerExecStatusType -libpqprop_get_query_result(WalProposerConn * conn) +WalProposerExecStatusType +walprop_get_query_result(WalProposerConn *conn) { PGresult *result; WalProposerExecStatusType return_val; @@ -255,20 +216,20 @@ libpqprop_get_query_result(WalProposerConn * conn) return return_val; } -static pgsocket -libpqprop_socket(WalProposerConn * conn) +pgsocket +walprop_socket(WalProposerConn *conn) { return PQsocket(conn->pg_conn); } -static int -libpqprop_flush(WalProposerConn * conn) +int +walprop_flush(WalProposerConn *conn) { return (PQflush(conn->pg_conn)); } -static void -libpqprop_finish(WalProposerConn * conn) +void +walprop_finish(WalProposerConn *conn) { if (conn->recvbuf != NULL) PQfreemem(conn->recvbuf); @@ -282,8 +243,8 @@ libpqprop_finish(WalProposerConn * conn) * On success, the data is placed in *buf. It is valid until the next call * to this function. */ -static PGAsyncReadResult -libpqprop_async_read(WalProposerConn * conn, char **buf, int *amount) +PGAsyncReadResult +walprop_async_read(WalProposerConn *conn, char **buf, int *amount) { int result; @@ -353,8 +314,8 @@ libpqprop_async_read(WalProposerConn * conn, char **buf, int *amount) } } -static PGAsyncWriteResult -libpqprop_async_write(WalProposerConn * conn, void const *buf, size_t size) +PGAsyncWriteResult +walprop_async_write(WalProposerConn *conn, void const *buf, size_t size) { int result; @@ -408,8 +369,12 @@ libpqprop_async_write(WalProposerConn * conn, void const *buf, size_t size) } } -static bool -libpqprop_blocking_write(WalProposerConn * conn, void const *buf, size_t size) +/* + * This function is very similar to walprop_async_write. For more + * information, refer to the comments there. + */ +bool +walprop_blocking_write(WalProposerConn *conn, void const *buf, size_t size) { int result; @@ -417,10 +382,6 @@ libpqprop_blocking_write(WalProposerConn * conn, void const *buf, size_t size) if (!ensure_nonblocking_status(conn, false)) return false; - /* - * Ths function is very similar to libpqprop_async_write. For more - * information, refer to the comments there - */ if ((result = PQputCopyData(conn->pg_conn, buf, size)) == -1) return false; diff --git a/pgxn/neon/neon.c b/pgxn/neon/neon.c index 2a2a163ee8..5c98902554 100644 --- a/pgxn/neon/neon.c +++ b/pgxn/neon/neon.c @@ -32,7 +32,6 @@ void _PG_init(void) { pg_init_libpagestore(); - pg_init_libpqwalproposer(); pg_init_walproposer(); EmitWarningsOnPlaceholders("neon"); diff --git a/pgxn/neon/neon.h b/pgxn/neon/neon.h index dad9c1b508..6b9ba372fb 100644 --- a/pgxn/neon/neon.h +++ b/pgxn/neon/neon.h @@ -13,7 +13,6 @@ #define NEON_H extern void pg_init_libpagestore(void); -extern void pg_init_libpqwalproposer(void); extern void pg_init_walproposer(void); #endif /* NEON_H */ diff --git a/pgxn/neon/walproposer.c b/pgxn/neon/walproposer.c index ff37be2de1..29290fa736 100644 --- a/pgxn/neon/walproposer.c +++ b/pgxn/neon/walproposer.c @@ -79,9 +79,6 @@ bool am_wal_proposer; char *neon_timeline_walproposer = NULL; char *neon_tenant_walproposer = NULL; -/* Declared in walproposer.h, defined here, initialized in libpqwalproposer.c */ -WalProposerFunctionsType *WalProposerFunctions = NULL; - #define WAL_PROPOSER_SLOT_NAME "wal_proposer_slot" static int n_safekeepers = 0; @@ -438,10 +435,6 @@ WalProposerInitImpl(XLogRecPtr flushRecPtr, uint64 systemId) char *sep; char *port; - /* Load the libpq-specific functions */ - if (WalProposerFunctions == NULL) - elog(ERROR, "libpqwalproposer didn't initialize correctly"); - load_file("libpqwalreceiver", false); if (WalReceiverFunctions == NULL) elog(ERROR, "libpqwalreceiver didn't initialize correctly"); diff --git a/pgxn/neon/walproposer.h b/pgxn/neon/walproposer.h index 051c7c02a6..e237947441 100644 --- a/pgxn/neon/walproposer.h +++ b/pgxn/neon/walproposer.h @@ -446,31 +446,31 @@ typedef enum } WalProposerConnStatusType; /* Re-exported PQerrorMessage */ -typedef char *(*walprop_error_message_fn) (WalProposerConn * conn); +extern char *walprop_error_message(WalProposerConn *conn); /* Re-exported PQstatus */ -typedef WalProposerConnStatusType(*walprop_status_fn) (WalProposerConn * conn); +extern WalProposerConnStatusType walprop_status(WalProposerConn *conn); /* Re-exported PQconnectStart */ -typedef WalProposerConn * (*walprop_connect_start_fn) (char *conninfo); +extern WalProposerConn * walprop_connect_start(char *conninfo); /* Re-exported PQconectPoll */ -typedef WalProposerConnectPollStatusType(*walprop_connect_poll_fn) (WalProposerConn * conn); +extern WalProposerConnectPollStatusType walprop_connect_poll(WalProposerConn *conn); /* Blocking wrapper around PQsendQuery */ -typedef bool (*walprop_send_query_fn) (WalProposerConn * conn, char *query); +extern bool walprop_send_query(WalProposerConn *conn, char *query); /* Wrapper around PQconsumeInput + PQisBusy + PQgetResult */ -typedef WalProposerExecStatusType(*walprop_get_query_result_fn) (WalProposerConn * conn); +extern WalProposerExecStatusType walprop_get_query_result(WalProposerConn *conn); /* Re-exported PQsocket */ -typedef pgsocket (*walprop_socket_fn) (WalProposerConn * conn); +extern pgsocket walprop_socket(WalProposerConn *conn); /* Wrapper around PQconsumeInput (if socket's read-ready) + PQflush */ -typedef int (*walprop_flush_fn) (WalProposerConn * conn); +extern int walprop_flush(WalProposerConn *conn); /* Re-exported PQfinish */ -typedef void (*walprop_finish_fn) (WalProposerConn * conn); +extern void walprop_finish(WalProposerConn *conn); /* * Ergonomic wrapper around PGgetCopyData @@ -486,9 +486,7 @@ typedef void (*walprop_finish_fn) (WalProposerConn * conn); * performs a bit of extra checking work that's always required and is normally * somewhat verbose. */ -typedef PGAsyncReadResult(*walprop_async_read_fn) (WalProposerConn * conn, - char **buf, - int *amount); +extern PGAsyncReadResult walprop_async_read(WalProposerConn *conn, char **buf, int *amount); /* * Ergonomic wrapper around PQputCopyData + PQflush @@ -497,69 +495,14 @@ typedef PGAsyncReadResult(*walprop_async_read_fn) (WalProposerConn * conn, * * For information on the meaning of return codes, refer to PGAsyncWriteResult. */ -typedef PGAsyncWriteResult(*walprop_async_write_fn) (WalProposerConn * conn, - void const *buf, - size_t size); +extern PGAsyncWriteResult walprop_async_write(WalProposerConn *conn, void const *buf, size_t size); /* * Blocking equivalent to walprop_async_write_fn * * Returns 'true' if successful, 'false' on failure. */ -typedef bool (*walprop_blocking_write_fn) (WalProposerConn * conn, void const *buf, size_t size); - -/* All libpqwalproposer exported functions collected together. */ -typedef struct WalProposerFunctionsType -{ - walprop_error_message_fn walprop_error_message; - walprop_status_fn walprop_status; - walprop_connect_start_fn walprop_connect_start; - walprop_connect_poll_fn walprop_connect_poll; - walprop_send_query_fn walprop_send_query; - walprop_get_query_result_fn walprop_get_query_result; - walprop_socket_fn walprop_socket; - walprop_flush_fn walprop_flush; - walprop_finish_fn walprop_finish; - walprop_async_read_fn walprop_async_read; - walprop_async_write_fn walprop_async_write; - walprop_blocking_write_fn walprop_blocking_write; -} WalProposerFunctionsType; - -/* Allow the above functions to be "called" with normal syntax */ -#define walprop_error_message(conn) \ - WalProposerFunctions->walprop_error_message(conn) -#define walprop_status(conn) \ - WalProposerFunctions->walprop_status(conn) -#define walprop_connect_start(conninfo) \ - WalProposerFunctions->walprop_connect_start(conninfo) -#define walprop_connect_poll(conn) \ - WalProposerFunctions->walprop_connect_poll(conn) -#define walprop_send_query(conn, query) \ - WalProposerFunctions->walprop_send_query(conn, query) -#define walprop_get_query_result(conn) \ - WalProposerFunctions->walprop_get_query_result(conn) -#define walprop_set_nonblocking(conn, arg) \ - WalProposerFunctions->walprop_set_nonblocking(conn, arg) -#define walprop_socket(conn) \ - WalProposerFunctions->walprop_socket(conn) -#define walprop_flush(conn) \ - WalProposerFunctions->walprop_flush(conn) -#define walprop_finish(conn) \ - WalProposerFunctions->walprop_finish(conn) -#define walprop_async_read(conn, buf, amount) \ - WalProposerFunctions->walprop_async_read(conn, buf, amount) -#define walprop_async_write(conn, buf, size) \ - WalProposerFunctions->walprop_async_write(conn, buf, size) -#define walprop_blocking_write(conn, buf, size) \ - WalProposerFunctions->walprop_blocking_write(conn, buf, size) - -/* - * The runtime location of the libpqwalproposer functions. - * - * This pointer is set by the initializer in libpqwalproposer, so that we - * can use it later. - */ -extern PGDLLIMPORT WalProposerFunctionsType * WalProposerFunctions; +extern bool walprop_blocking_write(WalProposerConn *conn, void const *buf, size_t size); extern uint64 BackpressureThrottlingTime(void); From 7ca72578f9ad5a675701c04e31d36722bce2ad9a Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Tue, 18 Oct 2022 13:40:57 +0300 Subject: [PATCH 40/64] Enable plv8 again Now with quickfix for https://github.com/plv8/plv8/issues/503 --- Dockerfile.compute-node-v14 | 5 +++-- Dockerfile.compute-node-v15 | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Dockerfile.compute-node-v14 b/Dockerfile.compute-node-v14 index ed57b29009..f5ccdf7e99 100644 --- a/Dockerfile.compute-node-v14 +++ b/Dockerfile.compute-node-v14 @@ -71,10 +71,12 @@ RUN apt update && \ RUN apt update && \ apt install -y --no-install-recommends -t testing binutils +# Sed is used to patch for https://github.com/plv8/plv8/issues/503 RUN wget https://github.com/plv8/plv8/archive/refs/tags/v3.1.4.tar.gz && \ tar xvzf v3.1.4.tar.gz && \ cd plv8-3.1.4 && \ export PATH="/usr/local/pgsql/bin:$PATH" && \ + sed -i 's/MemoryContextAlloc(/MemoryContextAllocZero(/' plv8.cc && \ make -j $(getconf _NPROCESSORS_ONLN) && \ make -j $(getconf _NPROCESSORS_ONLN) install && \ rm -rf /plv8-* && \ @@ -116,8 +118,7 @@ RUN wget https://github.com/zachasme/h3-pg/archive/refs/tags/v4.0.1.tar.gz -O h3 # FROM build-deps AS neon-pg-ext-build COPY --from=postgis-build /usr/local/pgsql/ /usr/local/pgsql/ -# plv8 still sometimes crashes during the creation -# COPY --from=plv8-build /usr/local/pgsql/ /usr/local/pgsql/ +COPY --from=plv8-build /usr/local/pgsql/ /usr/local/pgsql/ COPY --from=h3-pg-build /usr/local/pgsql/ /usr/local/pgsql/ COPY --from=h3-pg-build /h3/usr / COPY pgxn/ pgxn/ diff --git a/Dockerfile.compute-node-v15 b/Dockerfile.compute-node-v15 index bdb4330c4f..ec555ad932 100644 --- a/Dockerfile.compute-node-v15 +++ b/Dockerfile.compute-node-v15 @@ -76,10 +76,12 @@ RUN apt update && \ RUN apt update && \ apt install -y --no-install-recommends -t testing binutils +# Sed is used to patch for https://github.com/plv8/plv8/issues/503 RUN wget https://github.com/plv8/plv8/archive/refs/tags/v3.1.4.tar.gz && \ tar xvzf v3.1.4.tar.gz && \ cd plv8-3.1.4 && \ export PATH="/usr/local/pgsql/bin:$PATH" && \ + sed -i 's/MemoryContextAlloc(/MemoryContextAllocZero(/' plv8.cc && \ make -j $(getconf _NPROCESSORS_ONLN) && \ make -j $(getconf _NPROCESSORS_ONLN) install && \ rm -rf /plv8-* && \ @@ -121,8 +123,7 @@ RUN wget https://github.com/zachasme/h3-pg/archive/refs/tags/v4.0.1.tar.gz -O h3 # FROM build-deps AS neon-pg-ext-build COPY --from=postgis-build /usr/local/pgsql/ /usr/local/pgsql/ -# plv8 still sometimes crashes during the creation -# COPY --from=plv8-build /usr/local/pgsql/ /usr/local/pgsql/ +COPY --from=plv8-build /usr/local/pgsql/ /usr/local/pgsql/ COPY --from=h3-pg-build /usr/local/pgsql/ /usr/local/pgsql/ COPY --from=h3-pg-build /h3/usr / COPY pgxn/ pgxn/ From 989d78aac837e57c1ef7aaf35af5ded10aa8b010 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Tue, 18 Oct 2022 02:11:11 +0300 Subject: [PATCH 41/64] Buffer the TCP incoming stream on libpq connections. Reduces the number of syscalls needed to read the commands from the compute. Here's a snippet of strace output from the pageserver, when performing a sequential scan on a table, with prefetch: 3084934 recvfrom(47, "d", 1, 0, NULL, NULL) = 1 3084934 recvfrom(47, "\0\0\0\37", 4, 0, NULL, NULL) = 4 3084934 recvfrom(47, "\2\1\0\0\0\0\362\302\360\0\0\0\6\177\0\0002\276\0\0@\f\0\0\0\0\3", 27, 0, NULL, NULL) = 27 3084934 pread64(28, "\0\0\0\1\0\0\0\0\0\0\0\253 "..., 8192, 25190400) = 8192 3084934 write(45, "B\0\0\0\25\0\0\0\6\177\0\0002\276\0\0@\f\0\0\0\3A\0\0\32\355\0\0\0\0\1"..., 7010) = 7010 3084934 poll([{fd=46, events=POLLIN}, {fd=48, events=POLLIN}], 2, 60000) = 1 ([{fd=46, revents=POLLIN}]) 3084934 read(46, "\0\0\0\0p\311q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237\362\0\0\237\362\0"..., 8192) = 8192 3084934 sendto(47, "d\0\0 \5f\0\0\0\0p\311q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237"..., 8198, MSG_NOSIGNAL, NULL, 0) = 8198 3084934 recvfrom(47, "d", 1, 0, NULL, NULL) = 1 3084934 recvfrom(47, "\0\0\0\37", 4, 0, NULL, NULL) = 4 3084934 recvfrom(47, "\2\1\0\0\0\0\362\302\360\0\0\0\6\177\0\0002\276\0\0@\f\0\0\0\0\4", 27, 0, NULL, NULL) = 27 3084934 pread64(28, " \0=\0L\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0;;\0\0\0\4\4\0"..., 8192, 25198592) = 8192 3084934 write(45, "B\0\0\0\25\0\0\0\6\177\0\0002\276\0\0@\f\0\0\0\4A\0\0\32\355\0\0\0\0\1"..., 7010) = 7010 3084934 poll([{fd=46, events=POLLIN}, {fd=48, events=POLLIN}], 2, 60000) = 1 ([{fd=46, revents=POLLIN}]) 3084934 read(46, "\0\0\0\0\260\344q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237\362\0\0\237\362\0"..., 8192) = 8192 3084934 sendto(47, "d\0\0 \5f\0\0\0\0\260\344q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237"..., 8198, MSG_NOSIGNAL, NULL, 0) = 8198 3084934 recvfrom(47, "d", 1, 0, NULL, NULL) = 1 3084934 recvfrom(47, "\0\0\0\37", 4, 0, NULL, NULL) = 4 3084934 recvfrom(47, "\2\1\0\0\0\0\362\302\360\0\0\0\6\177\0\0002\276\0\0@\f\0\0\0\0\5", 27, 0, NULL, NULL) = 27 3084934 write(45, "B\0\0\0\25\0\0\0\6\177\0\0002\276\0\0@\f\0\0\0\5A\0\0\32\355\0\0\0\0\1"..., 7010) = 7010 3084934 poll([{fd=46, events=POLLIN}, {fd=48, events=POLLIN}], 2, 60000) = 1 ([{fd=46, revents=POLLIN}]) 3084934 read(46, "\0\0\0\0\330\377q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237\362\0\0\237\362\0"..., 8192) = 8192 3084934 sendto(47, "d\0\0 \5f\0\0\0\0\330\377q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237"..., 8198, MSG_NOSIGNAL, NULL, 0) = 8198 This shows the interaction for three get_page_at_lsn requests. For each request, the pageserver performs three recvfrom syscalls to read the incoming request from the socket. After this patch, those recvfrom calls are gone: 3086123 read(47, "\0\0\0\0\360\222q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237\362\0\0\237\362\0"..., 8192) = 8192 3086123 sendto(45, "d\0\0 \5f\0\0\0\0\360\222q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237"..., 8198, MSG_NOSIGNAL, NULL, 0) = 8198 3086123 pread64(29, " "..., 8192, 25182208) = 8192 3086123 write(46, "B\0\0\0\25\0\0\0\6\177\0\0002\276\0\0@\f\0\0\0\2A\0\0\32\355\0\0\0\0\1"..., 7010) = 7010 3086123 poll([{fd=47, events=POLLIN}, {fd=49, events=POLLIN}], 2, 60000) = 1 ([{fd=47, revents=POLLIN}]) 3086123 read(47, "\0\0\0\0000\256q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237\362\0\0\237\362\0"..., 8192) = 8192 3086123 sendto(45, "d\0\0 \5f\0\0\0\0000\256q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237"..., 8198, MSG_NOSIGNAL, NULL, 0) = 8198 3086123 pread64(29, "\0\0\0\1\0\0\0\0\0\0\0\253 "..., 8192, 25190400) = 8192 3086123 write(46, "B\0\0\0\25\0\0\0\6\177\0\0002\276\0\0@\f\0\0\0\3A\0\0\32\355\0\0\0\0\1"..., 7010) = 7010 3086123 poll([{fd=47, events=POLLIN}, {fd=49, events=POLLIN}], 2, 60000) = 1 ([{fd=47, revents=POLLIN}]) 3086123 read(47, "\0\0\0\0p\311q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237\362\0\0\237\362\0"..., 8192) = 8192 3086123 sendto(45, "d\0\0 \5f\0\0\0\0p\311q\1\0\0\4\0\f\1\200\1\0 \4 \0\0\0\0\200\237"..., 8198, MSG_NOSIGNAL, NULL, 0) = 8198 3086123 pread64(29, " \0=\0L\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0;;\0\0\0\4\4\0"..., 8192, 25198592) = 8192 3086123 write(46, "B\0\0\0\25\0\0\0\6\177\0\0002\276\0\0@\f\0\0\0\4A\0\0\32\355\0\0\0\0\1"..., 7010) = 7010 3086123 poll([{fd=47, events=POLLIN}, {fd=49, events=POLLIN}], 2, 60000) = 1 ([{fd=47, revents=POLLIN}]) In this test, the compute sends a batch of prefetch requests, and they are read from the socket in one syscall. That syscall was not captured by the strace snippet above, but there are much fewer of them than before. --- libs/utils/src/postgres_backend_async.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/utils/src/postgres_backend_async.rs b/libs/utils/src/postgres_backend_async.rs index 87e4478a99..53f6759d62 100644 --- a/libs/utils/src/postgres_backend_async.rs +++ b/libs/utils/src/postgres_backend_async.rs @@ -15,7 +15,7 @@ use std::sync::Arc; use std::task::Poll; use tracing::{debug, error, trace}; -use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt}; +use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, BufReader}; use tokio_rustls::TlsAcceptor; #[async_trait::async_trait] @@ -66,8 +66,8 @@ pub enum ProcessMsgResult { /// Always-writeable sock_split stream. /// May not be readable. See [`PostgresBackend::take_stream_in`] pub enum Stream { - Unencrypted(tokio::net::TcpStream), - Tls(Box>), + Unencrypted(BufReader), + Tls(Box>>), Broken, } @@ -157,7 +157,7 @@ impl PostgresBackend { let peer_addr = socket.peer_addr()?; Ok(Self { - stream: Stream::Unencrypted(socket), + stream: Stream::Unencrypted(BufReader::new(socket)), buf_out: BytesMut::with_capacity(10 * 1024), state: ProtoState::Initialization, md5_salt: [0u8; 4], From 8fbe437768e2545855a0f928794abc679b7f9d0b Mon Sep 17 00:00:00 2001 From: bojanserafimov Date: Tue, 18 Oct 2022 11:53:28 -0400 Subject: [PATCH 42/64] Improve pageserver IO metrics (#2629) --- pageserver/src/metrics.rs | 20 ++++++++++++++------ test_runner/fixtures/compare_fixtures.py | 5 +++-- test_runner/fixtures/metrics.py | 2 ++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/pageserver/src/metrics.rs b/pageserver/src/metrics.rs index 5c2f81d731..b654be031c 100644 --- a/pageserver/src/metrics.rs +++ b/pageserver/src/metrics.rs @@ -107,18 +107,20 @@ static CURRENT_LOGICAL_SIZE: Lazy = Lazy::new(|| { // Metrics for cloud upload. These metrics reflect data uploaded to cloud storage, // or in testing they estimate how much we would upload if we did. -static NUM_PERSISTENT_FILES_CREATED: Lazy = Lazy::new(|| { - register_int_counter!( +static NUM_PERSISTENT_FILES_CREATED: Lazy = Lazy::new(|| { + register_int_counter_vec!( "pageserver_created_persistent_files_total", "Number of files created that are meant to be uploaded to cloud storage", + &["tenant_id", "timeline_id"] ) .expect("failed to define a metric") }); -static PERSISTENT_BYTES_WRITTEN: Lazy = Lazy::new(|| { - register_int_counter!( +static PERSISTENT_BYTES_WRITTEN: Lazy = Lazy::new(|| { + register_int_counter_vec!( "pageserver_written_persistent_bytes_total", "Total bytes written that are meant to be uploaded to cloud storage", + &["tenant_id", "timeline_id"] ) .expect("failed to define a metric") }); @@ -386,8 +388,12 @@ impl TimelineMetrics { let current_logical_size_gauge = CURRENT_LOGICAL_SIZE .get_metric_with_label_values(&[&tenant_id, &timeline_id]) .unwrap(); - let num_persistent_files_created = NUM_PERSISTENT_FILES_CREATED.clone(); - let persistent_bytes_written = PERSISTENT_BYTES_WRITTEN.clone(); + let num_persistent_files_created = NUM_PERSISTENT_FILES_CREATED + .get_metric_with_label_values(&[&tenant_id, &timeline_id]) + .unwrap(); + let persistent_bytes_written = PERSISTENT_BYTES_WRITTEN + .get_metric_with_label_values(&[&tenant_id, &timeline_id]) + .unwrap(); TimelineMetrics { tenant_id, @@ -419,6 +425,8 @@ impl Drop for TimelineMetrics { let _ = WAIT_LSN_TIME.remove_label_values(&[tenant_id, timeline_id]); let _ = CURRENT_PHYSICAL_SIZE.remove_label_values(&[tenant_id, timeline_id]); let _ = CURRENT_LOGICAL_SIZE.remove_label_values(&[tenant_id, timeline_id]); + let _ = NUM_PERSISTENT_FILES_CREATED.remove_label_values(&[tenant_id, timeline_id]); + let _ = PERSISTENT_BYTES_WRITTEN.remove_label_values(&[tenant_id, timeline_id]); for op in STORAGE_TIME_OPERATIONS { let _ = STORAGE_TIME.remove_label_values(&[op, tenant_id, timeline_id]); diff --git a/test_runner/fixtures/compare_fixtures.py b/test_runner/fixtures/compare_fixtures.py index 78a12c6c45..2d36d90bd6 100644 --- a/test_runner/fixtures/compare_fixtures.py +++ b/test_runner/fixtures/compare_fixtures.py @@ -130,11 +130,12 @@ class NeonCompare(PgCompare): "size", timeline_size / (1024 * 1024), "MB", report=MetricReport.LOWER_IS_BETTER ) + params = f'{{tenant_id="{self.env.initial_tenant}",timeline_id="{self.timeline}"}}' total_files = self.zenbenchmark.get_int_counter_value( - self.env.pageserver, "pageserver_created_persistent_files_total" + self.env.pageserver, "pageserver_created_persistent_files_total" + params ) total_bytes = self.zenbenchmark.get_int_counter_value( - self.env.pageserver, "pageserver_written_persistent_bytes_total" + self.env.pageserver, "pageserver_written_persistent_bytes_total" + params ) self.zenbenchmark.record( "data_uploaded", total_bytes / (1024 * 1024), "MB", report=MetricReport.LOWER_IS_BETTER diff --git a/test_runner/fixtures/metrics.py b/test_runner/fixtures/metrics.py index 4d680aa641..62e3cbbe99 100644 --- a/test_runner/fixtures/metrics.py +++ b/test_runner/fixtures/metrics.py @@ -60,4 +60,6 @@ PAGESERVER_PER_TENANT_METRICS = [ "pageserver_wait_lsn_seconds_bucket", "pageserver_wait_lsn_seconds_count", "pageserver_wait_lsn_seconds_sum", + "pageserver_created_persistent_files_total", + "pageserver_written_persistent_bytes_total", ] From c67cf340400b03df95587104cdfd2af861ad38a3 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 19 Oct 2022 11:16:36 +0300 Subject: [PATCH 43/64] Update GH Action version (#2646) --- .github/workflows/codestyle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml index 961d811a51..66f9f33256 100644 --- a/.github/workflows/codestyle.yml +++ b/.github/workflows/codestyle.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: true fetch-depth: 2 From 91411c415ad9a48e9da2278fe21be73bd1eb7ace Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Wed, 19 Oct 2022 12:32:03 +0300 Subject: [PATCH 44/64] Persists latest_gc_cutoff_lsn before performing GC (#2558) * Persists latest_gc_cutoff_lsn before performing GC * Peform some refactoring and code deduplication refer #2539 * Add test for persisting GC cutoff * Fix python test style warnings * Bump postgres version * Reduce number of iterations in test_gc_cutoff test * Bump postgres version * Undo bumping postgres version --- pageserver/src/tenant/timeline.rs | 127 ++++++++++++++------------ pageserver/src/tenant_tasks.rs | 8 +- test_runner/regress/test_gc_cutoff.py | 38 ++++++++ 3 files changed, 114 insertions(+), 59 deletions(-) create mode 100644 test_runner/regress/test_gc_cutoff.py diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index 0f8e60f8d3..1728c7be32 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -1220,78 +1220,76 @@ impl Timeline { // TODO: This perhaps should be done in 'flush_frozen_layers', after flushing // *all* the layers, to avoid fsyncing the file multiple times. let disk_consistent_lsn = Lsn(lsn_range.end.0 - 1); - self.update_disk_consistent_lsn(disk_consistent_lsn, layer_paths_to_upload)?; + let old_disk_consistent_lsn = self.disk_consistent_lsn.load(); + // If we were able to advance 'disk_consistent_lsn', save it the metadata file. + // After crash, we will restart WAL streaming and processing from that point. + if disk_consistent_lsn != old_disk_consistent_lsn { + assert!(disk_consistent_lsn > old_disk_consistent_lsn); + self.update_metadata_file(disk_consistent_lsn, layer_paths_to_upload)?; + // Also update the in-memory copy + self.disk_consistent_lsn.store(disk_consistent_lsn); + } Ok(()) } /// Update metadata file - fn update_disk_consistent_lsn( + fn update_metadata_file( &self, disk_consistent_lsn: Lsn, layer_paths_to_upload: HashMap, ) -> Result<()> { - // If we were able to advance 'disk_consistent_lsn', save it the metadata file. - // After crash, we will restart WAL streaming and processing from that point. - let old_disk_consistent_lsn = self.disk_consistent_lsn.load(); - if disk_consistent_lsn != old_disk_consistent_lsn { - assert!(disk_consistent_lsn > old_disk_consistent_lsn); + // We can only save a valid 'prev_record_lsn' value on disk if we + // flushed *all* in-memory changes to disk. We only track + // 'prev_record_lsn' in memory for the latest processed record, so we + // don't remember what the correct value that corresponds to some old + // LSN is. But if we flush everything, then the value corresponding + // current 'last_record_lsn' is correct and we can store it on disk. + let RecordLsn { + last: last_record_lsn, + prev: prev_record_lsn, + } = self.last_record_lsn.load(); + let ondisk_prev_record_lsn = if disk_consistent_lsn == last_record_lsn { + Some(prev_record_lsn) + } else { + None + }; - // We can only save a valid 'prev_record_lsn' value on disk if we - // flushed *all* in-memory changes to disk. We only track - // 'prev_record_lsn' in memory for the latest processed record, so we - // don't remember what the correct value that corresponds to some old - // LSN is. But if we flush everything, then the value corresponding - // current 'last_record_lsn' is correct and we can store it on disk. - let RecordLsn { - last: last_record_lsn, - prev: prev_record_lsn, - } = self.last_record_lsn.load(); - let ondisk_prev_record_lsn = if disk_consistent_lsn == last_record_lsn { - Some(prev_record_lsn) - } else { - None - }; + let ancestor_timeline_id = self + .ancestor_timeline + .as_ref() + .map(|ancestor| ancestor.timeline_id); - let ancestor_timeline_id = self - .ancestor_timeline - .as_ref() - .map(|ancestor| ancestor.timeline_id); + let metadata = TimelineMetadata::new( + disk_consistent_lsn, + ondisk_prev_record_lsn, + ancestor_timeline_id, + self.ancestor_lsn, + *self.latest_gc_cutoff_lsn.read(), + self.initdb_lsn, + self.pg_version, + ); - let metadata = TimelineMetadata::new( - disk_consistent_lsn, - ondisk_prev_record_lsn, - ancestor_timeline_id, - self.ancestor_lsn, - *self.latest_gc_cutoff_lsn.read(), - self.initdb_lsn, - self.pg_version, - ); + fail_point!("checkpoint-before-saving-metadata", |x| bail!( + "{}", + x.unwrap() + )); - fail_point!("checkpoint-before-saving-metadata", |x| bail!( - "{}", - x.unwrap() - )); + save_metadata( + self.conf, + self.timeline_id, + self.tenant_id, + &metadata, + false, + )?; - save_metadata( - self.conf, - self.timeline_id, + if self.upload_layers.load(atomic::Ordering::Relaxed) { + storage_sync::schedule_layer_upload( self.tenant_id, - &metadata, - false, - )?; - - if self.upload_layers.load(atomic::Ordering::Relaxed) { - storage_sync::schedule_layer_upload( - self.tenant_id, - self.timeline_id, - layer_paths_to_upload, - Some(metadata), - ); - } - - // Also update the in-memory copy - self.disk_consistent_lsn.store(disk_consistent_lsn); + self.timeline_id, + layer_paths_to_upload, + Some(metadata), + ); } Ok(()) @@ -1961,6 +1959,9 @@ impl Timeline { new_gc_cutoff ); write_guard.store_and_unlock(new_gc_cutoff).wait(); + + // Persist metadata file + self.update_metadata_file(self.disk_consistent_lsn.load(), HashSet::new())?; } info!("GC starting"); @@ -2087,6 +2088,18 @@ impl Timeline { result.layers_removed += 1; } + info!( + "GC completed removing {} layers, cuttof {}", + result.layers_removed, new_gc_cutoff + ); + if result.layers_removed != 0 { + fail_point!("gc-before-save-metadata", |_| { + info!("Abnormaly terinate pageserver at gc-before-save-metadata fail point"); + std::process::abort(); + }); + return Ok(result); + } + if self.upload_layers.load(atomic::Ordering::Relaxed) { storage_sync::schedule_layer_delete( self.tenant_id, diff --git a/pageserver/src/tenant_tasks.rs b/pageserver/src/tenant_tasks.rs index 8329b15c08..030055df6d 100644 --- a/pageserver/src/tenant_tasks.rs +++ b/pageserver/src/tenant_tasks.rs @@ -70,8 +70,10 @@ async fn compaction_loop(tenant_id: TenantId) { // Run compaction let mut sleep_duration = tenant.get_compaction_period(); if let Err(e) = tenant.compaction_iteration() { - error!("Compaction failed, retrying: {e:#}"); sleep_duration = wait_duration; + error!("Compaction failed, retrying in {:?}: {e:#}", sleep_duration); + #[cfg(feature = "testing")] + std::process::abort(); } // Sleep @@ -119,8 +121,10 @@ async fn gc_loop(tenant_id: TenantId) { if gc_horizon > 0 { if let Err(e) = tenant.gc_iteration(None, gc_horizon, tenant.get_pitr_interval(), false) { - error!("Gc failed, retrying: {e:#}"); sleep_duration = wait_duration; + error!("Gc failed, retrying in {:?}: {e:#}", sleep_duration); + #[cfg(feature = "testing")] + std::process::abort(); } } diff --git a/test_runner/regress/test_gc_cutoff.py b/test_runner/regress/test_gc_cutoff.py new file mode 100644 index 0000000000..946c689a30 --- /dev/null +++ b/test_runner/regress/test_gc_cutoff.py @@ -0,0 +1,38 @@ +import pytest +from fixtures.neon_fixtures import NeonEnvBuilder, PgBin +from performance.test_perf_pgbench import get_scales_matrix + + +# Test gc_cuttoff +# +# This test set fail point after at the end of GC and checks +# that pageserver normally restarts after it +@pytest.mark.parametrize("scale", get_scales_matrix(10)) +def test_gc_cutoff(neon_env_builder: NeonEnvBuilder, pg_bin: PgBin, scale: int): + env = neon_env_builder.init_start() + pageserver_http = env.pageserver.http_client() + + # Use aggressive GC and checkpoint settings, so that we also exercise GC during the test + tenant_id, _ = env.neon_cli.create_tenant( + conf={ + "gc_period": "10 s", + "gc_horizon": f"{1024 ** 2}", + "checkpoint_distance": f"{1024 ** 2}", + "compaction_target_size": f"{1024 ** 2}", + # set PITR interval to be small, so we can do GC + "pitr_interval": "1 s", + } + ) + pg = env.postgres.create_start("main", tenant_id=tenant_id) + connstr = pg.connstr() + pg_bin.run_capture(["pgbench", "-i", f"-s{scale}", connstr]) + + pageserver_http.configure_failpoints(("gc-before-save-metadata", "return")) + + for i in range(5): + try: + pg_bin.run_capture(["pgbench", "-T100", connstr]) + except Exception: + env.pageserver.stop() + env.pageserver.start() + pageserver_http.configure_failpoints(("gc-before-save-metadata", "return")) From 6b49b370fc1bcd4f8c6b6ed81f79dc8f7fcc076b Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Wed, 19 Oct 2022 13:16:55 +0300 Subject: [PATCH 45/64] Fix build after applying PR #2558 --- pageserver/src/tenant/timeline.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index 1728c7be32..a771f82caf 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -1961,7 +1961,7 @@ impl Timeline { write_guard.store_and_unlock(new_gc_cutoff).wait(); // Persist metadata file - self.update_metadata_file(self.disk_consistent_lsn.load(), HashSet::new())?; + self.update_metadata_file(self.disk_consistent_lsn.load(), HashMap::new())?; } info!("GC starting"); From 7576b18b14720708f2873083c50874da913eaf27 Mon Sep 17 00:00:00 2001 From: Anastasia Lubennikova Date: Tue, 18 Oct 2022 14:45:51 +0300 Subject: [PATCH 46/64] [compute_tools] fix GRANT CREATE ON SCHEMA public - run the grant query in each database --- compute_tools/src/spec.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compute_tools/src/spec.rs b/compute_tools/src/spec.rs index 89a6a93510..84d72714db 100644 --- a/compute_tools/src/spec.rs +++ b/compute_tools/src/spec.rs @@ -380,10 +380,6 @@ pub fn handle_grants(node: &ComputeNode, client: &mut Client) -> Result<()> { info!("grant query {}", &query); client.execute(query.as_str(), &[])?; - - // Explicitly grant CREATE ON SCHEMA PUBLIC to the web_access user. - // This is needed since postgres 15, where this privilege is removed by default. - client.execute("GRANT CREATE ON SCHEMA public TO web_access", &[])?; } // Do some per-database access adjustments. We'd better do this at db creation time, @@ -426,6 +422,12 @@ pub fn handle_grants(node: &ComputeNode, client: &mut Client) -> Result<()> { db.owner.quote() ); db_client.simple_query(&alter_query)?; + + // Explicitly grant CREATE ON SCHEMA PUBLIC to the web_access user. + // This is needed since postgres 15, where this privilege is removed by default. + let grant_query: String = "GRANT CREATE ON SCHEMA public TO web_access".to_string(); + info!("grant query for db {} : {}", &db.name, &grant_query); + db_client.simple_query(&grant_query)?; } Ok(()) From 4d1e48f3b9a4b7064787513fd2c455f0001f6e18 Mon Sep 17 00:00:00 2001 From: Alexey Kondratov Date: Wed, 19 Oct 2022 19:20:06 +0200 Subject: [PATCH 47/64] [compute_ctl] Use postgres::config to properly escape database names (#2652) We've got at least one user in production that cannot create a database with a trailing space in the name. This happens because we use `url` crate for manipulating the DATABASE_URL, but it follows a standard that doesn't fit really well with Postgres. For example, it trims all trailing spaces from the path: > Remove any leading and trailing C0 control or space from input. > See: https://url.spec.whatwg.org/#url-parsing But we used `set_path()` to set database name and it's totally valid to have trailing spaces in the database name in Postgres. Thus, use `postgres::config::Config` to modify database name in the connection details. --- compute_tools/src/pg_helpers.rs | 22 +++++----- compute_tools/src/spec.rs | 54 ++++++++++++------------- compute_tools/tests/pg_helpers_tests.rs | 4 +- 3 files changed, 39 insertions(+), 41 deletions(-) diff --git a/compute_tools/src/pg_helpers.rs b/compute_tools/src/pg_helpers.rs index ad7ea0abc8..42aa00af01 100644 --- a/compute_tools/src/pg_helpers.rs +++ b/compute_tools/src/pg_helpers.rs @@ -8,11 +8,10 @@ use std::process::Child; use std::time::{Duration, Instant}; use anyhow::{bail, Result}; +use notify::{RecursiveMode, Watcher}; use postgres::{Client, Transaction}; use serde::Deserialize; -use notify::{RecursiveMode, Watcher}; - const POSTGRES_WAIT_TIMEOUT: Duration = Duration::from_millis(60 * 1000); // milliseconds /// Rust representation of Postgres role info with only those fields @@ -169,7 +168,7 @@ impl Database { /// it may require a proper quoting too. pub fn to_pg_options(&self) -> String { let mut params: String = self.options.as_pg_options(); - write!(params, " OWNER {}", &self.owner.quote()) + write!(params, " OWNER {}", &self.owner.pg_quote()) .expect("String is documented to not to error during write operations"); params @@ -180,18 +179,17 @@ impl Database { /// intended to be used for DB / role names. pub type PgIdent = String; -/// Generic trait used to provide quoting for strings used in the -/// Postgres SQL queries. Currently used only to implement quoting -/// of identifiers, but could be used for literals in the future. -pub trait PgQuote { - fn quote(&self) -> String; +/// Generic trait used to provide quoting / encoding for strings used in the +/// Postgres SQL queries and DATABASE_URL. +pub trait Escaping { + fn pg_quote(&self) -> String; } -impl PgQuote for PgIdent { +impl Escaping for PgIdent { /// This is intended to mimic Postgres quote_ident(), but for simplicity it - /// always quotes provided string with `""` and escapes every `"`. Not idempotent, - /// i.e. if string is already escaped it will be escaped again. - fn quote(&self) -> String { + /// always quotes provided string with `""` and escapes every `"`. + /// **Not idempotent**, i.e. if string is already escaped it will be escaped again. + fn pg_quote(&self) -> String { let result = format!("\"{}\"", self.replace('"', "\"\"")); result } diff --git a/compute_tools/src/spec.rs b/compute_tools/src/spec.rs index 84d72714db..e0c0e9404b 100644 --- a/compute_tools/src/spec.rs +++ b/compute_tools/src/spec.rs @@ -1,7 +1,9 @@ use std::path::Path; +use std::str::FromStr; use anyhow::Result; use log::{info, log_enabled, warn, Level}; +use postgres::config::Config; use postgres::{Client, NoTls}; use serde::Deserialize; @@ -115,8 +117,8 @@ pub fn handle_roles(spec: &ComputeSpec, client: &mut Client) -> Result<()> { if existing_roles.iter().any(|r| r.name == op.name) { let query: String = format!( "ALTER ROLE {} RENAME TO {}", - op.name.quote(), - new_name.quote() + op.name.pg_quote(), + new_name.pg_quote() ); warn!("renaming role '{}' to '{}'", op.name, new_name); @@ -162,7 +164,7 @@ pub fn handle_roles(spec: &ComputeSpec, client: &mut Client) -> Result<()> { } if update_role { - let mut query: String = format!("ALTER ROLE {} ", name.quote()); + let mut query: String = format!("ALTER ROLE {} ", name.pg_quote()); info_print!(" -> update"); query.push_str(&role.to_pg_options()); @@ -170,7 +172,7 @@ pub fn handle_roles(spec: &ComputeSpec, client: &mut Client) -> Result<()> { } } else { info!("role name: '{}'", &name); - let mut query: String = format!("CREATE ROLE {} ", name.quote()); + let mut query: String = format!("CREATE ROLE {} ", name.pg_quote()); info!("role create query: '{}'", &query); info_print!(" -> create"); @@ -179,7 +181,7 @@ pub fn handle_roles(spec: &ComputeSpec, client: &mut Client) -> Result<()> { let grant_query = format!( "GRANT pg_read_all_data, pg_write_all_data TO {}", - name.quote() + name.pg_quote() ); xact.execute(grant_query.as_str(), &[])?; info!("role grant query: '{}'", &grant_query); @@ -215,7 +217,7 @@ pub fn handle_role_deletions(node: &ComputeNode, client: &mut Client) -> Result< // We do not check either role exists or not, // Postgres will take care of it for us if op.action == "delete_role" { - let query: String = format!("DROP ROLE IF EXISTS {}", &op.name.quote()); + let query: String = format!("DROP ROLE IF EXISTS {}", &op.name.pg_quote()); warn!("deleting role '{}'", &op.name); xact.execute(query.as_str(), &[])?; @@ -230,17 +232,16 @@ pub fn handle_role_deletions(node: &ComputeNode, client: &mut Client) -> Result< fn reassign_owned_objects(node: &ComputeNode, role_name: &PgIdent) -> Result<()> { for db in &node.spec.cluster.databases { if db.owner != *role_name { - let mut connstr = node.connstr.clone(); - // database name is always the last and the only component of the path - connstr.set_path(&db.name); + let mut conf = Config::from_str(node.connstr.as_str())?; + conf.dbname(&db.name); - let mut client = Client::connect(connstr.as_str(), NoTls)?; + let mut client = conf.connect(NoTls)?; // This will reassign all dependent objects to the db owner let reassign_query = format!( "REASSIGN OWNED BY {} TO {}", - role_name.quote(), - db.owner.quote() + role_name.pg_quote(), + db.owner.pg_quote() ); info!( "reassigning objects owned by '{}' in db '{}' to '{}'", @@ -249,7 +250,7 @@ fn reassign_owned_objects(node: &ComputeNode, role_name: &PgIdent) -> Result<()> client.simple_query(&reassign_query)?; // This now will only drop privileges of the role - let drop_query = format!("DROP OWNED BY {}", role_name.quote()); + let drop_query = format!("DROP OWNED BY {}", role_name.pg_quote()); client.simple_query(&drop_query)?; } } @@ -279,7 +280,7 @@ pub fn handle_databases(spec: &ComputeSpec, client: &mut Client) -> Result<()> { // We do not check either DB exists or not, // Postgres will take care of it for us "delete_db" => { - let query: String = format!("DROP DATABASE IF EXISTS {}", &op.name.quote()); + let query: String = format!("DROP DATABASE IF EXISTS {}", &op.name.pg_quote()); warn!("deleting database '{}'", &op.name); client.execute(query.as_str(), &[])?; @@ -291,8 +292,8 @@ pub fn handle_databases(spec: &ComputeSpec, client: &mut Client) -> Result<()> { if existing_dbs.iter().any(|r| r.name == op.name) { let query: String = format!( "ALTER DATABASE {} RENAME TO {}", - op.name.quote(), - new_name.quote() + op.name.pg_quote(), + new_name.pg_quote() ); warn!("renaming database '{}' to '{}'", op.name, new_name); @@ -320,7 +321,7 @@ pub fn handle_databases(spec: &ComputeSpec, client: &mut Client) -> Result<()> { // XXX: db owner name is returned as quoted string from Postgres, // when quoting is needed. let new_owner = if r.owner.starts_with('"') { - db.owner.quote() + db.owner.pg_quote() } else { db.owner.clone() }; @@ -328,15 +329,15 @@ pub fn handle_databases(spec: &ComputeSpec, client: &mut Client) -> Result<()> { if new_owner != r.owner { let query: String = format!( "ALTER DATABASE {} OWNER TO {}", - name.quote(), - db.owner.quote() + name.pg_quote(), + db.owner.pg_quote() ); info_print!(" -> update"); client.execute(query.as_str(), &[])?; } } else { - let mut query: String = format!("CREATE DATABASE {} ", name.quote()); + let mut query: String = format!("CREATE DATABASE {} ", name.pg_quote()); info_print!(" -> create"); query.push_str(&db.to_pg_options()); @@ -366,7 +367,7 @@ pub fn handle_grants(node: &ComputeNode, client: &mut Client) -> Result<()> { .cluster .roles .iter() - .map(|r| r.name.quote()) + .map(|r| r.name.pg_quote()) .collect::>(); for db in &spec.cluster.databases { @@ -374,7 +375,7 @@ pub fn handle_grants(node: &ComputeNode, client: &mut Client) -> Result<()> { let query: String = format!( "GRANT CREATE ON DATABASE {} TO {}", - dbname.quote(), + dbname.pg_quote(), roles.join(", ") ); info!("grant query {}", &query); @@ -385,12 +386,11 @@ pub fn handle_grants(node: &ComputeNode, client: &mut Client) -> Result<()> { // Do some per-database access adjustments. We'd better do this at db creation time, // but CREATE DATABASE isn't transactional. So we cannot create db + do some grants // atomically. - let mut db_connstr = node.connstr.clone(); for db in &node.spec.cluster.databases { - // database name is always the last and the only component of the path - db_connstr.set_path(&db.name); + let mut conf = Config::from_str(node.connstr.as_str())?; + conf.dbname(&db.name); - let mut db_client = Client::connect(db_connstr.as_str(), NoTls)?; + let mut db_client = conf.connect(NoTls)?; // This will only change ownership on the schema itself, not the objects // inside it. Without it owner of the `public` schema will be `cloud_admin` @@ -419,7 +419,7 @@ pub fn handle_grants(node: &ComputeNode, client: &mut Client) -> Result<()> { END IF;\n\ END\n\ $$;", - db.owner.quote() + db.owner.pg_quote() ); db_client.simple_query(&alter_query)?; diff --git a/compute_tools/tests/pg_helpers_tests.rs b/compute_tools/tests/pg_helpers_tests.rs index bae944440e..24cad4663a 100644 --- a/compute_tools/tests/pg_helpers_tests.rs +++ b/compute_tools/tests/pg_helpers_tests.rs @@ -33,9 +33,9 @@ mod pg_helpers_tests { } #[test] - fn quote_ident() { + fn ident_pg_quote() { let ident: PgIdent = PgIdent::from("\"name\";\\n select 1;"); - assert_eq!(ident.quote(), "\"\"\"name\"\";\\n select 1;\""); + assert_eq!(ident.pg_quote(), "\"\"\"name\"\";\\n select 1;\""); } } From b237feedab9d6ecec6a16379a9a7c045c7255aa4 Mon Sep 17 00:00:00 2001 From: MMeent Date: Wed, 19 Oct 2022 22:47:11 +0200 Subject: [PATCH 48/64] Add more redo metrics: (#2645) - Measure size of redo WAL (new histogram), with bounds between 24B-32kB - Add 2 more buckets at the upper end of the redo time histogram We often (>0.1% of several hours each day) take more than 250ms to do the redo round-trip to the postgres process. We need to measure these redo times more precisely. --- pageserver/src/metrics.rs | 26 +++++++++++++++++++++++++- pageserver/src/walredo.rs | 23 ++++++++++++++++++----- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/pageserver/src/metrics.rs b/pageserver/src/metrics.rs index b654be031c..7ae2d0f14c 100644 --- a/pageserver/src/metrics.rs +++ b/pageserver/src/metrics.rs @@ -277,11 +277,15 @@ pub static TENANT_TASK_EVENTS: Lazy = Lazy::new(|| { /// smallest redo processing times. These buckets allow us to measure down /// to 5us, which equates to 200'000 pages/sec, which equates to 1.6GB/sec. /// This is much better than the previous 5ms aka 200 pages/sec aka 1.6MB/sec. +/// +/// Values up to 1s are recorded because metrics show that we have redo +/// durations and lock times larger than 0.250s. macro_rules! redo_histogram_time_buckets { () => { vec![ 0.000_005, 0.000_010, 0.000_025, 0.000_050, 0.000_100, 0.000_250, 0.000_500, 0.001_000, - 0.002_500, 0.005_000, 0.010_000, 0.025_000, 0.050_000, 0.100_000, 0.250_000, + 0.002_500, 0.005_000, 0.010_000, 0.025_000, 0.050_000, 0.100_000, 0.250_000, 0.500_000, + 1.000_000, ] }; } @@ -296,6 +300,17 @@ macro_rules! redo_histogram_count_buckets { }; } +macro_rules! redo_bytes_histogram_count_buckets { + () => { + // powers of (2^.5), from 2^4.5 to 2^15 (22 buckets) + // rounded up to the next multiple of 8 to capture any MAXALIGNed record of that size, too. + vec![ + 24.0, 32.0, 48.0, 64.0, 96.0, 128.0, 184.0, 256.0, 368.0, 512.0, 728.0, 1024.0, 1456.0, + 2048.0, 2904.0, 4096.0, 5800.0, 8192.0, 11592.0, 16384.0, 23176.0, 32768.0, + ] + }; +} + pub static WAL_REDO_TIME: Lazy = Lazy::new(|| { register_histogram!( "pageserver_wal_redo_seconds", @@ -323,6 +338,15 @@ pub static WAL_REDO_RECORDS_HISTOGRAM: Lazy = Lazy::new(|| { .expect("failed to define a metric") }); +pub static WAL_REDO_BYTES_HISTOGRAM: Lazy = Lazy::new(|| { + register_histogram!( + "pageserver_wal_redo_bytes_histogram", + "Histogram of number of records replayed per redo", + redo_bytes_histogram_count_buckets!(), + ) + .expect("failed to define a metric") +}); + pub static WAL_REDO_RECORD_COUNTER: Lazy = Lazy::new(|| { register_int_counter!( "pageserver_replayed_wal_records_total", diff --git a/pageserver/src/walredo.rs b/pageserver/src/walredo.rs index 15a9408dc9..1dd27caba6 100644 --- a/pageserver/src/walredo.rs +++ b/pageserver/src/walredo.rs @@ -39,7 +39,8 @@ use utils::crashsafe_dir::path_with_suffix_extension; use utils::{bin_ser::BeSer, id::TenantId, lsn::Lsn, nonblock::set_nonblock}; use crate::metrics::{ - WAL_REDO_RECORDS_HISTOGRAM, WAL_REDO_RECORD_COUNTER, WAL_REDO_TIME, WAL_REDO_WAIT_TIME, + WAL_REDO_BYTES_HISTOGRAM, WAL_REDO_RECORDS_HISTOGRAM, WAL_REDO_RECORD_COUNTER, WAL_REDO_TIME, + WAL_REDO_WAIT_TIME, }; use crate::pgdatadir_mapping::{key_to_rel_block, key_to_slru_block}; use crate::reltag::{RelTag, SlruKind}; @@ -244,12 +245,23 @@ impl PostgresRedoManager { let end_time = Instant::now(); let duration = end_time.duration_since(lock_time); + let len = records.len(); + let nbytes = records.iter().fold(0, |acumulator, record| { + acumulator + + match &record.1 { + NeonWalRecord::Postgres { rec, .. } => rec.len(), + _ => unreachable!("Only PostgreSQL records are accepted in this batch"), + } + }); + WAL_REDO_TIME.observe(duration.as_secs_f64()); - WAL_REDO_RECORDS_HISTOGRAM.observe(records.len() as f64); + WAL_REDO_RECORDS_HISTOGRAM.observe(len as f64); + WAL_REDO_BYTES_HISTOGRAM.observe(nbytes as f64); debug!( - "postgres applied {} WAL records in {} us to reconstruct page image at LSN {}", - records.len(), + "postgres applied {} WAL records ({} bytes) in {} us to reconstruct page image at LSN {}", + len, + nbytes, duration.as_micros(), lsn ); @@ -258,8 +270,9 @@ impl PostgresRedoManager { // next request will launch a new one. if result.is_err() { error!( - "error applying {} WAL records to reconstruct page image at LSN {}", + "error applying {} WAL records ({} bytes) to reconstruct page image at LSN {}", records.len(), + nbytes, lsn ); let process = process_guard.take().unwrap(); From bc5ec43056773f4a6742fb64dbff681392b02dd3 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Tue, 18 Oct 2022 18:23:27 +0300 Subject: [PATCH 49/64] Fix flaky physical-size tests in test_timeline_size.py. These two tests, test_timeline_physical_size_post_compaction and test_timeline_physical_size_post_gc, assumed that after you have waited for the WAL from a bulk insertion to arrive, and you run a cycle of checkpoint and compaction, no new layer files are created. Because if a new layer file is created while we are calculating the incremental and non-incremental physical sizes, they might differ. However, the tests used a very small checkpoint_distance, so even a small amount of WAL generated in PostgreSQL could cause a new layer file to be created. Autovacuum can kick in at any time, and do that. That caused occasional failues in the test. I was able to reproduce it reliably by adding a long delay between the incremental and non-incremental size calculations: ``` --- a/pageserver/src/http/routes.rs +++ b/pageserver/src/http/routes.rs @@ -129,6 +129,9 @@ async fn build_timeline_info( } }; let current_physical_size = Some(timeline.get_physical_size()); + if include_non_incremental_physical_size { + std::thread::sleep(std::time::Duration::from_millis(60000)); + } let info = TimelineInfo { tenant_id: timeline.tenant_id, ``` To fix, disable autovacuum for the table. Autovacuum could still kick in for other tables, e.g. catalog tables, but that seems less likely to generate enough WAL to causea new layer file to be flushed. If this continues to be a problem in the future, we could simply retry the physical size call a few times, if there's a mismatch. A mismatch could happen every once in a while, but it's very unlikely to happen more than once or twice in a row. Fixes https://github.com/neondatabase/neon/issues/2212 --- test_runner/regress/test_timeline_size.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test_runner/regress/test_timeline_size.py b/test_runner/regress/test_timeline_size.py index d26d5f3afa..d783f897f9 100644 --- a/test_runner/regress/test_timeline_size.py +++ b/test_runner/regress/test_timeline_size.py @@ -270,9 +270,15 @@ def test_timeline_physical_size_post_compaction(neon_env_builder: NeonEnvBuilder new_timeline_id = env.neon_cli.create_branch("test_timeline_physical_size_post_compaction") pg = env.postgres.create_start("test_timeline_physical_size_post_compaction") + # We don't want autovacuum to run on the table, while we are calculating the + # physical size, because that could cause a new layer to be created and a + # mismatch between the incremental and non-incremental size. (If that still + # happens, because of some other background activity or autovacuum on other + # tables, we could simply retry the size calculations. It's unlikely that + # that would happen more than once.) pg.safe_psql_many( [ - "CREATE TABLE foo (t text)", + "CREATE TABLE foo (t text) WITH (autovacuum_enabled = off)", """INSERT INTO foo SELECT 'long string to consume some space' || g FROM generate_series(1, 100000) g""", @@ -297,9 +303,10 @@ def test_timeline_physical_size_post_gc(neon_env_builder: NeonEnvBuilder): new_timeline_id = env.neon_cli.create_branch("test_timeline_physical_size_post_gc") pg = env.postgres.create_start("test_timeline_physical_size_post_gc") + # Like in test_timeline_physical_size_post_compaction, disable autovacuum pg.safe_psql_many( [ - "CREATE TABLE foo (t text)", + "CREATE TABLE foo (t text) WITH (autovacuum_enabled = off)", """INSERT INTO foo SELECT 'long string to consume some space' || g FROM generate_series(1, 100000) g""", From 7734929a8202c8cc41596a861ffbe0b51b5f3cb9 Mon Sep 17 00:00:00 2001 From: bojanserafimov Date: Wed, 19 Oct 2022 18:59:22 -0400 Subject: [PATCH 50/64] Remove stale todos (#2630) --- pageserver/src/http/routes.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pageserver/src/http/routes.rs b/pageserver/src/http/routes.rs index 91a385bf77..489adbb2cf 100644 --- a/pageserver/src/http/routes.rs +++ b/pageserver/src/http/routes.rs @@ -781,11 +781,6 @@ async fn failpoints_handler(mut request: Request) -> Result } // Run GC immediately on given timeline. -// FIXME: This is just for tests. See test_runner/regress/test_gc.py. -// This probably should require special authentication or a global flag to -// enable, I don't think we want to or need to allow regular clients to invoke -// GC. -// @hllinnaka in commits ec44f4b29, 3aca717f3 #[cfg(feature = "testing")] async fn timeline_gc_handler(mut request: Request) -> Result, ApiError> { let tenant_id: TenantId = parse_request_param(&request, "tenant_id")?; @@ -811,9 +806,6 @@ async fn timeline_gc_handler(mut request: Request) -> Result) -> Result, ApiError> { let tenant_id: TenantId = parse_request_param(&request, "tenant_id")?; From 9211923bef11da53421ca5949c558cfec13c7f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s?= Date: Thu, 20 Oct 2022 09:46:57 +0200 Subject: [PATCH 51/64] Pageserver Python tests should not fail if the server is built with no testing feature (#2636) Co-authored-by: andres --- test_runner/fixtures/neon_fixtures.py | 60 ++++++++++--------- test_runner/performance/test_perf_pgbench.py | 5 +- test_runner/regress/test_recovery.py | 7 +-- test_runner/regress/test_tenant_relocation.py | 6 +- 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/test_runner/fixtures/neon_fixtures.py b/test_runner/fixtures/neon_fixtures.py index 88910d2bdf..c6bfa7f69e 100644 --- a/test_runner/fixtures/neon_fixtures.py +++ b/test_runner/fixtures/neon_fixtures.py @@ -149,19 +149,6 @@ def pytest_configure(config): raise Exception('neon binaries not found at "{}"'.format(neon_binpath)) -def profiling_supported(): - """Return True if the pageserver was compiled with the 'profiling' feature""" - bin_pageserver = os.path.join(str(neon_binpath), "pageserver") - res = subprocess.run( - [bin_pageserver, "--version"], - check=True, - universal_newlines=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - return "profiling:true" in res.stdout - - def shareable_scope(fixture_name, config) -> Literal["session", "function"]: """Return either session of function scope, depending on TEST_SHARED_FIXTURES envvar. @@ -874,6 +861,17 @@ class NeonEnv: """Get a timeline directory's path based on the repo directory of the test environment""" return self.repo_dir / "tenants" / str(tenant_id) / "timelines" / str(timeline_id) + def get_pageserver_version(self) -> str: + bin_pageserver = os.path.join(str(neon_binpath), "pageserver") + res = subprocess.run( + [bin_pageserver, "--version"], + check=True, + universal_newlines=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + return res.stdout + @cached_property def auth_keys(self) -> AuthKeys: pub = (Path(self.repo_dir) / "auth_public_key.pem").read_bytes() @@ -972,10 +970,11 @@ class NeonPageserverApiException(Exception): class NeonPageserverHttpClient(requests.Session): - def __init__(self, port: int, auth_token: Optional[str] = None): + def __init__(self, port: int, is_testing_enabled_or_skip, auth_token: Optional[str] = None): super().__init__() self.port = port self.auth_token = auth_token + self.is_testing_enabled_or_skip = is_testing_enabled_or_skip if auth_token is not None: self.headers["Authorization"] = f"Bearer {auth_token}" @@ -994,6 +993,8 @@ class NeonPageserverHttpClient(requests.Session): self.get(f"http://localhost:{self.port}/v1/status").raise_for_status() def configure_failpoints(self, config_strings: tuple[str, str] | list[tuple[str, str]]) -> None: + self.is_testing_enabled_or_skip() + if isinstance(config_strings, tuple): pairs = [config_strings] else: @@ -1111,6 +1112,8 @@ class NeonPageserverHttpClient(requests.Session): def timeline_gc( self, tenant_id: TenantId, timeline_id: TimelineId, gc_horizon: Optional[int] ) -> dict[str, Any]: + self.is_testing_enabled_or_skip() + log.info( f"Requesting GC: tenant {tenant_id}, timeline {timeline_id}, gc_horizon {repr(gc_horizon)}" ) @@ -1126,6 +1129,8 @@ class NeonPageserverHttpClient(requests.Session): return res_json def timeline_compact(self, tenant_id: TenantId, timeline_id: TimelineId): + self.is_testing_enabled_or_skip() + log.info(f"Requesting compact: tenant {tenant_id}, timeline {timeline_id}") res = self.put( f"http://localhost:{self.port}/v1/tenant/{tenant_id}/timeline/{timeline_id}/compact" @@ -1150,6 +1155,8 @@ class NeonPageserverHttpClient(requests.Session): return res_json def timeline_checkpoint(self, tenant_id: TenantId, timeline_id: TimelineId): + self.is_testing_enabled_or_skip() + log.info(f"Requesting checkpoint: tenant {tenant_id}, timeline {timeline_id}") res = self.put( f"http://localhost:{self.port}/v1/tenant/{tenant_id}/timeline/{timeline_id}/checkpoint" @@ -1469,21 +1476,6 @@ class NeonCli(AbstractNeonCli): res.check_returncode() return res - def pageserver_enabled_features(self) -> Any: - bin_pageserver = os.path.join(str(neon_binpath), "pageserver") - args = [bin_pageserver, "--enabled-features"] - log.info('Running command "{}"'.format(" ".join(args))) - - res = subprocess.run( - args, - check=True, - universal_newlines=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - log.info(f"pageserver_enabled_features success: {res.stdout}") - return json.loads(res.stdout) - def pageserver_start( self, overrides=(), @@ -1642,6 +1634,7 @@ class NeonPageserver(PgProtocol): self.running = False self.service_port = port self.config_override = config_override + self.version = env.get_pageserver_version() def start(self, overrides=()) -> "NeonPageserver": """ @@ -1671,10 +1664,19 @@ class NeonPageserver(PgProtocol): def __exit__(self, exc_type, exc, tb): self.stop(immediate=True) + def is_testing_enabled_or_skip(self): + if "testing:true" not in self.version: + pytest.skip("pageserver was built without 'testing' feature") + + def is_profiling_enabled_or_skip(self): + if "profiling:true" not in self.version: + pytest.skip("pageserver was built without 'profiling' feature") + def http_client(self, auth_token: Optional[str] = None) -> NeonPageserverHttpClient: return NeonPageserverHttpClient( port=self.service_port.http, auth_token=auth_token, + is_testing_enabled_or_skip=self.is_testing_enabled_or_skip, ) diff --git a/test_runner/performance/test_perf_pgbench.py b/test_runner/performance/test_perf_pgbench.py index 656826d6a3..0ed3e45971 100644 --- a/test_runner/performance/test_perf_pgbench.py +++ b/test_runner/performance/test_perf_pgbench.py @@ -9,7 +9,6 @@ from typing import Dict, List import pytest from fixtures.benchmark_fixture import MetricReport, PgBenchInitResult, PgBenchRunResult from fixtures.compare_fixtures import NeonCompare, PgCompare -from fixtures.neon_fixtures import profiling_supported from fixtures.utils import get_scale_for_db @@ -187,10 +186,8 @@ def test_pgbench_flamegraph(zenbenchmark, pg_bin, neon_env_builder, scale: int, neon_env_builder.pageserver_config_override = """ profiling="page_requests" """ - if not profiling_supported(): - pytest.skip("pageserver was built without 'profiling' feature") - env = neon_env_builder.init_start() + env.pageserver.is_profiling_enabled_or_skip() env.neon_cli.create_branch("empty", "main") neon_compare = NeonCompare(zenbenchmark, env, pg_bin, "pgbench") diff --git a/test_runner/regress/test_recovery.py b/test_runner/regress/test_recovery.py index d0ba96e8e0..e70b1351ba 100644 --- a/test_runner/regress/test_recovery.py +++ b/test_runner/regress/test_recovery.py @@ -13,13 +13,8 @@ def test_pageserver_recovery(neon_env_builder: NeonEnvBuilder): neon_env_builder.pageserver_config_override = "tenant_config={checkpoint_distance = 1048576}" env = neon_env_builder.init() + env.pageserver.is_testing_enabled_or_skip() - # Check if failpoints enables. Otherwise the test doesn't make sense - f = env.neon_cli.pageserver_enabled_features() - - assert ( - "testing" in f["features"] - ), "Build pageserver with --features=testing option to run this test" neon_env_builder.start() # Create a branch for us diff --git a/test_runner/regress/test_tenant_relocation.py b/test_runner/regress/test_tenant_relocation.py index a3245d65e4..e14434ffdc 100644 --- a/test_runner/regress/test_tenant_relocation.py +++ b/test_runner/regress/test_tenant_relocation.py @@ -346,7 +346,11 @@ def test_tenant_relocation( log.info("new pageserver ports pg %s http %s", new_pageserver_pg_port, new_pageserver_http_port) pageserver_bin = pathlib.Path(neon_binpath) / "pageserver" - new_pageserver_http = NeonPageserverHttpClient(port=new_pageserver_http_port, auth_token=None) + new_pageserver_http = NeonPageserverHttpClient( + port=new_pageserver_http_port, + auth_token=None, + is_testing_enabled_or_skip=env.pageserver.is_testing_enabled_or_skip, + ) with new_pageserver_helper( new_pageserver_dir, From 50297bef9fb5163e067a76001062d68ab5498b84 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 20 Oct 2022 12:49:54 +0300 Subject: [PATCH 52/64] RFC about Tenant / Timeline guard objects (#2660) Co-authored-by: Heikki Linnakangas --- docs/SUMMARY.md | 2 + docs/rfcs/019-tenant-timeline-lifecycles.md | 91 +++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 docs/rfcs/019-tenant-timeline-lifecycles.md diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index fb6467ffd5..faf2b2336f 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -80,4 +80,6 @@ - [015-storage-messaging](rfcs/015-storage-messaging.md) - [016-connection-routing](rfcs/016-connection-routing.md) - [017-timeline-data-management](rfcs/017-timeline-data-management.md) +- [018-storage-messaging-2](rfcs/018-storage-messaging-2.md) +- [019-tenant-timeline-lifecycles](rfcs/019-tenant-timeline-lifecycles.md) - [cluster-size-limits](rfcs/cluster-size-limits.md) diff --git a/docs/rfcs/019-tenant-timeline-lifecycles.md b/docs/rfcs/019-tenant-timeline-lifecycles.md new file mode 100644 index 0000000000..2734bf17b9 --- /dev/null +++ b/docs/rfcs/019-tenant-timeline-lifecycles.md @@ -0,0 +1,91 @@ +# Managing Tenant and Timeline lifecycles + +## Summary + +The pageserver has a Tenant object in memory for each tenant it manages, and a +Timeline for each timeline. There are a lot of tasks that operate on the tenants +and timelines with references to those objects. We have some mechanisms to track +which tasks are operating on each Tenant and Timeline, and to request them to +shutdown when a tenant or timeline is deleted, but it does not cover all uses, +and as a result we have many race conditions around tenant/timeline shutdown. + +## Motivation + +We have a bunch of race conditions that can produce weird errors and can be hard +to track down. + +## Non Goals + +This RFC only covers the problem of ensuring that a task/thread isn't operating +on a Tenant or Timeline. It does not cover what states, aside from Active and +non-Active, each Tenant and Timeline should have, or when exactly the transitions +should happen. + +## Impacted components (e.g. pageserver, safekeeper, console, etc) + +Pageserver. Although I wonder if the safekeeper should have a similar mechanism. + +## Current situation + +Most pageserver tasks of are managed by task_mgr.rs: + +- LibpqEndpointListener +- HttpEndPointListener +- WalReceiverManager and -Connection +- GarbageCollector and Compaction +- InitialLogicalSizeCalculation + +In addition to those tasks, the walreceiver performs some direct tokio::spawn +calls to spawn tasks that are not registered with 'task_mgr'. And all of these +tasks can spawn extra operations with tokio spawn_blocking. + +Whenever a tenant or timeline is removed from the system, by pageserver +shutdown, delete_timeline or tenant-detach operation, we rely on the task +registry in 'task_mgr.rs' to wait until there are no tasks operating on the +tenant or timeline, before its Tenant/Timeline object is removed. That relies on +each task to register itself with the tenant/timeline ID in +'task_mgr.rs'. However, there are many gaps in that. For example, +GarbageCollection and Compaction tasks are registered with the tenant, but when +they proceed to operate on a particular timeline of the tenant, they don't +register with timeline ID. Because of that, the timeline can be deleted while GC +or compaction is running on it, causing failures in the GC or compaction (see +https://github.com/neondatabase/neon/issues/2442). + +Another problem is that the task registry only works for tokio Tasks. There is +no way to register a piece of code that runs inside spawn_blocking(), for +example. + +## Proposed implementation + +This "voluntary" registration of tasks is fragile. Let's use Rust language features +to enforce that a tenant/timeline cannot be removed from the system when there is +still some code operating on it. + +Let's introduce new Guard objects for Tenant and Timeline, and do all actions through +the Guard object. Something like: + +TenantActiveGuard: Guard object over Arc. When you acquire the guard, +the code checks that the tenant is in Active state. If it's not, you get an +error. You can change the state of the tenant to Stopping while there are +ActiveTenantGuard objects still on it, to prevent new ActiveTenantGuards from +being acquired, but the Tenant cannot be removed until all the guards are gone. + +TenantMaintenanceGuard: Like ActiveTenantGuard, but can be held even when the +tenant is not in Active state. Used for operations like attach/detach. Perhaps +allow only one such guard on a Tenant at a time. + +Similarly for Timelines. We don't currentl have a "state" on Timeline, but I think +we need at least two states: Active and Stopping. The Stopping state is used at +deletion, to prevent new TimelineActiveGuards from appearing, while you wait for +existing TimelineActiveGuards to die out. + +The shutdown-signaling, using shutdown_watcher() and is_shutdown_requested(), +probably also needs changes to deal with the new Guards. The rule is that if you +have a TenantActiveGuard, and the tenant's state changes from Active to +Stopping, the is_shutdown_requested() function should return true, and +shutdown_watcher() future should return. + +This signaling doesn't neessarily need to cover all cases. For example, if you +have a block of code in spawn_blocking(), it might be acceptable if +is_shutdown_requested() doesn't return true even though the tenant is in +Stopping state, as long as the code finishes reasonably fast. From 84c5f681b07479b4d128d2e0e31d0a2d01f6b9fa Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 20 Oct 2022 13:44:03 +0300 Subject: [PATCH 53/64] Fix test feature detection (#2659) Follow-up of #2636 and #2654 , fixing the test detection feature. Pageserver currently outputs features as ``` /target/debug/pageserver --version Neon page server git:7734929a8202c8cc41596a861ffbe0b51b5f3cb9 failpoints: true, features: ["testing", "profiling"] ``` --- test_runner/fixtures/neon_fixtures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_runner/fixtures/neon_fixtures.py b/test_runner/fixtures/neon_fixtures.py index c6bfa7f69e..a77b3958c9 100644 --- a/test_runner/fixtures/neon_fixtures.py +++ b/test_runner/fixtures/neon_fixtures.py @@ -1665,11 +1665,11 @@ class NeonPageserver(PgProtocol): self.stop(immediate=True) def is_testing_enabled_or_skip(self): - if "testing:true" not in self.version: + if '"testing"' not in self.version: pytest.skip("pageserver was built without 'testing' feature") def is_profiling_enabled_or_skip(self): - if "profiling:true" not in self.version: + if '"profiling"' not in self.version: pytest.skip("pageserver was built without 'profiling' feature") def http_client(self, auth_token: Optional[str] = None) -> NeonPageserverHttpClient: From 306a47c4fab6f9c0c2cf83af64848750ff772335 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 20 Oct 2022 14:19:17 +0300 Subject: [PATCH 54/64] Use uninit mark files during timeline init for atomic creation (#2489) Part of https://github.com/neondatabase/neon/pull/2239 Regular, from scratch, timeline creation involves initdb to be run in a separate directory, data from this directory to be imported into pageserver and, finally, timeline-related background tasks to start. This PR ensures we don't leave behind any directories that are not marked as temporary and that pageserver removes such directories on restart, allowing timeline creation to be retried with the same IDs, if needed. It would be good to later rewrite the logic to use a temporary directory, similar what tenant creation does. Yet currently it's harder than this change, so not done. --- libs/remote_storage/src/local_fs.rs | 2 +- .../src/{crashsafe_dir.rs => crashsafe.rs} | 43 +- libs/utils/src/lib.rs | 4 +- pageserver/src/bin/pageserver.rs | 2 +- pageserver/src/config.rs | 13 + pageserver/src/import_datadir.rs | 16 +- pageserver/src/page_service.rs | 18 +- pageserver/src/pgdatadir_mapping.rs | 4 +- pageserver/src/storage_sync/download.rs | 2 +- pageserver/src/tenant.rs | 619 ++++++++++++++---- pageserver/src/tenant_mgr.rs | 236 +++++-- .../src/walreceiver/connection_manager.rs | 4 +- pageserver/src/walredo.rs | 2 +- test_runner/regress/test_broken_timeline.py | 41 +- test_runner/regress/test_import.py | 6 +- test_runner/regress/test_tenants.py | 24 +- 16 files changed, 777 insertions(+), 259 deletions(-) rename libs/utils/src/{crashsafe_dir.rs => crashsafe.rs} (84%) diff --git a/libs/remote_storage/src/local_fs.rs b/libs/remote_storage/src/local_fs.rs index 5723a512f6..2f824cc453 100644 --- a/libs/remote_storage/src/local_fs.rs +++ b/libs/remote_storage/src/local_fs.rs @@ -16,7 +16,7 @@ use tokio::{ io::{self, AsyncReadExt, AsyncSeekExt, AsyncWriteExt}, }; use tracing::*; -use utils::crashsafe_dir::path_with_suffix_extension; +use utils::crashsafe::path_with_suffix_extension; use crate::{Download, DownloadError, RemoteObjectId}; diff --git a/libs/utils/src/crashsafe_dir.rs b/libs/utils/src/crashsafe.rs similarity index 84% rename from libs/utils/src/crashsafe_dir.rs rename to libs/utils/src/crashsafe.rs index 032ab0a916..3726779cb2 100644 --- a/libs/utils/src/crashsafe_dir.rs +++ b/libs/utils/src/crashsafe.rs @@ -12,16 +12,8 @@ pub fn create_dir(path: impl AsRef) -> io::Result<()> { let path = path.as_ref(); fs::create_dir(path)?; - File::open(path)?.sync_all()?; - - if let Some(parent) = path.parent() { - File::open(parent)?.sync_all() - } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - "can't find parent", - )) - } + fsync_file_and_parent(path)?; + Ok(()) } /// Similar to [`std::fs::create_dir_all`], except we fsync all @@ -65,12 +57,12 @@ pub fn create_dir_all(path: impl AsRef) -> io::Result<()> { // Fsync the created directories from child to parent. for &path in dirs_to_create.iter() { - File::open(path)?.sync_all()?; + fsync(path)?; } // If we created any new directories, fsync the parent. if !dirs_to_create.is_empty() { - File::open(path)?.sync_all()?; + fsync(path)?; } Ok(()) @@ -92,6 +84,33 @@ pub fn path_with_suffix_extension(original_path: impl AsRef, suffix: &str) .with_extension(new_extension.as_ref()) } +pub fn fsync_file_and_parent(file_path: &Path) -> io::Result<()> { + let parent = file_path.parent().ok_or_else(|| { + io::Error::new( + io::ErrorKind::Other, + format!("File {file_path:?} has no parent"), + ) + })?; + + fsync(file_path)?; + fsync(parent)?; + Ok(()) +} + +pub fn fsync(path: &Path) -> io::Result<()> { + File::open(path) + .map_err(|e| io::Error::new(e.kind(), format!("Failed to open the file {path:?}: {e}"))) + .and_then(|file| { + file.sync_all().map_err(|e| { + io::Error::new( + e.kind(), + format!("Failed to sync file {path:?} data and metadata: {e}"), + ) + }) + }) + .map_err(|e| io::Error::new(e.kind(), format!("Failed to fsync file {path:?}: {e}"))) +} + #[cfg(test)] mod tests { use tempfile::tempdir; diff --git a/libs/utils/src/lib.rs b/libs/utils/src/lib.rs index 2c80556446..f1f48f5a90 100644 --- a/libs/utils/src/lib.rs +++ b/libs/utils/src/lib.rs @@ -22,8 +22,8 @@ pub mod pq_proto; // dealing with connstring parsing and handy access to it's parts pub mod connstring; -// helper functions for creating and fsyncing directories/trees -pub mod crashsafe_dir; +// helper functions for creating and fsyncing +pub mod crashsafe; // common authentication routines pub mod auth; diff --git a/pageserver/src/bin/pageserver.rs b/pageserver/src/bin/pageserver.rs index 12f594077e..9317dd5dd7 100644 --- a/pageserver/src/bin/pageserver.rs +++ b/pageserver/src/bin/pageserver.rs @@ -87,7 +87,7 @@ fn main() -> anyhow::Result<()> { let tenants_path = conf.tenants_path(); if !tenants_path.exists() { - utils::crashsafe_dir::create_dir_all(conf.tenants_path()).with_context(|| { + utils::crashsafe::create_dir_all(conf.tenants_path()).with_context(|| { format!( "Failed to create tenants root dir at '{}'", tenants_path.display() diff --git a/pageserver/src/config.rs b/pageserver/src/config.rs index 6e3c7baad8..b797866e43 100644 --- a/pageserver/src/config.rs +++ b/pageserver/src/config.rs @@ -7,6 +7,7 @@ use anyhow::{anyhow, bail, ensure, Context, Result}; use remote_storage::RemoteStorageConfig; use std::env; +use utils::crashsafe::path_with_suffix_extension; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -24,6 +25,7 @@ use crate::tenant_config::{TenantConf, TenantConfOpt}; /// The name of the metadata file pageserver creates per timeline. pub const METADATA_FILE_NAME: &str = "metadata"; +pub const TIMELINE_UNINIT_MARK_SUFFIX: &str = "___uninit"; const TENANT_CONFIG_NAME: &str = "config"; pub mod defaults { @@ -364,6 +366,17 @@ impl PageServerConf { self.timelines_path(tenant_id).join(timeline_id.to_string()) } + pub fn timeline_uninit_mark_file_path( + &self, + tenant_id: TenantId, + timeline_id: TimelineId, + ) -> PathBuf { + path_with_suffix_extension( + self.timeline_path(&timeline_id, &tenant_id), + TIMELINE_UNINIT_MARK_SUFFIX, + ) + } + /// Points to a place in pageserver's local directory, /// where certain timeline's metadata file should be located. pub fn metadata_path(&self, timeline_id: TimelineId, tenant_id: TenantId) -> PathBuf { diff --git a/pageserver/src/import_datadir.rs b/pageserver/src/import_datadir.rs index 23c4351b4e..ee3dc684e3 100644 --- a/pageserver/src/import_datadir.rs +++ b/pageserver/src/import_datadir.rs @@ -43,19 +43,19 @@ pub fn get_lsn_from_controlfile(path: &Path) -> Result { /// The code that deals with the checkpoint would not work right if the /// cluster was not shut down cleanly. pub fn import_timeline_from_postgres_datadir( - path: &Path, tline: &Timeline, - lsn: Lsn, + pgdata_path: &Path, + pgdata_lsn: Lsn, ) -> Result<()> { let mut pg_control: Option = None; // TODO this shoud be start_lsn, which is not necessarily equal to end_lsn (aka lsn) // Then fishing out pg_control would be unnecessary - let mut modification = tline.begin_modification(lsn); + let mut modification = tline.begin_modification(pgdata_lsn); modification.init_empty()?; // Import all but pg_wal - let all_but_wal = WalkDir::new(path) + let all_but_wal = WalkDir::new(pgdata_path) .into_iter() .filter_entry(|entry| !entry.path().ends_with("pg_wal")); for entry in all_but_wal { @@ -63,7 +63,7 @@ pub fn import_timeline_from_postgres_datadir( let metadata = entry.metadata().expect("error getting dir entry metadata"); if metadata.is_file() { let absolute_path = entry.path(); - let relative_path = absolute_path.strip_prefix(path)?; + let relative_path = absolute_path.strip_prefix(pgdata_path)?; let file = File::open(absolute_path)?; let len = metadata.len() as usize; @@ -84,7 +84,7 @@ pub fn import_timeline_from_postgres_datadir( "Postgres cluster was not shut down cleanly" ); ensure!( - pg_control.checkPointCopy.redo == lsn.0, + pg_control.checkPointCopy.redo == pgdata_lsn.0, "unexpected checkpoint REDO pointer" ); @@ -92,10 +92,10 @@ pub fn import_timeline_from_postgres_datadir( // this reads the checkpoint record itself, advancing the tip of the timeline to // *after* the checkpoint record. And crucially, it initializes the 'prev_lsn'. import_wal( - &path.join("pg_wal"), + &pgdata_path.join("pg_wal"), tline, Lsn(pg_control.checkPointCopy.redo), - lsn, + pgdata_lsn, )?; Ok(()) diff --git a/pageserver/src/page_service.rs b/pageserver/src/page_service.rs index 795a99058d..9b2bb3114d 100644 --- a/pageserver/src/page_service.rs +++ b/pageserver/src/page_service.rs @@ -32,7 +32,7 @@ use utils::{ use crate::basebackup; use crate::config::{PageServerConf, ProfilingConfig}; -use crate::import_datadir::{import_basebackup_from_tar, import_wal_from_tar}; +use crate::import_datadir::import_wal_from_tar; use crate::metrics::{LIVE_CONNECTIONS_COUNT, SMGR_QUERY_TIME}; use crate::profiling::profpoint_start; use crate::reltag::RelTag; @@ -500,11 +500,8 @@ impl PageServerHandler { task_mgr::associate_with(Some(tenant_id), Some(timeline_id)); // Create empty timeline info!("creating new timeline"); - let timeline = tenant_mgr::get_tenant(tenant_id, true)?.create_empty_timeline( - timeline_id, - base_lsn, - pg_version, - )?; + let tenant = tenant_mgr::get_tenant(tenant_id, true)?; + let timeline = tenant.create_empty_timeline(timeline_id, base_lsn, pg_version)?; // TODO mark timeline as not ready until it reaches end_lsn. // We might have some wal to import as well, and we should prevent compute @@ -527,7 +524,8 @@ impl PageServerHandler { // - use block_in_place() let mut copyin_stream = Box::pin(copyin_stream(pgb)); let reader = SyncIoBridge::new(StreamReader::new(&mut copyin_stream)); - tokio::task::block_in_place(|| import_basebackup_from_tar(&timeline, reader, base_lsn))?; + tokio::task::block_in_place(|| timeline.import_basebackup_from_tar(reader, base_lsn))?; + timeline.initialize()?; // Drain the rest of the Copy data let mut bytes_after_tar = 0; @@ -544,12 +542,6 @@ impl PageServerHandler { // It wouldn't work if base came from vanilla postgres though, // since we discard some log files. - // Flush data to disk, then upload to s3 - info!("flushing layers"); - timeline.checkpoint(CheckpointConfig::Flush)?; - - timeline.launch_wal_receiver()?; - info!("done"); Ok(()) } diff --git a/pageserver/src/pgdatadir_mapping.rs b/pageserver/src/pgdatadir_mapping.rs index fc9867dc05..424ce4769a 100644 --- a/pageserver/src/pgdatadir_mapping.rs +++ b/pageserver/src/pgdatadir_mapping.rs @@ -1403,7 +1403,9 @@ pub fn create_test_timeline( timeline_id: utils::id::TimelineId, pg_version: u32, ) -> Result> { - let tline = tenant.create_empty_timeline(timeline_id, Lsn(8), pg_version)?; + let tline = tenant + .create_empty_timeline(timeline_id, Lsn(8), pg_version)? + .initialize()?; let mut m = tline.begin_modification(Lsn(8)); m.init_empty()?; m.commit()?; diff --git a/pageserver/src/storage_sync/download.rs b/pageserver/src/storage_sync/download.rs index 61ef164f14..6f9b2e2071 100644 --- a/pageserver/src/storage_sync/download.rs +++ b/pageserver/src/storage_sync/download.rs @@ -22,7 +22,7 @@ use crate::{ TEMP_FILE_SUFFIX, }; use utils::{ - crashsafe_dir::path_with_suffix_extension, + crashsafe::path_with_suffix_extension, id::{TenantId, TenantTimelineId, TimelineId}, }; diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index 47ef9284b8..93c473f0fe 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -14,7 +14,7 @@ use anyhow::{bail, ensure, Context, Result}; use tokio::sync::watch; use tracing::*; -use utils::crashsafe_dir::path_with_suffix_extension; +use utils::crashsafe::path_with_suffix_extension; use std::cmp::min; use std::collections::hash_map::Entry; @@ -23,10 +23,12 @@ use std::collections::HashMap; use std::fs; use std::fs::File; use std::fs::OpenOptions; +use std::io; use std::io::Write; use std::num::NonZeroU64; use std::ops::Bound::Included; use std::path::Path; +use std::path::PathBuf; use std::process::Command; use std::process::Stdio; use std::sync::Arc; @@ -49,7 +51,7 @@ pub use pageserver_api::models::TenantState; use toml_edit; use utils::{ - crashsafe_dir, + crashsafe, id::{TenantId, TimelineId}, lsn::{Lsn, RecordLsn}, }; @@ -120,6 +122,216 @@ pub struct Tenant { upload_layers: bool, } +/// A timeline with some of its files on disk, being initialized. +/// This struct ensures the atomicity of the timeline init: it's either properly created and inserted into pageserver's memory, or +/// its local files are removed. In the worst case of a crash, an uninit mark file is left behind, which causes the directory +/// to be removed on next restart. +/// +/// The caller is responsible for proper timeline data filling before the final init. +#[must_use] +pub struct UninitializedTimeline<'t> { + owning_tenant: &'t Tenant, + timeline_id: TimelineId, + raw_timeline: Option<(Timeline, TimelineUninitMark)>, +} + +/// An uninit mark file, created along the timeline dir to ensure the timeline either gets fully initialized and loaded into pageserver's memory, +/// or gets removed eventually. +/// +/// XXX: it's important to create it near the timeline dir, not inside it to ensure timeline dir gets removed first. +#[must_use] +struct TimelineUninitMark { + uninit_mark_deleted: bool, + uninit_mark_path: PathBuf, + timeline_path: PathBuf, +} + +impl UninitializedTimeline<'_> { + /// Ensures timeline data is valid, loads it into pageserver's memory and removes uninit mark file on success. + pub fn initialize(self) -> anyhow::Result> { + let mut timelines = self.owning_tenant.timelines.lock().unwrap(); + self.initialize_with_lock(&mut timelines, true) + } + + fn initialize_with_lock( + mut self, + timelines: &mut HashMap>, + load_layer_map: bool, + ) -> anyhow::Result> { + let timeline_id = self.timeline_id; + let tenant_id = self.owning_tenant.tenant_id; + + let (new_timeline, uninit_mark) = self.raw_timeline.take().with_context(|| { + format!("No timeline for initalization found for {tenant_id}/{timeline_id}") + })?; + let new_timeline = Arc::new(new_timeline); + + let new_disk_consistent_lsn = new_timeline.get_disk_consistent_lsn(); + // TODO it would be good to ensure that, but apparently a lot of our testing is dependend on that at least + // ensure!(new_disk_consistent_lsn.is_valid(), + // "Timeline {tenant_id}/{timeline_id} has invalid disk_consistent_lsn and cannot be initialized"); + + match timelines.entry(timeline_id) { + Entry::Occupied(_) => anyhow::bail!( + "Found freshly initialized timeline {tenant_id}/{timeline_id} in the tenant map" + ), + Entry::Vacant(v) => { + if load_layer_map { + new_timeline + .load_layer_map(new_disk_consistent_lsn) + .with_context(|| { + format!( + "Failed to load layermap for timeline {tenant_id}/{timeline_id}" + ) + })?; + } + uninit_mark.remove_uninit_mark().with_context(|| { + format!( + "Failed to remove uninit mark file for timeline {tenant_id}/{timeline_id}" + ) + })?; + v.insert(Arc::clone(&new_timeline)); + new_timeline.launch_wal_receiver().with_context(|| { + format!("Failed to launch walreceiver for timeline {tenant_id}/{timeline_id}") + })?; + } + } + + Ok(new_timeline) + } + + /// Prepares timeline data by loading it from the basebackup archive. + pub fn import_basebackup_from_tar( + &self, + reader: impl std::io::Read, + base_lsn: Lsn, + ) -> anyhow::Result<()> { + let raw_timeline = self.raw_timeline()?; + import_datadir::import_basebackup_from_tar(raw_timeline, reader, base_lsn).with_context( + || { + format!( + "Failed to import basebackup for timeline {}/{}", + self.owning_tenant.tenant_id, self.timeline_id + ) + }, + )?; + + fail::fail_point!("before-checkpoint-new-timeline", |_| { + bail!("failpoint before-checkpoint-new-timeline"); + }); + + raw_timeline + .checkpoint(CheckpointConfig::Flush) + .with_context(|| { + format!( + "Failed to checkpoint after basebackup import for timeline {}/{}", + self.owning_tenant.tenant_id, self.timeline_id + ) + })?; + Ok(()) + } + + fn raw_timeline(&self) -> anyhow::Result<&Timeline> { + Ok(&self + .raw_timeline + .as_ref() + .with_context(|| { + format!( + "No raw timeline {}/{} found", + self.owning_tenant.tenant_id, self.timeline_id + ) + })? + .0) + } +} + +impl Drop for UninitializedTimeline<'_> { + fn drop(&mut self) { + if let Some((_, uninit_mark)) = self.raw_timeline.take() { + let _entered = info_span!("drop_uninitialized_timeline", tenant = %self.owning_tenant.tenant_id, timeline = %self.timeline_id).entered(); + error!("Timeline got dropped without initializing, cleaning its files"); + cleanup_timeline_directory(uninit_mark); + } + } +} + +fn cleanup_timeline_directory(uninit_mark: TimelineUninitMark) { + let timeline_path = &uninit_mark.timeline_path; + match ignore_absent_files(|| fs::remove_dir_all(timeline_path)) { + Ok(()) => { + info!("Timeline dir {timeline_path:?} removed successfully, removing the uninit mark") + } + Err(e) => { + error!("Failed to clean up uninitialized timeline directory {timeline_path:?}: {e:?}") + } + } + drop(uninit_mark); // mark handles its deletion on drop, gets retained if timeline dir exists +} + +impl TimelineUninitMark { + /// Useful for initializing timelines, existing on disk after the restart. + pub fn dummy() -> Self { + Self { + uninit_mark_deleted: true, + uninit_mark_path: PathBuf::new(), + timeline_path: PathBuf::new(), + } + } + + fn new(uninit_mark_path: PathBuf, timeline_path: PathBuf) -> Self { + Self { + uninit_mark_deleted: false, + uninit_mark_path, + timeline_path, + } + } + + fn remove_uninit_mark(mut self) -> anyhow::Result<()> { + if !self.uninit_mark_deleted { + self.delete_mark_file_if_present()?; + } + + Ok(()) + } + + fn delete_mark_file_if_present(&mut self) -> Result<(), anyhow::Error> { + let uninit_mark_file = &self.uninit_mark_path; + let uninit_mark_parent = uninit_mark_file + .parent() + .with_context(|| format!("Uninit mark file {uninit_mark_file:?} has no parent"))?; + ignore_absent_files(|| fs::remove_file(&uninit_mark_file)).with_context(|| { + format!("Failed to remove uninit mark file at path {uninit_mark_file:?}") + })?; + crashsafe::fsync(uninit_mark_parent).context("Failed to fsync uninit mark parent")?; + self.uninit_mark_deleted = true; + + Ok(()) + } +} + +impl Drop for TimelineUninitMark { + fn drop(&mut self) { + if !self.uninit_mark_deleted { + if self.timeline_path.exists() { + error!( + "Uninit mark {} is not removed, timeline {} stays uninitialized", + self.uninit_mark_path.display(), + self.timeline_path.display() + ) + } else { + // unblock later timeline creation attempts + warn!( + "Removing intermediate uninit mark file {}", + self.uninit_mark_path.display() + ); + if let Err(e) = self.delete_mark_file_if_present() { + error!("Failed to remove the uninit mark file: {e}") + } + } + } + } +} + /// A repository corresponds to one .neon directory. One repository holds multiple /// timelines, forked off from the same initial call to 'initdb'. impl Tenant { @@ -162,19 +374,10 @@ impl Tenant { new_timeline_id: TimelineId, initdb_lsn: Lsn, pg_version: u32, - ) -> Result> { - // XXX: keep the lock to avoid races during timeline creation - let mut timelines = self.timelines.lock().unwrap(); - - anyhow::ensure!( - timelines.get(&new_timeline_id).is_none(), - "Timeline {new_timeline_id} already exists" - ); - - let timeline_path = self.conf.timeline_path(&new_timeline_id, &self.tenant_id); - if timeline_path.exists() { - bail!("Timeline directory already exists, but timeline is missing in repository map. This is a bug.") - } + ) -> anyhow::Result { + let timelines = self.timelines.lock().unwrap(); + let timeline_uninit_mark = self.create_timeline_uninit_mark(new_timeline_id, &timelines)?; + drop(timelines); let new_metadata = TimelineMetadata::new( Lsn(0), @@ -185,11 +388,13 @@ impl Tenant { initdb_lsn, pg_version, ); - let new_timeline = - self.create_initialized_timeline(new_timeline_id, new_metadata, &mut timelines)?; - new_timeline.layers.write().unwrap().next_open_layer_at = Some(initdb_lsn); - - Ok(new_timeline) + self.prepare_timeline( + new_timeline_id, + new_metadata, + timeline_uninit_mark, + true, + None, + ) } /// Create a new timeline. @@ -205,14 +410,10 @@ impl Tenant { ancestor_timeline_id: Option, mut ancestor_start_lsn: Option, pg_version: u32, - ) -> Result>> { + ) -> anyhow::Result>> { let new_timeline_id = new_timeline_id.unwrap_or_else(TimelineId::generate); - if self - .conf - .timeline_path(&new_timeline_id, &self.tenant_id) - .exists() - { + if self.get_timeline(new_timeline_id).is_ok() { debug!("timeline {new_timeline_id} already exists"); return Ok(None); } @@ -391,21 +592,32 @@ impl Tenant { timeline_id, metadata.pg_version() ); - let ancestor = metadata - .ancestor_timeline() - .and_then(|ancestor_timeline_id| timelines_accessor.get(&ancestor_timeline_id)) - .cloned(); - match timelines_accessor.entry(timeline_id) { - Entry::Occupied(_) => warn!( + + if timelines_accessor.contains_key(&timeline_id) { + warn!( "Timeline {}/{} already exists in the tenant map, skipping its initialization", self.tenant_id, timeline_id - ), - Entry::Vacant(v) => { - let timeline = self - .initialize_new_timeline(timeline_id, metadata, ancestor) - .with_context(|| format!("Failed to initialize timeline {timeline_id}"))?; - v.insert(timeline); - } + ); + continue; + } else { + let ancestor = metadata + .ancestor_timeline() + .and_then(|ancestor_timeline_id| timelines_accessor.get(&ancestor_timeline_id)) + .cloned(); + let timeline = UninitializedTimeline { + owning_tenant: self, + timeline_id, + raw_timeline: Some(( + self.create_timeline_data(timeline_id, metadata, ancestor) + .with_context(|| { + format!("Failed to initialize timeline {timeline_id}") + })?, + TimelineUninitMark::dummy(), + )), + }; + let initialized_timeline = + timeline.initialize_with_lock(&mut timelines_accessor, true)?; + timelines_accessor.insert(timeline_id, initialized_timeline); } } @@ -599,12 +811,12 @@ impl Tenant { self.tenant_conf.write().unwrap().update(&new_tenant_conf); } - fn initialize_new_timeline( + fn create_timeline_data( &self, new_timeline_id: TimelineId, new_metadata: TimelineMetadata, ancestor: Option>, - ) -> anyhow::Result> { + ) -> anyhow::Result { if let Some(ancestor_timeline_id) = new_metadata.ancestor_timeline() { anyhow::ensure!( ancestor.is_some(), @@ -612,9 +824,8 @@ impl Tenant { ) } - let new_disk_consistent_lsn = new_metadata.disk_consistent_lsn(); let pg_version = new_metadata.pg_version(); - let new_timeline = Arc::new(Timeline::new( + Ok(Timeline::new( self.conf, Arc::clone(&self.tenant_conf), new_metadata, @@ -624,15 +835,7 @@ impl Tenant { Arc::clone(&self.walredo_mgr), self.upload_layers, pg_version, - )); - - new_timeline - .load_layer_map(new_disk_consistent_lsn) - .context("failed to load layermap")?; - - new_timeline.launch_wal_receiver()?; - - Ok(new_timeline) + )) } pub fn new( @@ -914,11 +1117,14 @@ impl Tenant { src: TimelineId, dst: TimelineId, start_lsn: Option, - ) -> Result> { + ) -> anyhow::Result> { // We need to hold this lock to prevent GC from starting at the same time. GC scans the directory to learn // about timelines, so otherwise a race condition is possible, where we create new timeline and GC // concurrently removes data that is needed by the new timeline. let _gc_cs = self.gc_cs.lock().unwrap(); + let timelines = self.timelines.lock().unwrap(); + let timeline_uninit_mark = self.create_timeline_uninit_mark(dst, &timelines)?; + drop(timelines); // In order for the branch creation task to not wait for GC/compaction, // we need to make sure that the starting LSN of the child branch is not out of scope midway by @@ -929,12 +1135,12 @@ impl Tenant { // Step 2 is to avoid initializing the new branch using data removed by past GC iterations // or in-queue GC iterations. - // XXX: keep the lock to avoid races during timeline creation - let mut timelines = self.timelines.lock().unwrap(); - let src_timeline = timelines - .get(&src) - // message about timeline being remote is one .context up in the stack - .ok_or_else(|| anyhow::anyhow!("unknown timeline id: {src}"))?; + let src_timeline = self.get_timeline(src).with_context(|| { + format!( + "No ancestor {} found for timeline {}/{}", + src, self.tenant_id, dst + ) + })?; let latest_gc_cutoff_lsn = src_timeline.get_latest_gc_cutoff_lsn(); @@ -988,7 +1194,17 @@ impl Tenant { src_timeline.initdb_lsn, src_timeline.pg_version, ); - let new_timeline = self.create_initialized_timeline(dst, metadata, &mut timelines)?; + let mut timelines = self.timelines.lock().unwrap(); + let new_timeline = self + .prepare_timeline( + dst, + metadata, + timeline_uninit_mark, + false, + Some(src_timeline), + )? + .initialize_with_lock(&mut timelines, true)?; + drop(timelines); info!("branched timeline {dst} from {src} at {start_lsn}"); Ok(new_timeline) @@ -1000,7 +1216,10 @@ impl Tenant { &self, timeline_id: TimelineId, pg_version: u32, - ) -> Result> { + ) -> anyhow::Result> { + let timelines = self.timelines.lock().unwrap(); + let timeline_uninit_mark = self.create_timeline_uninit_mark(timeline_id, &timelines)?; + drop(timelines); // create a `tenant/{tenant_id}/timelines/basebackup-{timeline_id}.{TEMP_FILE_SUFFIX}/` // temporary directory for basebackup files for the given timeline. let initdb_path = path_with_suffix_extension( @@ -1010,24 +1229,65 @@ impl Tenant { TEMP_FILE_SUFFIX, ); - // Init temporarily repo to get bootstrap data + // an uninit mark was placed before, nothing else can access this timeline files + // current initdb was not run yet, so remove whatever was left from the previous runs + if initdb_path.exists() { + fs::remove_dir_all(&initdb_path).with_context(|| { + format!( + "Failed to remove already existing initdb directory: {}", + initdb_path.display() + ) + })?; + } + // Init temporarily repo to get bootstrap data, this creates a directory in the `initdb_path` path run_initdb(self.conf, &initdb_path, pg_version)?; - let pgdata_path = initdb_path; - - let lsn = import_datadir::get_lsn_from_controlfile(&pgdata_path)?.align(); + // this new directory is very temporary, set to remove it immediately after bootstrap, we don't need it + scopeguard::defer! { + if let Err(e) = fs::remove_dir_all(&initdb_path) { + // this is unlikely, but we will remove the directory on pageserver restart or another bootstrap call + error!("Failed to remove temporary initdb directory '{}': {}", initdb_path.display(), e); + } + } + let pgdata_path = &initdb_path; + let pgdata_lsn = import_datadir::get_lsn_from_controlfile(pgdata_path)?.align(); // Import the contents of the data directory at the initial checkpoint // LSN, and any WAL after that. // Initdb lsn will be equal to last_record_lsn which will be set after import. - // Because we know it upfront avoid having an option or dummy zero value by passing it to create_empty_timeline. - let timeline = self.create_empty_timeline(timeline_id, lsn, pg_version)?; - import_datadir::import_timeline_from_postgres_datadir(&pgdata_path, &*timeline, lsn)?; + // Because we know it upfront avoid having an option or dummy zero value by passing it to the metadata. + let new_metadata = TimelineMetadata::new( + Lsn(0), + None, + None, + Lsn(0), + pgdata_lsn, + pgdata_lsn, + pg_version, + ); + let raw_timeline = + self.prepare_timeline(timeline_id, new_metadata, timeline_uninit_mark, true, None)?; + + let tenant_id = raw_timeline.owning_tenant.tenant_id; + let unfinished_timeline = raw_timeline.raw_timeline()?; + import_datadir::import_timeline_from_postgres_datadir( + unfinished_timeline, + pgdata_path, + pgdata_lsn, + ) + .with_context(|| { + format!("Failed to import pgdatadir for timeline {tenant_id}/{timeline_id}") + })?; fail::fail_point!("before-checkpoint-new-timeline", |_| { - bail!("failpoint before-checkpoint-new-timeline"); + anyhow::bail!("failpoint before-checkpoint-new-timeline"); }); + unfinished_timeline + .checkpoint(CheckpointConfig::Forced) + .with_context(|| format!("Failed to checkpoint after pgdatadir import for timeline {tenant_id}/{timeline_id}"))?; - timeline.checkpoint(CheckpointConfig::Forced)?; + let mut timelines = self.timelines.lock().unwrap(); + let timeline = raw_timeline.initialize_with_lock(&mut timelines, false)?; + drop(timelines); info!( "created root timeline {} timeline.lsn {}", @@ -1035,25 +1295,65 @@ impl Tenant { timeline.get_last_record_lsn() ); - // Remove temp dir. We don't need it anymore - fs::remove_dir_all(pgdata_path)?; - Ok(timeline) } - fn create_initialized_timeline( + /// Creates intermediate timeline structure and its files, without loading it into memory. + /// It's up to the caller to import the necesary data and import the timeline into memory. + fn prepare_timeline( &self, new_timeline_id: TimelineId, new_metadata: TimelineMetadata, - timelines: &mut MutexGuard>>, - ) -> Result> { - crashsafe_dir::create_dir_all(self.conf.timeline_path(&new_timeline_id, &self.tenant_id)) - .with_context(|| { - format!( - "Failed to create timeline {}/{} directory", - new_timeline_id, self.tenant_id - ) - })?; + uninit_mark: TimelineUninitMark, + init_layers: bool, + ancestor: Option>, + ) -> anyhow::Result { + let tenant_id = self.tenant_id; + + match self.create_timeline_files( + &uninit_mark.timeline_path, + new_timeline_id, + new_metadata, + ancestor, + ) { + Ok(new_timeline) => { + if init_layers { + new_timeline.layers.write().unwrap().next_open_layer_at = + Some(new_timeline.initdb_lsn); + } + debug!( + "Successfully created initial files for timeline {tenant_id}/{new_timeline_id}" + ); + Ok(UninitializedTimeline { + owning_tenant: self, + timeline_id: new_timeline_id, + raw_timeline: Some((new_timeline, uninit_mark)), + }) + } + Err(e) => { + error!("Failed to create initial files for timeline {tenant_id}/{new_timeline_id}, cleaning up: {e:?}"); + cleanup_timeline_directory(uninit_mark); + Err(e) + } + } + } + + fn create_timeline_files( + &self, + timeline_path: &Path, + new_timeline_id: TimelineId, + new_metadata: TimelineMetadata, + ancestor: Option>, + ) -> anyhow::Result { + let timeline_data = self + .create_timeline_data(new_timeline_id, new_metadata.clone(), ancestor) + .context("Failed to create timeline data structure")?; + crashsafe::create_dir_all(timeline_path).context("Failed to create timeline directory")?; + + fail::fail_point!("after-timeline-uninit-mark-creation", |_| { + anyhow::bail!("failpoint after-timeline-uninit-mark-creation"); + }); + save_metadata( self.conf, new_timeline_id, @@ -1061,37 +1361,49 @@ impl Tenant { &new_metadata, true, ) - .with_context(|| { - format!( - "Failed to create timeline {}/{} metadata", - new_timeline_id, self.tenant_id - ) - })?; + .context("Failed to create timeline metadata")?; - let ancestor = new_metadata - .ancestor_timeline() - .and_then(|ancestor_timeline_id| timelines.get(&ancestor_timeline_id)) - .cloned(); - let new_timeline = self - .initialize_new_timeline(new_timeline_id, new_metadata, ancestor) + Ok(timeline_data) + } + + /// Attempts to create an uninit mark file for the timeline initialization. + /// Bails, if the timeline is already loaded into the memory (i.e. initialized before), or the uninit mark file already exists. + /// + /// This way, we need to hold the timelines lock only for small amount of time during the mark check/creation per timeline init. + fn create_timeline_uninit_mark( + &self, + timeline_id: TimelineId, + timelines: &MutexGuard>>, + ) -> anyhow::Result { + let tenant_id = self.tenant_id; + + anyhow::ensure!( + timelines.get(&timeline_id).is_none(), + "Timeline {tenant_id}/{timeline_id} already exists in pageserver's memory" + ); + let timeline_path = self.conf.timeline_path(&timeline_id, &tenant_id); + anyhow::ensure!( + !timeline_path.exists(), + "Timeline {} already exists, cannot create its uninit mark file", + timeline_path.display() + ); + + let uninit_mark_path = self + .conf + .timeline_uninit_mark_file_path(tenant_id, timeline_id); + fs::File::create(&uninit_mark_path) + .context("Failed to create uninit mark file") + .and_then(|_| { + crashsafe::fsync_file_and_parent(&uninit_mark_path) + .context("Failed to fsync uninit mark file") + }) .with_context(|| { - format!( - "Failed to initialize timeline {}/{}", - new_timeline_id, self.tenant_id - ) + format!("Failed to crate uninit mark for timeline {tenant_id}/{timeline_id}") })?; - match timelines.entry(new_timeline_id) { - Entry::Occupied(_) => bail!( - "Found freshly initialized timeline {} in the tenant map", - new_timeline_id - ), - Entry::Vacant(v) => { - v.insert(Arc::clone(&new_timeline)); - } - } + let uninit_mark = TimelineUninitMark::new(uninit_mark_path, timeline_path); - Ok(new_timeline) + Ok(uninit_mark) } } @@ -1111,7 +1423,7 @@ fn run_initdb( initdb_lib_dir.display(), ); - let initdb_output = Command::new(initdb_bin_path) + let initdb_output = Command::new(&initdb_bin_path) .args(&["-D", &initdb_target_dir.to_string_lossy()]) .args(&["-U", &conf.superuser]) .args(&["-E", "utf8"]) @@ -1124,7 +1436,13 @@ fn run_initdb( .env("DYLD_LIBRARY_PATH", &initdb_lib_dir) .stdout(Stdio::null()) .output() - .context("failed to execute initdb")?; + .with_context(|| { + format!( + "failed to execute {} at target dir {}", + initdb_bin_path.display(), + initdb_target_dir.display() + ) + })?; if !initdb_output.status.success() { bail!( "initdb failed: '{}'", @@ -1163,6 +1481,19 @@ pub fn dump_layerfile_from_path(path: &Path, verbose: bool) -> Result<()> { Ok(()) } +fn ignore_absent_files(fs_operation: F) -> io::Result<()> +where + F: Fn() -> io::Result<()>, +{ + fs_operation().or_else(|e| { + if e.kind() == io::ErrorKind::NotFound { + Ok(()) + } else { + Err(e) + } + }) +} + #[cfg(test)] pub mod harness { use bytes::{Bytes, BytesMut}; @@ -1379,7 +1710,9 @@ mod tests { #[test] fn test_basic() -> Result<()> { let tenant = TenantHarness::create("test_basic")?.load(); - let tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; let writer = tline.writer(); writer.put(*TEST_KEY, Lsn(0x10), &Value::Image(TEST_IMG("foo at 0x10")))?; @@ -1401,13 +1734,18 @@ mod tests { #[test] fn no_duplicate_timelines() -> Result<()> { let tenant = TenantHarness::create("no_duplicate_timelines")?.load(); - let _ = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let _ = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; match tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION) { Ok(_) => panic!("duplicate timeline creation should fail"), Err(e) => assert_eq!( e.to_string(), - format!("Timeline {TIMELINE_ID} already exists") + format!( + "Timeline {}/{} already exists in pageserver's memory", + tenant.tenant_id, TIMELINE_ID + ) ), } @@ -1427,7 +1765,9 @@ mod tests { #[test] fn test_branch() -> Result<()> { let tenant = TenantHarness::create("test_branch")?.load(); - let tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; let writer = tline.writer(); use std::str::from_utf8; @@ -1522,7 +1862,9 @@ mod tests { let tenant = TenantHarness::create("test_prohibit_branch_creation_on_garbage_collected_data")? .load(); - let tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; make_some_layers(tline.as_ref(), Lsn(0x20))?; // this removes layers before lsn 40 (50 minus 10), so there are two remaining layers, image and delta for 31-50 @@ -1552,7 +1894,9 @@ mod tests { let tenant = TenantHarness::create("test_prohibit_branch_creation_on_pre_initdb_lsn")?.load(); - tenant.create_empty_timeline(TIMELINE_ID, Lsn(0x50), DEFAULT_PG_VERSION)?; + tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0x50), DEFAULT_PG_VERSION)? + .initialize()?; // try to branch at lsn 0x25, should fail because initdb lsn is 0x50 match tenant.branch_timeline(TIMELINE_ID, NEW_TIMELINE_ID, Some(Lsn(0x25))) { Ok(_) => panic!("branching should have failed"), @@ -1596,7 +1940,9 @@ mod tests { fn test_retain_data_in_parent_which_is_needed_for_child() -> Result<()> { let tenant = TenantHarness::create("test_retain_data_in_parent_which_is_needed_for_child")?.load(); - let tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; make_some_layers(tline.as_ref(), Lsn(0x20))?; tenant.branch_timeline(TIMELINE_ID, NEW_TIMELINE_ID, Some(Lsn(0x40)))?; @@ -1613,7 +1959,9 @@ mod tests { fn test_parent_keeps_data_forever_after_branching() -> Result<()> { let tenant = TenantHarness::create("test_parent_keeps_data_forever_after_branching")?.load(); - let tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; make_some_layers(tline.as_ref(), Lsn(0x20))?; tenant.branch_timeline(TIMELINE_ID, NEW_TIMELINE_ID, Some(Lsn(0x40)))?; @@ -1641,8 +1989,9 @@ mod tests { let harness = TenantHarness::create(TEST_NAME)?; { let tenant = harness.load(); - let tline = - tenant.create_empty_timeline(TIMELINE_ID, Lsn(0x8000), DEFAULT_PG_VERSION)?; + let tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0x8000), DEFAULT_PG_VERSION)? + .initialize()?; make_some_layers(tline.as_ref(), Lsn(0x8000))?; tline.checkpoint(CheckpointConfig::Forced)?; } @@ -1662,7 +2011,9 @@ mod tests { // create two timelines { let tenant = harness.load(); - let tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; make_some_layers(tline.as_ref(), Lsn(0x20))?; tline.checkpoint(CheckpointConfig::Forced)?; @@ -1698,7 +2049,9 @@ mod tests { let harness = TenantHarness::create(TEST_NAME)?; let tenant = harness.load(); - tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; drop(tenant); let metadata_path = harness.timeline_path(&TIMELINE_ID).join(METADATA_FILE_NAME); @@ -1735,7 +2088,9 @@ mod tests { #[test] fn test_images() -> Result<()> { let tenant = TenantHarness::create("test_images")?.load(); - let tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; let writer = tline.writer(); writer.put(*TEST_KEY, Lsn(0x10), &Value::Image(TEST_IMG("foo at 0x10")))?; @@ -1785,7 +2140,9 @@ mod tests { #[test] fn test_bulk_insert() -> Result<()> { let tenant = TenantHarness::create("test_bulk_insert")?.load(); - let tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; let mut lsn = Lsn(0x10); @@ -1825,7 +2182,9 @@ mod tests { #[test] fn test_random_updates() -> Result<()> { let tenant = TenantHarness::create("test_random_updates")?.load(); - let tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; const NUM_KEYS: usize = 1000; @@ -1895,7 +2254,9 @@ mod tests { #[test] fn test_traverse_branches() -> Result<()> { let tenant = TenantHarness::create("test_traverse_branches")?.load(); - let mut tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let mut tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; const NUM_KEYS: usize = 1000; @@ -1974,7 +2335,9 @@ mod tests { #[test] fn test_traverse_ancestors() -> Result<()> { let tenant = TenantHarness::create("test_traverse_ancestors")?.load(); - let mut tline = tenant.create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)?; + let mut tline = tenant + .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? + .initialize()?; const NUM_KEYS: usize = 100; const NUM_TLINES: usize = 50; diff --git a/pageserver/src/tenant_mgr.rs b/pageserver/src/tenant_mgr.rs index b2c927d4fc..f1db50bf7f 100644 --- a/pageserver/src/tenant_mgr.rs +++ b/pageserver/src/tenant_mgr.rs @@ -12,7 +12,7 @@ use tracing::*; use remote_storage::GenericRemoteStorage; -use crate::config::{PageServerConf, METADATA_FILE_NAME}; +use crate::config::{PageServerConf, METADATA_FILE_NAME, TIMELINE_UNINIT_MARK_SUFFIX}; use crate::http::models::TenantInfo; use crate::storage_sync::index::{LayerFileMetadata, RemoteIndex, RemoteTimelineIndex}; use crate::storage_sync::{self, LocalTimelineInitStatus, SyncStartupData, TimelineLocalFiles}; @@ -24,7 +24,7 @@ use crate::tenant_config::TenantConfOpt; use crate::walredo::PostgresRedoManager; use crate::TEMP_FILE_SUFFIX; -use utils::crashsafe_dir::{self, path_with_suffix_extension}; +use utils::crashsafe::{self, path_with_suffix_extension}; use utils::id::{TenantId, TimelineId}; mod tenants_state { @@ -265,58 +265,98 @@ fn create_tenant_files( temporary_tenant_dir.display() ); - let temporary_tenant_timelines_dir = rebase_directory( - &conf.timelines_path(&tenant_id), - &target_tenant_directory, - &temporary_tenant_dir, - )?; - let temporary_tenant_config_path = rebase_directory( - &conf.tenant_config_path(tenant_id), - &target_tenant_directory, - &temporary_tenant_dir, - )?; - // top-level dir may exist if we are creating it through CLI - crashsafe_dir::create_dir_all(&temporary_tenant_dir).with_context(|| { + crashsafe::create_dir_all(&temporary_tenant_dir).with_context(|| { format!( "could not create temporary tenant directory {}", temporary_tenant_dir.display() ) })?; - // first, create a config in the top-level temp directory, fsync the file - Tenant::persist_tenant_config(&temporary_tenant_config_path, tenant_conf, true)?; - // then, create a subdirectory in the top-level temp directory, fsynced - crashsafe_dir::create_dir(&temporary_tenant_timelines_dir).with_context(|| { + + let creation_result = try_create_target_tenant_dir( + conf, + tenant_conf, + tenant_id, + &temporary_tenant_dir, + &target_tenant_directory, + ); + + if creation_result.is_err() { + error!("Failed to create directory structure for tenant {tenant_id}, cleaning tmp data"); + if let Err(e) = fs::remove_dir_all(&temporary_tenant_dir) { + error!("Failed to remove temporary tenant directory {temporary_tenant_dir:?}: {e}") + } else if let Err(e) = crashsafe::fsync(&temporary_tenant_dir) { + error!( + "Failed to fsync removed temporary tenant directory {temporary_tenant_dir:?}: {e}" + ) + } + } + + creation_result +} + +fn try_create_target_tenant_dir( + conf: &'static PageServerConf, + tenant_conf: TenantConfOpt, + tenant_id: TenantId, + temporary_tenant_dir: &Path, + target_tenant_directory: &Path, +) -> Result<(), anyhow::Error> { + let temporary_tenant_timelines_dir = rebase_directory( + &conf.timelines_path(&tenant_id), + target_tenant_directory, + temporary_tenant_dir, + ) + .with_context(|| format!("Failed to resolve tenant {tenant_id} temporary timelines dir"))?; + let temporary_tenant_config_path = rebase_directory( + &conf.tenant_config_path(tenant_id), + target_tenant_directory, + temporary_tenant_dir, + ) + .with_context(|| format!("Failed to resolve tenant {tenant_id} temporary config path"))?; + + Tenant::persist_tenant_config(&temporary_tenant_config_path, tenant_conf, true).with_context( + || { + format!( + "Failed to write tenant {} config to {}", + tenant_id, + temporary_tenant_config_path.display() + ) + }, + )?; + crashsafe::create_dir(&temporary_tenant_timelines_dir).with_context(|| { format!( - "could not create temporary tenant timelines directory {}", + "could not create tenant {} temporary timelines directory {}", + tenant_id, temporary_tenant_timelines_dir.display() ) })?; - fail::fail_point!("tenant-creation-before-tmp-rename", |_| { anyhow::bail!("failpoint tenant-creation-before-tmp-rename"); }); - // move-rename tmp directory with all files synced into a permanent directory, fsync its parent - fs::rename(&temporary_tenant_dir, &target_tenant_directory).with_context(|| { + fs::rename(&temporary_tenant_dir, target_tenant_directory).with_context(|| { format!( - "failed to move temporary tenant directory {} into the permanent one {}", + "failed to move tenant {} temporary directory {} into the permanent one {}", + tenant_id, temporary_tenant_dir.display(), target_tenant_directory.display() ) })?; let target_dir_parent = target_tenant_directory.parent().with_context(|| { format!( - "Failed to get tenant dir parent for {}", + "Failed to get tenant {} dir parent for {}", + tenant_id, target_tenant_directory.display() ) })?; - fs::File::open(target_dir_parent)?.sync_all()?; - - info!( - "created tenant directory structure in {}", - target_tenant_directory.display() - ); + crashsafe::fsync(target_dir_parent).with_context(|| { + format!( + "Failed to fsync renamed directory's parent {} for tenant {}", + target_dir_parent.display(), + tenant_id, + ) + })?; Ok(()) } @@ -602,6 +642,15 @@ fn is_temporary(path: &Path) -> bool { } } +fn is_uninit_mark(path: &Path) -> bool { + match path.file_name() { + Some(name) => name + .to_string_lossy() + .ends_with(TIMELINE_UNINIT_MARK_SUFFIX), + None => false, + } +} + fn collect_timelines_for_tenant( config: &'static PageServerConf, tenant_path: &Path, @@ -644,28 +693,74 @@ fn collect_timelines_for_tenant( e ); } + } else if is_uninit_mark(&timeline_dir) { + let timeline_uninit_mark_file = &timeline_dir; + info!( + "Found an uninit mark file {}, removing the timeline and its uninit mark", + timeline_uninit_mark_file.display() + ); + let timeline_id = timeline_uninit_mark_file + .file_stem() + .and_then(OsStr::to_str) + .unwrap_or_default() + .parse::() + .with_context(|| { + format!( + "Could not parse timeline id out of the timeline uninit mark name {}", + timeline_uninit_mark_file.display() + ) + })?; + let timeline_dir = config.timeline_path(&timeline_id, &tenant_id); + if let Err(e) = + remove_timeline_and_uninit_mark(&timeline_dir, timeline_uninit_mark_file) + { + error!("Failed to clean up uninit marked timeline: {e:?}"); + } } else { - match collect_timeline_files(&timeline_dir) { - Ok((timeline_id, metadata, timeline_files)) => { - tenant_timelines.insert( - timeline_id, - TimelineLocalFiles::collected(metadata, timeline_files), - ); + let timeline_id = timeline_dir + .file_name() + .and_then(OsStr::to_str) + .unwrap_or_default() + .parse::() + .with_context(|| { + format!( + "Could not parse timeline id out of the timeline dir name {}", + timeline_dir.display() + ) + })?; + let timeline_uninit_mark_file = + config.timeline_uninit_mark_file_path(tenant_id, timeline_id); + if timeline_uninit_mark_file.exists() { + info!("Found an uninit mark file for timeline {tenant_id}/{timeline_id}, removing the timeline and its uninit mark"); + if let Err(e) = remove_timeline_and_uninit_mark( + &timeline_dir, + &timeline_uninit_mark_file, + ) { + error!("Failed to clean up uninit marked timeline: {e:?}"); } - Err(e) => { - error!( - "Failed to process timeline dir contents at '{}', reason: {:?}", - timeline_dir.display(), - e - ); - match remove_if_empty(&timeline_dir) { - Ok(true) => info!( - "Removed empty timeline directory {}", - timeline_dir.display() - ), - Ok(false) => (), - Err(e) => { - error!("Failed to remove empty timeline directory: {e:?}") + } else { + match collect_timeline_files(&timeline_dir) { + Ok((metadata, timeline_files)) => { + tenant_timelines.insert( + timeline_id, + TimelineLocalFiles::collected(metadata, timeline_files), + ); + } + Err(e) => { + error!( + "Failed to process timeline dir contents at '{}', reason: {:?}", + timeline_dir.display(), + e + ); + match remove_if_empty(&timeline_dir) { + Ok(true) => info!( + "Removed empty timeline directory {}", + timeline_dir.display() + ), + Ok(false) => (), + Err(e) => { + error!("Failed to remove empty timeline directory: {e:?}") + } } } } @@ -688,24 +783,41 @@ fn collect_timelines_for_tenant( Ok((tenant_id, TenantAttachData::Ready(tenant_timelines))) } +fn remove_timeline_and_uninit_mark(timeline_dir: &Path, uninit_mark: &Path) -> anyhow::Result<()> { + fs::remove_dir_all(&timeline_dir) + .or_else(|e| { + if e.kind() == std::io::ErrorKind::NotFound { + // we can leave the uninit mark without a timeline dir, + // just remove the mark then + Ok(()) + } else { + Err(e) + } + }) + .with_context(|| { + format!( + "Failed to remove unit marked timeline directory {}", + timeline_dir.display() + ) + })?; + fs::remove_file(&uninit_mark).with_context(|| { + format!( + "Failed to remove timeline uninit mark file {}", + uninit_mark.display() + ) + })?; + + Ok(()) +} + // discover timeline files and extract timeline metadata // NOTE: ephemeral files are excluded from the list fn collect_timeline_files( timeline_dir: &Path, -) -> anyhow::Result<( - TimelineId, - TimelineMetadata, - HashMap, -)> { +) -> anyhow::Result<(TimelineMetadata, HashMap)> { let mut timeline_files = HashMap::new(); let mut timeline_metadata_path = None; - let timeline_id = timeline_dir - .file_name() - .and_then(OsStr::to_str) - .unwrap_or_default() - .parse::() - .context("Could not parse timeline id out of the timeline dir name")?; let timeline_dir_entries = fs::read_dir(&timeline_dir).context("Failed to list timeline dir contents")?; for entry in timeline_dir_entries { @@ -754,5 +866,5 @@ fn collect_timeline_files( "Timeline has no ancestor and no layer files" ); - Ok((timeline_id, metadata, timeline_files)) + Ok((metadata, timeline_files)) } diff --git a/pageserver/src/walreceiver/connection_manager.rs b/pageserver/src/walreceiver/connection_manager.rs index 29179e9871..01389e52f4 100644 --- a/pageserver/src/walreceiver/connection_manager.rs +++ b/pageserver/src/walreceiver/connection_manager.rs @@ -1374,7 +1374,9 @@ mod tests { timeline: harness .load() .create_empty_timeline(TIMELINE_ID, Lsn(0), crate::DEFAULT_PG_VERSION) - .expect("Failed to create an empty timeline for dummy wal connection manager"), + .expect("Failed to create an empty timeline for dummy wal connection manager") + .initialize() + .unwrap(), wal_connect_timeout: Duration::from_secs(1), lagging_wal_timeout: Duration::from_secs(1), max_lsn_wal_lag: NonZeroU64::new(1024 * 1024).unwrap(), diff --git a/pageserver/src/walredo.rs b/pageserver/src/walredo.rs index 1dd27caba6..b8874a0223 100644 --- a/pageserver/src/walredo.rs +++ b/pageserver/src/walredo.rs @@ -35,7 +35,7 @@ use std::sync::Mutex; use std::time::Duration; use std::time::Instant; use tracing::*; -use utils::crashsafe_dir::path_with_suffix_extension; +use utils::crashsafe::path_with_suffix_extension; use utils::{bin_ser::BeSer, id::TenantId, lsn::Lsn, nonblock::set_nonblock}; use crate::metrics::{ diff --git a/test_runner/regress/test_broken_timeline.py b/test_runner/regress/test_broken_timeline.py index 7baa67935d..101cce9ffc 100644 --- a/test_runner/regress/test_broken_timeline.py +++ b/test_runner/regress/test_broken_timeline.py @@ -111,18 +111,20 @@ def test_create_multiple_timelines_parallel(neon_simple_env: NeonEnv): future.result() -def test_fix_broken_timelines_on_startup(neon_simple_env: NeonEnv): +def test_timeline_init_break_before_checkpoint(neon_simple_env: NeonEnv): env = neon_simple_env pageserver_http = env.pageserver.http_client() tenant_id, _ = env.neon_cli.create_tenant() + timelines_dir = env.repo_dir / "tenants" / str(tenant_id) / "timelines" old_tenant_timelines = env.neon_cli.list_timelines(tenant_id) + initial_timeline_dirs = [d for d in timelines_dir.iterdir()] - # Introduce failpoint when creating a new timeline + # Introduce failpoint during timeline init (some intermediate files are on disk), before it's checkpointed. pageserver_http.configure_failpoints(("before-checkpoint-new-timeline", "return")) with pytest.raises(Exception, match="before-checkpoint-new-timeline"): - _ = env.neon_cli.create_timeline("test_fix_broken_timelines", tenant_id) + _ = env.neon_cli.create_timeline("test_timeline_init_break_before_checkpoint", tenant_id) # Restart the page server env.neon_cli.pageserver_stop(immediate=True) @@ -133,3 +135,36 @@ def test_fix_broken_timelines_on_startup(neon_simple_env: NeonEnv): assert ( new_tenant_timelines == old_tenant_timelines ), f"Pageserver after restart should ignore non-initialized timelines for tenant {tenant_id}" + + timeline_dirs = [d for d in timelines_dir.iterdir()] + assert ( + timeline_dirs == initial_timeline_dirs + ), "pageserver should clean its temp timeline files on timeline creation failure" + + +def test_timeline_create_break_after_uninit_mark(neon_simple_env: NeonEnv): + env = neon_simple_env + pageserver_http = env.pageserver.http_client() + + tenant_id, _ = env.neon_cli.create_tenant() + + timelines_dir = env.repo_dir / "tenants" / str(tenant_id) / "timelines" + old_tenant_timelines = env.neon_cli.list_timelines(tenant_id) + initial_timeline_dirs = [d for d in timelines_dir.iterdir()] + + # Introduce failpoint when creating a new timeline uninit mark, before any other files were created + pageserver_http.configure_failpoints(("after-timeline-uninit-mark-creation", "return")) + with pytest.raises(Exception, match="after-timeline-uninit-mark-creation"): + _ = env.neon_cli.create_timeline("test_timeline_create_break_after_uninit_mark", tenant_id) + + # Creating the timeline didn't finish. The other timelines on tenant should still be present and work normally. + # "New" timeline is not present in the list, allowing pageserver to retry the same request + new_tenant_timelines = env.neon_cli.list_timelines(tenant_id) + assert ( + new_tenant_timelines == old_tenant_timelines + ), f"Pageserver after restart should ignore non-initialized timelines for tenant {tenant_id}" + + timeline_dirs = [d for d in timelines_dir.iterdir()] + assert ( + timeline_dirs == initial_timeline_dirs + ), "pageserver should clean its temp timeline files on timeline creation failure" diff --git a/test_runner/regress/test_import.py b/test_runner/regress/test_import.py index 5910b4f74f..c888c6f7ee 100644 --- a/test_runner/regress/test_import.py +++ b/test_runner/regress/test_import.py @@ -105,15 +105,11 @@ def test_import_from_vanilla(test_output_dir, pg_bin, vanilla_pg, neon_env_build with pytest.raises(Exception): import_tar(corrupt_base_tar, wal_tar) - # Clean up - # TODO it should clean itself - client = env.pageserver.http_client() - client.timeline_delete(tenant, timeline) - # Importing correct backup works import_tar(base_tar, wal_tar) # Wait for data to land in s3 + client = env.pageserver.http_client() wait_for_last_record_lsn(client, tenant, timeline, Lsn(end_lsn)) wait_for_upload(client, tenant, timeline, Lsn(end_lsn)) diff --git a/test_runner/regress/test_tenants.py b/test_runner/regress/test_tenants.py index 37c5a130e2..4ffea60950 100644 --- a/test_runner/regress/test_tenants.py +++ b/test_runner/regress/test_tenants.py @@ -23,7 +23,7 @@ def test_tenant_creation_fails(neon_simple_env: NeonEnv): initial_tenants = sorted( map(lambda t: t.split()[0], neon_simple_env.neon_cli.list_tenants().stdout.splitlines()) ) - initial_tenant_dirs = set([d for d in tenants_dir.iterdir()]) + initial_tenant_dirs = [d for d in tenants_dir.iterdir()] pageserver_http = neon_simple_env.pageserver.http_client() pageserver_http.configure_failpoints(("tenant-creation-before-tmp-rename", "return")) @@ -35,26 +35,10 @@ def test_tenant_creation_fails(neon_simple_env: NeonEnv): ) assert initial_tenants == new_tenants, "should not create new tenants" - new_tenant_dirs = list(set([d for d in tenants_dir.iterdir()]) - initial_tenant_dirs) - assert len(new_tenant_dirs) == 1, "should have new tenant directory created" - tmp_tenant_dir = new_tenant_dirs[0] - assert str(tmp_tenant_dir).endswith( - ".___temp" - ), "new tenant directory created should be a temporary one" - - neon_simple_env.pageserver.stop() - neon_simple_env.pageserver.start() - - tenants_after_restart = sorted( - map(lambda t: t.split()[0], neon_simple_env.neon_cli.list_tenants().stdout.splitlines()) - ) - dirs_after_restart = set([d for d in tenants_dir.iterdir()]) + new_tenant_dirs = [d for d in tenants_dir.iterdir()] assert ( - tenants_after_restart == initial_tenants - ), "should load all non-corrupt tenants after restart" - assert ( - dirs_after_restart == initial_tenant_dirs - ), "pageserver should clean its temp tenant dirs on restart" + new_tenant_dirs == initial_tenant_dirs + ), "pageserver should clean its temp tenant dirs on tenant creation failure" def test_tenants_normal_work(neon_env_builder: NeonEnvBuilder): From f5ab9f761bfb3bcc8cfff942520517cba7aa462c Mon Sep 17 00:00:00 2001 From: Arthur Petukhovsky Date: Thu, 20 Oct 2022 16:14:32 +0300 Subject: [PATCH 55/64] Remove flaky checks in test_delete_force (#2567) --- test_runner/regress/test_wal_acceptor.py | 25 +++++------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/test_runner/regress/test_wal_acceptor.py b/test_runner/regress/test_wal_acceptor.py index 4451ba9d57..79adfb7b68 100644 --- a/test_runner/regress/test_wal_acceptor.py +++ b/test_runner/regress/test_wal_acceptor.py @@ -1114,10 +1114,7 @@ def test_delete_force(neon_env_builder: NeonEnvBuilder, auth_enabled: bool): cur.execute("INSERT INTO t (key) VALUES (1)") # Remove initial tenant's br1 (active) - assert sk_http.timeline_delete_force(tenant_id, timeline_id_1) == { - "dir_existed": True, - "was_active": True, - } + assert sk_http.timeline_delete_force(tenant_id, timeline_id_1)["dir_existed"] assert not (sk_data_dir / str(tenant_id) / str(timeline_id_1)).exists() assert (sk_data_dir / str(tenant_id) / str(timeline_id_2)).is_dir() assert (sk_data_dir / str(tenant_id) / str(timeline_id_3)).is_dir() @@ -1125,10 +1122,7 @@ def test_delete_force(neon_env_builder: NeonEnvBuilder, auth_enabled: bool): assert (sk_data_dir / str(tenant_id_other) / str(timeline_id_other)).is_dir() # Ensure repeated deletion succeeds - assert sk_http.timeline_delete_force(tenant_id, timeline_id_1) == { - "dir_existed": False, - "was_active": False, - } + assert not sk_http.timeline_delete_force(tenant_id, timeline_id_1)["dir_existed"] assert not (sk_data_dir / str(tenant_id) / str(timeline_id_1)).exists() assert (sk_data_dir / str(tenant_id) / str(timeline_id_2)).is_dir() assert (sk_data_dir / str(tenant_id) / str(timeline_id_3)).is_dir() @@ -1145,10 +1139,7 @@ def test_delete_force(neon_env_builder: NeonEnvBuilder, auth_enabled: bool): assert (sk_data_dir / str(tenant_id_other) / str(timeline_id_other)).is_dir() # Remove initial tenant's br2 (inactive) - assert sk_http.timeline_delete_force(tenant_id, timeline_id_2) == { - "dir_existed": True, - "was_active": False, - } + assert sk_http.timeline_delete_force(tenant_id, timeline_id_2)["dir_existed"] assert not (sk_data_dir / str(tenant_id) / str(timeline_id_1)).exists() assert not (sk_data_dir / str(tenant_id) / str(timeline_id_2)).exists() assert (sk_data_dir / str(tenant_id) / str(timeline_id_3)).is_dir() @@ -1156,10 +1147,7 @@ def test_delete_force(neon_env_builder: NeonEnvBuilder, auth_enabled: bool): assert (sk_data_dir / str(tenant_id_other) / str(timeline_id_other)).is_dir() # Remove non-existing branch, should succeed - assert sk_http.timeline_delete_force(tenant_id, TimelineId("00" * 16)) == { - "dir_existed": False, - "was_active": False, - } + assert not sk_http.timeline_delete_force(tenant_id, TimelineId("00" * 16))["dir_existed"] assert not (sk_data_dir / str(tenant_id) / str(timeline_id_1)).exists() assert not (sk_data_dir / str(tenant_id) / str(timeline_id_2)).exists() assert (sk_data_dir / str(tenant_id) / str(timeline_id_3)).exists() @@ -1168,10 +1156,7 @@ def test_delete_force(neon_env_builder: NeonEnvBuilder, auth_enabled: bool): # Remove initial tenant fully (two branches are active) response = sk_http.tenant_delete_force(tenant_id) - assert response[str(timeline_id_3)] == { - "dir_existed": True, - "was_active": True, - } + assert response[str(timeline_id_3)]["dir_existed"] assert not (sk_data_dir / str(tenant_id)).exists() assert (sk_data_dir / str(tenant_id_other) / str(timeline_id_other)).is_dir() From eb1bdcc6cfb72293019186021f40297affc6dc33 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 20 Oct 2022 13:21:36 +0300 Subject: [PATCH 56/64] If an FSM or VM page cannot be reconstructed, fill it with zeros. If we cannot reconstruct an FSM or VM page, while creating image layers, fill it with zeros instead. That should always be safe, for the FSM and VM, in the sense that you won't lose actual user data. It will get cleaned up by VACUUM later. We had a bug with FSM/VM truncation, where we truncated the FSM and VM at WAL replay to a smaller size than PostgreSQL originally did. We thought was harmless, as the FSM and VM are not critical for correctness and can be zeroed out or truncated without affecting user data. However, it lead to a situation where PostgreSQL created incremental WAL records for pages that we had already truncated away in the pageserver, and when we tried to replay those WAL records, that failed. That lead to a permanent error in image layer creation, and prevented it from ever finishing. See https://github.com/neondatabase/neon/issues/2601. With this patch, those pages will be filled with zeros in the image layer, which allows the image layer creation to finish. --- pageserver/src/lib.rs | 2 ++ pageserver/src/pgdatadir_mapping.rs | 11 +++++++++++ pageserver/src/tenant/timeline.rs | 29 ++++++++++++++++++++++++++++- pageserver/src/walingest.rs | 3 +-- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/pageserver/src/lib.rs b/pageserver/src/lib.rs index fe5114a247..c75f940386 100644 --- a/pageserver/src/lib.rs +++ b/pageserver/src/lib.rs @@ -46,6 +46,8 @@ pub const DELTA_FILE_MAGIC: u16 = 0x5A61; pub const LOG_FILE_NAME: &str = "pageserver.log"; +static ZERO_PAGE: bytes::Bytes = bytes::Bytes::from_static(&[0u8; 8192]); + /// Config for the Repository checkpointer #[derive(Debug, Clone, Copy)] pub enum CheckpointConfig { diff --git a/pageserver/src/pgdatadir_mapping.rs b/pageserver/src/pgdatadir_mapping.rs index 424ce4769a..ca931ed37d 100644 --- a/pageserver/src/pgdatadir_mapping.rs +++ b/pageserver/src/pgdatadir_mapping.rs @@ -1373,6 +1373,17 @@ fn is_rel_block_key(key: Key) -> bool { key.field1 == 0x00 && key.field4 != 0 } +pub fn is_rel_fsm_block_key(key: Key) -> bool { + key.field1 == 0x00 && key.field4 != 0 && key.field5 == FSM_FORKNUM && key.field6 != 0xffffffff +} + +pub fn is_rel_vm_block_key(key: Key) -> bool { + key.field1 == 0x00 + && key.field4 != 0 + && key.field5 == VISIBILITYMAP_FORKNUM + && key.field6 != 0xffffffff +} + pub fn key_to_slru_block(key: Key) -> Result<(SlruKind, u32, BlockNumber)> { Ok(match key.field1 { 0x01 => { diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index a771f82caf..d6ce644bb5 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -34,6 +34,7 @@ use crate::keyspace::{KeyPartitioning, KeySpace}; use crate::metrics::TimelineMetrics; use crate::pgdatadir_mapping::BlockNumber; use crate::pgdatadir_mapping::LsnForTimestamp; +use crate::pgdatadir_mapping::{is_rel_fsm_block_key, is_rel_vm_block_key}; use crate::reltag::RelTag; use crate::tenant_config::TenantConfOpt; @@ -52,6 +53,7 @@ use crate::task_mgr::TaskKind; use crate::walreceiver::{is_etcd_client_initialized, spawn_connection_manager_task}; use crate::walredo::WalRedoManager; use crate::CheckpointConfig; +use crate::ZERO_PAGE; use crate::{ page_cache, storage_sync::{self, index::LayerFileMetadata}, @@ -1496,7 +1498,32 @@ impl Timeline { for range in &partition.ranges { let mut key = range.start; while key < range.end { - let img = self.get(key, lsn)?; + let img = match self.get(key, lsn) { + Ok(img) => img, + Err(err) => { + // If we fail to reconstruct a VM or FSM page, we can zero the + // page without losing any actual user data. That seems better + // than failing repeatedly and getting stuck. + // + // We had a bug at one point, where we truncated the FSM and VM + // in the pageserver, but the Postgres didn't know about that + // and continued to generate incremental WAL records for pages + // that didn't exist in the pageserver. Trying to replay those + // WAL records failed to find the previous image of the page. + // This special case allows us to recover from that situation. + // See https://github.com/neondatabase/neon/issues/2601. + // + // Unfortunately we cannot do this for the main fork, or for + // any metadata keys, keys, as that would lead to actual data + // loss. + if is_rel_fsm_block_key(key) || is_rel_vm_block_key(key) { + warn!("could not reconstruct FSM or VM key {key}, filling with zeros: {err:?}"); + ZERO_PAGE.clone() + } else { + return Err(err); + } + } + }; image_layer_writer.put_image(key, &img)?; key = key.next(); } diff --git a/pageserver/src/walingest.rs b/pageserver/src/walingest.rs index d3d2c6d9b2..9a6b99d991 100644 --- a/pageserver/src/walingest.rs +++ b/pageserver/src/walingest.rs @@ -34,6 +34,7 @@ use crate::pgdatadir_mapping::*; use crate::reltag::{RelTag, SlruKind}; use crate::tenant::Timeline; use crate::walrecord::*; +use crate::ZERO_PAGE; use postgres_ffi::pg_constants; use postgres_ffi::relfile_utils::{FSM_FORKNUM, MAIN_FORKNUM, VISIBILITYMAP_FORKNUM}; use postgres_ffi::v14::nonrelfile_utils::mx_offset_to_member_segment; @@ -43,8 +44,6 @@ use postgres_ffi::TransactionId; use postgres_ffi::BLCKSZ; use utils::lsn::Lsn; -static ZERO_PAGE: Bytes = Bytes::from_static(&[0u8; 8192]); - pub struct WalIngest<'a> { timeline: &'a Timeline, From 7404777efc9cddd0c98cb3ee5de769a6225da4af Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Thu, 20 Oct 2022 20:06:05 +0300 Subject: [PATCH 57/64] Pin pages with speculative insert tuples to prevent their reconstruction because spec_token is not wal logged (#2657) * Pin pages with speculative insert tuples to prevent their reconstruction because spec_token is not wal logged refer ##2587 * Bump postgres versions --- vendor/postgres-v14 | 2 +- vendor/postgres-v15 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/postgres-v14 b/vendor/postgres-v14 index 19d948fd47..bdd502a8da 160000 --- a/vendor/postgres-v14 +++ b/vendor/postgres-v14 @@ -1 +1 @@ -Subproject commit 19d948fd47f45d83367062d9a54709cf2d9c8921 +Subproject commit bdd502a8da5de9e0ac709caabc0401455c97d235 diff --git a/vendor/postgres-v15 b/vendor/postgres-v15 index 339f2d642d..f7c5269e9c 160000 --- a/vendor/postgres-v15 +++ b/vendor/postgres-v15 @@ -1 +1 @@ -Subproject commit 339f2d642d7d430c44839f8293ae271f90e3cb81 +Subproject commit f7c5269e9c7e818653ad6fe95ba072d1901c4497 From 30984c163ca28818a7c0d35f42817d015fc7645e Mon Sep 17 00:00:00 2001 From: Sergey Melnikov Date: Thu, 20 Oct 2022 23:01:01 +0300 Subject: [PATCH 58/64] Fix race between pushing image to ECR and copying to dockerhub (#2662) --- .github/workflows/build_and_test.yml | 42 ++++++++++++++++------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index d90455ccca..460d73a552 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -481,6 +481,7 @@ jobs: neon-image: runs-on: dev + needs: [ tag ] container: gcr.io/kaniko-project/executor:v1.9.0-debug steps: @@ -494,10 +495,11 @@ jobs: run: echo "{\"credsStore\":\"ecr-login\"}" > /kaniko/.docker/config.json - name: Kaniko build neon - run: /kaniko/executor --snapshotMode=redo --cache=true --cache-repo 369495373322.dkr.ecr.eu-central-1.amazonaws.com/cache --snapshotMode=redo --context . --build-arg GIT_VERSION=${{ github.sha }} --destination 369495373322.dkr.ecr.eu-central-1.amazonaws.com/neon:$GITHUB_RUN_ID + run: /kaniko/executor --snapshotMode=redo --cache=true --cache-repo 369495373322.dkr.ecr.eu-central-1.amazonaws.com/cache --snapshotMode=redo --context . --build-arg GIT_VERSION=${{ github.sha }} --destination 369495373322.dkr.ecr.eu-central-1.amazonaws.com/neon:${{needs.tag.outputs.build-tag}} compute-tools-image: runs-on: dev + needs: [ tag ] container: gcr.io/kaniko-project/executor:v1.9.0-debug steps: @@ -508,11 +510,12 @@ jobs: run: echo "{\"credsStore\":\"ecr-login\"}" > /kaniko/.docker/config.json - name: Kaniko build compute tools - run: /kaniko/executor --snapshotMode=redo --cache=true --cache-repo 369495373322.dkr.ecr.eu-central-1.amazonaws.com/cache --snapshotMode=redo --context . --build-arg GIT_VERSION=${{ github.sha }} --dockerfile Dockerfile.compute-tools --destination 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-tools:$GITHUB_RUN_ID + run: /kaniko/executor --snapshotMode=redo --cache=true --cache-repo 369495373322.dkr.ecr.eu-central-1.amazonaws.com/cache --snapshotMode=redo --context . --build-arg GIT_VERSION=${{ github.sha }} --dockerfile Dockerfile.compute-tools --destination 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-tools:${{needs.tag.outputs.build-tag}} compute-node-image: runs-on: dev container: gcr.io/kaniko-project/executor:v1.9.0-debug + needs: [ tag ] steps: - name: Checkout uses: actions/checkout@v1 # v3 won't work with kaniko @@ -527,11 +530,12 @@ jobs: # cloud repo depends on this image name, thus duplicating it # remove compute-node when cloud repo is updated - name: Kaniko build compute node with extensions v14 (compatibility) - run: /kaniko/executor --skip-unused-stages --snapshotMode=redo --cache=true --cache-repo 369495373322.dkr.ecr.eu-central-1.amazonaws.com/cache --snapshotMode=redo --context . --build-arg GIT_VERSION=${{ github.sha }} --dockerfile Dockerfile.compute-node-v14 --destination 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node:$GITHUB_RUN_ID + run: /kaniko/executor --skip-unused-stages --snapshotMode=redo --cache=true --cache-repo 369495373322.dkr.ecr.eu-central-1.amazonaws.com/cache --snapshotMode=redo --context . --build-arg GIT_VERSION=${{ github.sha }} --dockerfile Dockerfile.compute-node-v14 --destination 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node:${{needs.tag.outputs.build-tag}} compute-node-image-v14: runs-on: dev container: gcr.io/kaniko-project/executor:v1.9.0-debug + needs: [ tag ] steps: - name: Checkout uses: actions/checkout@v1 # v3 won't work with kaniko @@ -543,12 +547,13 @@ jobs: run: echo "{\"credsStore\":\"ecr-login\"}" > /kaniko/.docker/config.json - name: Kaniko build compute node with extensions v14 - run: /kaniko/executor --skip-unused-stages --snapshotMode=redo --cache=true --cache-repo 369495373322.dkr.ecr.eu-central-1.amazonaws.com/cache --context . --build-arg GIT_VERSION=${{ github.sha }} --dockerfile Dockerfile.compute-node-v14 --destination 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v14:$GITHUB_RUN_ID + run: /kaniko/executor --skip-unused-stages --snapshotMode=redo --cache=true --cache-repo 369495373322.dkr.ecr.eu-central-1.amazonaws.com/cache --context . --build-arg GIT_VERSION=${{ github.sha }} --dockerfile Dockerfile.compute-node-v14 --destination 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v14:${{needs.tag.outputs.build-tag}} compute-node-image-v15: runs-on: dev container: gcr.io/kaniko-project/executor:v1.9.0-debug + needs: [ tag ] steps: - name: Checkout uses: actions/checkout@v1 # v3 won't work with kaniko @@ -560,11 +565,11 @@ jobs: run: echo "{\"credsStore\":\"ecr-login\"}" > /kaniko/.docker/config.json - name: Kaniko build compute node with extensions v15 - run: /kaniko/executor --skip-unused-stages --snapshotMode=redo --cache=true --cache-repo 369495373322.dkr.ecr.eu-central-1.amazonaws.com/cache --context . --build-arg GIT_VERSION=${{ github.sha }} --dockerfile Dockerfile.compute-node-v15 --destination 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v15:$GITHUB_RUN_ID + run: /kaniko/executor --skip-unused-stages --snapshotMode=redo --cache=true --cache-repo 369495373322.dkr.ecr.eu-central-1.amazonaws.com/cache --context . --build-arg GIT_VERSION=${{ github.sha }} --dockerfile Dockerfile.compute-node-v15 --destination 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v15:${{needs.tag.outputs.build-tag}} promote-images: runs-on: dev - needs: [ neon-image, compute-node-image, compute-node-image-v14, compute-node-image-v15, compute-tools-image ] + needs: [ tag, neon-image, compute-node-image, compute-node-image-v14, compute-node-image-v15, compute-tools-image ] if: github.event_name != 'workflow_dispatch' container: amazon/aws-cli strategy: @@ -577,8 +582,9 @@ jobs: steps: - name: Promote image to latest - run: - MANIFEST=$(aws ecr batch-get-image --repository-name ${{ matrix.name }} --image-ids imageTag=$GITHUB_RUN_ID --query 'images[].imageManifest' --output text) && aws ecr put-image --repository-name ${{ matrix.name }} --image-tag latest --image-manifest "$MANIFEST" + run: | + export MANIFEST=$(aws ecr batch-get-image --repository-name ${{ matrix.name }} --image-ids imageTag=${{needs.tag.outputs.build-tag}} --query 'images[].imageManifest' --output text) + aws ecr put-image --repository-name ${{ matrix.name }} --image-tag latest --image-manifest "$MANIFEST" push-docker-hub: runs-on: dev @@ -597,19 +603,19 @@ jobs: echo "{\"credsStore\":\"ecr-login\"}" > /github/home/.docker/config.json - name: Pull neon image from ECR - run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/neon:latest neon + run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/neon:${{needs.tag.outputs.build-tag}} neon - name: Pull compute tools image from ECR - run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-tools:latest compute-tools + run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-tools:${{needs.tag.outputs.build-tag}} compute-tools - name: Pull compute node image from ECR - run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node:latest compute-node + run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node:${{needs.tag.outputs.build-tag}} compute-node - name: Pull compute node v14 image from ECR - run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v14:latest compute-node-v14 + run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v14:${{needs.tag.outputs.build-tag}} compute-node-v14 - name: Pull compute node v15 image from ECR - run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v15:latest compute-node-v15 + run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v15:${{needs.tag.outputs.build-tag}} compute-node-v15 - name: Pull rust image from ECR run: crane pull 369495373322.dkr.ecr.eu-central-1.amazonaws.com/rust:pinned rust @@ -619,11 +625,11 @@ jobs: (github.ref_name == 'main' || github.ref_name == 'release') && github.event_name != 'workflow_dispatch' run: | - crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/neon:$GITHUB_RUN_ID 093970136003.dkr.ecr.us-east-2.amazonaws.com/neon:latest - crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-tools:$GITHUB_RUN_ID 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-tools:latest - crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node:$GITHUB_RUN_ID 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-node:latest - crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v14:$GITHUB_RUN_ID 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-node-v14:latest - crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v15:$GITHUB_RUN_ID 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-node-v15:latest + crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/neon:${{needs.tag.outputs.build-tag}} 093970136003.dkr.ecr.us-east-2.amazonaws.com/neon:latest + crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-tools:${{needs.tag.outputs.build-tag}} 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-tools:latest + crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node:${{needs.tag.outputs.build-tag}} 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-node:latest + crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v14:${{needs.tag.outputs.build-tag}} 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-node-v14:latest + crane copy 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-v15:${{needs.tag.outputs.build-tag}} 093970136003.dkr.ecr.us-east-2.amazonaws.com/compute-node-v15:latest - name: Configure Docker Hub login run: | From cca1ace651a3bcc177503c1bbcbf3b290bbad918 Mon Sep 17 00:00:00 2001 From: Dmitry Rodionov Date: Thu, 20 Oct 2022 23:20:28 +0300 Subject: [PATCH 59/64] make launch_wal_receiver infallible --- pageserver/src/tenant.rs | 4 +--- pageserver/src/tenant/timeline.rs | 8 +++----- pageserver/src/walreceiver/connection_manager.rs | 3 +-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index 93c473f0fe..6aae740a78 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -191,9 +191,7 @@ impl UninitializedTimeline<'_> { ) })?; v.insert(Arc::clone(&new_timeline)); - new_timeline.launch_wal_receiver().with_context(|| { - format!("Failed to launch walreceiver for timeline {tenant_id}/{timeline_id}") - })?; + new_timeline.launch_wal_receiver(); } } diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index d6ce644bb5..8f325d31ec 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -602,11 +602,11 @@ impl Timeline { result } - pub fn launch_wal_receiver(self: &Arc) -> anyhow::Result<()> { + pub fn launch_wal_receiver(self: &Arc) { if !is_etcd_client_initialized() { if cfg!(test) { info!("not launching WAL receiver because etcd client hasn't been initialized"); - return Ok(()); + return; } else { panic!("etcd client not initialized"); } @@ -634,9 +634,7 @@ impl Timeline { walreceiver_connect_timeout, lagging_wal_timeout, max_lsn_wal_lag, - )?; - - Ok(()) + ); } /// diff --git a/pageserver/src/walreceiver/connection_manager.rs b/pageserver/src/walreceiver/connection_manager.rs index 01389e52f4..3a5d1c7ad6 100644 --- a/pageserver/src/walreceiver/connection_manager.rs +++ b/pageserver/src/walreceiver/connection_manager.rs @@ -47,7 +47,7 @@ pub fn spawn_connection_manager_task( wal_connect_timeout: Duration, lagging_wal_timeout: Duration, max_lsn_wal_lag: NonZeroU64, -) -> anyhow::Result<()> { +) { let mut etcd_client = get_etcd_client().clone(); let tenant_id = timeline.tenant_id; @@ -95,7 +95,6 @@ pub fn spawn_connection_manager_task( info_span!("wal_connection_manager", tenant = %tenant_id, timeline = %timeline_id), ), ); - Ok(()) } /// Attempts to subscribe for timeline updates, pushed by safekeepers into the broker. From fc4ea3553ebed97a11503e970f77196f7d39a4ca Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 21 Oct 2022 02:39:55 +0300 Subject: [PATCH 60/64] test_gc_cutoff.py fixes (#2655) * Fix bogus early exit from GC. Commit 91411c415a added this failpoint, but the early exit was not intentional. * Cleanup test_gc_cutoff.py test. - Remove the 'scale' parameter, this isn't a benchmark - Tweak pgbench and pageserver options to create garbage faster that the the GC can collect away. The test used to take just under 5 minutes, which was uncomfortably close to the default 5 minute test timeout, and annoyingly even without the hard limit. These changes bring it down to about 1-2 minutes. - Improve comments, fix typos - Rename the failpoint. The old name, 'gc-before-save-metadata' implied that the failpoint was before the metadata update, but it was in fact much later in the function. - Move the call to persist the metadata outside the lock, to avoid holding it for too long. To verify that this test still covers the original bug, https://github.com/neondatabase/neon/issues/2539, I commenting out updating the metadata file like this: ``` diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index 1e857a9a..f8a9f34a 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -1962,7 +1962,7 @@ impl Timeline { } // Persist the new GC cutoff value in the metadata file, before // we actually remove anything. - self.update_metadata_file(self.disk_consistent_lsn.load(), HashMap::new())?; + //self.update_metadata_file(self.disk_consistent_lsn.load(), HashMap::new())?; info!("GC starting"); ``` It doesn't fail every time with that, but it did fail after about 5 runs. --- pageserver/src/tenant/timeline.rs | 15 ++++++--------- test_runner/regress/test_gc_cutoff.py | 27 ++++++++++++++------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index 8f325d31ec..a0ac0adea2 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -1984,10 +1984,10 @@ impl Timeline { new_gc_cutoff ); write_guard.store_and_unlock(new_gc_cutoff).wait(); - - // Persist metadata file - self.update_metadata_file(self.disk_consistent_lsn.load(), HashMap::new())?; } + // Persist the new GC cutoff value in the metadata file, before + // we actually remove anything. + self.update_metadata_file(self.disk_consistent_lsn.load(), HashMap::new())?; info!("GC starting"); @@ -2114,15 +2114,12 @@ impl Timeline { } info!( - "GC completed removing {} layers, cuttof {}", + "GC completed removing {} layers, cutoff {}", result.layers_removed, new_gc_cutoff ); + if result.layers_removed != 0 { - fail_point!("gc-before-save-metadata", |_| { - info!("Abnormaly terinate pageserver at gc-before-save-metadata fail point"); - std::process::abort(); - }); - return Ok(result); + fail_point!("after-timeline-gc-removed-layers"); } if self.upload_layers.load(atomic::Ordering::Relaxed) { diff --git a/test_runner/regress/test_gc_cutoff.py b/test_runner/regress/test_gc_cutoff.py index 946c689a30..22b77d2cf1 100644 --- a/test_runner/regress/test_gc_cutoff.py +++ b/test_runner/regress/test_gc_cutoff.py @@ -1,14 +1,13 @@ -import pytest from fixtures.neon_fixtures import NeonEnvBuilder, PgBin -from performance.test_perf_pgbench import get_scales_matrix -# Test gc_cuttoff +# Test gc_cutoff # -# This test set fail point after at the end of GC and checks -# that pageserver normally restarts after it -@pytest.mark.parametrize("scale", get_scales_matrix(10)) -def test_gc_cutoff(neon_env_builder: NeonEnvBuilder, pg_bin: PgBin, scale: int): +# This test sets fail point at the end of GC, and checks that pageserver +# normally restarts after it. Also, there should be GC ERRORs in the log, +# but the fixture checks the log for any unexpected ERRORs after every +# test anyway, so it doesn't need any special attention here. +def test_gc_cutoff(neon_env_builder: NeonEnvBuilder, pg_bin: PgBin): env = neon_env_builder.init_start() pageserver_http = env.pageserver.http_client() @@ -18,21 +17,23 @@ def test_gc_cutoff(neon_env_builder: NeonEnvBuilder, pg_bin: PgBin, scale: int): "gc_period": "10 s", "gc_horizon": f"{1024 ** 2}", "checkpoint_distance": f"{1024 ** 2}", - "compaction_target_size": f"{1024 ** 2}", + "compaction_period": "5 s", # set PITR interval to be small, so we can do GC "pitr_interval": "1 s", + "compaction_threshold": "3", + "image_creation_threshold": "2", } ) pg = env.postgres.create_start("main", tenant_id=tenant_id) - connstr = pg.connstr() - pg_bin.run_capture(["pgbench", "-i", f"-s{scale}", connstr]) + connstr = pg.connstr(options="-csynchronous_commit=off") + pg_bin.run_capture(["pgbench", "-i", "-s10", connstr]) - pageserver_http.configure_failpoints(("gc-before-save-metadata", "return")) + pageserver_http.configure_failpoints(("after-timeline-gc-removed-layers", "exit")) for i in range(5): try: - pg_bin.run_capture(["pgbench", "-T100", connstr]) + pg_bin.run_capture(["pgbench", "-N", "-c5", "-T100", "-Mprepared", connstr]) except Exception: env.pageserver.stop() env.pageserver.start() - pageserver_http.configure_failpoints(("gc-before-save-metadata", "return")) + pageserver_http.configure_failpoints(("after-timeline-gc-removed-layers", "exit")) From a347d2b6ac22f3ab30297b1237f3d16ef682c118 Mon Sep 17 00:00:00 2001 From: Anastasia Lubennikova Date: Thu, 20 Oct 2022 20:27:26 +0300 Subject: [PATCH 61/64] #2616 handle 'Unsupported pg_version' error properly --- control_plane/src/compute.rs | 12 +++++------ control_plane/src/local_env.rs | 30 +++++++++++++------------- libs/postgres_ffi/wal_craft/src/lib.rs | 22 +++++++++---------- pageserver/src/config.rs | 24 ++++++++++----------- pageserver/src/tenant.rs | 4 ++-- pageserver/src/walredo.rs | 25 +++++++++++++++------ 6 files changed, 65 insertions(+), 52 deletions(-) diff --git a/control_plane/src/compute.rs b/control_plane/src/compute.rs index 89994c5647..9f32ad31c1 100644 --- a/control_plane/src/compute.rs +++ b/control_plane/src/compute.rs @@ -183,18 +183,18 @@ impl PostgresNode { } fn sync_safekeepers(&self, auth_token: &Option, pg_version: u32) -> Result { - let pg_path = self.env.pg_bin_dir(pg_version).join("postgres"); + let pg_path = self.env.pg_bin_dir(pg_version)?.join("postgres"); let mut cmd = Command::new(&pg_path); cmd.arg("--sync-safekeepers") .env_clear() .env( "LD_LIBRARY_PATH", - self.env.pg_lib_dir(pg_version).to_str().unwrap(), + self.env.pg_lib_dir(pg_version)?.to_str().unwrap(), ) .env( "DYLD_LIBRARY_PATH", - self.env.pg_lib_dir(pg_version).to_str().unwrap(), + self.env.pg_lib_dir(pg_version)?.to_str().unwrap(), ) .env("PGDATA", self.pgdata().to_str().unwrap()) .stdout(Stdio::piped()) @@ -422,7 +422,7 @@ impl PostgresNode { } fn pg_ctl(&self, args: &[&str], auth_token: &Option) -> Result<()> { - let pg_ctl_path = self.env.pg_bin_dir(self.pg_version).join("pg_ctl"); + let pg_ctl_path = self.env.pg_bin_dir(self.pg_version)?.join("pg_ctl"); let mut cmd = Command::new(pg_ctl_path); cmd.args( [ @@ -440,11 +440,11 @@ impl PostgresNode { .env_clear() .env( "LD_LIBRARY_PATH", - self.env.pg_lib_dir(self.pg_version).to_str().unwrap(), + self.env.pg_lib_dir(self.pg_version)?.to_str().unwrap(), ) .env( "DYLD_LIBRARY_PATH", - self.env.pg_lib_dir(self.pg_version).to_str().unwrap(), + self.env.pg_lib_dir(self.pg_version)?.to_str().unwrap(), ); if let Some(token) = auth_token { cmd.env("ZENITH_AUTH_TOKEN", token); diff --git a/control_plane/src/local_env.rs b/control_plane/src/local_env.rs index f4fbc99420..34ddb41f32 100644 --- a/control_plane/src/local_env.rs +++ b/control_plane/src/local_env.rs @@ -3,7 +3,7 @@ //! Now it also provides init method which acts like a stub for proper installation //! script which will use local paths. -use anyhow::{bail, ensure, Context}; +use anyhow::{bail, ensure, Context, Result}; use reqwest::Url; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DisplayFromStr}; @@ -201,28 +201,28 @@ impl LocalEnv { self.pg_distrib_dir.clone() } - pub fn pg_distrib_dir(&self, pg_version: u32) -> PathBuf { + pub fn pg_distrib_dir(&self, pg_version: u32) -> Result { let path = self.pg_distrib_dir.clone(); match pg_version { - 14 => path.join(format!("v{pg_version}")), - 15 => path.join(format!("v{pg_version}")), - _ => panic!("Unsupported postgres version: {}", pg_version), + 14 => Ok(path.join(format!("v{pg_version}"))), + 15 => Ok(path.join(format!("v{pg_version}"))), + _ => bail!("Unsupported postgres version: {}", pg_version), } } - pub fn pg_bin_dir(&self, pg_version: u32) -> PathBuf { + pub fn pg_bin_dir(&self, pg_version: u32) -> Result { match pg_version { - 14 => self.pg_distrib_dir(pg_version).join("bin"), - 15 => self.pg_distrib_dir(pg_version).join("bin"), - _ => panic!("Unsupported postgres version: {}", pg_version), + 14 => Ok(self.pg_distrib_dir(pg_version)?.join("bin")), + 15 => Ok(self.pg_distrib_dir(pg_version)?.join("bin")), + _ => bail!("Unsupported postgres version: {}", pg_version), } } - pub fn pg_lib_dir(&self, pg_version: u32) -> PathBuf { + pub fn pg_lib_dir(&self, pg_version: u32) -> Result { match pg_version { - 14 => self.pg_distrib_dir(pg_version).join("lib"), - 15 => self.pg_distrib_dir(pg_version).join("lib"), - _ => panic!("Unsupported postgres version: {}", pg_version), + 14 => Ok(self.pg_distrib_dir(pg_version)?.join("lib")), + 15 => Ok(self.pg_distrib_dir(pg_version)?.join("lib")), + _ => bail!("Unsupported postgres version: {}", pg_version), } } @@ -422,10 +422,10 @@ impl LocalEnv { "directory '{}' already exists. Perhaps already initialized?", base_path.display() ); - if !self.pg_bin_dir(pg_version).join("postgres").exists() { + if !self.pg_bin_dir(pg_version)?.join("postgres").exists() { bail!( "Can't find postgres binary at {}", - self.pg_bin_dir(pg_version).display() + self.pg_bin_dir(pg_version)?.display() ); } for binary in ["pageserver", "safekeeper"] { diff --git a/libs/postgres_ffi/wal_craft/src/lib.rs b/libs/postgres_ffi/wal_craft/src/lib.rs index 7ffe19e209..f0203ce322 100644 --- a/libs/postgres_ffi/wal_craft/src/lib.rs +++ b/libs/postgres_ffi/wal_craft/src/lib.rs @@ -37,22 +37,22 @@ pub static REQUIRED_POSTGRES_CONFIG: Lazy> = Lazy::new(|| { }); impl Conf { - pub fn pg_distrib_dir(&self) -> PathBuf { + pub fn pg_distrib_dir(&self) -> Result { let path = self.pg_distrib_dir.clone(); match self.pg_version { - 14 => path.join(format!("v{}", self.pg_version)), - 15 => path.join(format!("v{}", self.pg_version)), - _ => panic!("Unsupported postgres version: {}", self.pg_version), + 14 => Ok(path.join(format!("v{}", self.pg_version))), + 15 => Ok(path.join(format!("v{}", self.pg_version))), + _ => bail!("Unsupported postgres version: {}", self.pg_version), } } - fn pg_bin_dir(&self) -> PathBuf { - self.pg_distrib_dir().join("bin") + fn pg_bin_dir(&self) -> Result { + Ok(self.pg_distrib_dir()?.join("bin")) } - fn pg_lib_dir(&self) -> PathBuf { - self.pg_distrib_dir().join("lib") + fn pg_lib_dir(&self) -> Result { + Ok(self.pg_distrib_dir()?.join("lib")) } pub fn wal_dir(&self) -> PathBuf { @@ -60,12 +60,12 @@ impl Conf { } fn new_pg_command(&self, command: impl AsRef) -> Result { - let path = self.pg_bin_dir().join(command); + let path = self.pg_bin_dir()?.join(command); ensure!(path.exists(), "Command {:?} does not exist", path); let mut cmd = Command::new(path); cmd.env_clear() - .env("LD_LIBRARY_PATH", self.pg_lib_dir()) - .env("DYLD_LIBRARY_PATH", self.pg_lib_dir()); + .env("LD_LIBRARY_PATH", self.pg_lib_dir()?) + .env("DYLD_LIBRARY_PATH", self.pg_lib_dir()?); Ok(cmd) } diff --git a/pageserver/src/config.rs b/pageserver/src/config.rs index b797866e43..2872fc6255 100644 --- a/pageserver/src/config.rs +++ b/pageserver/src/config.rs @@ -387,28 +387,28 @@ impl PageServerConf { // // Postgres distribution paths // - pub fn pg_distrib_dir(&self, pg_version: u32) -> PathBuf { + pub fn pg_distrib_dir(&self, pg_version: u32) -> Result { let path = self.pg_distrib_dir.clone(); match pg_version { - 14 => path.join(format!("v{pg_version}")), - 15 => path.join(format!("v{pg_version}")), - _ => panic!("Unsupported postgres version: {}", pg_version), + 14 => Ok(path.join(format!("v{pg_version}"))), + 15 => Ok(path.join(format!("v{pg_version}"))), + _ => bail!("Unsupported postgres version: {}", pg_version), } } - pub fn pg_bin_dir(&self, pg_version: u32) -> PathBuf { + pub fn pg_bin_dir(&self, pg_version: u32) -> Result { match pg_version { - 14 => self.pg_distrib_dir(pg_version).join("bin"), - 15 => self.pg_distrib_dir(pg_version).join("bin"), - _ => panic!("Unsupported postgres version: {}", pg_version), + 14 => Ok(self.pg_distrib_dir(pg_version)?.join("bin")), + 15 => Ok(self.pg_distrib_dir(pg_version)?.join("bin")), + _ => bail!("Unsupported postgres version: {}", pg_version), } } - pub fn pg_lib_dir(&self, pg_version: u32) -> PathBuf { + pub fn pg_lib_dir(&self, pg_version: u32) -> Result { match pg_version { - 14 => self.pg_distrib_dir(pg_version).join("lib"), - 15 => self.pg_distrib_dir(pg_version).join("lib"), - _ => panic!("Unsupported postgres version: {}", pg_version), + 14 => Ok(self.pg_distrib_dir(pg_version)?.join("lib")), + 15 => Ok(self.pg_distrib_dir(pg_version)?.join("lib")), + _ => bail!("Unsupported postgres version: {}", pg_version), } } diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index 6aae740a78..0e9a6ce4ea 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -1412,8 +1412,8 @@ fn run_initdb( initdb_target_dir: &Path, pg_version: u32, ) -> Result<()> { - let initdb_bin_path = conf.pg_bin_dir(pg_version).join("initdb"); - let initdb_lib_dir = conf.pg_lib_dir(pg_version); + let initdb_bin_path = conf.pg_bin_dir(pg_version)?.join("initdb"); + let initdb_lib_dir = conf.pg_lib_dir(pg_version)?; info!( "running {} in {}, libdir: {}", initdb_bin_path.display(), diff --git a/pageserver/src/walredo.rs b/pageserver/src/walredo.rs index b8874a0223..e683c301d8 100644 --- a/pageserver/src/walredo.rs +++ b/pageserver/src/walredo.rs @@ -610,13 +610,26 @@ impl PostgresRedoProcess { ); fs::remove_dir_all(&datadir)?; } + let pg_bin_dir_path = conf.pg_bin_dir(pg_version).map_err(|e| { + Error::new( + ErrorKind::Other, + format!("incorrect pg_bin_dir path: {}", e), + ) + })?; + let pg_lib_dir_path = conf.pg_lib_dir(pg_version).map_err(|e| { + Error::new( + ErrorKind::Other, + format!("incorrect pg_lib_dir path: {}", e), + ) + })?; + info!("running initdb in {}", datadir.display()); - let initdb = Command::new(conf.pg_bin_dir(pg_version).join("initdb")) + let initdb = Command::new(pg_bin_dir_path.join("initdb")) .args(&["-D", &datadir.to_string_lossy()]) .arg("-N") .env_clear() - .env("LD_LIBRARY_PATH", conf.pg_lib_dir(pg_version)) - .env("DYLD_LIBRARY_PATH", conf.pg_lib_dir(pg_version)) + .env("LD_LIBRARY_PATH", &pg_lib_dir_path) + .env("DYLD_LIBRARY_PATH", &pg_lib_dir_path) // macOS .close_fds() .output() .map_err(|e| Error::new(e.kind(), format!("failed to execute initdb: {e}")))?; @@ -642,14 +655,14 @@ impl PostgresRedoProcess { } // Start postgres itself - let mut child = Command::new(conf.pg_bin_dir(pg_version).join("postgres")) + let mut child = Command::new(pg_bin_dir_path.join("postgres")) .arg("--wal-redo") .stdin(Stdio::piped()) .stderr(Stdio::piped()) .stdout(Stdio::piped()) .env_clear() - .env("LD_LIBRARY_PATH", conf.pg_lib_dir(pg_version)) - .env("DYLD_LIBRARY_PATH", conf.pg_lib_dir(pg_version)) + .env("LD_LIBRARY_PATH", &pg_lib_dir_path) + .env("DYLD_LIBRARY_PATH", &pg_lib_dir_path) .env("PGDATA", &datadir) // The redo process is not trusted, so it runs in seccomp mode // (see seccomp in zenith_wal_redo.c). We have to make sure it doesn't From 52e75fead996b66631e4d7354accb89d4860527b Mon Sep 17 00:00:00 2001 From: Anastasia Lubennikova Date: Fri, 21 Oct 2022 11:50:29 +0300 Subject: [PATCH 62/64] Use anyhow::Result explicitly --- control_plane/src/local_env.rs | 8 ++++---- libs/postgres_ffi/wal_craft/src/lib.rs | 6 +++--- pageserver/src/config.rs | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/control_plane/src/local_env.rs b/control_plane/src/local_env.rs index 34ddb41f32..10b2db6396 100644 --- a/control_plane/src/local_env.rs +++ b/control_plane/src/local_env.rs @@ -3,7 +3,7 @@ //! Now it also provides init method which acts like a stub for proper installation //! script which will use local paths. -use anyhow::{bail, ensure, Context, Result}; +use anyhow::{bail, ensure, Context}; use reqwest::Url; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DisplayFromStr}; @@ -201,7 +201,7 @@ impl LocalEnv { self.pg_distrib_dir.clone() } - pub fn pg_distrib_dir(&self, pg_version: u32) -> Result { + pub fn pg_distrib_dir(&self, pg_version: u32) -> anyhow::Result { let path = self.pg_distrib_dir.clone(); match pg_version { @@ -211,14 +211,14 @@ impl LocalEnv { } } - pub fn pg_bin_dir(&self, pg_version: u32) -> Result { + pub fn pg_bin_dir(&self, pg_version: u32) -> anyhow::Result { match pg_version { 14 => Ok(self.pg_distrib_dir(pg_version)?.join("bin")), 15 => Ok(self.pg_distrib_dir(pg_version)?.join("bin")), _ => bail!("Unsupported postgres version: {}", pg_version), } } - pub fn pg_lib_dir(&self, pg_version: u32) -> Result { + pub fn pg_lib_dir(&self, pg_version: u32) -> anyhow::Result { match pg_version { 14 => Ok(self.pg_distrib_dir(pg_version)?.join("lib")), 15 => Ok(self.pg_distrib_dir(pg_version)?.join("lib")), diff --git a/libs/postgres_ffi/wal_craft/src/lib.rs b/libs/postgres_ffi/wal_craft/src/lib.rs index f0203ce322..c4404b37ba 100644 --- a/libs/postgres_ffi/wal_craft/src/lib.rs +++ b/libs/postgres_ffi/wal_craft/src/lib.rs @@ -37,7 +37,7 @@ pub static REQUIRED_POSTGRES_CONFIG: Lazy> = Lazy::new(|| { }); impl Conf { - pub fn pg_distrib_dir(&self) -> Result { + pub fn pg_distrib_dir(&self) -> anyhow::Result { let path = self.pg_distrib_dir.clone(); match self.pg_version { @@ -47,11 +47,11 @@ impl Conf { } } - fn pg_bin_dir(&self) -> Result { + fn pg_bin_dir(&self) -> anyhow::Result { Ok(self.pg_distrib_dir()?.join("bin")) } - fn pg_lib_dir(&self) -> Result { + fn pg_lib_dir(&self) -> anyhow::Result { Ok(self.pg_distrib_dir()?.join("lib")) } diff --git a/pageserver/src/config.rs b/pageserver/src/config.rs index 2872fc6255..4f80fc96b5 100644 --- a/pageserver/src/config.rs +++ b/pageserver/src/config.rs @@ -387,7 +387,7 @@ impl PageServerConf { // // Postgres distribution paths // - pub fn pg_distrib_dir(&self, pg_version: u32) -> Result { + pub fn pg_distrib_dir(&self, pg_version: u32) -> anyhow::Result { let path = self.pg_distrib_dir.clone(); match pg_version { @@ -397,14 +397,14 @@ impl PageServerConf { } } - pub fn pg_bin_dir(&self, pg_version: u32) -> Result { + pub fn pg_bin_dir(&self, pg_version: u32) -> anyhow::Result { match pg_version { 14 => Ok(self.pg_distrib_dir(pg_version)?.join("bin")), 15 => Ok(self.pg_distrib_dir(pg_version)?.join("bin")), _ => bail!("Unsupported postgres version: {}", pg_version), } } - pub fn pg_lib_dir(&self, pg_version: u32) -> Result { + pub fn pg_lib_dir(&self, pg_version: u32) -> anyhow::Result { match pg_version { 14 => Ok(self.pg_distrib_dir(pg_version)?.join("lib")), 15 => Ok(self.pg_distrib_dir(pg_version)?.join("lib")), From 39e4bdb99e6bcdb39462237e053314c717e82b3b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 21 Oct 2022 13:58:43 +0300 Subject: [PATCH 63/64] Actualize tenant and timeline API modifiers (#2661) * Actualize tenant and timeline API modifiers * Use anyhow::Result explicitly --- pageserver/src/tenant.rs | 90 +++---- pageserver/src/tenant/timeline.rs | 374 +++++++++++++++--------------- 2 files changed, 215 insertions(+), 249 deletions(-) diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index 0e9a6ce4ea..69c89a80b4 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -11,7 +11,7 @@ //! parent timeline, and the last LSN that has been written to disk. //! -use anyhow::{bail, ensure, Context, Result}; +use anyhow::{bail, ensure, Context}; use tokio::sync::watch; use tracing::*; use utils::crashsafe::path_with_suffix_extension; @@ -25,7 +25,6 @@ use std::fs::File; use std::fs::OpenOptions; use std::io; use std::io::Write; -use std::num::NonZeroU64; use std::ops::Bound::Included; use std::path::Path; use std::path::PathBuf; @@ -292,7 +291,7 @@ impl TimelineUninitMark { Ok(()) } - fn delete_mark_file_if_present(&mut self) -> Result<(), anyhow::Error> { + fn delete_mark_file_if_present(&mut self) -> anyhow::Result<()> { let uninit_mark_file = &self.uninit_mark_path; let uninit_mark_parent = uninit_mark_file .parent() @@ -470,7 +469,7 @@ impl Tenant { horizon: u64, pitr: Duration, checkpoint_before_gc: bool, - ) -> Result { + ) -> anyhow::Result { let timeline_str = target_timeline_id .map(|x| x.to_string()) .unwrap_or_else(|| "-".to_string()); @@ -486,7 +485,7 @@ impl Tenant { /// This function is periodically called by compactor task. /// Also it can be explicitly requested per timeline through page server /// api's 'compact' command. - pub fn compaction_iteration(&self) -> Result<()> { + pub fn compaction_iteration(&self) -> anyhow::Result<()> { // Scan through the hashmap and collect a list of all the timelines, // while holding the lock. Then drop the lock and actually perform the // compactions. We don't want to block everything else while the @@ -510,7 +509,7 @@ impl Tenant { /// /// Used at graceful shutdown. /// - pub fn checkpoint(&self) -> Result<()> { + pub fn checkpoint(&self) -> anyhow::Result<()> { // Scan through the hashmap and collect a list of all the timelines, // while holding the lock. Then drop the lock and actually perform the // checkpoints. We don't want to block everything else while the @@ -681,7 +680,7 @@ impl Tenant { /// before the children. fn tree_sort_timelines( timelines: HashMap, -) -> Result> { +) -> anyhow::Result> { let mut result = Vec::with_capacity(timelines.len()); let mut now = Vec::with_capacity(timelines.len()); @@ -784,27 +783,6 @@ impl Tenant { .unwrap_or(self.conf.default_tenant_conf.pitr_interval) } - pub fn get_wal_receiver_connect_timeout(&self) -> Duration { - let tenant_conf = self.tenant_conf.read().unwrap(); - tenant_conf - .walreceiver_connect_timeout - .unwrap_or(self.conf.default_tenant_conf.walreceiver_connect_timeout) - } - - pub fn get_lagging_wal_timeout(&self) -> Duration { - let tenant_conf = self.tenant_conf.read().unwrap(); - tenant_conf - .lagging_wal_timeout - .unwrap_or(self.conf.default_tenant_conf.lagging_wal_timeout) - } - - pub fn get_max_lsn_wal_lag(&self) -> NonZeroU64 { - let tenant_conf = self.tenant_conf.read().unwrap(); - tenant_conf - .max_lsn_wal_lag - .unwrap_or(self.conf.default_tenant_conf.max_lsn_wal_lag) - } - pub fn update_tenant_config(&self, new_tenant_conf: TenantConfOpt) { self.tenant_conf.write().unwrap().update(&new_tenant_conf); } @@ -836,7 +814,7 @@ impl Tenant { )) } - pub fn new( + pub(super) fn new( conf: &'static PageServerConf, tenant_conf: TenantConfOpt, walredo_mgr: Arc, @@ -859,7 +837,7 @@ impl Tenant { } /// Locate and load config - pub fn load_tenant_config( + pub(super) fn load_tenant_config( conf: &'static PageServerConf, tenant_id: TenantId, ) -> anyhow::Result { @@ -901,7 +879,7 @@ impl Tenant { Ok(tenant_conf) } - pub fn persist_tenant_config( + pub(super) fn persist_tenant_config( target_config_path: &Path, tenant_conf: TenantConfOpt, first_save: bool, @@ -994,7 +972,7 @@ impl Tenant { horizon: u64, pitr: Duration, checkpoint_before_gc: bool, - ) -> Result { + ) -> anyhow::Result { let mut totals: GcResult = Default::default(); let now = Instant::now(); @@ -1411,7 +1389,7 @@ fn run_initdb( conf: &'static PageServerConf, initdb_target_dir: &Path, pg_version: u32, -) -> Result<()> { +) -> anyhow::Result<()> { let initdb_bin_path = conf.pg_bin_dir(pg_version)?.join("initdb"); let initdb_lib_dir = conf.pg_lib_dir(pg_version)?; info!( @@ -1457,7 +1435,7 @@ impl Drop for Tenant { } } /// Dump contents of a layer file to stdout. -pub fn dump_layerfile_from_path(path: &Path, verbose: bool) -> Result<()> { +pub fn dump_layerfile_from_path(path: &Path, verbose: bool) -> anyhow::Result<()> { use std::os::unix::fs::FileExt; // All layer files start with a two-byte "magic" value, to identify the kind of @@ -1562,13 +1540,13 @@ pub mod harness { } impl<'a> TenantHarness<'a> { - pub fn create(test_name: &'static str) -> Result { + pub fn create(test_name: &'static str) -> anyhow::Result { Self::create_internal(test_name, false) } - pub fn create_exclusive(test_name: &'static str) -> Result { + pub fn create_exclusive(test_name: &'static str) -> anyhow::Result { Self::create_internal(test_name, true) } - fn create_internal(test_name: &'static str, exclusive: bool) -> Result { + fn create_internal(test_name: &'static str, exclusive: bool) -> anyhow::Result { let lock_guard = if exclusive { (None, Some(LOCK.write().unwrap())) } else { @@ -1602,7 +1580,7 @@ pub mod harness { self.try_load().expect("failed to load test tenant") } - pub fn try_load(&self) -> Result { + pub fn try_load(&self) -> anyhow::Result { let walredo_mgr = Arc::new(TestRedoManager); let tenant = Tenant::new( @@ -1682,7 +1660,7 @@ pub mod harness { }, records.len() ); - println!("{}", s); + println!("{s}"); Ok(TEST_IMG(&s)) } @@ -1706,7 +1684,7 @@ mod tests { Lazy::new(|| Key::from_slice(&hex!("112222222233333333444444445500000001"))); #[test] - fn test_basic() -> Result<()> { + fn test_basic() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_basic")?.load(); let tline = tenant .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? @@ -1730,7 +1708,7 @@ mod tests { } #[test] - fn no_duplicate_timelines() -> Result<()> { + fn no_duplicate_timelines() -> anyhow::Result<()> { let tenant = TenantHarness::create("no_duplicate_timelines")?.load(); let _ = tenant .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? @@ -1761,7 +1739,7 @@ mod tests { /// Test branch creation /// #[test] - fn test_branch() -> Result<()> { + fn test_branch() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_branch")?.load(); let tline = tenant .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? @@ -1814,7 +1792,7 @@ mod tests { Ok(()) } - fn make_some_layers(tline: &Timeline, start_lsn: Lsn) -> Result<()> { + fn make_some_layers(tline: &Timeline, start_lsn: Lsn) -> anyhow::Result<()> { let mut lsn = start_lsn; #[allow(non_snake_case)] { @@ -1856,7 +1834,7 @@ mod tests { } #[test] - fn test_prohibit_branch_creation_on_garbage_collected_data() -> Result<()> { + fn test_prohibit_branch_creation_on_garbage_collected_data() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_prohibit_branch_creation_on_garbage_collected_data")? .load(); @@ -1888,7 +1866,7 @@ mod tests { } #[test] - fn test_prohibit_branch_creation_on_pre_initdb_lsn() -> Result<()> { + fn test_prohibit_branch_creation_on_pre_initdb_lsn() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_prohibit_branch_creation_on_pre_initdb_lsn")?.load(); @@ -1915,7 +1893,7 @@ mod tests { // FIXME: This currently fails to error out. Calling GC doesn't currently // remove the old value, we'd need to work a little harder #[test] - fn test_prohibit_get_for_garbage_collected_data() -> Result<()> { + fn test_prohibit_get_for_garbage_collected_data() -> anyhow::Result<()> { let repo = RepoHarness::create("test_prohibit_get_for_garbage_collected_data")? .load(); @@ -1935,7 +1913,7 @@ mod tests { */ #[test] - fn test_retain_data_in_parent_which_is_needed_for_child() -> Result<()> { + fn test_retain_data_in_parent_which_is_needed_for_child() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_retain_data_in_parent_which_is_needed_for_child")?.load(); let tline = tenant @@ -1954,7 +1932,7 @@ mod tests { Ok(()) } #[test] - fn test_parent_keeps_data_forever_after_branching() -> Result<()> { + fn test_parent_keeps_data_forever_after_branching() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_parent_keeps_data_forever_after_branching")?.load(); let tline = tenant @@ -1982,7 +1960,7 @@ mod tests { } #[test] - fn timeline_load() -> Result<()> { + fn timeline_load() -> anyhow::Result<()> { const TEST_NAME: &str = "timeline_load"; let harness = TenantHarness::create(TEST_NAME)?; { @@ -2003,7 +1981,7 @@ mod tests { } #[test] - fn timeline_load_with_ancestor() -> Result<()> { + fn timeline_load_with_ancestor() -> anyhow::Result<()> { const TEST_NAME: &str = "timeline_load_with_ancestor"; let harness = TenantHarness::create(TEST_NAME)?; // create two timelines @@ -2042,7 +2020,7 @@ mod tests { } #[test] - fn corrupt_metadata() -> Result<()> { + fn corrupt_metadata() -> anyhow::Result<()> { const TEST_NAME: &str = "corrupt_metadata"; let harness = TenantHarness::create(TEST_NAME)?; let tenant = harness.load(); @@ -2084,7 +2062,7 @@ mod tests { } #[test] - fn test_images() -> Result<()> { + fn test_images() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_images")?.load(); let tline = tenant .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? @@ -2136,7 +2114,7 @@ mod tests { // repeat 50 times. // #[test] - fn test_bulk_insert() -> Result<()> { + fn test_bulk_insert() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_bulk_insert")?.load(); let tline = tenant .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? @@ -2178,7 +2156,7 @@ mod tests { } #[test] - fn test_random_updates() -> Result<()> { + fn test_random_updates() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_random_updates")?.load(); let tline = tenant .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? @@ -2250,7 +2228,7 @@ mod tests { } #[test] - fn test_traverse_branches() -> Result<()> { + fn test_traverse_branches() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_traverse_branches")?.load(); let mut tline = tenant .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? @@ -2331,7 +2309,7 @@ mod tests { } #[test] - fn test_traverse_ancestors() -> Result<()> { + fn test_traverse_ancestors() -> anyhow::Result<()> { let tenant = TenantHarness::create("test_traverse_ancestors")?.load(); let mut tline = tenant .create_empty_timeline(TIMELINE_ID, Lsn(0), DEFAULT_PG_VERSION)? diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index a0ac0adea2..ccd094b65a 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -1,6 +1,6 @@ //! -use anyhow::{anyhow, bail, ensure, Context, Result}; +use anyhow::{anyhow, bail, ensure, Context}; use bytes::Bytes; use fail::fail_point; use itertools::Itertools; @@ -307,10 +307,6 @@ pub struct GcInfo { /// Public interface functions impl Timeline { - //------------------------------------------------------------------------------ - // Public GET functions - //------------------------------------------------------------------------------ - /// Get the LSN where this branch was created pub fn get_ancestor_lsn(&self) -> Lsn { self.ancestor_lsn @@ -445,7 +441,7 @@ impl Timeline { &self, lsn: Lsn, latest_gc_cutoff_lsn: &RcuReadGuard, - ) -> Result<()> { + ) -> anyhow::Result<()> { ensure!( lsn >= **latest_gc_cutoff_lsn, "LSN {} is earlier than latest GC horizon {} (we might've already garbage collected needed data)", @@ -455,12 +451,6 @@ impl Timeline { Ok(()) } - //------------------------------------------------------------------------------ - // Public PUT functions, to update the repository with new page versions. - // - // These are called by the WAL receiver to digest WAL records. - //------------------------------------------------------------------------------ - /// Flush to disk all data that was written with the put_* functions /// /// NOTE: This has nothing to do with checkpoint in PostgreSQL. We don't @@ -479,6 +469,91 @@ impl Timeline { } } + pub fn compact(&self) -> anyhow::Result<()> { + let last_record_lsn = self.get_last_record_lsn(); + + // Last record Lsn could be zero in case the timelie was just created + if !last_record_lsn.is_valid() { + warn!("Skipping compaction for potentially just initialized timeline, it has invalid last record lsn: {last_record_lsn}"); + return Ok(()); + } + + // + // High level strategy for compaction / image creation: + // + // 1. First, calculate the desired "partitioning" of the + // currently in-use key space. The goal is to partition the + // key space into roughly fixed-size chunks, but also take into + // account any existing image layers, and try to align the + // chunk boundaries with the existing image layers to avoid + // too much churn. Also try to align chunk boundaries with + // relation boundaries. In principle, we don't know about + // relation boundaries here, we just deal with key-value + // pairs, and the code in pgdatadir_mapping.rs knows how to + // map relations into key-value pairs. But in practice we know + // that 'field6' is the block number, and the fields 1-5 + // identify a relation. This is just an optimization, + // though. + // + // 2. Once we know the partitioning, for each partition, + // decide if it's time to create a new image layer. The + // criteria is: there has been too much "churn" since the last + // image layer? The "churn" is fuzzy concept, it's a + // combination of too many delta files, or too much WAL in + // total in the delta file. Or perhaps: if creating an image + // file would allow to delete some older files. + // + // 3. After that, we compact all level0 delta files if there + // are too many of them. While compacting, we also garbage + // collect any page versions that are no longer needed because + // of the new image layers we created in step 2. + // + // TODO: This high level strategy hasn't been implemented yet. + // Below are functions compact_level0() and create_image_layers() + // but they are a bit ad hoc and don't quite work like it's explained + // above. Rewrite it. + let _layer_removal_cs = self.layer_removal_cs.lock().unwrap(); + + let target_file_size = self.get_checkpoint_distance(); + + // Define partitioning schema if needed + + match self.repartition( + self.get_last_record_lsn(), + self.get_compaction_target_size(), + ) { + Ok((partitioning, lsn)) => { + // 2. Create new image layers for partitions that have been modified + // "enough". + let layer_paths_to_upload = self.create_image_layers(&partitioning, lsn, false)?; + if !layer_paths_to_upload.is_empty() + && self.upload_layers.load(atomic::Ordering::Relaxed) + { + storage_sync::schedule_layer_upload( + self.tenant_id, + self.timeline_id, + layer_paths_to_upload, + None, + ); + } + + // 3. Compact + let timer = self.metrics.compact_time_histo.start_timer(); + self.compact_level0(target_file_size)?; + timer.stop_and_record(); + } + Err(err) => { + // no partitioning? This is normal, if the timeline was just created + // as an empty timeline. Also in unit tests, when we use the timeline + // as a simple key-value store, ignoring the datadir layout. Log the + // error but continue. + error!("could not compact, repartitioning keyspace failed: {err:?}"); + } + }; + + Ok(()) + } + /// Mutate the timeline with a [`TimelineWriter`]. pub fn writer(&self) -> TimelineWriter<'_> { TimelineWriter { @@ -486,6 +561,80 @@ impl Timeline { _write_guard: self.write_lock.lock().unwrap(), } } + + /// Retrieve current logical size of the timeline. + /// + /// The size could be lagging behind the actual number, in case + /// the initial size calculation has not been run (gets triggered on the first size access). + pub fn get_current_logical_size(self: &Arc) -> anyhow::Result { + let current_size = self.current_logical_size.current_size()?; + debug!("Current size: {current_size:?}"); + + let size = current_size.size(); + if let (CurrentLogicalSize::Approximate(_), Some(init_lsn)) = + (current_size, self.current_logical_size.initial_part_end) + { + self.try_spawn_size_init_task(init_lsn); + } + + Ok(size) + } + + /// Check if more than 'checkpoint_distance' of WAL has been accumulated in + /// the in-memory layer, and initiate flushing it if so. + /// + /// Also flush after a period of time without new data -- it helps + /// safekeepers to regard pageserver as caught up and suspend activity. + pub fn check_checkpoint_distance(self: &Arc) -> anyhow::Result<()> { + let last_lsn = self.get_last_record_lsn(); + let layers = self.layers.read().unwrap(); + if let Some(open_layer) = &layers.open_layer { + let open_layer_size = open_layer.size()?; + drop(layers); + let last_freeze_at = self.last_freeze_at.load(); + let last_freeze_ts = *(self.last_freeze_ts.read().unwrap()); + let distance = last_lsn.widening_sub(last_freeze_at); + // Checkpointing the open layer can be triggered by layer size or LSN range. + // S3 has a 5 GB limit on the size of one upload (without multi-part upload), and + // we want to stay below that with a big margin. The LSN distance determines how + // much WAL the safekeepers need to store. + if distance >= self.get_checkpoint_distance().into() + || open_layer_size > self.get_checkpoint_distance() + || (distance > 0 && last_freeze_ts.elapsed() >= self.get_checkpoint_timeout()) + { + info!( + "check_checkpoint_distance {}, layer size {}, elapsed since last flush {:?}", + distance, + open_layer_size, + last_freeze_ts.elapsed() + ); + + self.freeze_inmem_layer(true); + self.last_freeze_at.store(last_lsn); + *(self.last_freeze_ts.write().unwrap()) = Instant::now(); + + // Launch a task to flush the frozen layer to disk, unless + // a task was already running. (If the task was running + // at the time that we froze the layer, it must've seen the + // the layer we just froze before it exited; see comments + // in flush_frozen_layers()) + if let Ok(guard) = self.layer_flush_lock.try_lock() { + drop(guard); + let self_clone = Arc::clone(self); + task_mgr::spawn( + task_mgr::BACKGROUND_RUNTIME.handle(), + task_mgr::TaskKind::LayerFlushTask, + Some(self.tenant_id), + Some(self.timeline_id), + "layer flush task", + false, + async move { self_clone.flush_frozen_layers(false) }, + ); + } + } + } + Ok(()) + } } // Private functions @@ -529,7 +678,7 @@ impl Timeline { /// /// Loads the metadata for the timeline into memory, but not the layer map. #[allow(clippy::too_many_arguments)] - pub fn new( + pub(super) fn new( conf: &'static PageServerConf, tenant_conf: Arc>, metadata: TimelineMetadata, @@ -602,7 +751,7 @@ impl Timeline { result } - pub fn launch_wal_receiver(self: &Arc) { + pub(super) fn launch_wal_receiver(self: &Arc) { if !is_etcd_client_initialized() { if cfg!(test) { info!("not launching WAL receiver because etcd client hasn't been initialized"); @@ -641,7 +790,7 @@ impl Timeline { /// Scan the timeline directory to populate the layer map. /// Returns all timeline-related files that were found and loaded. /// - pub fn load_layer_map(&self, disk_consistent_lsn: Lsn) -> anyhow::Result<()> { + pub(super) fn load_layer_map(&self, disk_consistent_lsn: Lsn) -> anyhow::Result<()> { let mut layers = self.layers.write().unwrap(); let mut num_layers = 0; @@ -727,30 +876,12 @@ impl Timeline { Ok(()) } - pub fn layer_removal_guard(&self) -> anyhow::Result> { + pub(super) fn layer_removal_guard(&self) -> anyhow::Result> { self.layer_removal_cs .try_lock() .map_err(|e| anyhow!("cannot lock compaction critical section {e}")) } - /// Retrieve current logical size of the timeline. - /// - /// The size could be lagging behind the actual number, in case - /// the initial size calculation has not been run (gets triggered on the first size access). - pub fn get_current_logical_size(self: &Arc) -> anyhow::Result { - let current_size = self.current_logical_size.current_size()?; - debug!("Current size: {current_size:?}"); - - let size = current_size.size(); - if let (CurrentLogicalSize::Approximate(_), Some(init_lsn)) = - (current_size, self.current_logical_size.initial_part_end) - { - self.try_spawn_size_init_task(init_lsn); - } - - Ok(size) - } - fn try_spawn_size_init_task(self: &Arc, init_lsn: Lsn) { let timeline_id = self.timeline_id; @@ -971,7 +1102,7 @@ impl Timeline { Some((lsn, img)) } - fn get_ancestor_timeline(&self) -> Result> { + fn get_ancestor_timeline(&self) -> anyhow::Result> { let ancestor = self.ancestor_timeline.as_ref().with_context(|| { format!( "Ancestor is missing. Timeline id: {} Ancestor id {:?}", @@ -1030,14 +1161,14 @@ impl Timeline { Ok(layer) } - fn put_value(&self, key: Key, lsn: Lsn, val: &Value) -> Result<()> { + fn put_value(&self, key: Key, lsn: Lsn, val: &Value) -> anyhow::Result<()> { //info!("PUT: key {} at {}", key, lsn); let layer = self.get_layer_for_write(lsn)?; layer.put_value(key, lsn, val)?; Ok(()) } - fn put_tombstone(&self, key_range: Range, lsn: Lsn) -> Result<()> { + fn put_tombstone(&self, key_range: Range, lsn: Lsn) -> anyhow::Result<()> { let layer = self.get_layer_for_write(lsn)?; layer.put_tombstone(key_range, lsn)?; @@ -1076,64 +1207,6 @@ impl Timeline { drop(layers); } - /// - /// Check if more than 'checkpoint_distance' of WAL has been accumulated in - /// the in-memory layer, and initiate flushing it if so. - /// - /// Also flush after a period of time without new data -- it helps - /// safekeepers to regard pageserver as caught up and suspend activity. - /// - pub fn check_checkpoint_distance(self: &Arc) -> Result<()> { - let last_lsn = self.get_last_record_lsn(); - let layers = self.layers.read().unwrap(); - if let Some(open_layer) = &layers.open_layer { - let open_layer_size = open_layer.size()?; - drop(layers); - let last_freeze_at = self.last_freeze_at.load(); - let last_freeze_ts = *(self.last_freeze_ts.read().unwrap()); - let distance = last_lsn.widening_sub(last_freeze_at); - // Checkpointing the open layer can be triggered by layer size or LSN range. - // S3 has a 5 GB limit on the size of one upload (without multi-part upload), and - // we want to stay below that with a big margin. The LSN distance determines how - // much WAL the safekeepers need to store. - if distance >= self.get_checkpoint_distance().into() - || open_layer_size > self.get_checkpoint_distance() - || (distance > 0 && last_freeze_ts.elapsed() >= self.get_checkpoint_timeout()) - { - info!( - "check_checkpoint_distance {}, layer size {}, elapsed since last flush {:?}", - distance, - open_layer_size, - last_freeze_ts.elapsed() - ); - - self.freeze_inmem_layer(true); - self.last_freeze_at.store(last_lsn); - *(self.last_freeze_ts.write().unwrap()) = Instant::now(); - - // Launch a task to flush the frozen layer to disk, unless - // a task was already running. (If the task was running - // at the time that we froze the layer, it must've seen the - // the layer we just froze before it exited; see comments - // in flush_frozen_layers()) - if let Ok(guard) = self.layer_flush_lock.try_lock() { - drop(guard); - let self_clone = Arc::clone(self); - task_mgr::spawn( - task_mgr::BACKGROUND_RUNTIME.handle(), - task_mgr::TaskKind::LayerFlushTask, - Some(self.tenant_id), - Some(self.timeline_id), - "layer flush task", - false, - async move { self_clone.flush_frozen_layers(false) }, - ); - } - } - } - Ok(()) - } - /// Flush all frozen layers to disk. /// /// Only one task at a time can be doing layer-flushing for a @@ -1141,7 +1214,7 @@ impl Timeline { /// currently doing the flushing, this function will wait for it /// to finish. If 'wait' is false, this function will return /// immediately instead. - fn flush_frozen_layers(&self, wait: bool) -> Result<()> { + fn flush_frozen_layers(&self, wait: bool) -> anyhow::Result<()> { let flush_lock_guard = if wait { self.layer_flush_lock.lock().unwrap() } else { @@ -1180,7 +1253,7 @@ impl Timeline { } /// Flush one frozen in-memory layer to disk, as a new delta layer. - fn flush_frozen_layer(&self, frozen_layer: Arc) -> Result<()> { + fn flush_frozen_layer(&self, frozen_layer: Arc) -> anyhow::Result<()> { // As a special case, when we have just imported an image into the repository, // instead of writing out a L0 delta layer, we directly write out image layer // files instead. This is possible as long as *all* the data imported into the @@ -1238,7 +1311,7 @@ impl Timeline { &self, disk_consistent_lsn: Lsn, layer_paths_to_upload: HashMap, - ) -> Result<()> { + ) -> anyhow::Result<()> { // We can only save a valid 'prev_record_lsn' value on disk if we // flushed *all* in-memory changes to disk. We only track // 'prev_record_lsn' in memory for the latest processed record, so we @@ -1299,7 +1372,7 @@ impl Timeline { fn create_delta_layer( &self, frozen_layer: &InMemoryLayer, - ) -> Result<(PathBuf, LayerFileMetadata)> { + ) -> anyhow::Result<(PathBuf, LayerFileMetadata)> { // Write it out let new_delta = frozen_layer.write_to_disk()?; let new_delta_path = new_delta.path(); @@ -1334,92 +1407,7 @@ impl Timeline { Ok((new_delta_path, LayerFileMetadata::new(sz))) } - pub fn compact(&self) -> anyhow::Result<()> { - let last_record_lsn = self.get_last_record_lsn(); - - // Last record Lsn could be zero in case the timelie was just created - if !last_record_lsn.is_valid() { - warn!("Skipping compaction for potentially just initialized timeline, it has invalid last record lsn: {last_record_lsn}"); - return Ok(()); - } - - // - // High level strategy for compaction / image creation: - // - // 1. First, calculate the desired "partitioning" of the - // currently in-use key space. The goal is to partition the - // key space into roughly fixed-size chunks, but also take into - // account any existing image layers, and try to align the - // chunk boundaries with the existing image layers to avoid - // too much churn. Also try to align chunk boundaries with - // relation boundaries. In principle, we don't know about - // relation boundaries here, we just deal with key-value - // pairs, and the code in pgdatadir_mapping.rs knows how to - // map relations into key-value pairs. But in practice we know - // that 'field6' is the block number, and the fields 1-5 - // identify a relation. This is just an optimization, - // though. - // - // 2. Once we know the partitioning, for each partition, - // decide if it's time to create a new image layer. The - // criteria is: there has been too much "churn" since the last - // image layer? The "churn" is fuzzy concept, it's a - // combination of too many delta files, or too much WAL in - // total in the delta file. Or perhaps: if creating an image - // file would allow to delete some older files. - // - // 3. After that, we compact all level0 delta files if there - // are too many of them. While compacting, we also garbage - // collect any page versions that are no longer needed because - // of the new image layers we created in step 2. - // - // TODO: This high level strategy hasn't been implemented yet. - // Below are functions compact_level0() and create_image_layers() - // but they are a bit ad hoc and don't quite work like it's explained - // above. Rewrite it. - let _layer_removal_cs = self.layer_removal_cs.lock().unwrap(); - - let target_file_size = self.get_checkpoint_distance(); - - // Define partitioning schema if needed - - match self.repartition( - self.get_last_record_lsn(), - self.get_compaction_target_size(), - ) { - Ok((partitioning, lsn)) => { - // 2. Create new image layers for partitions that have been modified - // "enough". - let layer_paths_to_upload = self.create_image_layers(&partitioning, lsn, false)?; - if !layer_paths_to_upload.is_empty() - && self.upload_layers.load(atomic::Ordering::Relaxed) - { - storage_sync::schedule_layer_upload( - self.tenant_id, - self.timeline_id, - layer_paths_to_upload, - None, - ); - } - - // 3. Compact - let timer = self.metrics.compact_time_histo.start_timer(); - self.compact_level0(target_file_size)?; - timer.stop_and_record(); - } - Err(err) => { - // no partitioning? This is normal, if the timeline was just created - // as an empty timeline. Also in unit tests, when we use the timeline - // as a simple key-value store, ignoring the datadir layout. Log the - // error but continue. - error!("could not compact, repartitioning keyspace failed: {err:?}"); - } - }; - - Ok(()) - } - - fn repartition(&self, lsn: Lsn, partition_size: u64) -> Result<(KeyPartitioning, Lsn)> { + fn repartition(&self, lsn: Lsn, partition_size: u64) -> anyhow::Result<(KeyPartitioning, Lsn)> { let mut partitioning_guard = self.partitioning.lock().unwrap(); if partitioning_guard.1 == Lsn(0) || lsn.0 - partitioning_guard.1 .0 > self.repartition_threshold @@ -1433,7 +1421,7 @@ impl Timeline { } // Is it time to create a new image layer for the given partition? - fn time_for_new_image_layer(&self, partition: &KeySpace, lsn: Lsn) -> Result { + fn time_for_new_image_layer(&self, partition: &KeySpace, lsn: Lsn) -> anyhow::Result { let layers = self.layers.read().unwrap(); for part_range in &partition.ranges { @@ -1478,7 +1466,7 @@ impl Timeline { partitioning: &KeyPartitioning, lsn: Lsn, force: bool, - ) -> Result> { + ) -> anyhow::Result> { let timer = self.metrics.create_images_time_histo.start_timer(); let mut image_layers: Vec = Vec::new(); for partition in partitioning.parts.iter() { @@ -1571,7 +1559,7 @@ impl Timeline { /// Collect a bunch of Level 0 layer files, and compact and reshuffle them as /// as Level 1 files. /// - fn compact_level0(&self, target_file_size: u64) -> Result<()> { + fn compact_level0(&self, target_file_size: u64) -> anyhow::Result<()> { let layers = self.layers.read().unwrap(); let mut level0_deltas = layers.get_level0_deltas()?; drop(layers); @@ -1881,12 +1869,12 @@ impl Timeline { /// /// The 'pitr' duration is used to calculate a 'pitr_cutoff', which can be used to determine /// whether a record is needed for PITR. - pub fn update_gc_info( + pub(super) fn update_gc_info( &self, retain_lsns: Vec, cutoff_horizon: Lsn, pitr: Duration, - ) -> Result<()> { + ) -> anyhow::Result<()> { let mut gc_info = self.gc_info.write().unwrap(); gc_info.horizon_cutoff = cutoff_horizon; @@ -1941,7 +1929,7 @@ impl Timeline { /// within a layer file. We can only remove the whole file if it's fully /// obsolete. /// - pub fn gc(&self) -> Result { + pub(super) fn gc(&self) -> anyhow::Result { let mut result: GcResult = Default::default(); let now = SystemTime::now(); @@ -2261,11 +2249,11 @@ impl<'a> TimelineWriter<'a> { /// /// This will implicitly extend the relation, if the page is beyond the /// current end-of-file. - pub fn put(&self, key: Key, lsn: Lsn, value: &Value) -> Result<()> { + pub fn put(&self, key: Key, lsn: Lsn, value: &Value) -> anyhow::Result<()> { self.tl.put_value(key, lsn, value) } - pub fn delete(&self, key_range: Range, lsn: Lsn) -> Result<()> { + pub fn delete(&self, key_range: Range, lsn: Lsn) -> anyhow::Result<()> { self.tl.put_tombstone(key_range, lsn) } From 2709878b8be8f34602bc5273d31fe3ad07fd8aac Mon Sep 17 00:00:00 2001 From: Sergey Melnikov Date: Fri, 21 Oct 2022 14:21:22 +0300 Subject: [PATCH 64/64] Deploy scram proxies into new account (#2643) --- .../dev-us-east-2-beta.neon-proxy-scram.yaml | 31 +++++++++++++++++++ .github/workflows/build_and_test.yml | 28 +++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 .github/helm-values/dev-us-east-2-beta.neon-proxy-scram.yaml diff --git a/.github/helm-values/dev-us-east-2-beta.neon-proxy-scram.yaml b/.github/helm-values/dev-us-east-2-beta.neon-proxy-scram.yaml new file mode 100644 index 0000000000..f2247fa4c1 --- /dev/null +++ b/.github/helm-values/dev-us-east-2-beta.neon-proxy-scram.yaml @@ -0,0 +1,31 @@ +# Helm chart values for neon-proxy-scram. +# This is a YAML-formatted file. + +image: + repository: neondatabase/neon + +settings: + authBackend: "console" + authEndpoint: "http://console-staging.local/management/api/v2" + domain: "*.us-east-2.aws.neon.build" + +# -- Additional labels for neon-proxy pods +podLabels: + zenith_service: proxy-scram + zenith_env: dev + zenith_region: us-east-2 + zenith_region_slug: us-east-2 + +exposedService: + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: external + service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip + service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing + external-dns.alpha.kubernetes.io/hostname: us-east-2.aws.neon.build + +#metrics: +# enabled: true +# serviceMonitor: +# enabled: true +# selector: +# release: kube-prometheus-stack diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 460d73a552..14ee61c5b9 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -825,3 +825,31 @@ jobs: DOCKER_TAG=${{needs.tag.outputs.build-tag}} helm upgrade ${{ matrix.proxy_job }} neondatabase/neon-proxy --namespace neon-proxy --install -f .github/helm-values/${{ matrix.proxy_config }}.yaml --set image.tag=${DOCKER_TAG} --wait --timeout 15m0s helm upgrade ${{ matrix.proxy_job }}-scram neondatabase/neon-proxy --namespace neon-proxy --install -f .github/helm-values/${{ matrix.proxy_config }}-scram.yaml --set image.tag=${DOCKER_TAG} --wait --timeout 15m0s + + deploy-proxy-new: + runs-on: dev + container: 369495373322.dkr.ecr.eu-central-1.amazonaws.com/ansible:pinned + # Compute image isn't strictly required for proxy deploy, but let's still wait for it to run all deploy jobs consistently. + needs: [ push-docker-hub, calculate-deploy-targets, tag, regress-tests ] + if: | + (github.ref_name == 'main' || github.ref_name == 'release') && + github.event_name != 'workflow_dispatch' + defaults: + run: + shell: bash + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: true + fetch-depth: 0 + + - name: Configure environment + run: | + helm repo add neondatabase https://neondatabase.github.io/helm-charts + aws --region us-east-2 eks update-kubeconfig --name dev-us-east-2-beta --role-arn arn:aws:iam::369495373322:role/github-runner + + - name: Re-deploy proxy + run: | + DOCKER_TAG=${{needs.tag.outputs.build-tag}} + helm upgrade neon-proxy-scram neondatabase/neon-proxy --namespace neon-proxy --create-namespace --install -f .github/helm-values/dev-us-east-2-beta.neon-proxy-scram.yaml --set image.tag=${DOCKER_TAG} --wait --timeout 15m0s