text:
« Movies that should have been Trilogies
Molly's Game »
Movie of the Month: November 2017
December 1, 2017 by fandangogroovers
This month's contenders are:
Murder on the Orient Express – Kenneth Branagh's lavish and glossy take on the classic Agatha Christie murder mystery. All the A-list cast are outstanding especially Michelle Pfeiffer. Is it better than the revered 1970's Sidney Lumet version? Probably not, however, it offers enough new gloss to make it worth seeing especially for those who haven't seen any of the many other versions.
The Killing of a Sacred Deer – As with director Yorgos Lanthimos previous movie, The Lobster, it may be hard to decide if it is a masterpiece or an esoteric rant. I would go with the former on both counts.
Professor Marston & the Wonder Women – The unusual origins of the Wonder Woman Comic book are explored in what is either a tender love story, or the most vanilla BDSM movie depending on your point of view. The performances are excellent, particularly the always brilliant Rebecca Hall. Not the best Wonder Woman movie of the year, but by far the best of the month!
The Florida Project – Poignant drama set on the edge of society just outside Disney World in Florida. There is little in the way of plot, this doesn't matter as the cast of newcomers and unknowns (along with an excellent as always Willem Dafoe) tell the powerful story of the shame of our generation, the so called hidden homeless.
Paddington 2 – The first Paddington movie was so much better than expected. This sequel doesn't disappoint. Hugh Grant and Brendan Gleeson are excellent additions to the cast.
Justice League – The Avengers (2012) was the sixth film of the MCU after introducing all its main characters. It did a great job of bringing this disparate group together. Justice League was the DCEU's chance to do the same, they really screwed it up. The film spends the first half a movie introducing characters, the second half battling a the worst, most uninteresting villain in the history of comic book movies.
Film Stars Don't Die in Liverpool – True story of the romance between a young British actor and fading movie star Gloria Grahame. I am a big fan of both Gloria Grahame and Annette Bening who plays her here, so the stakes were high, it doesn't disappoint.
Battle of the Sexes – Billed as the story of the 1973 tennis match between Billie Jean King and Bobby Riggs, reportedly the most watched televised sports event of all time. The film is so much more; a love story, the story of King's coming out, and most notably the origin of the WTA. The biggest surprise, the story isn't just about King, Riggs' story is sympathetically told and interesting. Emma Stone and Steve Carell are both brilliant.
Ingrid Goes West – obsession and stalking in the cyber generation. I didn't exactly like or enjoy this movie, probably because I hated most of the characters, Dan (O'Shea Jackson Jr.) being the exception. However, it was strangely compelling. The end is perfect anchors the films context. You expect Elizabeth Olsen to be good, and she is in what a supporting role, Aubrey Plaza is brilliant in the lead.
Molly's Game – Shown as a secret screening a month before its UK release. Writer Aaron Sorkin's directorial debut tells the true story of Molly Bloom, the woman who ran a high-stakes poker game for the rich and famous until the mob and the FBI got in the way. The snappy dialogue that you would expect from Sorkin comes to life thanks to the brilliant Jessica Chastain and Idris Elba.
Before I started writing this, I didn't know what the movie of the month would be, It suddenly became clear it had to be: The Florida Project
Posted in Movie Of The Month | Tagged Battle of the Sexes, Film Stars Don't Die in Liverpool, Ingrid Goes West, Justice League, Molly's Game, Murder on the Orient Express, Paddington 2, Professor Marston & the Wonder Women, The Florida Project, The Killing of a Sacred Deer | 4 Comments
on December 1, 2017 at 1:39 am | Reply Caz
I didn't get to see The Florida Project but I did see all of the others on your list. I haven't done mine yet but I think November has been a very strong and good month, as long as we take out Justice League of course!
on December 3, 2017 at 12:30 pm | Reply fandangogroovers
You have probably missed the Florida Project unless It gets a one off screening around awards time. Well worth checking out when I is released for home viewing. I didn't Professor Marston & the Wonder Women on your list, did you get to see that? Its good, not great but worth seeing for Rebecca Hall alone.
on December 3, 2017 at 12:55 pm Caz
I saw Wonder Woman in October, totally loved that!
Florida Project I don't believe was shown at Cineworld and I don't think I saw much surrounding its what seems very limited release! I didn't see Professor Marston either.
on December 3, 2017 at 1:32 pm fandangogroovers
I have four local Cineworlds, only one of them showed The Florida Project, it was only on for a week.


text:
Shells Part 3
By the outbreak of war in 1914, heavy naval shells had reached approximately the form they would take for the next three decades. Heavy armor-piercing (AP) shells, equipped with caps designed to prevent them from shattering on impact with face-hardened armor, could carry small quantities of explosives, 1-2% of shell weight, through armor plate and detonate on the other side. Other shells, often known as common, carried much more explosive, but were fuzed to detonate on impact, or possibly after piercing a much thinner armored plate. But there was plenty of room for variation on these themes, and some nations had done a much better job than others at anticipating the demands of war.
A British 15" AP shell of 1943
The British in particular had badly misjudged how their shells would be used in action. They had based much of their doctrine around long-range engagements with common shells, intended to destroy the enemy's unarmored upperworks, start fires and demoralize the crew, with AP shells to be held for finishing off enemy ships at closer range. This was used as a justification for not carrying out oblique impact tests on their AP projectiles, which turned out to be a serious mistake at Jutland, where few projectiles penetrated heavy German armor. Action was quickly taken to address this, and in 1918, a new shell, known as the Greenboy from its paint scheme, was issued to the fleet. It had a new, much harder, AP cap and a redesigned body for better penetration, particularly during oblique impacts, while an improved delay fuze and a new explosive, shellite, would allow it to penetrate armor and reach the ship's vitals in a fit state to burst.
A British 8" shell showing the dye marker system
In the aftermath of WWI, all of the various powers continued their shell development program, gradually refining the shape, metallurgy, and heat treatment of their shells to improve penetration. As "all-or-nothing" armor schemes became common, the various common-type shells fell into disuse, leaving battleships armed with AP and maybe a high-explosive/high-capacity shell for shore bombardment. A typical WWII-era AP shell could penetrate armor about 40% thicker than an immediate postwar shell of the same caliber. One important innovation during this era was the use of dye markers to make spotting easier when multiple ships were firing on the same target. The dye packet was usually underneath the windscreen, which was often modified with vents to allow the dye to flow out and color the shell's splash. Each ship within a squadron would be assigned a different color, allowing its splashes to be distinguished.
Shell splashes rise during gunnery training.
While the general trend of shell procurement after WWI was fairly conservative, there were a few exotic ideas that made it off the drawing board. In the US, the gas shell was developed, a standard AP shell where 25% of the filler was replaced by some form of gas, which would be released inside the ship. Both the USN and RN took the threat of such shells very seriously in the interwar years, although none of them ever saw action. British experiments with thermite fillings for incendiary purposes were unsuccessful, and the idea was quietly shelved.
A diagram of the Type 91 AP shell
The only nation to make a radical departure from the general trend of shell development in the interwar years was Japan. In 1924, during a test on the battleship Tosa, cancelled under the Washington Naval Treaty, one shell, striking 25m short, ran under the water and penetrated the hull under the belt, detonating in the engine room and doing extensive damage. The Japanese seized on this method of attack, and developed an armor-piercing projectile, the Type 91, optimized for underwater hits.1 It was a very long shell, as part of a separate Japanese plan to outrange the American fleet, with a windscreen designed to break away when the shell struck the water. This left a flat face on the AP cap, which gave better stability underwater.2 Optimizing the shell for underwater hits made it somewhat less effective at penetrating armor, but the biggest compromise was in the area of fuzing. While a normal AP shell might have a delay of 0.02-0.05 seconds, the Type 91 used a delay of .4 seconds. This meant that when fired against lightly-armored targets, the Type 91 tended to penetrate out the far side of the vessel before it went off. There were several other drawbacks. First, the range had to be fairly great, so that the shell was falling steeply enough to pass under the belt before it lost too much speed. Second, the technique was not practiced due to secrecy, and these hits proved to be vanishingly rare in action. The only example was during the Battle of Cape Esperance, when a single 8" shell reached the forward magazine of the light cruiser Boise. This was exactly the kind of hit the Japanese had wanted, but the resulting fire was quenched almost immediately by the flooding from the breach the shell had made in the hull.3
A Type 3 Sanshikidan
Nor was the Type 91 the only unusual projectile the Japanese developed. While most countries gave their heavy guns a theoretical AA capability through the use of time fuzes on high explosive (HE) shells and special range tables,4 the Japanese developed a specialized AA shell for their heavy guns, the famous Type 3 Sanshikidan. It was loaded and fired like a regular shell, with a time fuze, set before the shells went up the hoists, to set off the bursting charge. When that happened, hundreds of small tubes filled with an incendiary compound were released, each spouting a 16' flame for the next 5 seconds. In theory, each 18.1" incendiary shrapnel shell from Yamato could produce a burst radius of 397', as opposed to 223' for the HE shell, although both values are probably high. A salvo of these shells, which could take up as much as 40% of a Japanese battleship's magazines by the end of the war, was supposed to create a barrier for attacking aircraft, but American pilots considered them much more effective for creating light shows than for doing damage.5
A Sanshikidan projectile in action
Of course, there's one nation that I haven't mentioned in all of this, a nation that made the greatest strides in heavy naval shells, and kept developing them decades later. Next time, I'll discuss the USN's shells from the 1930s and onward.
1 Interestingly, the French had looked into underwater hits as a means of attack during the years leading up to WWI, although they were unable to come up with an effective projectile, and appear to have abandoned the concept after the war. ⇑
2 Basically, a pointed nose gave any overturning force a longer lever, so the shell would tumble and lose velocity faster. ⇑
3 Another odd feature of these shells was the use of Trinitroanisole as the bursting charge. This was more powerful than most other options, but required a lot of cushioning to keep it from going off on impact, to the point that they probably would have been better off with TNT. ⇑
4 In practice, of course, this capability was next to useless. The time fuzes would have to be set manually, and shooting at a fast-moving target using a paper range table (like this one for the 16"/50s of Iowa) would be an exercise in futility. Heavier guns were occasionally used against torpedo bombers by firing into the sea ahead of them, hoping to raise splashes that might bring down the low-flying airplanes. ⇑
5 These shells were also used during the bombardment of Henderson Field, and a few were used against ships during the opening phase of the First Naval Battle of Guadalcanal before the Japanese managed to get AP shells up from the magazines. ⇑
by bean
May 01, 2019John Schilling said...
So, the bit where the British were going to start by tearing up the enemy's ships with long-range HE/common shell - how did that work out in practice, or did they just change their mind and not even try by the time WWI came around?
May 01, 2019bean said...
It worked quite well in the Russo-Japanese War. Wasn't really attempted in WWI, probably because of changes in ship design. Pre-dreads had lots and lots of their firepower exposed in the form of the secondaries. This wasn't true during the dreadnought era. All the important bits were armored anyway, so you pretty much had to go with AP. At Jutland, almost everything the British fired was AP or SAP.
May 01, 2019doctorpat said...
Bean, You mentioned the British general shell crisis being an issue in the attack on the Dardanelles. Is this what you meant, that the naval APs were in short supply and didn't work?
Pretty much. There were two problems during the bombardment of the Dardanelles. First, the shells didn't work that well. Lots of duds and partial detonation, poor fuzing for bombardment work, etc. Second, there weren't enough of them. The British had only bought enough real shells for a full load for each ship, plus a reserve of IIRC 30-40%. (Skimping on ammunition in peacetime isn't a modern invention.) In fairness, their fleet was expanding rapidly, and they probably thought there would be time to build more shells if war broke out. The problem was that the Army in France needed way more shells than it was getting, so the Navy wasn't going to be able to replace any they fired at the Turks very well. This wasn't the end of the world because they had a bunch of pre-dreadnoughts with obsolete guns, but it did mean they couldn't simply drench the Turks in high explosives.
(Also, have you been reading ahead? That post isn't going live until the end of the month.)
"Pre-dreads had lots and lots of their firepower exposed in the form of the secondaries. This wasn't true during the dreadnought era."
I would argue that dreadnought-era ships had lots and lots of their effective firepower exposed in the form of rangefinders and directors, with less armor than secondary-gun casemates and more vulnerable to being smoked out or burned out from below. More generally, the list of dreadnought battleships substantially degraded or outright mission-killed by hits that didn't penetrate the citadel is not small.
If the British had designed their battleship armament for maximum effectiveness with HC shell at long range and AP at close range, then they might have done better to stick with that until they could redesign the AP shells.
May 02, 2019ADifferentAnonymous said...
A salvo of these [Type 3 Sanshikidan] shells, which could take up as much as 40% of a Japanese battleship's magazines by the end of the war
I take it this is because of depletion of normal shells and not because of deliberately increased emphasis on the incendiaries?
On one hand, you're not wrong, and the British screwed up their shell procurement by the numbers. On the other, I strongly suspect this was nowhere near as apparent to them as it is to us, with the benefits of both hindsight and a much broader view of the situation. Keep in mind just how fast technology was changing in this period. Only a handful of battleships had directors at all when war broke out, and it wasn't entirely clear that that was the way of the future. The shell standards were set a few years before that, and nobody seems to have thought to revise them. (This wasn't a problem unique to the British, either. The Germans did something very similar in WWII.) Also, a lot of the British shells were SAP, although they were really close to British AP in penetration.
I would sort of question the theory that dreadnoughts are as vulnerable as pre-dreads. Yes, it's possible to mission-kill one without citadel penetration, but a lot of those involved things like turret hits, which are a lot more effective coming from an AP shell than an HE shell. For that matter, dreadnought battles of any kind didn't happen before 1914, and after 1914, the British were too busy to redesign their AP shells.
@ADA
What depletion of normal shells? The only time the Japanese battleships fired normal shells in the later half of the war was at Samar. And they didn't fire nearly enough to do that. The Japanese liked the Type 3, but they were awful about overclaiming shot-down aircraft.
"Also, a lot of the British shells were SAP, although they were really close to British AP in penetration."
Presumably because the British AP was breaking up whenever it hit heavy armor at an angle, giving it the same weakness as SAP without the compensatory doubled or trebled explosive content.
Did the SAP have reliable fuzes, or were they mostly duds? I mean, almost every type of shell fired from battleships in that era seems to have been mostly-duds in practice, so I know where to bet. But SAP or base-fused HE that works would have been ideal for what the British were apparently aiming for and probably a pretty good dreadnought-wrecker overall.
The fuze problems were common across all British base fuzed shells.
May 03, 2019Tony Zbaraschuk said...
The other thing to note is that statistical quality control was not even in its infancy in the 1900-1914 period; the British testing protocol (grab a few random shells from the lot, test one, if it failed test another, if any of them worked, pass the lot) was so inadequate that a statistician who looked at it decided that a lot that was more than 50% bad would probably pass the test.
First, let me point out that I have another post on the shell problem at Jutland in particular, and everyone keeps stealing my points.
The problem was worse than just bad statistical control. If a batch failed, the manufacturers would start claiming special circumstances and trying to get the navy to buy it anyway.
June 06, 2019Charles Bugajsky said...
Kinetic energy, a 1 ton shell with a hardened armor piercing tip does not blast its was through armor plate. The shell traveling at something like 2,000 fps [FEET PER SECOND], has an incredible kinetic energy striking proper angle, striking at a proper angle, that will punch a hole through the armor plate.
Well 'big deal' in some ways. With the shell staying intact it would just about punch a hole about the same size as the hole in arrived in. The subtle thing about all this is the shell is carrying explosives. How many pounds do you think, 500, 800, more, less? About 35 pounds actually.
So now we have a 2,000 pound shell traveling at 2,000 feet per second piercing the armor plate of an opponent. Maybe the shell has dropped down to 1,600 fps - it is still in tack and only threatening the 16 inches in front of it.
It is worked out that the explosives in the shell delay exploding in what we now call micro seconds. With the shell speeding along a very small explosion now breaks up the shell from the inside. 50 pound, 800 pound, and all sorts of ragged steel is now flying around in many directions inside the ship. Once inside the ship these very high speed chunks are what causes all sorts of serious damage.
This is an extremely well done site.
Japanese 'bombardment shells' are excellently explained. Henderson Field on Guadalcanal was bombarded with them numerously and the airfield was back in operation within hours afterwards. These big 'shotgun' shells did not blast 40 foot deep 50 foot wide holes in the runway or surrounding area. Had the Japanese used their HE shells, whether from a cruiser or battleship, the runway area would look like the face of the moon.
Now HE shells work in much the way armor piercing shells except they are designed to explode on contact. A Japanese shell weighing in the 1,600+ pound range, traveling at roughly 1,800 feet per second, meeting no resistance, for mud offers none, the shell goes deep and when it does explode the mud will travel upwards leaving a large hole.
Comments from SlateStarCodex:
All comments are reviewed before being displayed.
E-mail (required, will not be published):
You can use Markdown in comments!
Enter value:
SSC Naval Gazing Posts
@Chuck,…
Yes, it should be. I think I was changing tenses and got confused. Fixed now.…
Uh, payed? Shouldn't that be paid? (I think I write the same dialect as you do)…
@Lambert…
I've actually been to an operating whaling shore station, in Albany, Western Aus…
Aside from transgressive gourmands who want to be able to say they've feasted on…
Thanks for that. I tried to find that law, which is mentioned a lot of places o…
Oklahoma law doesn't actually prohibit whaling per se. The relevant statute (s…
Particularly weird given that I finished it a month ago. …
ICNW
Riverine
RTW 2
SYWTBABB
SYWTBAMN
WW 2
Page last modified on April 28, 2020, at 04:20 PM
Minimous theme originally by Andy Thompson, adapted by David Gilbert
powered by BlogIt

redpajama_set_name: RedPajamaCommonCrawl


Holidays can be a great source of adventure and relaxation, however, for some of us they can also be a very stressful experience, marked by anxiety and apprehension. Here, I talk about travel stress and how to beat it using 7 helpful tips.
Who doesn't love holiday time? For all of us it is a chance to switch off from daily demands, spend quality time with loved ones, unwind and enjoy whatever type of holiday we love, from lying on a beach to trekking in the Himalayas.
It should just be a time of play and pleasure, although according to a recent survey of 1,000 Brits (1), while the majority of holidaymakers felt more relaxed on holiday, stress can still create some chaos and generally affects women more than men.
With the benefit of 16 years employment in the travel industry here are my 7 top tips for planning a stress free holiday.
To avoid long days and sleepless nights from managing the pre holiday workload, plan ahead for deadlines, request back up if needs be and discuss essentials with bosses and colleagues before you need to.
Modern technology keeps us available 24/7 which can make it hard to switch off. Leave the office in the office and remember that your brain needs a holiday too!
Write a check list of all the items you need to take and tick it off as you pack them (useful for reference to in the rare event of lost luggage). To save time try this pre-prepared version.
Start packing a week or two beforehand.
Double check facilities and appliances at your destination to avoid taking unnecessary items.
If the weather is likely to vary, think layers! Pack clothes that can be built up or taken off!
If you can't choose which clothes to take, pick a simple colour range for a few key outfits.
Stress and lost sleep before you leave, colds from in-flight air systems, mosquito bites and tummy bugs are but a few of the typical health issues that can hinder our holiday happiness.
Tormentil Complex - for the healthy function of the lower bowel in case of the dreaded diarrhoea!
Neem insect repellent - a repellent for mosquitoes, midges and flies. And don't forget the must have mini's from the 15ml range, ideal for travelling!
Echinaforce® to help the immune system fight colds and flu and available in a handy 15ml size, great for travelling.
Digestisan for relief of indigestion, fullness and flatulence and available in a handy 15ml size, great for travelling.
Dormeasan® helps restore natural sleep which can be especially useful when travelling in different time zones or after travelling out of our normal hours.
Stress Relief Daytime for mild stress and anxiety. Available in a handy 15ml size, great for travelling.
Do you need a visa or any vaccinations?
When does your passport expire? (Some countries require at least 6 months validity for entry).
Have you got adequate travel insurance? Make sure you are looked after in the event of cancellation, illness, accident or lost luggage.
Are you hiring a car? Check that you have 'excess protection cover' to avoid significant charges locally, or a huge sum should the car be damaged.
For added peace of mind, double check with your car hire company about recent changes to UK driving licenses.
Are you using a mobile app for your boarding pass? Be sure your phone is fully charged or keep a paper copy with you.
The beach dweller? The sightseer? The retreater? The book reader? The intrepid traveller? Whether you are travelling with family, a partner or a group of friends, it is more than likely that you will encounter differing ideas about how to spend time.
My husband and I are a great example. To prevent me becoming a crazy-crammer and him a holiday-hermit, we've made an agreement to sightsee early in the day and rest later. It's useful to manage differing expectations ahead of time and know the 'must see' places in advance. Flexibility is name of the game when travelling.
With the combo of boats, planes, traffic, foreign cultures, different climates, young children, not to mention unforeseeable events, things often don't go as planned. Keep a sense of humour, be realistic about what you can and can't fit in and remember to relax. If you can't wind down on holiday, when can you?!
Leaving work and dashing to the airport or flying back and dashing to work tend to increase the pre or post holiday stress levels.
Give yourself a break if possible and allow a day at the end of your holiday if not at the beginning as well.
It might look like a good idea to maximise holiday time, book that last flight home, then rush into work but that rapid re-entry into everyday life may just banish the benefits of your well earned break. With a day at home to adjust and unpack you are more likely to prolong the positives.
Home again? Post holiday blues knocking on the door? What was it about the holiday that you enjoyed most? Quality time with family or friends? Time to relax and unwind?
A chance to visit new places? If you can identify the key values that made your holiday special, take time to think about how you could meet these needs more regularly in your day to day life, and if all else fails start planning your next holiday!


text:
Alina Hrushyna –en ucraniano, Аліна Грушина– (nacida como Alina Akobiya, 5 de septiembre de 1999) es una deportista ucraniana que compite en lucha libre.

Ganó una medalla de bronce en el Campeonato Mundial de Lucha de 2022 y tres medallas en el Campeonato Europeo de Lucha entre los años 2020 y 2022.

Palmarés internacional

Referencias

Luchadores de Ucrania

redpajama_set_name: RedPajamaWikipedia


I snapped this pic on my way into work. It rained yesterday, so after lunch the humidity got a hold of it, can you say big hair?! Anyhoo, I'm still loving it!
This entry was posted in Hair, Natural, natural hair. Bookmark the permalink.


text:
package org.apache.ignite.internal.cache.query.index.sorted;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndexKeyType;
import org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndexTree;
import org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKey;
import org.apache.ignite.internal.dto.IgniteDataTransferObject;
import org.apache.ignite.internal.pagemem.FullPageId;
import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
import org.apache.ignite.internal.pagemem.wal.record.IndexRenameRootPageRecord;
import org.apache.ignite.internal.processors.cache.CacheGroupContext;
import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
import org.apache.ignite.internal.processors.cache.persistence.RootPage;
import org.apache.ignite.internal.processors.cache.persistence.metastorage.pendingtask.DurableBackgroundTask;
import org.apache.ignite.internal.processors.cache.persistence.metastorage.pendingtask.DurableBackgroundTaskResult;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIoResolver;
import org.apache.ignite.internal.util.future.GridFinishedFuture;
import org.apache.ignite.internal.util.future.GridFutureAdapter;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.internal.util.worker.GridWorker;
import org.apache.ignite.thread.IgniteThread;
import org.jetbrains.annotations.Nullable;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singleton;

/**
 * Task for background cleaning of index trees.
 */
public class DurableBackgroundCleanupIndexTreeTaskV2 extends IgniteDataTransferObject implements
    DurableBackgroundTask<Long> {
    /** Serial version uid. */
    private static final long serialVersionUID = 0L;

    /**
     * Index tree index factory.
     * NOTE: Change only in tests, to control the creation of trees in the task.
     */
    public static InlineIndexTreeFactory idxTreeFactory = new InlineIndexTreeFactory();

    /** Logger. */
    @Nullable private transient volatile IgniteLogger log;

    /** Unique id. */
    private String uid;

    /** Cache group name. */
    @Nullable private String grpName;

    /** Cache name. */
    private String cacheName;

    /** Index name. */
    private String idxName;

    /** Old name of underlying index tree name. */
    private String oldTreeName;

    /** New name of underlying index tree name. */
    private String newTreeName;

    /** Number of segments. */
    private int segments;

    /** Need to rename index root pages. */
    private transient volatile boolean needToRen;

    /** Index root pages. Mapping: segment number -> index root page. */
    private final transient Map<Integer, RootPage> rootPages = new ConcurrentHashMap<>();

    /** Worker cleaning index trees. */
    @Nullable private transient volatile GridWorker worker;

    /** Total number of pages recycled from index trees. */
    private final transient AtomicLong pageCnt = new AtomicLong();

    /**
     * Constructor.
     *
     * @param grpName Cache group name.
     * @param cacheName Cache name.
     * @param idxName Index name.
     * @param oldTreeName Old name of underlying index tree name.
     * @param newTreeName New name of underlying index tree name.
     * @param segments Number of segments.
     * @param trees Index trees.
     */
    public DurableBackgroundCleanupIndexTreeTaskV2(
        @Nullable String grpName,
        String cacheName,
        String idxName,
        String oldTreeName,
        String newTreeName,
        int segments,
        @Nullable InlineIndexTree[] trees
    ) {
        uid = UUID.randomUUID().toString();
        this.grpName = grpName;
        this.cacheName = cacheName;
        this.idxName = idxName;
        this.oldTreeName = oldTreeName;
        this.newTreeName = newTreeName;
        this.segments = segments;

        if (trees != null) {
            assert trees.length == segments :
                "Invalid number of index trees [trees=" + trees.length + ", segments=" + segments + ']';

            this.rootPages.putAll(toRootPages(trees));
        }

        needToRen = true;
    }

    /**
     * Default constructor for {@link Externalizable}.
     */
    public DurableBackgroundCleanupIndexTreeTaskV2() {
        // No-op.
    }

    /** {@inheritDoc} */
    @Override protected void writeExternalData(ObjectOutput out) throws IOException {
        U.writeLongString(out, uid);
        U.writeLongString(out, grpName);
        U.writeLongString(out, cacheName);
        U.writeLongString(out, idxName);
        U.writeLongString(out, oldTreeName);
        U.writeLongString(out, newTreeName);
        out.writeInt(segments);
    }

    /** {@inheritDoc} */
    @Override protected void readExternalData(
        byte protoVer,
        ObjectInput in
    ) throws IOException, ClassNotFoundException {
        uid = U.readLongString(in);
        grpName = U.readLongString(in);
        cacheName = U.readLongString(in);
        idxName = U.readLongString(in);
        oldTreeName = U.readLongString(in);
        newTreeName = U.readLongString(in);
        segments = in.readInt();
    }

    /** {@inheritDoc} */
    @Override public String name() {
        return "drop-sql-index-" + cacheName + "-" + idxName + "-" + uid;
    }

    /** {@inheritDoc} */
    @Override public void cancel() {
        rootPages.clear();

        GridWorker w = worker;

        if (w != null) {
            worker = null;

            U.awaitForWorkersStop(singleton(w), true, log);
        }
    }

    /** {@inheritDoc} */
    @Override public IgniteInternalFuture<DurableBackgroundTaskResult<Long>> executeAsync(GridKernalContext ctx) {
        assert worker == null;

        log = ctx.log(DurableBackgroundCleanupIndexTreeTaskV2.class);

        IgniteInternalFuture<DurableBackgroundTaskResult<Long>> outFut;

        CacheGroupContext grpCtx = ctx.cache().cacheGroup(CU.cacheGroupId(cacheName, grpName));

        if (grpCtx != null) {
            try {
                // Renaming should be done once when adding (and immediately launched) a task at the time of drop the index.
                // To avoid problems due to node crash between renaming and adding a task.
                if (needToRen) {
                    // If the node falls before renaming, then the index was definitely not dropped.
                    // If the node crashes after renaming, the task will delete the old index trees,
                    // and the node will rebuild this index when the node starts.
                    renameIndexRootPages(grpCtx, cacheName, oldTreeName, newTreeName, segments);

                    // After restoring from MetaStorage, it will also be {@code false}.
                    needToRen = false;
                }

                if (rootPages.isEmpty())
                    rootPages.putAll(findIndexRootPages(grpCtx, cacheName, newTreeName, segments));

                if (!rootPages.isEmpty()) {
                    GridFutureAdapter<DurableBackgroundTaskResult<Long>> fut = new GridFutureAdapter<>();

                    GridWorker w = new GridWorker(
                        ctx.igniteInstanceName(),
                        "async-worker-" + name(),
                        log
                    ) {
                        /** {@inheritDoc} */
                        @Override protected void body() {
                            try {
                                Iterator<Map.Entry<Integer, RootPage>> it = rootPages.entrySet().iterator();

                                while (it.hasNext()) {
                                    Map.Entry<Integer, RootPage> e = it.next();

                                    RootPage rootPage = e.getValue();
                                    int segment = e.getKey();

                                    long pages = destroyIndexTrees(grpCtx, rootPage, cacheName, newTreeName, segment);

                                    if (pages > 0)
                                        pageCnt.addAndGet(pages);

                                    it.remove();
                                }

                                fut.onDone(DurableBackgroundTaskResult.complete(pageCnt.get()));
                            }
                            catch (Throwable t) {
                                fut.onDone(DurableBackgroundTaskResult.restart(t));
                            }
                            finally {
                                worker = null;
                            }
                        }
                    };

                    new IgniteThread(w).start();

                    this.worker = w;

                    outFut = fut;
                }
                else
                    outFut = new GridFinishedFuture<>(DurableBackgroundTaskResult.complete());
            }
            catch (Throwable t) {
                outFut = new GridFinishedFuture<>(DurableBackgroundTaskResult.restart(t));
            }
        }
        else
            outFut = new GridFinishedFuture<>(DurableBackgroundTaskResult.complete());

        return outFut;
    }

    /**
     * Destroying index trees.
     *
     * @param grpCtx Cache group context.
     * @param rootPage Index root page.
     * @param cacheName Cache name.
     * @param treeName Name of underlying index tree name.
     * @param segment Segment number.
     * @return Total number of pages recycled from this tree.
     * @throws IgniteCheckedException If failed.
     */
    public static long destroyIndexTrees(
        CacheGroupContext grpCtx,
        RootPage rootPage,
        String cacheName,
        String treeName,
        int segment
    ) throws IgniteCheckedException {
        long pageCnt = 0;

        grpCtx.shared().database().checkpointReadLock();

        try {
            InlineIndexTree tree = idxTreeFactory.create(grpCtx, rootPage, treeName);

            pageCnt += tree.destroy(null, true);

            if (grpCtx.offheap().dropRootPageForIndex(CU.cacheId(cacheName), treeName, segment) != null)
                pageCnt++;
        }
        finally {
            grpCtx.shared().database().checkpointReadUnlock();
        }

        return pageCnt;
    }

    /**
     * Finding the root pages of the index.
     *
     * @param grpCtx Cache group context.
     * @param cacheName Cache name.
     * @param treeName Name of underlying index tree name.
     * @param segments Number of segments.
     * @return Index root pages. Mapping: segment number -> index root page.
     * @throws IgniteCheckedException If failed.
     */
    public static Map<Integer, RootPage> findIndexRootPages(
        CacheGroupContext grpCtx,
        String cacheName,
        String treeName,
        int segments
    ) throws IgniteCheckedException {
        Map<Integer, RootPage> rootPages = new HashMap<>();

        for (int i = 0; i < segments; i++) {
            RootPage rootPage = grpCtx.offheap().findRootPageForIndex(CU.cacheId(cacheName), treeName, i);

            if (rootPage != null)
                rootPages.put(i, rootPage);
        }

        return rootPages;
    }

    /**
     * Renaming the root index pages.
     *
     * @param grpCtx Cache group context.
     * @param cacheName Cache name.
     * @param oldTreeName Old name of underlying index tree name.
     * @param newTreeName New name of underlying index tree name.
     * @param segments Number of segments.
     * @throws IgniteCheckedException If failed.
     */
    public static void renameIndexRootPages(
        CacheGroupContext grpCtx,
        String cacheName,
        String oldTreeName,
        String newTreeName,
        int segments
    ) throws IgniteCheckedException {
        IgniteWriteAheadLogManager wal = grpCtx.shared().wal();

        int cacheId = CU.cacheId(cacheName);

        if (wal != null)
            wal.log(new IndexRenameRootPageRecord(cacheId, oldTreeName, newTreeName, segments));

        grpCtx.shared().database().checkpointReadLock();

        try {
            for (int i = 0; i < segments; i++)
                grpCtx.offheap().renameRootPageForIndex(cacheId, oldTreeName, newTreeName, i);
        }
        finally {
            grpCtx.shared().database().checkpointReadUnlock();
        }
    }

    /**
     * Create index root pages based on its trees.
     *
     * @param trees Index trees.
     * @return Index root pages. Mapping: segment number -> index root page.
     */
    public static Map<Integer, RootPage> toRootPages(InlineIndexTree[] trees) {
        if (F.isEmpty(trees))
            return emptyMap();
        else {
            Map<Integer, RootPage> res = new HashMap<>();

            for (int i = 0; i < trees.length; i++) {
                InlineIndexTree tree = trees[i];

                assert tree != null : "No tree for segment: " + i;

                res.put(i, new RootPage(new FullPageId(tree.getMetaPageId(), tree.groupId()), tree.created()));
            }
            return res;
        }
    }

    /**
     * A do-nothing {@link InlineIndexRowHandlerFactory} implementation.
     */
    public static class NoopRowHandlerFactory implements InlineIndexRowHandlerFactory {
        /** {@inheritDoc} */
        @Override public InlineIndexRowHandler create(
            SortedIndexDefinition sdef,
            IndexKeyTypeSettings keyTypeSettings
        ) {
            return new InlineIndexRowHandler() {
                /** {@inheritDoc} */
                @Override public IndexKey indexKey(int idx, CacheDataRow row) {
                    return null;
                }

                /** {@inheritDoc} */
                @Override public List<InlineIndexKeyType> inlineIndexKeyTypes() {
                    return emptyList();
                }

                /** {@inheritDoc} */
                @Override public List<IndexKeyDefinition> indexKeyDefinitions() {
                    return emptyList();
                }

                @Override public IndexKeyTypeSettings indexKeyTypeSettings() {
                    return null;
                }

                /** {@inheritDoc} */
                @Override public int partition(CacheDataRow row) {
                    return 0;
                }

                /** {@inheritDoc} */
                @Override public Object cacheKey(CacheDataRow row) {
                    return null;
                }

                /** {@inheritDoc} */
                @Override public Object cacheValue(CacheDataRow row) {
                    return null;
                }
            };
        }
    }

    /**
     * Factory for creating index trees.
     */
    public static class InlineIndexTreeFactory {
        /**
         * Creation of an index tree.
         *
         * @param grpCtx Cache group context.
         * @param rootPage Index root page.
         * @param treeName Name of underlying index tree name.
         * @return New index tree.
         * @throws IgniteCheckedException If failed.
         */
        protected InlineIndexTree create(
            CacheGroupContext grpCtx,
            RootPage rootPage,
            String treeName
        ) throws IgniteCheckedException {
            return new InlineIndexTree(
                null,
                grpCtx,
                treeName,
                grpCtx.offheap(),
                grpCtx.offheap().reuseListForIndex(treeName),
                grpCtx.dataRegion().pageMemory(),
                PageIoResolver.DEFAULT_PAGE_IO_RESOLVER,
                rootPage.pageId().pageId(),
                false,
                0,
                0,
                new IndexKeyTypeSettings(),
                null,
                null,
                new NoopRowHandlerFactory(),
                null
            );
        }
    }

    /** {@inheritDoc} */
    @Override public String toString() {
        return S.toString(DurableBackgroundCleanupIndexTreeTaskV2.class, this);
    }
}

redpajama_set_name: RedPajamaGithub