Awhile back my good friend Esther asked what I've been eating now that I am on the road full time. Maybe she was asking because of the new announcement about her and Jacob. They are going to be living in an Airstream (so dreamy!) for their next adventure. While Esther and Jacob are learning the ropes, I'll share what our meals look like.
The morning doesn't start before I have my double cappuccino. My Nespresso machine (along with our rice cooker) is one of the few appliances we brought with us.
My Nespresso machine and rice cooker.
I also calculate how many coffee capsules I need on each leg of our trip and buy them ahead of time to store in our cargo.
As for what we eat in the morning, it's usually pretty simple. We buy several packages of gravlax (thin slices of cold smoked salmon) from IKEA and keep them in our freezer. We eat one package a week, sometimes more depending on what we are doing during the week.
We put that gravlax on a toasted bagel with cream cheese (mustard for the hubby) and capers. When tomato season comes, I'll add a slice of tomato. Most of the time we wrap this up in tinfoil and take it for the road. Each package gives us three bagel breakfasts.
If we are eating it in the RV, I'll add grapefruit or orange juice as well.
That's our go-to breakfast but if you let me, I'd eat eggs every day! Mr. Misadventures makes killer scrambled eggs (it's in his French DNA) which we eat with toast. We do the same with fried or poached eggs.
From time to time we'll do yogurt and granola, but both the granola and the yogurt we're finding on the road is too sweet, so I don't eat it as often as I did before the RV.
When I have them, I also like whole wheat frozen waffles, but the hubby doesn't like them so I eat them when he goes out for sunrise shooting without me.
Lastly, I also bought a container of grits, but I have just been way too lazy to make them (full confession).
Nine times out of ten we eat lunch on the road. We prep sandwiches: tuna salad, egg salad or turkey. Or we prepare pasta salads ahead of time and bring them in our cooler in the back of our Jeep.
The pasta salads are either macaroni or orzo and we put in a variety of things: celery, cucumber, artichoke hearts, sun-dried tomatoes (or fresh tomatoes), black olives, eggs and tuna.
Sometimes if we have left over soba noodles (see dinner) we'll throw in some sesame oil, furkake spices and soy sauce and eat that.
On cold days we'll bring a thermos is miso soup as well.
If we are stuck inside because of weather or fatigue (going from sunrise to sunset for several days in a row can catch up with you) then we will steam tamales that we picked up in Tucson along with refried beans, or we'll steam some Trader Joe dumplings.
Warmer days we'll have pasta salad, cottage cheese or open a can of sardines. Colder days we'll make clam and seaweed miso soup that we brought home from Kyoto or hit soba noodles.
All depends on weather and availability of fresh veggies. If it's nice outside we'll BBQ sausage (chicken or lamb); lamb (we bought a whole bunch in Santa Fe) or salmon. We've also done steaks twice and hamburgers twice. We are not big beef eaters so it's only every once in awhile.
We've given up on chicken except for sausages because it always seems to get overcooked.
Along with that we'll BBQ whatever fresh vegetables we can find. This winter that's been zucchini, squash, eggplant, the occasional corn on the cob. We've done portobello mushrooms once and yams a couple of times. Looking forward to some different vegetable choices soon.
We finish the plate with steamed rice or sometimes we just eat the protein and veggies.
On cold days or if we are staying at an RV parks that don't accommodate bbqing, we don't want to smell up the RV by cooking meat or frying anything so we'll make pasta with vodka sauce that we eat with chicken meatballs from IKEA, or we'll just eat the pasta with butter and soy sauce.
We also have vegetable meatballs from IKEA that we'll eat with rice. Or a frozen vegetable stir fry from Trader Joe's over rice.
We'll make soba noodles with fish cakes, frozen shrimp and spinach, sometimes with a poached egg on top.
For a special treat we'll open a can of Comtesse du Barry either cassoulet, confit de canard or pintade with mushrooms.
I carry Sahale Snacks every where: in my backpack, in our cooler, in the glove compartment, in cargo and in our cupboard. Depending on my mood I'll go for more salty or sweet.
We eat a lot of hummus, pistachios, plantation chips and dark chocolate. I bought a couple pounds of bulk black licorice pieces from IKEA. I eat a few pieces almost every day. I also buy the big boxes of Swedish cookies from IKEA and put 6-8 in plastic bags which I stick in the freezer and dole out one of those a week as a treat.
The hubby has a yogurt every evening, I'll have one once a week or so.
We drink a single coffee in the morning and juice. The rest of the day it's lots of water, both still and sparkling, some coconut water and lemonade. If I can find, but it's super rare, I'll drink aloe water or juice as well.
We've got wine, beer, champagne, cognac, eau de vie, Jim Beam apple and vodka for salty dogs (thank you Jim!).
Jessica is just as gourmand as we are, so before I left San Francisco I bought an outrageous amount of her organic canned food which I give her with pumpkin. She also drinks lots of cold water, if it ain't fresh she ain't drinking it.
You asked and I gave.
Maybe with way too much detail, but once you get me started on food, it's hard to get me to stop! I am positive there will be adjustments based on seasonality and location so I'll update you again in the coming months.
What do I really miss when it comes to food?
Good bread, specifically Acme. Sushi. Dungeness crab, we missed the whole season in San Francisco (Nov-Mar). Asian food in general. Limitless avocado and tomatoes. Cold press juices.
How about you? What kinds of meals do you make on long trips or camping trips? When you travel away from home, what do you miss?
You sound like you eat better on the road then I do at home! Bagel, Lox and cream cheese–yummy–Since I eat in most of the time I generally make some kind of protein (meat) and veggies and leave it at that. If I eat lunch out-depending on my mood-I will either eat what would normally constitute a dinner (I don't eat dinner those nights) or go light–a slice or two if good old NY Pizza!!
You have no idea how much I love that you took your Nespresso and a rice cooker along in your RV. It's so good to know you can maintain a high standard of eating even while you're on the road. This might be dumb but does the RV have an oven?? If so you can easily make your own granola. I make mine all of the time and the boxed stuff tastes so bland in comparison!
Sounds like you eat better than we eat most days! I love eating fresh fruits and veggies but they are so expensive here. The cucumbers and tomatoes look amazing! One of my favorite things!
I would love to do that some day. That sounds like so much fun!
You guys are eating amazing for being in an rv!! I love that you guys are still sticking to a good diet while on the road like this.
Wow I can't get over how beautiful the inside of the RV is. Better than some regular kitchens I've seen.
First of all that RV kitchen is nicer than my home kitchen! So lovely. The food looks amazing, I could travel around like this – I could live like this!
I'm so impressed with how you're pulling this off and being so healthy. I'm totally inspired.
Your food is so healthy and delicious! It's so good that you are doing well in preparing food.
I'd love to have a RV and travel with my family. Love you menu ideas, looks delicious and a lot of fun!
I love the idea of the Nespresso machine for making cappucinos. One of the challenges of being on the road is to not stop to buy coffee and meals, so making your own good coffee is both convenient and a way to save money. I love your RV kitchen, btw. Looks really nice!
So many delicious and healthy meals. I need to get myself on more of a healthy eating habits!


text:
Predictive Text: an Algorithm for Laughs
Botnik Studios combines the worlds of predictive text and comedy by making tools for remixing language. CEO Jamie Brew joins Cheddar to discuss how the company is helping humans and computers collaborate like never before.
Will Neil Patrick Harris Ever Reboot 'Doogie Howser?'
From theater to TV to streaming, it's hard to find a platform that Neil Patrick Harris hasn't been able to entertain audiences on. He joins Cheddar to discuss his approach to comedy and whether he'll ever reprise his role as the child doctor, Doogie Howser.
The Miz and Maryse Challenge Jeff Bezos
WWE superstars The Miz and Maryse have their sights set on one of the biggest names in tech. They join Cheddar to challenge Jeff Bezos to a meeting in the ring.
CollegeHumor Drops Out of the Internet With 'Dropout'
From Steve Jobs to Mark Zuckerberg, college dropouts have a long history of achieving great success. CollegeHumor hopes it will follow suit with its new ad-free subscription service, 'Dropout.' CEO Richard Cusick joins Cheddar to discuss how the platform fits into the media landscape.

redpajama_set_name: RedPajamaCommonCrawl


text:
Chasing the Vine: New Zealand's Vineyard Marathons
05 May 2018 – 12 May 2018
Take an active approach to exploring New Zealand's wine regions with a range of vineyard marathons.
Enjoy running through a natural landscape of wineries, orchards, beach front and late autumn countryside in the Hawke's Bay International Marathon.
Credit: Hawke's Bay Marathon
Download Image (3992x2242px, 2327KB)
The 10th Saint Clair Marathon takes its course through some of Marlborough and New Zealand's best-known vineyards.
Credit: Saint Clair Marathon
Beginning at the Saint Clair cellar door, you'll wind your way through the Allan Scott and Cloudy Bay wineries and at the finish line be presented with some of New Zealand's best sauvignon blanc.
The inaugural Explore Waiheke Half-Marathon in New Zealand will give runners and wine lovers exceptional access to the island's best features.
Credit: Explore Waiheke
From the wild hillsides to sunbaked plains and curving golden sand beaches, the wine regions of New Zealand produce full-bodied reds and aromatic whites. The combination of great landscapes and award-winning wines is hard to resist – and what better way to earn that indulgent glass or two than with a vineyard marathon?
Whether you're a "social" runner or a serious athlete, you'll find a trail for every fitness level. Each marathon or half-marathon provides a way to experience the regions, from cellar doors and across beachfronts to winding island roads. With a flagship vineyard at the end of each run, you'll also have the perfect motivation to reach the finish line.
These three key events – from the inaugural Waiheke Island Half-Marathon in Auckland to the Hawke's Bay on the east coast of the North Island, and down to Marlborough at the top of the South Island – will take you past a vast number of New Zealand vineyards.
Waiheke Half Marathon – 5 May, 2018
The island of Waiheke, in Auckland's Hauraki Gulf, is blessed with extraordinary natural features. Its ancient rock base, marine position and warmth have given rise to many of Waiheke's award-winning vineyards, which produce primarily red wines such as syrah.
The inaugural Explore Waiheke Half-Marathon will give runners and wine lovers exceptional access to the island's best features. The 2018 event will take place on Saturday 5 May 2018, beginning and ending in Cable Bay vineyards. You'll follow the predominantly flat course all over the western tip of the island, hitting the coastline on several sides, all with a different sea view. And those same cool sea breezes that do special things to the island's grapes will also help to get you through the run.
A 35-minute crossing from downtown Auckland on a regular ferry, Waiheke is a sensational destination for those exploring the Auckland region. With varied terrain and a fresh sea breeze, the island offers plenty of action, including kayaking, mountain biking and zip-lining.
Saint Clair Vineyard Half Marathon – 12 May, 2018
The Marlborough region packs a punch when it comes to New Zealand wine, in particular with its world-class sauvignon blanc. Its broad slopes produce more than three-quarters of New Zealand's grapes by weight, making the region a significant player in terms of volume as well as quality.
Marlborough sauvignon blanc is well-established but the region's second-largest varietal is its fantastic pinot noir. The hills that surround the wine-growing areas enjoy consistently sunny and dry weather – making it good for grapes and great for exploring.
The 10th Saint Clair marathon on Saturday, 12 May 2018, takes its course through some of the region's best-known vineyards. Beginning at the Saint Clair cellar door, you'll wind your way through the Allan Scott and Cloudy Bay wineries, along riversides and through the vineyards, all the while surrounded by the sunny Marlborough hills on the horizon.
Marlborough's rivers are perfect for swimming, the hills ideal for trekking, and the blue waters of the Queen Charlotte Sounds are a wonderful spot to fish or swim with dolphins. To get there take a three-and-a-half-hour ferry ride from Wellington on the North Island to Picton, on the Interislander or simply drive up the scenic coast from Christchurch. There are regular flights into Blenheim Airport from Auckland and Wellington.
Hawke's Bay International Marathon – 12 May, 2018
Like its rich red wines, including merlot as well as Bordeaux blends, and whites such as chardonnay, the Hawke's Bay region is a place to savour. Sitting on the east coast of the North Island, Hawke's Bay is a sweeping half-circle sheltered from the north by the Mahia Peninsula down to Cape Kidnappers in the south. Its reputation as a holiday spot is as well-established as its internationally-regarded wines.
The Air New Zealand Hawke's Bay International Marathon, on 12 May, 2018, takes place right in the centre of the region, with a track traversing a variety of terrains. Flat and gentle for the most part, the marathon begins at the Napier waterfront before heading up through spectacular scenery, while the half-marathon and 10-kilometre run take you through privately owned vineyards and groves of olive trees towards the cellar doors of Sileni Estates vineyard. With a kids' run in the afternoon and post-race festivities, there is no reason to stop once the race is over.
Hawke's Bay is renowned for the Art Deco architecture in Napier as well as its remarkably sunny weather. Easy access to the water and beaches make it simple for you to enjoy the sunshine. Get outdoors with a game of golf on Cape Kidnappers or climb Te Mata Peak for a 360-degree view. Napier is an easy flight from Auckland, Wellington or Christchurch on Air New Zealand.
Auckland: An introduction
Waiheke Island named in Lonely Planet's top five
Marlborough: An introduction
Hawke's Bay: An introduction
Waiheke Half Marathon
Visit Waiheke
Explore Waiheke
Saint Clair Half Marathon
Destination Marlborough
Saint Clair Winery
Allan Scott Winery
Cloudy Bay Winery
Hawke's Bay Marathon
Hawke's Bay Tourism
Sileni Estate


text:
Q: Why is there an 'h' at the end of the word 'cheetah'? This question is prompted by another question on Stack Exchange regarding the addition of a last letter for no apparent reason during transliteration from Aramaic to Greek :

We have the Aramaic given (חקל דמא haqel d'ma, field of blood) (Acts 1:18–19)—but again, with an otherwise inexplicable χ attached to the end: Ἁκελδαμάχ.

It made me wonder if an additional letter is being added during transliteration which might be regarded as a 'breathing' requirement for pronunciation.
And I therefore considered English as to whether we have 'breathing' letters at the end of words.
My question on BH is therefore :
Is the 'h' at the end of 'cheetah' merely there to indicate that the 'a' should be sounded as /ə/ rather than /eɪ/ ?

A: Way too long for a comment, but perhaps useful...

[T]here are languages, such as Arabic, Malay, and Urdu, where /h/ can occur at the end of syllables, e.g., Malay basah /basah/ "wet". Notice that, in analysing syllable structure, we are talking about sounds (phonemes); the spelling is irrelevant. Thus, while many English words end in an h letter, this letter never represents an /h/ sound. It may be silent as in messiah, cheetah, or [...]

From: The Handbook of English Pronunciation by Marnie Reed and John M. Levis
Note that bahasa Indonesia has citah for cheetah.
Messiah is interesting:

The modern English form represents an attempt to make the word look more Hebrew, and dates from the Geneva Bible (1560).

From: Online Etymology Dictionary
As can be seen at TheFreeDictionary.com, many, if not a clear majority of, English words ending in ah seem to originate from the Middle East or the Indian subcontinent or even further east. However, many more English words end in a. It seems that only words from those regions are likely to be transliterated to end in ah.
According to The Gem Set in Gold: Dhamma Chanting, English translation with Pāli & Hindi by S. N. Goenka:

ḥ is an aspiration following the vowel, e.g., aḥ is like 'uh'. [Hindi only, not Pāli. And the ḥ is also a vowel.]

So, here's a theory: It started with the spelling Messiah and then (English-speaking) people just started using that spelling for all kinds of words (with such aspirations, locally) from those regions.
If this would be true, it would be a nice connection to OP's other interest.

redpajama_set_name: RedPajamaStackExchange


text:
Signal Contributor
Reps. Steve Knight and Michael McCaul | Defending Homeland and Human Dignity
Get breaking news and local stories in your inbox!
Weekday Local News Emails
Despite the constant partisan rhetoric that most see on cable news, the 115th Congress has been actively and effectively working to address many of the nation's most pressing challenges. Two particular issues have found wide bipartisan consensus from both Republicans and Democrats: human trafficking and the growing opioid epidemic that has touched communities in every state.
Human trafficking is one of the most heinous crimes a person can commit. Forcing another human into labor, often in the form of compulsory sexual exploitation, should be recognized for what it is: modern-day slavery. According to the International Labor Organization, human trafficking is now a $150 billion industry with over 20 million victims worldwide. For the sake of our own communities' safety and the protection of our neighbors, we must recognize that America is not immune from these terrible crimes.
At the same time, the opioid crisis has plagued our communities and is claiming the lives of too many of our friends and loved ones. In fact, every day opioid overdoses claim the lives of more than 115 Americans. Much like human trafficking, a large portion of the activity, production assets and planning for the distribution of these drugs enters our country through the southern border via criminal organizations.
As representatives of two border states, California and Texas, and having built careers in law enforcement, we both have seen firsthand the need for stronger laws to combat threats, such as these, that harm our communities and our national security. Thankfully, we have found almost unanimous bipartisan agreement in both chambers of Congress that these issues are priorities that must be addressed.
Earlier this year, President Trump signed Chairman McCaul's bill, H.R. 4708, the Department of Homeland Security Blue Campaign Authorization Act, into law. This law will provide guidance to federal, state and local law enforcement agencies to help detect, intercept and stop human traffickers.
Additionally, the House passed Rep. Knight's H.R. 5546, to authorize the use of certain Department of Defense (DoD) funds for combating opioid trafficking and abuse in the United States, with strong bipartisan support. This bill is expected to pass the Senate in the coming weeks and would allow DoD resources to be used to combat the international illegal drug trade.
These are just two of the many ways the 115th Congress is working hard to protect your families and defend your human rights. In an environment saturated with such heavy partisan rhetoric, it is important to remember the real accomplishments that are being achieved every day to help Americans.
Rep. Steve Knight, R-Palmdale, represents the 25th Congressional District, which includes the Santa Clarita Valley. Rep. Michael McCaul, R-Texas, is chairman of the House Committee on Homeland Security.
Betty Arenson | Cheapening Evil Words Is Costly
Our View | Witnessing the Best and Worst
Latest stories on SignalSCV.com
Featured • News
Faith & Religion • Featured • News • Seniors
Environment • Events • Featured • Food & Entertainment • News


text:
Pensacola man allegedly shot 6-month-old American pit bull puppy that startled him
A Pensacola man was allegedly startled by a pit bull puppy that ran up to him on the street, pulled out a gun and shot the dog, according to ECSO
Pensacola man allegedly shot 6-month-old American pit bull puppy that startled him A Pensacola man was allegedly startled by a pit bull puppy that ran up to him on the street, pulled out a gun and shot the dog, according to ECSO Check out this story on pnj.com: https://www.pnj.com/story/news/crime/2020/01/08/pensacola-man-allegedly-shot-6-month-old-american-pit-bull/2843462001/
Colin Warren-Hicks, Pensacola News Journal Published 10:53 a.m. CT Jan. 8, 2020 | Updated 11:21 a.m. CT Jan. 8, 2020
A Pensacola man has been arrested after he was accused of shooting a six-month-old American pit bull that ran up to him on the street with its tail between its legs.
Jeremy Stallworth, 40, was arrested Wednesday and charged with animal cruelty, firing a weapon in public or on residential property, using a weapon during the commission of a felony and possession of a weapon by a convicted felon.
He was booked into the Escambia County Jail with a $26,000 bond.
Jeremy Stallworth (Photo: Courtesy of the Escambia County Jail)
According to his arrest report, Escambia County Sheriff's Office deputies arrived in the 1000 block of Concordia Boulevard on Tuesday evening and found a woman crouched by the side of her residence trying to coax her dog out from underneath the home.
After approximately one minute, the puppy emerged. The dog had sustained a gunshot wound to its front, left leg and walked with a limp. An ECSO deputy fashioned a makeshift tourniquet from a T-shirt to control the active bleeding, the report stated. Escambia County Animal Control took possession of the dog to provide medical aid.
Have you seen this man?: Synovus Bank robbed Tuesday in Escambia County, ECSO looking for suspect
Hatchet attack: Cantonment woman allegedly attacked her live-in boyfriend with hatchet
The dog owner explained that she had heard two gunshots outside her home and observed her dog running home while its leg bled heavily.
Two of the woman's neighbors told deputies they witnessed the shooting. According to the neighbors, the dog spotted a man walking down Concordia Boulevard and ran toward him. The man seemed to have become startled by the approaching dog and pulled a handgun out of his pants pocket, fired approximately three times and shot the dog, the report stated.
One witness told officers the dog had approached the shooter in a non-aggressive manner with its tail between its legs and had not barked.
The neighbors gave a description of the shooter, and deputies canvassed the area until they found a man matching the description who was later identified as Stallworth. He was arrested.
County records indicated that Stallworth remained in custody as of Wednesday morning.
Read or Share this story: https://www.pnj.com/story/news/crime/2020/01/08/pensacola-man-allegedly-shot-6-month-old-american-pit-bull/2843462001/
Police search for gunmen in Old East Hill neighborhood
Pensacola pedestrian killed while crossing Davis Highway
Rep. Matt Gaetz joins Democrats in War Powers Resolution vote
Man found dead from gunshot wound in West Pensacola
NWS cancels tornado watch for Pensacola area


text:
Tube passenger 'pushed under train' at Kentish Town station
Published on 2 December 2015, 3:32 PM by Fiona
from: http://www.telegraph.co.uk/news/uknews/crime/12028992/Man-pushed-under-train-at-Kentish-Town-tube-station.html
Police are investigating after a man was seriously injured at a north London tube station today
Police at the scene outside Kentish Town tube station in North London Photo: @amontoast
First impressions count. Make yours perfect
Many things contribute to giving a good first impression, from attire to attitude
Sponsored by HSBC
By Leon Watson
12:48PM GMT 02 Dec 2015
A man has been seriously injured after allegedly being pushed under a train at a north London tube station.
The incident happened at around 11.45am on Wednesday on a platform at Kentish Town.
Witnesses on Twitter claimed a man was pushed into the path of an on-coming train.
Musician Mel Mescalita, from north London, said shortly after: "Person was pushed under our tube train in Kentish Town. This world is f****d up."
Others said:
Don't stand close to the edge on the underground - just witnessed a guy get pushed in front of a train at Kentish Town! Hope he makes it.
— Roberto (@RobertoRadioTV) December 2, 2015
Police are investigating and are treating the incident as suspicious.
The Northern Line station is currently closed.
A fire engine, several ambulances and at least two police vans were parked outside Kentish Town station on Wednesday afternoon.
The general manager is currently inside the station inspecting the scene and all travelers are being redirected by police posted outside the gates.
Through the gates around six firemen could be seen gathered outside the ticket machines who left the station at around 1.45pm.
Shortly after a policeman emerged with a large paper bag marked as evidence.
"I've never seen anything like it," one tube worker, who said she had visited the crime scene in the station, told a colleague.
A woman, who asked not to be identified, said: "I was on the platform but I didn't really see it happen. But there was a loud bang that I heard on the platform and that was it. My ears were ringing."
"I'm not sure what the bang was. It was very loud."
An ambulance crew and a team from the capital's air ambulance treated the victim.
A spokesman for London Ambulance Service said: "We were called at 11.44am to Kentish Town Underground station to reports of a person hit by a train. We sent multiple resources to the scene, including a single responder in a car, an ambulance crew, our hazardous area response team and London's Air Ambulance.
"We treated a man at the scene and took him as a priority to a hospital in central London with a doctor from the air ambulance on board."
• Tube station abandons "stand on the right" escalator rule
A British Transport Police spokesman said: "We are currently investigating an incident at Kentish Town London Underground in which a man has been struck by a train.
"The incident happened at about 11.45am today and the man has suffered serious injuries and is currently being treated by paramedics from London Ambulance Service.
"We are currently treating the incident as suspicious and are appealing for any witnesses to the incident to come forward."
Pat Hansberry, operations director for the Northern line, said: "We are aware of an incident at around 11:40 this morning at Kentish Town Tube station.
"We are working closely with the police as they carry out their investigation."
Tags:	Assault Injury London LUL Passenger Push TfL Tube
LUL & Balfour fined for breach of health and safety law
Published on 5 December 2018, 9:40 AM
Rail Worker finds lost wedding on track
Woman killed 'leaning out of train window' between Bath and Bristol
Jubile line train travels between stations with it's doord open.
Published on 4 September 2018, 11:07 AM
Passenger dragged along platform
Published on 28 February 2018, 11:28 AM
Comment on London Mayor's Transport Strategy document released today
New signalling system trials for TfL
Published on 18 October 2017, 2:56 PM
DfT & NR seek bidders for Euston Station HS2 terminus development
Published on 7 February 2017, 11:17 AM
First direct transatlantic freight train from China arrives in London
Published on 19 January 2017, 12:13 PM


text:
/**
 * @file
 * Declares ignite::cache::Cache class.
 */

#ifndef _IGNITE_CACHE_CACHE
#define _IGNITE_CACHE_CACHE

#include <map>
#include <set>

#include <ignite/common/common.h>
#include <ignite/common/concurrent.h>
#include <ignite/ignite_error.h>

#include <ignite/cache/cache_peek_mode.h>
#include <ignite/cache/query/query_cursor.h>
#include <ignite/cache/query/query_fields_cursor.h>
#include <ignite/cache/query/query_scan.h>
#include <ignite/cache/query/query_sql.h>
#include <ignite/cache/query/query_text.h>
#include <ignite/cache/query/query_sql_fields.h>
#include <ignite/cache/query/continuous/continuous_query_handle.h>
#include <ignite/cache/query/continuous/continuous_query.h>
#include <ignite/impl/cache/cache_impl.h>
#include <ignite/impl/cache/cache_entry_processor_holder.h>
#include <ignite/impl/operations.h>
#include <ignite/impl/module_manager.h>
#include <ignite/ignite_error.h>

namespace ignite
{
    namespace cache
    {
        /**
         * Main entry point for all Data Grid APIs.
         *
         * Both key and value types should be default-constructable,
         * copy-constructable and assignable. Also BinaryType class
         * template should be specialized for both types.
         *
         * This class implemented as a reference to an implementation so copying
         * of this class instance will only create another reference to the same
         * underlying object. Underlying object released automatically once all
         * the instances are destructed.
         *
         * @tparam K Cache key type.
         * @tparam V Cache value type.
         */
        template<typename K, typename V>
        class IGNITE_IMPORT_EXPORT Cache
        {
        public:
            /**
             * Constructor.
             *
             * Internal method. Should not be used by user.
             *
             * @param impl Implementation.
             */
            Cache(impl::cache::CacheImpl* impl) :
                impl(impl)
            {
                // No-op.
            }

            /**
             * Get name of this cache (null for default cache).
             *
             * This method should only be used on the valid instance.
             *
             * @return Name of this cache (null for default cache).
             */
            const char* GetName() const
            {
                return impl.Get()->GetName();
            }

            /**
             * Checks whether this cache contains no key-value mappings.
             * Semantically equals to Cache.Size(CachePeekMode::PRIMARY) == 0.
             *
             * This method should only be used on the valid instance.
             *
             * @return True if cache is empty.
             */
            bool IsEmpty()
            {
                IgniteError err;

                bool res = IsEmpty(err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Checks whether this cache contains no key-value mappings.
             * Semantically equals to Cache.Size(CachePeekMode::PRIMARY) == 0.
             *
             * This method should only be used on the valid instance.
             *
             * @param err Error.
             * @return True if cache is empty.
             */
            bool IsEmpty(IgniteError& err)
            {
                return Size(err) == 0;
            }

            /**
             * Check if cache contains mapping for this key.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key.
             * @return True if cache contains mapping for this key.
             */
            bool ContainsKey(const K& key)
            {
                IgniteError err;

                bool res = ContainsKey(key, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Check if cache contains mapping for this key.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key.
             * @param err Error.
             * @return True if cache contains mapping for this key.
             */
            bool ContainsKey(const K& key, IgniteError& err)
            {
                impl::In1Operation<K> op(key);

                return impl.Get()->ContainsKey(op, err);
            }

            /**
             * Check if cache contains mapping for these keys.
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys.
             * @return True if cache contains mapping for all these keys.
             */
            bool ContainsKeys(const std::set<K>& keys)
            {
                IgniteError err;

                bool res = ContainsKeys(keys, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Check if cache contains mapping for these keys.
             *
             * This method should only be used on the valid instance.
             *
             * @param begin Iterator pointing to the beggining of the key sequence.
             * @param end Iterator pointing to the end of the key sequence.
             * @return True if cache contains mapping for all these keys.
             */
            template<typename InputIter>
            bool ContainsKeys(InputIter begin, InputIter end)
            {
                IgniteError err;

                impl::InIterOperation<K, V, InputIter> op(begin, end);

                bool res = impl.Get()->ContainsKeys(op, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Check if cache contains mapping for these keys.
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys.
             * @param err Error.
             * @return True if cache contains mapping for all these keys.
             */
            bool ContainsKeys(const std::set<K>& keys, IgniteError& err)
            {
                impl::InSetOperation<K> op(keys);

                return impl.Get()->ContainsKeys(op, err);
            }

            /**
             * Peeks at cached value using optional set of peek modes. This method will sequentially
             * iterate over given peek modes, and try to peek at value using each peek mode. Once a
             * non-null value is found, it will be immediately returned.
             * This method does not participate in any transactions, however, it may peek at transactional
             * value depending on the peek modes used.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key.
             * @param peekModes Peek modes.
             * @return Value.
             */
            V LocalPeek(const K& key, int32_t peekModes)
            {
                IgniteError err;

                V res = LocalPeek(key, peekModes, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Peeks at cached value using optional set of peek modes. This method will sequentially
             * iterate over given peek modes, and try to peek at value using each peek mode. Once a
             * non-null value is found, it will be immediately returned.
             * This method does not participate in any transactions, however, it may peek at transactional
             * value depending on the peek modes used.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key.
             * @param peekModes Peek modes.
             * @param err Error.
             * @return Value.
             */
            V LocalPeek(const K& key, int32_t peekModes, IgniteError& err)
            {
                impl::InCacheLocalPeekOperation<K> inOp(key, peekModes);
                impl::Out1Operation<V> outOp;

                impl.Get()->LocalPeek(inOp, outOp, peekModes, err);

                return outOp.GetResult();
            }

            /**
             * Retrieves value mapped to the specified key from cache.
             * If the value is not present in cache, then it will be looked up from swap storage. If
             * it's not present in swap, or if swap is disabled, and if read-through is allowed, value
             * will be loaded from persistent store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key.
             * @return Value.
             */
            V Get(const K& key)
            {
                IgniteError err;

                V res = Get(key, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Retrieves value mapped to the specified key from cache.
             * If the value is not present in cache, then it will be looked up from swap storage. If
             * it's not present in swap, or if swap is disabled, and if read-through is allowed, value
             * will be loaded from persistent store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key.
             * @param err Error.
             * @return Value.
             */
            V Get(const K& key, IgniteError& err)
            {
                impl::In1Operation<K> inOp(key);
                impl::Out1Operation<V> outOp;

                impl.Get()->Get(inOp, outOp, err);

                return outOp.GetResult();
            }

            /**
             * Retrieves values mapped to the specified keys from cache.
             * If some value is not present in cache, then it will be looked up from swap storage. If
             * it's not present in swap, or if swap is disabled, and if read-through is allowed, value
             * will be loaded from persistent store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys.
             * @return Map of key-value pairs.
             */
            std::map<K, V> GetAll(const std::set<K>& keys)
            {
                IgniteError err;

                std::map<K, V> res = GetAll(keys, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Retrieves values mapped to the specified keys from cache.
             * If some value is not present in cache, then it will be looked up from swap storage. If
             * it's not present in swap, or if swap is disabled, and if read-through is allowed, value
             * will be loaded from persistent store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys.
             * @param err Error.
             * @return Map of key-value pairs.
             */
            std::map<K, V> GetAll(const std::set<K>& keys, IgniteError& err)
            {
                impl::InSetOperation<K> inOp(keys);
                impl::OutMapOperation<K, V> outOp;

                impl.Get()->GetAll(inOp, outOp, err);

                return outOp.GetResult();
            }

            /**
             * Retrieves values mapped to the specified keys from cache.
             * If some value is not present in cache, then it will be looked up from swap storage. If
             * it's not present in swap, or if swap is disabled, and if read-through is allowed, value
             * will be loaded from persistent store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param begin Iterator pointing to the beggining of the key sequence.
             * @param end Iterator pointing to the end of the key sequence.
             * @param dst Output iterator. Should dereference to std::pair or CacheEntry.
             */
            template<typename InIter, typename OutIter>
            void GetAll(InIter begin, InIter end, OutIter dst)
            {
                IgniteError err;

                impl::InIterOperation<K, V, InIter> inOp(begin, end);
                impl::OutMapIterOperation<K, V, OutIter> outOp(dst);

                impl.Get()->GetAll(inOp, outOp, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Associates the specified value with the specified key in the cache.
             * If the cache previously contained a mapping for the key,
             * the old value is replaced by the specified value.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key with which the specified value is to be associated.
             * @param val Value to be associated with the specified key.
             */
            void Put(const K& key, const V& val)
            {
                IgniteError err;

                Put(key, val, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Associates the specified value with the specified key in the cache.
             * If the cache previously contained a mapping for the key,
             * the old value is replaced by the specified value.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key with which the specified value is to be associated.
             * @param val Value to be associated with the specified key.
             * @param err Error.
             */
            void Put(const K& key, const V& val, IgniteError& err)
            {
                impl::In2Operation<K, V> op(key, val);

                impl.Get()->Put(op, err);
            }

            /**
             * Stores given key-value pairs in cache.
             * If write-through is enabled, the stored values will be persisted to store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param vals Key-value pairs to store in cache.
             */
            void PutAll(const std::map<K, V>& vals)
            {
                IgniteError err;

                PutAll(vals, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Stores given key-value pairs in cache.
             * If write-through is enabled, the stored values will be persisted to store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param vals Key-value pairs to store in cache.
             * @param err Error.
             */
            void PutAll(const std::map<K, V>& vals, IgniteError& err)
            {
                impl::InMapOperation<K, V> op(vals);

                impl.Get()->PutAll(op, err);
            }

            /**
             * Stores given key-value pairs in cache.
             * If write-through is enabled, the stored values will be persisted to store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param begin Iterator pointing to the beggining of the key-value pair sequence.
             * @param end Iterator pointing to the end of the key-value pair sequence.
             */
            template<typename Iter>
            void PutAll(Iter begin, Iter end)
            {
                IgniteError err;

                impl::InIterOperation<K, V, Iter> op(begin, end);

                impl.Get()->PutAll(op, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Associates the specified value with the specified key in this cache,
             * returning an existing value if one existed.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key with which the specified value is to be associated.
             * @param val Value to be associated with the specified key.
             * @return The value associated with the key at the start of the
             *     operation or null if none was associated.
             */
            V GetAndPut(const K& key, const V& val)
            {
                IgniteError err;

                V res = GetAndPut(key, val, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Associates the specified value with the specified key in this cache,
             * returning an existing value if one existed.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key with which the specified value is to be associated.
             * @param val Value to be associated with the specified key.
             * @param err Error.
             * @return The value associated with the key at the start of the
             *     operation or null if none was associated.
             */
            V GetAndPut(const K& key, const V& val, IgniteError& err)
            {
                impl::In2Operation<K, V> inOp(key, val);
                impl::Out1Operation<V> outOp;

                impl.Get()->GetAndPut(inOp, outOp, err);

                return outOp.GetResult();
            }

            /**
             * Atomically replaces the value for a given key if and only if there is
             * a value currently mapped by the key.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key with which the specified value is to be associated.
             * @param val Value to be associated with the specified key.
             * @return The previous value associated with the specified key, or
             *     null if there was no mapping for the key.
             */
            V GetAndReplace(const K& key, const V& val)
            {
                IgniteError err;

                V res = GetAndReplace(key, val, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Atomically replaces the value for a given key if and only if there is
             * a value currently mapped by the key.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key with which the specified value is to be associated.
             * @param val Value to be associated with the specified key.
             * @param err Error.
             * @return The previous value associated with the specified key, or
             *     null if there was no mapping for the key.
             */
            V GetAndReplace(const K& key, const V& val, IgniteError& err)
            {
                impl::In2Operation<K, V> inOp(key, val);
                impl::Out1Operation<V> outOp;

                impl.Get()->GetAndReplace(inOp, outOp, err);

                return outOp.GetResult();
            }

            /**
             * Atomically removes the entry for a key only if currently mapped to some value.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key with which the specified value is associated.
             * @return The value if one existed or null if no mapping existed for this key.
             */
            V GetAndRemove(const K& key)
            {
                IgniteError err;

                V res = GetAndRemove(key, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Atomically removes the entry for a key only if currently mapped to some value.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key with which the specified value is associated.
             * @param err Error.
             * @return The value if one existed or null if no mapping existed for this key.
             */
            V GetAndRemove(const K& key, IgniteError& err)
            {
                impl::In1Operation<K> inOp(key);
                impl::Out1Operation<V> outOp;

                impl.Get()->GetAndRemove(inOp, outOp, err);

                return outOp.GetResult();
            }

            /**
             * Atomically associates the specified key with the given value if it is not
             * already associated with a value.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key with which the specified value is to be associated.
             * @param val Value to be associated with the specified key.
             * @return True if a value was set.
             */
            bool PutIfAbsent(const K& key, const V& val)
            {
                IgniteError err;

                bool res = PutIfAbsent(key, val, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Atomically associates the specified key with the given value if it is not
             * already associated with a value.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key with which the specified value is to be associated.
             * @param val Value to be associated with the specified key.
             * @param err Error.
             * @return True if a value was set.
             */
            bool PutIfAbsent(const K& key, const V& val, IgniteError& err)
            {
                impl::In2Operation<K, V> op(key, val);

                return impl.Get()->PutIfAbsent(op, err);
            }

            /**
             * Stores given key-value pair in cache only if cache had no previous mapping for it.
             * If cache previously contained value for the given key, then this value is returned.
             * In case of PARTITIONED or REPLICATED caches, the value will be loaded from the primary node,
             * which in its turn may load the value from the swap storage, and consecutively, if it's not
             * in swap, from the underlying persistent storage.
             * If the returned value is not needed, method putxIfAbsent() should be used instead of this one to
             * avoid the overhead associated with returning of the previous value.
             * If write-through is enabled, the stored value will be persisted to store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key to store in cache.
             * @param val Value to be associated with the given key.
             * @return Previously contained value regardless of whether put happened or not
             *     (null if there was no previous value).
             */
            V GetAndPutIfAbsent(const K& key, const V& val)
            {
                IgniteError err;

                V res = GetAndPutIfAbsent(key, val, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Stores given key-value pair in cache only if cache had no previous mapping for it.
             * If cache previously contained value for the given key, then this value is returned.
             * In case of PARTITIONED or REPLICATED caches, the value will be loaded from the primary node,
             * which in its turn may load the value from the swap storage, and consecutively, if it's not
             * in swap, from the underlying persistent storage.
             * If the returned value is not needed, method putxIfAbsent() should be used instead of this one to
             * avoid the overhead associated with returning of the previous value.
             * If write-through is enabled, the stored value will be persisted to store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key to store in cache.
             * @param val Value to be associated with the given key.
             * @param err Error.
             * @return Previously contained value regardless of whether put happened or not
             *     (null if there was no previous value).
             */
            V GetAndPutIfAbsent(const K& key, const V& val, IgniteError& err)
            {
                impl::In2Operation<K, V> inOp(key, val);
                impl::Out1Operation<V> outOp;

                impl.Get()->GetAndPutIfAbsent(inOp, outOp, err);

                return outOp.GetResult();
            }

            /**
             * Stores given key-value pair in cache only if there is a previous mapping for it.
             * If cache previously contained value for the given key, then this value is returned.
             * In case of PARTITIONED or REPLICATED caches, the value will be loaded from the primary node,
             * which in its turn may load the value from the swap storage, and consecutively, if it's not
             * in swap, rom the underlying persistent storage.
             * If write-through is enabled, the stored value will be persisted to store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key to store in cache.
             * @param val Value to be associated with the given key.
             * @return True if the value was replaced.
             */
            bool Replace(const K& key, const V& val)
            {
                IgniteError err;

                bool res = Replace(key, val, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Stores given key-value pair in cache only if there is a previous mapping for it.
             * If cache previously contained value for the given key, then this value is returned.
             * In case of PARTITIONED or REPLICATED caches, the value will be loaded from the primary node,
             * which in its turn may load the value from the swap storage, and consecutively, if it's not
             * in swap, rom the underlying persistent storage.
             * If write-through is enabled, the stored value will be persisted to store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key to store in cache.
             * @param val Value to be associated with the given key.
             * @param err Error.
             * @return True if the value was replaced.
             */
            bool Replace(const K& key, const V& val, IgniteError& err)
            {
                impl::In2Operation<K, V> op(key, val);

                return impl.Get()->Replace(op, err);
            }

            /**
             * Stores given key-value pair in cache only if only if the previous value is equal to the
             * old value passed as argument.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key to store in cache.
             * @param oldVal Old value to match.
             * @param newVal Value to be associated with the given key.
             * @return True if replace happened, false otherwise.
             */
            bool Replace(const K& key, const V& oldVal, const V& newVal)
            {
                IgniteError err;

                bool res = Replace(key, oldVal, newVal, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Stores given key-value pair in cache only if only if the previous value is equal to the
             * old value passed as argument.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key to store in cache.
             * @param oldVal Old value to match.
             * @param newVal Value to be associated with the given key.
             * @param err Error.
             * @return True if replace happened, false otherwise.
             */
            bool Replace(const K& key, const V& oldVal, const V& newVal, IgniteError& err)
            {
                impl::In3Operation<K, V, V> op(key, oldVal, newVal);

                return impl.Get()->ReplaceIfEqual(op, err);
            }

            /**
             * Attempts to evict all entries associated with keys.
             *
             * @note Entry will be evicted only if it's not used (not
             * participating in any locks or transactions).
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys to evict from cache.
             */
            void LocalEvict(const std::set<K>& keys)
            {
                IgniteError err;

                LocalEvict(keys, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Attempts to evict all entries associated with keys.
             *
             * @note Entry will be evicted only if it's not used (not
             * participating in any locks or transactions).
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys to evict from cache.
             * @param err Error.
             */
            void LocalEvict(const std::set<K>& keys, IgniteError& err)
            {
                impl::InSetOperation<K> op(keys);

                impl.Get()->LocalEvict(op, err);
            }

            /**
             * Attempts to evict all entries associated with keys.
             *
             * @note Entry will be evicted only if it's not used (not
             * participating in any locks or transactions).
             *
             * This method should only be used on the valid instance.
             *
             * @param begin Iterator pointing to the beggining of the key sequence.
             * @param end Iterator pointing to the end of the key sequence.
             */
            template<typename Iter>
            void LocalEvict(Iter begin, Iter end)
            {
                IgniteError err;

                impl::InIterOperation<K, V, Iter> op(begin, end);

                impl.Get()->LocalEvict(op, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Clear cache.
             *
             * This method should only be used on the valid instance.
             */
            void Clear()
            {
                IgniteError err;

                Clear(err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Clear cache.
             *
             * This method should only be used on the valid instance.
             *
             * @param err Error.
             */
            void Clear(IgniteError& err)
            {
                impl.Get()->Clear(err);
            }

            /**
             * Clear entry from the cache and swap storage, without notifying listeners or CacheWriters.
             * Entry is cleared only if it is not currently locked, and is not participating in a transaction.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key to clear.
             */
            void Clear(const K& key)
            {
                IgniteError err;

                Clear(key, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Clear entry from the cache and swap storage, without notifying listeners or CacheWriters.
             * Entry is cleared only if it is not currently locked, and is not participating in a transaction.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key to clear.
             * @param err Error.
             */
            void Clear(const K& key, IgniteError& err)
            {
                impl::In1Operation<K> op(key);

                impl.Get()->Clear(op, err);
            }

            /**
             * Clear entries from the cache and swap storage, without notifying listeners or CacheWriters.
             * Entry is cleared only if it is not currently locked, and is not participating in a transaction.
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys to clear.
             */
            void ClearAll(const std::set<K>& keys)
            {
                IgniteError err;

                ClearAll(keys, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Clear entries from the cache and swap storage, without notifying listeners or CacheWriters.
             * Entry is cleared only if it is not currently locked, and is not participating in a transaction.
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys to clear.
             * @param err Error.
             */
            void ClearAll(const std::set<K>& keys, IgniteError& err)
            {
                impl::InSetOperation<K> op(keys);

                impl.Get()->ClearAll(op, err);
            }

            /**
             * Clear entries from the cache and swap storage, without notifying listeners or CacheWriters.
             * Entry is cleared only if it is not currently locked, and is not participating in a transaction.
             *
             * This method should only be used on the valid instance.
             *
             * @param begin Iterator pointing to the beggining of the key sequence.
             * @param end Iterator pointing to the end of the key sequence.
             */
            template<typename Iter>
            void ClearAll(Iter begin, Iter end)
            {
                IgniteError err;

                impl::InIterOperation<K, V, Iter> op(begin, end);

                impl.Get()->ClearAll(op, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Clear entry from the cache and swap storage, without notifying listeners or CacheWriters.
             * Entry is cleared only if it is not currently locked, and is not participating in a transaction.
             *
             * @note This operation is local as it merely clears an entry from local cache, it does not
             * remove entries from remote caches.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key to clear.
             */
            void LocalClear(const K& key)
            {
                IgniteError err;

                LocalClear(key, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Clear entry from the cache and swap storage, without notifying listeners or CacheWriters.
             * Entry is cleared only if it is not currently locked, and is not participating in a transaction.
             *
             * @note This operation is local as it merely clears an entry from local cache, it does not
             * remove entries from remote caches.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key to clear.
             * @param err Error.
             */
            void LocalClear(const K& key, IgniteError& err)
            {
                impl::In1Operation<K> op(key);

                impl.Get()->LocalClear(op, err);
            }

            /**
             * Clear entries from the cache and swap storage, without notifying listeners or CacheWriters.
             * Entry is cleared only if it is not currently locked, and is not participating in a transaction.
             *
             * @note This operation is local as it merely clears entries from local cache, it does not
             * remove entries from remote caches.
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys to clear.
             */
            void LocalClearAll(const std::set<K>& keys)
            {
                IgniteError err;

                LocalClearAll(keys, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Clear entries from the cache and swap storage, without notifying listeners or CacheWriters.
             * Entry is cleared only if it is not currently locked, and is not participating in a transaction.
             *
             * @note This operation is local as it merely clears entries from local cache, it does not
             * remove entries from remote caches.
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys to clear.
             * @param err Error.
             */
            void LocalClearAll(const std::set<K>& keys, IgniteError& err)
            {
                impl::InSetOperation<K> op(keys);

                impl.Get()->LocalClearAll(op, err);
            }

            /**
             * Clear entries from the cache and swap storage, without notifying listeners or CacheWriters.
             * Entry is cleared only if it is not currently locked, and is not participating in a transaction.
             *
             * @note This operation is local as it merely clears entries from local cache, it does not
             * remove entries from remote caches.
             *
             * This method should only be used on the valid instance.
             *
             * @param begin Iterator pointing to the beggining of the key sequence.
             * @param end Iterator pointing to the end of the key sequence.
             */
            template<typename Iter>
            void LocalClearAll(Iter begin, Iter end)
            {
                IgniteError err;

                impl::InIterOperation<K, V, Iter> op(begin, end);

                impl.Get()->LocalClearAll(op, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Removes given key mapping from cache. If cache previously contained value for the given key,
             * then this value is returned. In case of PARTITIONED or REPLICATED caches, the value will be
             * loaded from the primary node, which in its turn may load the value from the disk-based swap
             * storage, and consecutively, if it's not in swap, from the underlying persistent storage.
             * If the returned value is not needed, method removex() should always be used instead of this
             * one to avoid the overhead associated with returning of the previous value.
             * If write-through is enabled, the value will be removed from store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key whose mapping is to be removed from cache.
             * @return False if there was no matching key.
             */
            bool Remove(const K& key)
            {
                IgniteError err;

                bool res = Remove(key, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Removes given key mapping from cache. If cache previously contained value for the given key,
             * then this value is returned. In case of PARTITIONED or REPLICATED caches, the value will be
             * loaded from the primary node, which in its turn may load the value from the disk-based swap
             * storage, and consecutively, if it's not in swap, from the underlying persistent storage.
             * If the returned value is not needed, method removex() should always be used instead of this
             * one to avoid the overhead associated with returning of the previous value.
             * If write-through is enabled, the value will be removed from store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key whose mapping is to be removed from cache.
             * @param err Error.
             * @return False if there was no matching key.
             */
            bool Remove(const K& key, IgniteError& err)
            {
                impl::In1Operation<K> op(key);

                return impl.Get()->Remove(op, err);
            }

            /**
             * Removes given key mapping from cache if one exists and value is equal to the passed in value.
             * If write-through is enabled, the value will be removed from store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key whose mapping is to be removed from cache.
             * @param val Value to match against currently cached value.
             * @return True if entry was removed, false otherwise.
             */
            bool Remove(const K& key, const V& val)
            {
                IgniteError err;

                bool res = Remove(key, val, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Removes given key mapping from cache if one exists and value is equal to the passed in value.
             * If write-through is enabled, the value will be removed from store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param key Key whose mapping is to be removed from cache.
             * @param val Value to match against currently cached value.
             * @param err Error.
             * @return True if entry was removed, false otherwise.
             */
            bool Remove(const K& key, const V& val, IgniteError& err)
            {
                impl::In2Operation<K, V> op(key, val);

                return impl.Get()->RemoveIfEqual(op, err);
            }

            /**
             * Removes given key mappings from cache.
             * If write-through is enabled, the value will be removed from store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys whose mappings are to be removed from cache.
             */
            void RemoveAll(const std::set<K>& keys)
            {
                IgniteError err;

                RemoveAll(keys, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Removes given key mappings from cache.
             * If write-through is enabled, the value will be removed from store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param keys Keys whose mappings are to be removed from cache.
             * @param err Error.
             */
            void RemoveAll(const std::set<K>& keys, IgniteError& err)
            {
                impl::InSetOperation<K> op(keys);

                impl.Get()->RemoveAll(op, err);
            }

            /**
             * Removes given key mappings from cache.
             * If write-through is enabled, the value will be removed from store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param begin Iterator pointing to the beggining of the key sequence.
             * @param end Iterator pointing to the end of the key sequence.
             */
            template<typename Iter>
            void RemoveAll(Iter begin, Iter end)
            {
                IgniteError err;

                impl::InIterOperation<K, V, Iter> op(begin, end);

                impl.Get()->RemoveAll(op, err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Removes all mappings from cache.
             * If write-through is enabled, the value will be removed from store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             */
            void RemoveAll()
            {
                IgniteError err;

                RemoveAll(err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Removes all mappings from cache.
             * If write-through is enabled, the value will be removed from store.
             * This method is transactional and will enlist the entry into ongoing transaction if there is one.
             *
             * This method should only be used on the valid instance.
             *
             * @param err Error.
             */
            void RemoveAll(IgniteError& err)
            {
                return impl.Get()->RemoveAll(err);
            }

            /**
             * Gets the number of all entries cached on this node.
             *
             * This method should only be used on the valid instance.
             *
             * @return Cache size on this node.
             */
            int32_t LocalSize()
            {
                return LocalSize(CachePeekMode::ALL);
            }

            /**
             * Gets the number of all entries cached on this node.
             *
             * This method should only be used on the valid instance.
             *
             * @param err Error.
             * @return Cache size on this node.
             */
            int32_t LocalSize(IgniteError& err)
            {
                return LocalSize(CachePeekMode::ALL, err);
            }

            /**
             * Gets the number of all entries cached on this node.
             *
             * This method should only be used on the valid instance.
             *
             * @param peekModes Peek modes.
             * @return Cache size on this node.
             */
            int32_t LocalSize(int32_t peekModes)
            {
                IgniteError err;

                int32_t res = LocalSize(peekModes, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Gets the number of all entries cached on this node.
             *
             * This method should only be used on the valid instance.
             *
             * @param peekModes Peek modes.
             * @param err Error.
             * @return Cache size on this node.
             */
            int32_t LocalSize(int32_t peekModes, IgniteError& err)
            {
                return impl.Get()->Size(peekModes, true, err);
            }

            /**
             * Gets the number of all entries cached across all nodes.
             * @note this operation is distributed and will query all participating nodes for their cache sizes.
             *
             * This method should only be used on the valid instance.
             *
             * @return Cache size across all nodes.
             */
            int32_t Size()
            {
                return Size(ignite::cache::CachePeekMode::ALL);
            }

            /**
             * Gets the number of all entries cached across all nodes.
             * @note This operation is distributed and will query all participating nodes for their cache sizes.
             *
             * This method should only be used on the valid instance.
             *
             * @param err Error.
             * @return Cache size across all nodes.
             */
            int32_t Size(IgniteError& err)
            {
                return Size(ignite::cache::CachePeekMode::ALL, err);
            }

            /**
             * Gets the number of all entries cached across all nodes.
             * @note This operation is distributed and will query all participating nodes for their cache sizes.
             *
             * This method should only be used on the valid instance.
             *
             * @param peekModes Peek modes.
             * @return Cache size across all nodes.
             */
            int32_t Size(int32_t peekModes)
            {
                IgniteError err;

                int32_t res = Size(peekModes, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Gets the number of all entries cached across all nodes.
             * @note This operation is distributed and will query all participating nodes for their cache sizes.
             *
             * This method should only be used on the valid instance.
             *
             * @param peekModes Peek modes.
             * @param err Error.
             * @return Cache size across all nodes.
             */
            int32_t Size(int32_t peekModes, IgniteError& err)
            {
                return impl.Get()->Size(peekModes, false, err);
            }

            /**
             * Perform SQL query.
             *
             * This method should only be used on the valid instance.
             *
             * @param qry Query.
             * @return Query cursor.
             */
            query::QueryCursor<K, V> Query(const query::SqlQuery& qry)
            {
                IgniteError err;

                query::QueryCursor<K, V> res = Query(qry, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Perform SQL query.
             *
             * This method should only be used on the valid instance.
             *
             * @param qry Query.
             * @param err Error.
             * @return Query cursor.
             */
            query::QueryCursor<K, V> Query(const query::SqlQuery& qry, IgniteError& err)
            {
                impl::cache::query::QueryCursorImpl* cursorImpl = impl.Get()->QuerySql(qry, err);

                return query::QueryCursor<K, V>(cursorImpl);
            }

            /**
             * Perform text query.
             *
             * This method should only be used on the valid instance.
             *
             * @param qry Query.
             * @return Query cursor.
             */
            query::QueryCursor<K, V> Query(const query::TextQuery& qry)
            {
                IgniteError err;

                query::QueryCursor<K, V> res = Query(qry, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Perform text query.
             *
             * This method should only be used on the valid instance.
             *
             * @param qry Query.
             * @param err Error.
             * @return Query cursor.
             */
            query::QueryCursor<K, V> Query(const query::TextQuery& qry, IgniteError& err)
            {
                impl::cache::query::QueryCursorImpl* cursorImpl = impl.Get()->QueryText(qry, err);

                return query::QueryCursor<K, V>(cursorImpl);
            }

            /**
             * Perform scan query.
             *
             * This method should only be used on the valid instance.
             *
             * @param qry Query.
             * @return Query cursor.
             */
            query::QueryCursor<K, V> Query(const query::ScanQuery& qry)
            {
                IgniteError err;

                query::QueryCursor<K, V> res = Query(qry, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Perform scan query.
             *
             * This method should only be used on the valid instance.
             *
             * @param qry Query.
             * @param err Error.
             * @return Query cursor.
             */
            query::QueryCursor<K, V> Query(const query::ScanQuery& qry, IgniteError& err)
            {
                impl::cache::query::QueryCursorImpl* cursorImpl = impl.Get()->QueryScan(qry, err);

                return query::QueryCursor<K, V>(cursorImpl);
            }

            /**
             * Perform sql fields query.
             *
             * This method should only be used on the valid instance.
             *
             * @param qry Query.
             * @return Query cursor.
             */
            query::QueryFieldsCursor Query(const query::SqlFieldsQuery& qry)
            {
                IgniteError err;

                query::QueryFieldsCursor res = Query(qry, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Perform sql fields query.
             *
             * This method should only be used on the valid instance.
             *
             * @param qry Query.
             * @param err Error.
             * @return Query cursor.
             */
            query::QueryFieldsCursor Query(const query::SqlFieldsQuery& qry, IgniteError& err)
            {
                impl::cache::query::QueryCursorImpl* cursorImpl = impl.Get()->QuerySqlFields(qry, err);

                return query::QueryFieldsCursor(cursorImpl);
            }

            /**
             * Invokes an CacheEntryProcessor against the MutableCacheEntry
             * specified by the provided key. If an entry does not exist for the
             * specified key, an attempt is made to load it (if a loader is
             * configured) or a surrogate entry, consisting of the key with a
             * null value is used instead.
             *
             * Return value, processor and argument classes should all be
             * default-constructable, copy-constructable and assignable. Also,
             * BinaryType class template should be specialized for every custom
             * class.
             *
             * Processor class should be registered as a cache entry processor using
             * IgniteBinding::RegisterCacheEntryProcessor() method. You can declare
             * #IgniteModuleInit() function to register your cache processors upon
             * module loading. There should be at most one instance of such function
             * per module.
             *
             * See the example below for details:
             * @code{.cpp}
             * IGNITE_EXPORTED_CALL void IgniteModuleInit(ignite::IgniteBindingContext& context)
             * {
             *     IgniteBinding binding = context.GetBinding();
             *
             *     binding.RegisterCacheEntryProcessor<MyProcessor1>();
             *     binding.RegisterCacheEntryProcessor<MyProcessor2>();
             *     // ...
             *     binding.RegisterCacheEntryProcessor<MyProcessorN>();
             * }
             * @endcode
             *
             * Additionally, processor class should be derived from the
             * ignite::CacheEntryProcessor class.
             *
             * @throw IgniteError on fail.
             *
             * @param key The key.
             * @param processor The processor.
             * @param arg The argument.
             * @return Result of the processing.
             */
            template<typename R, typename P, typename A>
            R Invoke(const K& key, const P& processor, const A& arg)
            {
                IgniteError err;

                R res = Invoke<R>(key, processor, arg, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Invokes an CacheEntryProcessor against the MutableCacheEntry
             * specified by the provided key. If an entry does not exist for the
             * specified key, an attempt is made to load it (if a loader is
             * configured) or a surrogate entry, consisting of the key with a
             * null value is used instead.
             *
             * Return value, processor and argument classes should all be
             * default-constructable, copy-constructable and assignable. Also,
             * BinaryType class template should be specialized for every custom
             * class.
             *
             * Processor class should be registered as a cache entry processor using
             * IgniteBinding::RegisterCacheEntryProcessor() method. You can declare
             * #IgniteModuleInit() function to register your cache processors upon
             * module loading. There should be at most one instance of such function
             * per module.
             *
             * See the example below for details:
             * @code{.cpp}
             * IGNITE_EXPORTED_CALL void IgniteModuleInit(ignite::IgniteBindingContext& context)
             * {
             *     IgniteBinding binding = context.GetBinding();
             *
             *     binding.RegisterCacheEntryProcessor<MyProcessor1>();
             *     binding.RegisterCacheEntryProcessor<MyProcessor2>();
             *     // ...
             *     binding.RegisterCacheEntryProcessor<MyProcessorN>();
             * }
             * @endcode
             *
             * Additionally, processor class should be derived from the
             * ignite::CacheEntryProcessor class.
             *
             * Sets err param which should be checked for the operation result.
             *
             * @param key The key.
             * @param processor The processor.
             * @param arg The argument.
             * @param err Error.
             * @return Result of the processing. Default-constructed value on error.
             */
            template<typename R, typename P, typename A>
            R Invoke(const K& key, const P& processor, const A& arg, IgniteError& err)
            {
                typedef impl::cache::CacheEntryProcessorHolder<P, A> ProcessorHolder;

                ProcessorHolder procHolder(processor, arg);

                impl::In2Operation<K, ProcessorHolder> inOp(key, procHolder);
                impl::Out1Operation<R> outOp;

                impl.Get()->Invoke(inOp, outOp, err);

                return outOp.GetResult();
            }

            /**
             * Start continuous query execution.
             *
             * @param qry Continuous query.
             * @return Continuous query handle.
             */
            query::continuous::ContinuousQueryHandle<K, V> QueryContinuous(
                const query::continuous::ContinuousQuery<K, V>& qry)
            {
                IgniteError err;

                query::continuous::ContinuousQueryHandle<K, V> res = QueryContinuous(qry, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Start continuous query execution.
             *
             * @param qry Continuous query.
             * @param err Error.
             * @return Continuous query handle.
             */
            query::continuous::ContinuousQueryHandle<K, V> QueryContinuous(
                const query::continuous::ContinuousQuery<K, V>& qry, IgniteError& err)
            {
                using namespace impl::cache::query::continuous;
                using namespace common::concurrent;

                const SharedPointer<ContinuousQueryImpl<K, V> >& qryImpl = qry.impl;

                if (!qryImpl.IsValid() || !qryImpl.Get()->HasListener())
                {
                    err = IgniteError(IgniteError::IGNITE_ERR_GENERIC,
                        "Event listener is not set for ContinuousQuery instance");

                    return query::continuous::ContinuousQueryHandle<K, V>();
                }

                ContinuousQueryHandleImpl* cqImpl = impl.Get()->QueryContinuous(qryImpl, err);

                return query::continuous::ContinuousQueryHandle<K, V>(cqImpl);
            }

            /**
             * Start continuous query execution with the initial query.
             *
             * @param qry Continuous query.
             * @param initialQry Initial query to be executed.
             * @return Continuous query handle.
             */
            template<typename Q>
            query::continuous::ContinuousQueryHandle<K, V> QueryContinuous(
                const query::continuous::ContinuousQuery<K, V>& qry,
                const Q& initialQry)
            {
                IgniteError err;

                query::continuous::ContinuousQueryHandle<K, V> res = QueryContinuous(qry, initialQry, err);

                IgniteError::ThrowIfNeeded(err);

                return res;
            }

            /**
             * Start continuous query execution with the initial query.
             *
             * @param qry Continuous query.
             * @param initialQry Initial query to be executed.
             * @param err Error.
             * @return Continuous query handle.
             */
            template<typename Q>
            query::continuous::ContinuousQueryHandle<K, V> QueryContinuous(
                const query::continuous::ContinuousQuery<K, V>& qry,
                const Q& initialQry, IgniteError& err)
            {
                using namespace impl::cache::query::continuous;
                using namespace common::concurrent;

                const SharedPointer<ContinuousQueryImpl<K, V> >& qryImpl = qry.impl;

                if (!qryImpl.IsValid() || !qryImpl.Get()->HasListener())
                {
                    err = IgniteError(IgniteError::IGNITE_ERR_GENERIC,
                        "Event listener is not set for ContinuousQuery instance");

                    return query::continuous::ContinuousQueryHandle<K, V>();
                }

                ContinuousQueryHandleImpl* cqImpl = impl.Get()->QueryContinuous(qryImpl, initialQry, err);

                return query::continuous::ContinuousQueryHandle<K, V>(cqImpl);
            }

            /**
             * Check if the instance is valid.
             *
             * Invalid instance can be returned if some of the previous
             * operations have resulted in a failure. For example invalid
             * instance can be returned by not-throwing version of method
             * in case of error. Invalid instances also often can be
             * created using default constructor.
             *
             * @return True if the instance is valid and can be used.
             */
            bool IsValid() const
            {
                return impl.IsValid();
            }

            /**
             * Executes LocalLoadCache on all cache nodes.
             */
            void LoadCache()
            {
                IgniteError err;

                impl.Get()->LoadCache(err);

                IgniteError::ThrowIfNeeded(err);
            }

            /**
             * Loads state from the underlying persistent storage.
             *
             * This method is not transactional and may end up loading a stale value into
             * cache if another thread has updated the value immediately after it has been
             * loaded. It is mostly useful when pre-loading the cache from underlying
             * data store before start, or for read-only caches.
             */
            void LocalLoadCache()
            {
                IgniteError err;

                impl.Get()->LocalLoadCache(err);

                IgniteError::ThrowIfNeeded(err);
            }

        private:
            /** Implementation delegate. */
            common::concurrent::SharedPointer<impl::cache::CacheImpl> impl;
        };
    }
}

#endif //_IGNITE_CACHE_CACHE

redpajama_set_name: RedPajamaGithub


Blends away imperfections & redness. Creates a soft & porcelain like look.
This CC cream is so rich and makes my skin super smooth! It also corrects my patchy tone.
It protects my skin from the sun & does not cause breakouts. Would buy again.
Achieve a perfect and natural no makeup look!
Tonymoly Luminous Pure Aura CC Cream blends into your skin color like a chameleon. Leaving it even toned, luminous & simply flawless.
The all in one cream offers: sunscreen, brightening, wrinkle repair, radiance, moisture, primer, base make-up.
The Tonymoly Luminous Pure Aura CC Cream features color change capsules that blend to match your skin tone.
After your skin care routine, dispense a pearl amount into your hand.
Using your fingertips or a makeup sponge, evenly apply from cheeks, forehead to nose and chin.
Layer Tonymoly Luminous Pure Aura CC Cream to conceal imperfections better.
I've tried like a million of CC creams, but this is my favourite one! It doesn't irritate my skin & looks so natural. Would recommend this to everyone!
Its good but I have to use a lot to cover my facial redness.
i heard a lot of good reviews about this product and i can only agree. it's very lightweight and blends in perfectly. i really like how it makes my skin look glowy and super fresh.